Compare commits
20 Commits
minify-nod
...
misskey-js
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b0a416566 | ||
|
|
9044fa5d1a | ||
|
|
3bb343e2fc | ||
|
|
f2fd8bfac1 | ||
|
|
1602ad843a | ||
|
|
e68236bd84 | ||
|
|
447b6f9e5f | ||
|
|
746bc322b7 | ||
|
|
a6aee82fcf | ||
|
|
6095b33ab2 | ||
|
|
5ac094e51b | ||
|
|
bdf013d547 | ||
|
|
96a2dda153 | ||
|
|
d69d2c8e8d | ||
|
|
8736bb42f2 | ||
|
|
effd78dc98 | ||
|
|
634ce0fa49 | ||
|
|
6e6a5222cd | ||
|
|
ce5a9630ca | ||
|
|
d123722616 |
@@ -1,223 +0,0 @@
|
||||
#âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
||||
# Misskey configuration
|
||||
#âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# ââââââââââââââââââââââââââ
|
||||
#ââââ Initial Setup Password ââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# Password to initiate setting up admin account.
|
||||
# It will not be used after the initial setup is complete.
|
||||
#
|
||||
# Be sure to change this when you set up Misskey via the Internet.
|
||||
#
|
||||
# The provider of the service who sets up Misskey on behalf of the customer should
|
||||
# set this value to something unique when generating the Misskey config file,
|
||||
# and provide it to the customer.
|
||||
setupPassword: example_password_please_change_this_or_you_will_get_hacked
|
||||
|
||||
# âââââââ
|
||||
#ââââ URL ââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# Final accessible URL seen by a user.
|
||||
url: 'http://misskey.local'
|
||||
|
||||
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
|
||||
# URL SETTINGS AFTER THAT!
|
||||
|
||||
# âââââââââââââââââââââââââ
|
||||
#ââââ Port and TLS settings ââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
#
|
||||
# Misskey requires a reverse proxy to support HTTPS connections.
|
||||
#
|
||||
# +----- https://example.tld/ ------------+
|
||||
# +------+ |+-------------+ +----------------+|
|
||||
# | User | ---> || Proxy (443) | ---> | Misskey (3000) ||
|
||||
# +------+ |+-------------+ +----------------+|
|
||||
# +---------------------------------------+
|
||||
#
|
||||
# You need to set up a reverse proxy. (e.g. nginx)
|
||||
# An encrypted connection with HTTPS is highly recommended
|
||||
# because tokens may be transferred in GET requests.
|
||||
|
||||
# The port that your Misskey server should listen on.
|
||||
port: 61812
|
||||
|
||||
# ââââââââââââââââââââââââââââ
|
||||
#ââââ PostgreSQL configuration âââââââââââââââââââââââââââââââââ
|
||||
|
||||
db:
|
||||
host: db
|
||||
port: 5432
|
||||
|
||||
# Database name
|
||||
db: misskey
|
||||
|
||||
# Auth
|
||||
user: postgres
|
||||
pass: postgres
|
||||
|
||||
# Whether disable Caching queries
|
||||
#disableCache: true
|
||||
|
||||
# Extra Connection options
|
||||
#extra:
|
||||
# ssl: true
|
||||
|
||||
dbReplications: false
|
||||
|
||||
# You can configure any number of replicas here
|
||||
#dbSlaves:
|
||||
# -
|
||||
# host:
|
||||
# port:
|
||||
# db:
|
||||
# user:
|
||||
# pass:
|
||||
# -
|
||||
# host:
|
||||
# port:
|
||||
# db:
|
||||
# user:
|
||||
# pass:
|
||||
|
||||
# âââââââââââââââââââââââ
|
||||
#ââââ Redis configuration ââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
redis:
|
||||
host: redis
|
||||
port: 6379
|
||||
#family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
#pass: example-pass
|
||||
#prefix: example-prefix
|
||||
#db: 1
|
||||
|
||||
#redisForPubsub:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForJobQueue:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForTimelines:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForReactions:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
# âââââââââââââââââââââââââââââ
|
||||
#ââââ MeiliSearch configuration ââââââââââââââââââââââââââââââ
|
||||
|
||||
#meilisearch:
|
||||
# host: meilisearch
|
||||
# port: 7700
|
||||
# apiKey: ''
|
||||
# ssl: true
|
||||
# index: ''
|
||||
|
||||
# âââââââââââââââââ
|
||||
#ââââ ID generation ââââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# You can select the ID generation method.
|
||||
# You don't usually need to change this setting, but you can
|
||||
# change it according to your preferences.
|
||||
|
||||
# Available methods:
|
||||
# aid ... Short, Millisecond accuracy
|
||||
# aidx ... Millisecond accuracy
|
||||
# meid ... Similar to ObjectID, Millisecond accuracy
|
||||
# ulid ... Millisecond accuracy
|
||||
# objectid ... This is left for backward compatibility
|
||||
|
||||
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
|
||||
# ID SETTINGS AFTER THAT!
|
||||
|
||||
id: 'aidx'
|
||||
|
||||
# ââââââââââââââââââ
|
||||
#ââââ Error tracking âââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# Sentry is available for error tracking.
|
||||
# See the Sentry documentation for more details on options.
|
||||
|
||||
#sentryForBackend:
|
||||
# enableNodeProfiling: true
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
#sentryForFrontend:
|
||||
# vueIntegration:
|
||||
# tracingOptions:
|
||||
# trackComponents: true
|
||||
# browserTracingIntegration:
|
||||
# replayIntegration:
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
# âââââââââââââââââââââââ
|
||||
#ââââ Other configuration ââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# Whether disable HSTS
|
||||
#disableHsts: true
|
||||
|
||||
# Number of worker processes
|
||||
#clusterLimit: 1
|
||||
|
||||
# Job concurrency per worker
|
||||
# deliverJobConcurrency: 128
|
||||
# inboxJobConcurrency: 16
|
||||
|
||||
# Job rate limiter
|
||||
# deliverJobPerSec: 128
|
||||
# inboxJobPerSec: 32
|
||||
|
||||
# Job attempts
|
||||
# deliverJobMaxAttempts: 12
|
||||
# inboxJobMaxAttempts: 8
|
||||
|
||||
# IP address family used for outgoing request (ipv4, ipv6 or dual)
|
||||
#outgoingAddressFamily: ipv4
|
||||
|
||||
# Proxy for HTTP/HTTPS
|
||||
#proxy: http://127.0.0.1:3128
|
||||
|
||||
proxyBypassHosts:
|
||||
- api.deepl.com
|
||||
- api-free.deepl.com
|
||||
- www.recaptcha.net
|
||||
- hcaptcha.com
|
||||
- challenges.cloudflare.com
|
||||
|
||||
# Proxy for SMTP/SMTPS
|
||||
#proxySmtp: http://127.0.0.1:3128 # use HTTP/1.1 CONNECT
|
||||
#proxySmtp: socks4://127.0.0.1:1080 # use SOCKS4
|
||||
#proxySmtp: socks5://127.0.0.1:1080 # use SOCKS5
|
||||
|
||||
# Media Proxy
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
allowedPrivateNetworks: [
|
||||
'127.0.0.1/32'
|
||||
]
|
||||
|
||||
# Upload or download file size limits (bytes)
|
||||
#maxFileSize: 262144000
|
||||
@@ -1,11 +1,4 @@
|
||||
# misskey settings
|
||||
# MISSKEY_URL=https://example.tld/
|
||||
|
||||
# db settings
|
||||
POSTGRES_PASSWORD=example-misskey-pass
|
||||
# DATABASE_PASSWORD=${POSTGRES_PASSWORD}
|
||||
POSTGRES_USER=example-misskey-user
|
||||
# DATABASE_USER=${POSTGRES_USER}
|
||||
POSTGRES_DB=misskey
|
||||
# DATABASE_DB=${POSTGRES_DB}
|
||||
DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}"
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#ââââ URL ââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# Final accessible URL seen by a user.
|
||||
# You can set url from an environment variable instead.
|
||||
url: https://example.tld/
|
||||
|
||||
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
|
||||
@@ -39,11 +38,9 @@ db:
|
||||
port: 5432
|
||||
|
||||
# Database name
|
||||
# You can set db from an environment variable instead.
|
||||
db: misskey
|
||||
|
||||
# Auth
|
||||
# You can set user and pass from environment variables instead.
|
||||
user: example-misskey-user
|
||||
pass: example-misskey-pass
|
||||
|
||||
@@ -54,23 +51,6 @@ db:
|
||||
#extra:
|
||||
# ssl: true
|
||||
|
||||
dbReplications: false
|
||||
|
||||
# You can configure any number of replicas here
|
||||
#dbSlaves:
|
||||
# -
|
||||
# host:
|
||||
# port:
|
||||
# db:
|
||||
# user:
|
||||
# pass:
|
||||
# -
|
||||
# host:
|
||||
# port:
|
||||
# db:
|
||||
# user:
|
||||
# pass:
|
||||
|
||||
# âââââââââââââââââââââââ
|
||||
#ââââ Redis configuration ââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
@@ -82,69 +62,15 @@ redis:
|
||||
#prefix: example-prefix
|
||||
#db: 1
|
||||
|
||||
#redisForPubsub:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
# âââââââââââââââââââââââââââââââ
|
||||
#ââââ Elasticsearch configuration ââââââââââââââââââââââââââââââ
|
||||
|
||||
#redisForJobQueue:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForTimelines:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForReactions:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
# âââââââââââââââââââââââââââââââââ
|
||||
#ââââ Fulltext search configuration ââââââââââââââââââââââââââââââ
|
||||
|
||||
# These are the setting items for the full-text search provider.
|
||||
fulltextSearch:
|
||||
# You can select the ID generation method.
|
||||
# - sqlLike (default)
|
||||
# Use SQL-like search.
|
||||
# This is a standard feature of PostgreSQL, so no special extensions are required.
|
||||
# - sqlPgroonga
|
||||
# Use pgroonga.
|
||||
# You need to install pgroonga and configure it as a PostgreSQL extension.
|
||||
# In addition to the above, you need to create a pgroonga index on the text column of the note table.
|
||||
# see: https://pgroonga.github.io/tutorial/
|
||||
# - meilisearch
|
||||
# Use Meilisearch.
|
||||
# You need to install Meilisearch and configure.
|
||||
provider: sqlLike
|
||||
|
||||
# For Meilisearch settings.
|
||||
# If you select "meilisearch" for "fulltextSearch.provider", it must be set.
|
||||
# You can set scope to local (default value) or global
|
||||
# (include notes from remote).
|
||||
|
||||
#meilisearch:
|
||||
# host: meilisearch
|
||||
# port: 7700
|
||||
# apiKey: ''
|
||||
# ssl: true
|
||||
# index: ''
|
||||
# scope: local
|
||||
#elasticsearch:
|
||||
# host: localhost
|
||||
# port: 9200
|
||||
# ssl: false
|
||||
# user:
|
||||
# pass:
|
||||
|
||||
# âââââââââââââââââ
|
||||
#ââââ ID generation ââââââââââââââââââââââââââââââââââââââââââââ
|
||||
@@ -155,7 +81,6 @@ fulltextSearch:
|
||||
|
||||
# Available methods:
|
||||
# aid ... Short, Millisecond accuracy
|
||||
# aidx ... Millisecond accuracy
|
||||
# meid ... Similar to ObjectID, Millisecond accuracy
|
||||
# ulid ... Millisecond accuracy
|
||||
# objectid ... This is left for backward compatibility
|
||||
@@ -163,27 +88,7 @@ fulltextSearch:
|
||||
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
|
||||
# ID SETTINGS AFTER THAT!
|
||||
|
||||
id: 'aidx'
|
||||
|
||||
# ââââââââââââââââââ
|
||||
#ââââ Error tracking âââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# Sentry is available for error tracking.
|
||||
# See the Sentry documentation for more details on options.
|
||||
|
||||
#sentryForBackend:
|
||||
# enableNodeProfiling: true
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
#sentryForFrontend:
|
||||
# vueIntegration:
|
||||
# tracingOptions:
|
||||
# trackComponents: true
|
||||
# browserTracingIntegration:
|
||||
# replayIntegration:
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
id: 'aid'
|
||||
|
||||
# âââââââââââââââââââââââ
|
||||
#ââââ Other configuration ââââââââââââââââââââââââââââââââââââââ
|
||||
@@ -200,7 +105,7 @@ id: 'aidx'
|
||||
|
||||
# Job rate limiter
|
||||
# deliverJobPerSec: 128
|
||||
# inboxJobPerSec: 32
|
||||
# inboxJobPerSec: 16
|
||||
|
||||
# Job attempts
|
||||
# deliverJobMaxAttempts: 12
|
||||
@@ -227,22 +132,15 @@ proxyBypassHosts:
|
||||
# Media Proxy
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
# For security reasons, uploading attachments from the intranet is prohibited,
|
||||
# but exceptions can be made from the following settings. Default value is "undefined".
|
||||
# Read changelog to learn more (Improvements of 12.90.0 (2021/09/04)).
|
||||
# Proxy remote files (default: false)
|
||||
#proxyRemoteFiles: true
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
|
||||
#allowedPrivateNetworks: [
|
||||
# '127.0.0.1/32'
|
||||
#]
|
||||
|
||||
# Upload or download file size limits (bytes)
|
||||
#maxFileSize: 262144000
|
||||
|
||||
# Log settings
|
||||
# logging:
|
||||
# sql:
|
||||
# # Outputs query parameters during SQL execution to the log.
|
||||
# # default: false
|
||||
# enableQueryParamLogging: false
|
||||
# # Disable query truncation. If set to true, the full text of the query will be output to the log.
|
||||
# # default: false
|
||||
# disableQueryTruncation: false
|
||||
|
||||
@@ -2,77 +2,6 @@
|
||||
# Misskey configuration
|
||||
#âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# ââââââââââââââââââââââââââââââââ
|
||||
#ââââ a boring but important thing âââââââââââââââââââââââââââââ
|
||||
|
||||
#
|
||||
# First of all, let me tell you a story that may possibly be
|
||||
# boring to you and possibly important to you.
|
||||
#
|
||||
# Misskey is licensed under the AGPLv3 license. This license is
|
||||
# known to be often misunderstood. Please read the following
|
||||
# instructions carefully and select the appropriate option so
|
||||
# that you do not negligently cause a license violation.
|
||||
#
|
||||
|
||||
# --------
|
||||
# Option 1: If you host Misskey AS-IS (without any changes to
|
||||
# the source code. forks are not included).
|
||||
#
|
||||
# Step 1: Congratulations! You don't need to do anything.
|
||||
|
||||
# --------
|
||||
# Option 2: If you have made changes to the source code (forks
|
||||
# are included) and publish a Git repository of source
|
||||
# code. There should be no access restrictions on
|
||||
# this repository. Strictly speaking, it doesn't have
|
||||
# to be a Git repository, but you'll probably use Git!
|
||||
#
|
||||
# Step 1: Build and run the Misskey server first.
|
||||
# Step 2: Open <https://your.misskey.example/admin/settings> in
|
||||
# your browser with the administrator account.
|
||||
# Step 3: Enter the URL of your Git repository in the
|
||||
# "Repository URL" field.
|
||||
|
||||
# --------
|
||||
# Option 3: If neither of the above applies to you.
|
||||
# (In this case, the source code should be published
|
||||
# on the Misskey interface. IT IS NOT ENOUGH TO
|
||||
# DISCLOSE THE SOURCE CODE WHEN A USER REQUESTS IT BY
|
||||
# E-MAIL OR OTHER MEANS. If you are not satisfied
|
||||
# with this, it is recommended that you read the
|
||||
# license again carefully. Anyway, enabling this
|
||||
# option will automatically generate and publish a
|
||||
# tarball at build time, protecting you from
|
||||
# inadvertent license violations. (There is no legal
|
||||
# guarantee, of course.) The tarball will generated
|
||||
# from the root directory of your codebase. So it is
|
||||
# also recommended to check <built/tarball> directory
|
||||
# once after building and before activating the server
|
||||
# to avoid ACCIDENTAL LEAKING OF SENSITIVE INFORMATION.
|
||||
# To prevent certain files from being included in the
|
||||
# tarball, add a glob pattern after line 15 in
|
||||
# <scripts/tarball.mjs>. DO NOT FORGET TO BUILD AFTER
|
||||
# ENABLING THIS OPTION!)
|
||||
#
|
||||
# Step 1: Uncomment the following line.
|
||||
#
|
||||
# publishTarballInsteadOfProvideRepositoryUrl: true
|
||||
|
||||
# ââââââââââââââââââââââââââ
|
||||
#ââââ Initial Setup Password ââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# Password to initiate setting up admin account.
|
||||
# It will not be used after the initial setup is complete.
|
||||
#
|
||||
# Be sure to change this when you set up Misskey via the Internet.
|
||||
#
|
||||
# The provider of the service who sets up Misskey on behalf of the customer should
|
||||
# set this value to something unique when generating the Misskey config file,
|
||||
# and provide it to the customer.
|
||||
#
|
||||
# setupPassword: example_password_please_change_this_or_you_will_get_hacked
|
||||
|
||||
# âââââââ
|
||||
#ââââ URL ââââââââââââââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
@@ -101,58 +30,6 @@ url: https://example.tld/
|
||||
# The port that your Misskey server should listen on.
|
||||
port: 3000
|
||||
|
||||
# You can also use UNIX domain socket.
|
||||
# socket: /path/to/misskey.sock
|
||||
# chmodSocket: '777'
|
||||
|
||||
# Proxy trust settings
|
||||
#
|
||||
# Specifies the IP addresses that Misskey will use as trusted
|
||||
# reverse proxies (e.g., nginx, Cloudflare). This affects how
|
||||
# Misskey determines the source IP for each request and is used
|
||||
# for important rate limiting and security features. If the value
|
||||
# is not set correctly, Misskey may use the IP address of the
|
||||
# reverse proxy instead of the actual source IP, which may lead to
|
||||
# unintended rate limiting or security vulnerabilities.
|
||||
# By default, the loopback network and private network address
|
||||
# ranges shown below are trusted.
|
||||
# If you are using a single reverse proxy and it is on the same
|
||||
# machine or the same private network as Misskey, it is unlikely you
|
||||
# need to change this setting, and the default setting is fine.
|
||||
# Also, if you are using multiple reverse proxy servers and they are
|
||||
# all on the same private network as Misskey, the default setting
|
||||
# is fine.
|
||||
# However, if you are using a reverse proxy server that accesses
|
||||
# Misskey web servers and streaming servers via public IP addresses
|
||||
# (for example, Cloudflare), you must set this variable.
|
||||
# When changing this setting, you can use one of the following values:
|
||||
#
|
||||
# - true: Trust all proxies
|
||||
# - false: Do not trust any proxies
|
||||
# - IP address, IP address range, or array of them: Trust hops that
|
||||
# match the specified criteria.
|
||||
# - Integer: Trust the nth hop from the front-facing proxy server as
|
||||
# the client.
|
||||
# For more information on how to configure this setting, please refer
|
||||
# to the Fastify documentation:
|
||||
# https://fastify.dev/docs/latest/Reference/Server/#trustproxy
|
||||
#
|
||||
# Note that if this variable is set, it overrides the default range,
|
||||
# so if you have both an external reverse proxy and a proxy on the
|
||||
# local host, you must include both IPs (or IP ranges).
|
||||
#
|
||||
#trustProxy:
|
||||
# - '10.0.0.0/8'
|
||||
# - '172.16.0.0/12'
|
||||
# - '192.168.0.0/16'
|
||||
# - '127.0.0.1/32'
|
||||
# - '::1/128'
|
||||
# - 'fc00::/7'
|
||||
# # Example: If you are using some external reverse proxies like CDNs,
|
||||
# # you may need to add the CDN IP ranges here.
|
||||
# # If you're using Cloudflare, you can find IP Ranges at:
|
||||
# # https://www.cloudflare.com/ips/
|
||||
|
||||
# ââââââââââââââââââââââââââââ
|
||||
#ââââ PostgreSQL configuration âââââââââââââââââââââââââââââââââ
|
||||
|
||||
@@ -174,23 +51,6 @@ db:
|
||||
#extra:
|
||||
# ssl: true
|
||||
|
||||
dbReplications: false
|
||||
|
||||
# You can configure any number of replicas here
|
||||
#dbSlaves:
|
||||
# -
|
||||
# host:
|
||||
# port:
|
||||
# db:
|
||||
# user:
|
||||
# pass:
|
||||
# -
|
||||
# host:
|
||||
# port:
|
||||
# db:
|
||||
# user:
|
||||
# pass:
|
||||
|
||||
# âââââââââââââââââââââââ
|
||||
#ââââ Redis configuration ââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
@@ -201,80 +61,16 @@ redis:
|
||||
#pass: example-pass
|
||||
#prefix: example-prefix
|
||||
#db: 1
|
||||
# You can specify more ioredis options...
|
||||
#username: example-username
|
||||
|
||||
#redisForPubsub:
|
||||
# âââââââââââââââââââââââââââââââ
|
||||
#ââââ Elasticsearch configuration ââââââââââââââââââââââââââââââ
|
||||
|
||||
#elasticsearch:
|
||||
# host: localhost
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
# # You can specify more ioredis options...
|
||||
# #username: example-username
|
||||
|
||||
#redisForJobQueue:
|
||||
# host: localhost
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
# # You can specify more ioredis options...
|
||||
# #username: example-username
|
||||
|
||||
#redisForTimelines:
|
||||
# host: localhost
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
# # You can specify more ioredis options...
|
||||
# #username: example-username
|
||||
|
||||
#redisForReactions:
|
||||
# host: localhost
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
# # You can specify more ioredis options...
|
||||
# #username: example-username
|
||||
|
||||
# âââââââââââââââââââââââââââââââââ
|
||||
#ââââ Fulltext search configuration ââââââââââââââââââââââââââââââ
|
||||
|
||||
# These are the setting items for the full-text search provider.
|
||||
fulltextSearch:
|
||||
# You can select the ID generation method.
|
||||
# - sqlLike (default)
|
||||
# Use SQL-like search.
|
||||
# This is a standard feature of PostgreSQL, so no special extensions are required.
|
||||
# - sqlPgroonga
|
||||
# Use pgroonga.
|
||||
# You need to install pgroonga and configure it as a PostgreSQL extension.
|
||||
# In addition to the above, you need to create a pgroonga index on the text column of the note table.
|
||||
# see: https://pgroonga.github.io/tutorial/
|
||||
# - meilisearch
|
||||
# Use Meilisearch.
|
||||
# You need to install Meilisearch and configure.
|
||||
provider: sqlLike
|
||||
|
||||
# For Meilisearch settings.
|
||||
# If you select "meilisearch" for "fulltextSearch.provider", it must be set.
|
||||
# You can set scope to local (default value) or global
|
||||
# (include notes from remote).
|
||||
|
||||
#meilisearch:
|
||||
# host: localhost
|
||||
# port: 7700
|
||||
# apiKey: ''
|
||||
# ssl: true
|
||||
# index: ''
|
||||
# scope: local
|
||||
# port: 9200
|
||||
# ssl: false
|
||||
# user:
|
||||
# pass:
|
||||
|
||||
# âââââââââââââââââ
|
||||
#ââââ ID generation ââââââââââââââââââââââââââââââââââââââââââââ
|
||||
@@ -285,7 +81,6 @@ fulltextSearch:
|
||||
|
||||
# Available methods:
|
||||
# aid ... Short, Millisecond accuracy
|
||||
# aidx ... Millisecond accuracy
|
||||
# meid ... Similar to ObjectID, Millisecond accuracy
|
||||
# ulid ... Millisecond accuracy
|
||||
# objectid ... This is left for backward compatibility
|
||||
@@ -293,27 +88,7 @@ fulltextSearch:
|
||||
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
|
||||
# ID SETTINGS AFTER THAT!
|
||||
|
||||
id: 'aidx'
|
||||
|
||||
# ââââââââââââââââââ
|
||||
#ââââ Error tracking âââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# Sentry is available for error tracking.
|
||||
# See the Sentry documentation for more details on options.
|
||||
|
||||
#sentryForBackend:
|
||||
# enableNodeProfiling: true
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
#sentryForFrontend:
|
||||
# vueIntegration:
|
||||
# tracingOptions:
|
||||
# trackComponents: true
|
||||
# browserTracingIntegration:
|
||||
# replayIntegration:
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
id: 'aid'
|
||||
|
||||
# âââââââââââââââââââââââ
|
||||
#ââââ Other configuration ââââââââââââââââââââââââââââââââââââââ
|
||||
@@ -321,31 +96,20 @@ id: 'aidx'
|
||||
# Whether disable HSTS
|
||||
#disableHsts: true
|
||||
|
||||
# Enable internal IP-based rate limiting (default: true)
|
||||
# To configure them in reverse proxy instead, set this to false.
|
||||
#enableIpRateLimit: true
|
||||
|
||||
# Number of worker processes
|
||||
#clusterLimit: 1
|
||||
|
||||
# Job concurrency per worker
|
||||
#deliverJobConcurrency: 128
|
||||
#inboxJobConcurrency: 16
|
||||
#relationshipJobConcurrency: 16
|
||||
# What's relationshipJob?:
|
||||
# Follow, unfollow, block and unblock(ings) while following-imports, etc. or account migrations.
|
||||
# deliverJobConcurrency: 128
|
||||
# inboxJobConcurrency: 16
|
||||
|
||||
# Job rate limiter
|
||||
#deliverJobPerSec: 128
|
||||
#inboxJobPerSec: 32
|
||||
#relationshipJobPerSec: 64
|
||||
# deliverJobPerSec: 128
|
||||
# inboxJobPerSec: 16
|
||||
|
||||
# Job attempts
|
||||
#deliverJobMaxAttempts: 12
|
||||
#inboxJobMaxAttempts: 8
|
||||
|
||||
# Local address used for outgoing requests
|
||||
#outgoingAddress: 127.0.0.1
|
||||
# deliverJobMaxAttempts: 12
|
||||
# inboxJobMaxAttempts: 8
|
||||
|
||||
# IP address family used for outgoing request (ipv4, ipv6 or dual)
|
||||
#outgoingAddressFamily: ipv4
|
||||
@@ -371,31 +135,22 @@ proxyBypassHosts:
|
||||
# * Perform image compression (on a different server resource than the main process)
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
# Proxy remote files (default: false)
|
||||
# Proxy remote files by this instance or mediaProxy to prevent remote files from running in remote domains.
|
||||
#proxyRemoteFiles: true
|
||||
|
||||
# Movie Thumbnail Generation URL
|
||||
# There is no reference implementation.
|
||||
# For example, Misskey will point to the following URL:
|
||||
# https://example.com/thumbnail.webp?thumbnail=1&url=https%3A%2F%2Fstorage.example.com%2Fpath%2Fto%2Fvideo.mp4
|
||||
#videoThumbnailGenerator: https://example.com
|
||||
|
||||
# For security reasons, uploading attachments from the intranet is prohibited,
|
||||
# but exceptions can be made from the following settings. Default value is "undefined".
|
||||
# Read changelog to learn more (Improvements of 12.90.0 (2021/09/04)).
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
|
||||
#allowedPrivateNetworks: [
|
||||
# '127.0.0.1/32'
|
||||
#]
|
||||
|
||||
# Upload or download file size limits (bytes)
|
||||
#maxFileSize: 262144000
|
||||
|
||||
# PID File of master process
|
||||
#pidFile: /tmp/misskey.pid
|
||||
|
||||
# Log settings
|
||||
# logging:
|
||||
# sql:
|
||||
# # Outputs query parameters during SQL execution to the log.
|
||||
# # default: false
|
||||
# enableQueryParamLogging: false
|
||||
# # Disable query truncation. If set to true, the full text of the query will be output to the log.
|
||||
# # default: false
|
||||
# disableQueryTruncation: false
|
||||
|
||||
@@ -1 +1 @@
|
||||
FROM mcr.microsoft.com/devcontainers/javascript-node:4.0.3-24-trixie
|
||||
FROM mcr.microsoft.com/devcontainers/javascript-node:0-18
|
||||
|
||||
@@ -1,24 +1,20 @@
|
||||
{
|
||||
"name": "Misskey",
|
||||
"dockerComposeFile": "compose.yml",
|
||||
"dockerComposeFile": "docker-compose.yml",
|
||||
"service": "app",
|
||||
"workspaceFolder": "/workspace",
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/node:1": {
|
||||
"version": "22.15.0"
|
||||
},
|
||||
"ghcr.io/devcontainers-extra/features/pnpm:2": {
|
||||
"version": "10.10.0"
|
||||
}
|
||||
"ghcr.io/devcontainers-contrib/features/pnpm:2": {}
|
||||
},
|
||||
"forwardPorts": [3000],
|
||||
"postCreateCommand": "/bin/bash .devcontainer/init.sh",
|
||||
"postCreateCommand": "sudo chmod 755 .devcontainer/init.sh && .devcontainer/init.sh",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"Vue.volar",
|
||||
"Vue.vscode-typescript-vue-plugin",
|
||||
"Orta.vscode-jest",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"mrmlnc.vscode-json5"
|
||||
|
||||
@@ -51,23 +51,6 @@ db:
|
||||
#extra:
|
||||
# ssl: true
|
||||
|
||||
dbReplications: false
|
||||
|
||||
# You can configure any number of replicas here
|
||||
#dbSlaves:
|
||||
# -
|
||||
# host:
|
||||
# port:
|
||||
# db:
|
||||
# user:
|
||||
# pass:
|
||||
# -
|
||||
# host:
|
||||
# port:
|
||||
# db:
|
||||
# user:
|
||||
# pass:
|
||||
|
||||
# âââââââââââââââââââââââ
|
||||
#ââââ Redis configuration ââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
@@ -79,47 +62,15 @@ redis:
|
||||
#prefix: example-prefix
|
||||
#db: 1
|
||||
|
||||
#redisForPubsub:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
# âââââââââââââââââââââââââââââââ
|
||||
#ââââ Elasticsearch configuration ââââââââââââââââââââââââââââââ
|
||||
|
||||
#redisForJobQueue:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForTimelines:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForReactions:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
# âââââââââââââââââââââââââââââ
|
||||
#ââââ MeiliSearch configuration ââââââââââââââââââââââââââââââ
|
||||
|
||||
#meilisearch:
|
||||
# host: meilisearch
|
||||
# port: 7700
|
||||
# apiKey: ''
|
||||
# ssl: true
|
||||
# index: ''
|
||||
#elasticsearch:
|
||||
# host: localhost
|
||||
# port: 9200
|
||||
# ssl: false
|
||||
# user:
|
||||
# pass:
|
||||
|
||||
# âââââââââââââââââ
|
||||
#ââââ ID generation ââââââââââââââââââââââââââââââââââââââââââââ
|
||||
@@ -130,7 +81,6 @@ redis:
|
||||
|
||||
# Available methods:
|
||||
# aid ... Short, Millisecond accuracy
|
||||
# aidx ... Millisecond accuracy
|
||||
# meid ... Similar to ObjectID, Millisecond accuracy
|
||||
# ulid ... Millisecond accuracy
|
||||
# objectid ... This is left for backward compatibility
|
||||
@@ -138,27 +88,7 @@ redis:
|
||||
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
|
||||
# ID SETTINGS AFTER THAT!
|
||||
|
||||
id: 'aidx'
|
||||
|
||||
# ââââââââââââââââââ
|
||||
#ââââ Error tracking âââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# Sentry is available for error tracking.
|
||||
# See the Sentry documentation for more details on options.
|
||||
|
||||
#sentryForBackend:
|
||||
# enableNodeProfiling: true
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
#sentryForFrontend:
|
||||
# vueIntegration:
|
||||
# tracingOptions:
|
||||
# trackComponents: true
|
||||
# browserTracingIntegration:
|
||||
# replayIntegration:
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
id: 'aid'
|
||||
|
||||
# âââââââââââââââââââââââ
|
||||
#ââââ Other configuration ââââââââââââââââââââââââââââââââââââââ
|
||||
@@ -175,7 +105,7 @@ id: 'aidx'
|
||||
|
||||
# Job rate limiter
|
||||
# deliverJobPerSec: 128
|
||||
# inboxJobPerSec: 32
|
||||
# inboxJobPerSec: 16
|
||||
|
||||
# Job attempts
|
||||
# deliverJobMaxAttempts: 12
|
||||
@@ -202,6 +132,12 @@ proxyBypassHosts:
|
||||
# Media Proxy
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
# Proxy remote files (default: false)
|
||||
#proxyRemoteFiles: true
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
|
||||
allowedPrivateNetworks: [
|
||||
'127.0.0.1/32'
|
||||
]
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
app:
|
||||
build:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
|
||||
volumes:
|
||||
- ../:/workspace:cached
|
||||
- node_modules:/workspace/node_modules
|
||||
|
||||
command: sleep infinity
|
||||
|
||||
@@ -28,7 +29,7 @@ services:
|
||||
|
||||
db:
|
||||
restart: unless-stopped
|
||||
image: postgres:18-alpine
|
||||
image: postgres:15-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
environment:
|
||||
@@ -45,7 +46,6 @@ services:
|
||||
volumes:
|
||||
postgres-data:
|
||||
redis-data:
|
||||
node_modules:
|
||||
|
||||
networks:
|
||||
internal_network:
|
||||
@@ -2,14 +2,10 @@
|
||||
|
||||
set -xe
|
||||
|
||||
sudo chown node node_modules
|
||||
sudo apt-get update
|
||||
sudo apt-get -y install libgtk2.0-0 libgtk-3-0 libgbm-dev libnotify-dev libnss3 libxss1 libasound2 libxtst6 xauth xvfb
|
||||
git config --global --add safe.directory /workspace
|
||||
sudo chown -R node /workspace
|
||||
git submodule update --init
|
||||
pnpm config set store-dir /home/node/.local/share/pnpm/store
|
||||
pnpm install --frozen-lockfile
|
||||
cp .devcontainer/devcontainer.yml .config/default.yml
|
||||
pnpm build
|
||||
pnpm migrate
|
||||
pnpm exec cypress install
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
Dockerfile
|
||||
build/
|
||||
built/
|
||||
src-js/
|
||||
db/
|
||||
.devcontainer/compose.yml
|
||||
docker-compose.yml
|
||||
elasticsearch/
|
||||
node_modules/
|
||||
packages/*/node_modules
|
||||
redis/
|
||||
files/
|
||||
misskey-assets/
|
||||
fluent-emojis/
|
||||
.pnp.*
|
||||
|
||||
@@ -28,4 +29,4 @@ fluent-emojis/
|
||||
|
||||
.idea/
|
||||
packages/*/.vscode/
|
||||
packages/backend/test/compose.yml
|
||||
packages/backend/test/docker-compose.yml
|
||||
|
||||
@@ -6,14 +6,6 @@ indent_size = 2
|
||||
charset = utf-8
|
||||
insert_final_newline = true
|
||||
end_of_line = lf
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[*.{yml,yaml}]
|
||||
indent_style = space
|
||||
|
||||
[packages/backend/migration/*.js]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
3
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
patreon: syuilo
|
||||
43
.github/ISSUE_TEMPLATE/01_bug-report.md
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
---
|
||||
name: đ Bug Report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: â ī¸bug?
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!--
|
||||
Thanks for reporting!
|
||||
First, in order to avoid duplicate Issues, please search to see if the problem you found has already been reported.
|
||||
Also, If you are NOT owner/admin of server, PLEASE DONT REPORT SERVER SPECIFIC ISSUES TO HERE! (e.g. feature XXX is not working in misskey.example) Please try with another misskey servers, and if your issue is only reproducible with specific server, contact your server's owner/admin first.
|
||||
-->
|
||||
|
||||
## đĄ Summary
|
||||
|
||||
<!-- Tell us what the bug is -->
|
||||
|
||||
## đĨ° Expected Behavior
|
||||
|
||||
<!--- Tell us what should happen -->
|
||||
|
||||
## đ¤Ŧ Actual Behavior
|
||||
|
||||
<!--
|
||||
Tell us what happens instead of the expected behavior.
|
||||
Please include errors from the developer console and/or server log files if you have access to them.
|
||||
-->
|
||||
|
||||
## đ Steps to Reproduce
|
||||
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
|
||||
## đ Environment
|
||||
|
||||
<!-- Tell us where on the platform it happens -->
|
||||
|
||||
Misskey version:
|
||||
Your OS:
|
||||
Your browser:
|
||||
97
.github/ISSUE_TEMPLATE/01_bug-report.yml
vendored
@@ -1,97 +0,0 @@
|
||||
name: đ Bug Report
|
||||
description: Create a report to help us improve
|
||||
labels: ["â ī¸bug?"]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for reporting!
|
||||
First, in order to avoid duplicate Issues, please search to see if the problem you found has already been reported.
|
||||
Also, If you are NOT owner/admin of server, PLEASE DONT REPORT SERVER SPECIFIC ISSUES TO HERE! (e.g. feature XXX is not working in misskey.example) Please try with another misskey servers, and if your issue is only reproducible with specific server, contact your server's owner/admin first.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: đĄ Summary
|
||||
description: Tell us what the bug is
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: đĨ° Expected Behavior
|
||||
description: Tell us what should happen
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: đ¤Ŧ Actual Behavior
|
||||
description: |
|
||||
Tell us what happens instead of the expected behavior.
|
||||
Please include errors from the developer console and/or server log files if you have access to them.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: đ Steps to Reproduce
|
||||
placeholder: |
|
||||
1.
|
||||
2.
|
||||
3.
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: đģ Frontend Environment
|
||||
description: |
|
||||
Tell us where on the platform it happens
|
||||
DO NOT WRITE "latest". Please provide the specific version.
|
||||
|
||||
Examples:
|
||||
* Model and OS of the device(s): MacBook Pro (14inch, 2021), macOS Ventura 13.4
|
||||
* Browser: Chrome 113.0.5672.126
|
||||
* Server URL: misskey.example.com
|
||||
* Misskey: 2026.x.x
|
||||
value: |
|
||||
* Model and OS of the device(s):
|
||||
* Browser:
|
||||
* Server URL:
|
||||
* Misskey:
|
||||
render: markdown
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: đ° Backend Environment (for server admin)
|
||||
description: |
|
||||
Tell us where on the platform it happens
|
||||
DO NOT WRITE "latest". Please provide the specific version.
|
||||
If you are using a managed service, put that after the version.
|
||||
|
||||
Examples:
|
||||
* Installation Method or Hosting Service: docker compose, k8s/docker, systemd, "Misskey install shell script", development environment
|
||||
* Misskey: 2026.x.x
|
||||
* Node: 20.x.x
|
||||
* PostgreSQL: 18.x.x
|
||||
* Redis: 7.x.x
|
||||
* OS and Architecture: Ubuntu 24.04.2 LTS aarch64
|
||||
value: |
|
||||
* Installation Method or Hosting Service:
|
||||
* Misskey:
|
||||
* Node:
|
||||
* PostgreSQL:
|
||||
* Redis:
|
||||
* OS and Architecture:
|
||||
render: markdown
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Do you want to address this bug yourself?
|
||||
options:
|
||||
- label: Yes, I will patch the bug myself and send a pull request
|
||||
12
.github/ISSUE_TEMPLATE/02_feature-request.md
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
name: ⨠Feature Request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: â¨Feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
<!-- Tell us what the suggestion is -->
|
||||
22
.github/ISSUE_TEMPLATE/02_feature-request.yml
vendored
@@ -1,22 +0,0 @@
|
||||
name: ⨠Feature Request
|
||||
description: Suggest an idea for this project
|
||||
labels: ["â¨Feature"]
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Summary
|
||||
description: Tell us what the suggestion is
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Purpose
|
||||
description: Describe the specific problem or need you think this feature will solve, and who it will help.
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Do you want to implement this feature yourself?
|
||||
options:
|
||||
- label: Yes, I will implement this by myself and send a pull request
|
||||
7
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,8 +1,7 @@
|
||||
contact_links:
|
||||
- name: đĒ Misskey Forum
|
||||
url: https://forum.misskey.io/
|
||||
about: Ask questions and share knowledge
|
||||
- name: đŦ Misskey official Discord
|
||||
url: https://discord.gg/Wp8gVStHW3
|
||||
about: Chat freely about Misskey
|
||||
# äģŽ
|
||||
- name: đŦ Start discussion
|
||||
url: https://github.com/misskey-dev/misskey/discussions
|
||||
about: The official forum to join conversation and ask question
|
||||
|
||||
43
.github/dependabot.yml
vendored
@@ -10,36 +10,23 @@ updates:
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 0
|
||||
|
||||
# Add only the root, not each workspace item
|
||||
# https://github.com/dependabot/dependabot-core/issues/4993#issuecomment-1289133027
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 0
|
||||
# List dependencies required to be updated together, sharing the same version numbers.
|
||||
# Those who simply have the common owner (e.g. @fastify) don't need to be listed.
|
||||
groups:
|
||||
aws-sdk:
|
||||
patterns:
|
||||
- "@aws-sdk/*"
|
||||
nestjs:
|
||||
patterns:
|
||||
- "@nestjs/*"
|
||||
slacc:
|
||||
patterns:
|
||||
- "slacc-*"
|
||||
storybook:
|
||||
patterns:
|
||||
- "storybook*"
|
||||
- "@storybook/*"
|
||||
swc-core:
|
||||
patterns:
|
||||
- "@swc/core*"
|
||||
typescript-eslint:
|
||||
patterns:
|
||||
- "@typescript-eslint/*"
|
||||
tensorflow:
|
||||
patterns:
|
||||
- "@tensorflow/*"
|
||||
- package-ecosystem: npm
|
||||
directory: "/packages/backend"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 0
|
||||
- package-ecosystem: npm
|
||||
directory: "/packages/frontend"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 0
|
||||
- package-ecosystem: npm
|
||||
directory: "/packages/sw"
|
||||
schedule:
|
||||
interval: daily
|
||||
open-pull-requests-limit: 0
|
||||
|
||||
40
.github/labeler.yml
vendored
@@ -1,34 +1,12 @@
|
||||
'packages/backend':
|
||||
- any:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['packages/backend/**/*']
|
||||
'âī¸Server':
|
||||
- packages/backend/**/*
|
||||
|
||||
'packages/backend:test':
|
||||
- any:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['packages/backend/test/**/*', 'packages/backend/test-federation/**/*']
|
||||
'đĨī¸Client':
|
||||
- packages/frontend/**/*
|
||||
|
||||
'packages/frontend':
|
||||
- any:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['packages/frontend/**/*']
|
||||
'đ§ĒTest':
|
||||
- cypress/**/*
|
||||
- packages/backend/test/**/*
|
||||
|
||||
'packages/frontend:test':
|
||||
- any:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['cypress/**/*']
|
||||
|
||||
'packages/sw':
|
||||
- any:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['packages/sw/**/*']
|
||||
|
||||
'packages/misskey-js':
|
||||
- any:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['packages/misskey-js/**/*']
|
||||
|
||||
'packages/misskey-js:test':
|
||||
- any:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: ['packages/misskey-js/test/**/*', 'packages/misskey-js/test-d/**/*']
|
||||
'âŧī¸ wrong locales':
|
||||
- any: ['locales/*.yml', '!locales/ja-JP.yml']
|
||||
|
||||
1
.github/min.node-version
vendored
@@ -1 +0,0 @@
|
||||
22.15.0
|
||||
6
.github/misskey/test.yml
vendored
@@ -1,7 +1,5 @@
|
||||
url: 'http://misskey.local'
|
||||
|
||||
setupPassword: example_password_please_change_this_or_you_will_get_hacked
|
||||
|
||||
# ããŧãĢãĢã§ããšãããã¨ããĢããŧããčĸĢããĒããããĢãããããããŠãĢããŽããŽã¨ã¯å¤ãã(äģĨä¸åã)
|
||||
port: 61812
|
||||
|
||||
@@ -14,6 +12,4 @@ db:
|
||||
redis:
|
||||
host: 127.0.0.1
|
||||
port: 56312
|
||||
id: aidx
|
||||
|
||||
proxyRemoteFiles: true
|
||||
id: aid
|
||||
|
||||
1
.github/pull_request_template.md
vendored
@@ -19,6 +19,5 @@ https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md
|
||||
## Checklist
|
||||
- [ ] Read the [contribution guide](https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md)
|
||||
- [ ] Test working in a local environment
|
||||
- [ ] (If needed) Add story of storybook
|
||||
- [ ] (If needed) Update CHANGELOG.md
|
||||
- [ ] (If possible) Add tests
|
||||
|
||||
10
.github/reviewer-lottery.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
groups:
|
||||
- name: devs
|
||||
reviewers: 2
|
||||
internal_reviewers: 1
|
||||
usernames:
|
||||
- syuilo
|
||||
- acid-chicken
|
||||
- EbiseLutica
|
||||
- rinsuki
|
||||
- tamaina
|
||||
@@ -1,14 +1,7 @@
|
||||
name: API report (misskey.js)
|
||||
name: API report
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/api-misskey-js.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/api-misskey-js.yml
|
||||
jobs:
|
||||
report:
|
||||
|
||||
@@ -16,15 +9,14 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.1
|
||||
uses: actions/checkout@v3.3.0
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- run: corepack enable
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
uses: actions/setup-node@v3.6.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
node-version: 18.x
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
43
.github/workflows/changelog-check.yml
vendored
@@ -1,43 +0,0 @@
|
||||
name: Check the description in CHANGELOG.md
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
check-changelog:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout head
|
||||
uses: actions/checkout@v6.0.1
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
|
||||
- name: Checkout base
|
||||
run: |
|
||||
mkdir _base
|
||||
cp -r .git _base/.git
|
||||
cd _base
|
||||
git fetch --depth 1 origin ${{ github.base_ref }}
|
||||
git checkout origin/${{ github.base_ref }} CHANGELOG.md
|
||||
|
||||
- name: Copy to Checker directory for CHANGELOG-base.md
|
||||
run: cp _base/CHANGELOG.md scripts/changelog-checker/CHANGELOG-base.md
|
||||
- name: Copy to Checker directory for CHANGELOG-head.md
|
||||
run: cp CHANGELOG.md scripts/changelog-checker/CHANGELOG-head.md
|
||||
- name: diff
|
||||
continue-on-error: true
|
||||
run: diff -u CHANGELOG-base.md CHANGELOG-head.md
|
||||
working-directory: scripts/changelog-checker
|
||||
|
||||
- name: Setup Checker
|
||||
run: npm install
|
||||
working-directory: scripts/changelog-checker
|
||||
- name: Run Checker
|
||||
run: npm run run
|
||||
working-directory: scripts/changelog-checker
|
||||
139
.github/workflows/check-misskey-js-autogen.yml
vendored
@@ -1,139 +0,0 @@
|
||||
name: Check Misskey JS autogen
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- improve-misskey-js-autogen-check
|
||||
paths:
|
||||
- packages/backend/**
|
||||
|
||||
jobs:
|
||||
# pull_request_target safety: permissions: read-all, and there are no secrets used in this job
|
||||
generate-misskey-js:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
|
||||
- name: setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
|
||||
- name: setup node
|
||||
id: setup-node
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: pnpm
|
||||
|
||||
- name: install dependencies
|
||||
run: pnpm i --frozen-lockfile
|
||||
|
||||
# generate api.json
|
||||
- name: Copy Config
|
||||
run: cp .config/example.yml .config/default.yml
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Generate API JSON
|
||||
run: pnpm --filter backend generate-api-json
|
||||
|
||||
# build misskey js
|
||||
- name: Build misskey-js
|
||||
run: |-
|
||||
cp packages/backend/built/api.json packages/misskey-js/generator/api.json
|
||||
pnpm run --filter misskey-js-type-generator generate
|
||||
|
||||
# packages/misskey-js/generator/built/autogen
|
||||
- name: Upload Generated
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: generated-misskey-js
|
||||
path: packages/misskey-js/generator/built/autogen
|
||||
|
||||
# pull_request_target safety: permissions: read-all, and no user codes are executed
|
||||
get-actual-misskey-js:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
if: ${{ github.event.pull_request.mergeable == null || github.event.pull_request.mergeable == true }}
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
persist-credentials: false
|
||||
ref: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
|
||||
- name: Upload From Merged
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: actual-misskey-js
|
||||
path: packages/misskey-js/src/autogen
|
||||
|
||||
# pull_request_target safety: nothing is cloned from repository
|
||||
comment-misskey-js-autogen:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [generate-misskey-js, get-actual-misskey-js]
|
||||
permissions:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: download generated-misskey-js
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: generated-misskey-js
|
||||
path: misskey-js-generated
|
||||
|
||||
- name: download actual-misskey-js
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
name: actual-misskey-js
|
||||
path: misskey-js-actual
|
||||
|
||||
- name: check misskey-js changes
|
||||
id: check-changes
|
||||
run: |
|
||||
diff -r -u --label=generated --label=on-tree ./misskey-js-generated ./misskey-js-actual > misskey-js.diff || true
|
||||
|
||||
if [ -s misskey-js.diff ]; then
|
||||
echo "changes=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "changes=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Print full diff
|
||||
run: cat ./misskey-js.diff
|
||||
|
||||
- name: send message
|
||||
if: steps.check-changes.outputs.changes == 'true'
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
comment-tag: check-misskey-js-autogen
|
||||
message: |-
|
||||
Thank you for sending us a great Pull Request! đ
|
||||
Please regenerate misskey-js type definitions! đ
|
||||
|
||||
example:
|
||||
```sh
|
||||
pnpm run build-misskey-js-with-types
|
||||
```
|
||||
|
||||
- name: send message
|
||||
if: steps.check-changes.outputs.changes == 'false'
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
comment-tag: check-misskey-js-autogen
|
||||
mode: delete
|
||||
message: "Thank you!"
|
||||
create_if_not_exists: false
|
||||
|
||||
- name: Make failure if changes are detected
|
||||
if: steps.check-changes.outputs.changes == 'true'
|
||||
run: exit 1
|
||||
29
.github/workflows/check-misskey-js-version.yml
vendored
@@ -1,29 +0,0 @@
|
||||
name: Check Misskey JS version
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ develop ]
|
||||
paths:
|
||||
- packages/misskey-js/package.json
|
||||
- package.json
|
||||
- .github/workflows/check-misskey-js-version.yml
|
||||
pull_request:
|
||||
branches: [ develop ]
|
||||
paths:
|
||||
- packages/misskey-js/package.json
|
||||
- package.json
|
||||
- .github/workflows/check-misskey-js-version.yml
|
||||
jobs:
|
||||
check-version:
|
||||
# ãĢãŧã㎠package.json 㨠packages/misskey-js/package.json ãŽããŧã¸ã§ãŗãä¸č´ããĻããããįĸēčĒãã
|
||||
name: Check version
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.1
|
||||
- name: Check version
|
||||
run: |
|
||||
if [ "$(jq -r '.version' package.json)" != "$(jq -r '.version' packages/misskey-js/package.json)" ]; then
|
||||
echo "Version mismatch!"
|
||||
exit 1
|
||||
fi
|
||||
81
.github/workflows/check-spdx-license-id.yml
vendored
@@ -1,81 +0,0 @@
|
||||
name: Check SPDX-License-Identifier
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
check-spdx-license-id:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.1
|
||||
- name: Check
|
||||
run: |
|
||||
counter=0
|
||||
|
||||
search() {
|
||||
local directory="$1"
|
||||
find "$directory" -type f \
|
||||
'(' \
|
||||
-name "*.cjs" -and -not -name '*.config.cjs' -o \
|
||||
-name "*.html" -o \
|
||||
-name "*.js" -and -not -name '*.config.js' -o \
|
||||
-name "*.mjs" -and -not -name '*.config.mjs' -o \
|
||||
-name "*.scss" -o \
|
||||
-name "*.ts" -and -not -name '*.config.ts' -o \
|
||||
-name "*.vue" \
|
||||
')' -and \
|
||||
-not -name '*eslint*'
|
||||
}
|
||||
|
||||
check() {
|
||||
local file="$1"
|
||||
if ! (
|
||||
grep -q "SPDX-FileCopyrightText: syuilo and misskey-project" "$file" ||
|
||||
grep -q "SPDX-License-Identifier: AGPL-3.0-only" "$file"
|
||||
); then
|
||||
echo "Missing: $file"
|
||||
((counter++))
|
||||
fi
|
||||
}
|
||||
|
||||
directories=(
|
||||
"cypress/e2e"
|
||||
"packages/backend/migration"
|
||||
"packages/backend/src"
|
||||
"packages/backend/test"
|
||||
"packages/frontend-shared/@types"
|
||||
"packages/frontend-shared/js"
|
||||
"packages/frontend-builder"
|
||||
"packages/frontend/.storybook"
|
||||
"packages/frontend/@types"
|
||||
"packages/frontend/lib"
|
||||
"packages/frontend/public"
|
||||
"packages/frontend/src"
|
||||
"packages/frontend/test"
|
||||
"packages/frontend-embed/@types"
|
||||
"packages/frontend-embed/src"
|
||||
"packages/icons-subsetter/src"
|
||||
"packages/misskey-bubble-game/src"
|
||||
"packages/misskey-reversi/src"
|
||||
"packages/sw/src"
|
||||
"scripts"
|
||||
)
|
||||
|
||||
for directory in "${directories[@]}"; do
|
||||
for file in $(search $directory); do
|
||||
check "$file"
|
||||
done
|
||||
done
|
||||
|
||||
if [ $counter -gt 0 ]; then
|
||||
echo "SPDX-License-Identifier is missing in $counter files."
|
||||
exit 1
|
||||
else
|
||||
echo "SPDX-License-Identifier is certainly described in all target files!"
|
||||
exit 0
|
||||
fi
|
||||
2
.github/workflows/check_copyright_year.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
||||
check_copyright_year:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
- uses: actions/checkout@v3.2.0
|
||||
- run: |
|
||||
if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then
|
||||
echo "Please change copyright year!"
|
||||
|
||||
84
.github/workflows/deploy-test-environment.yml
vendored
@@ -1,84 +0,0 @@
|
||||
name: deploy-test-environment
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
repository:
|
||||
description: 'Repository to deploy (optional, use the repository where this workflow is stored by default)'
|
||||
required: false
|
||||
default: ''
|
||||
branch_or_hash:
|
||||
description: 'Branch or Commit hash to deploy (optional, use the branch where this workflow is stored by default)'
|
||||
required: false
|
||||
default: ''
|
||||
wait_time:
|
||||
description: 'Time to wait in seconds (optional, 1800 seconds by default)'
|
||||
required: false
|
||||
default: ''
|
||||
|
||||
jobs:
|
||||
get-pr-ref:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'issue_comment' && github.event.issue.pull_request && startsWith(github.event.comment.body, '/preview')
|
||||
outputs:
|
||||
is-allowed-user: ${{ steps.check-allowed-users.outputs.is-allowed-user }}
|
||||
pr-ref: ${{ steps.get-ref.outputs.pr-ref }}
|
||||
wait_time: ${{ steps.get-wait-time.outputs.wait_time }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.1
|
||||
|
||||
- name: Check allowed users
|
||||
id: check-allowed-users
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ORG_ID: ${{ github.repository_owner_id }}
|
||||
COMMENT_AUTHOR: ${{ github.event.comment.user.login }}
|
||||
run: |
|
||||
MEMBERSHIP_STATUS=$(curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"https://api.github.com/organizations/$ORG_ID/public_members/$COMMENT_AUTHOR" \
|
||||
-o /dev/null -w '%{http_code}\n' -s)
|
||||
if [ "$MEMBERSHIP_STATUS" -eq 204 ]; then
|
||||
echo "is-allowed-user=true" > $GITHUB_OUTPUT
|
||||
else
|
||||
echo "is-allowed-user=false" > $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Get PR ref
|
||||
id: get-ref
|
||||
run: |
|
||||
PR_REF="refs/pull/${{ github.event.issue.number }}/head"
|
||||
echo "pr-ref=$PR_REF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Extract wait time
|
||||
id: get-wait-time
|
||||
env:
|
||||
COMMENT_BODY: ${{ github.event.comment.body }}
|
||||
run: |
|
||||
WAIT_TIME=$(echo "$COMMENT_BODY" | grep -oP '(?<=/preview\s)\d+' || echo "1800")
|
||||
echo "wait_time=$WAIT_TIME" > $GITHUB_OUTPUT
|
||||
|
||||
deploy-test-environment-pr-comment:
|
||||
needs: get-pr-ref
|
||||
if: needs.get-pr-ref.outputs.is-allowed-user == 'true'
|
||||
uses: joinmisskey/misskey-tga/.github/workflows/deploy-test-environment.yml@main
|
||||
with:
|
||||
repository: ${{ github.repository }}
|
||||
branch_or_hash: ${{ needs.get-pr-ref.outputs.pr-ref }}
|
||||
wait_time: ${{ needs.get-pr-ref.outputs.wait_time }}
|
||||
secrets:
|
||||
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
|
||||
deploy-test-environment-wd:
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
uses: joinmisskey/misskey-tga/.github/workflows/deploy-test-environment.yml@main
|
||||
with:
|
||||
repository: ${{ inputs.repository || github.repository }}
|
||||
branch_or_hash: ${{ inputs.branch_or_hash || github.ref_name }}
|
||||
wait_time: ${{ inputs.wait_time || '1800' }}
|
||||
secrets:
|
||||
DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }}
|
||||
81
.github/workflows/docker-develop.yml
vendored
@@ -6,83 +6,38 @@ on:
|
||||
- develop
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
REGISTRY_IMAGE: misskey/misskey
|
||||
|
||||
jobs:
|
||||
# see https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
|
||||
build:
|
||||
name: Build
|
||||
push_to_registry:
|
||||
name: Push Docker image to Docker Hub
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform:
|
||||
- linux/amd64
|
||||
- linux/arm64
|
||||
if: github.repository == 'misskey-dev/misskey'
|
||||
steps:
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v6.0.1
|
||||
uses: actions/checkout@v3.3.0
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2.3.0
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: misskey/misskey
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build and push by digest
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
- name: Build and Push to Docker Hub
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.platform }}
|
||||
platforms: ${{ steps.buildx.outputs.platforms }}
|
||||
provenance: false
|
||||
tags: misskey/misskey:develop
|
||||
labels: develop
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
merge:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create --tag ${{ env.REGISTRY_IMAGE }}:develop \
|
||||
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:develop
|
||||
|
||||
100
.github/workflows/docker.yml
vendored
@@ -5,101 +5,45 @@ on:
|
||||
types: [published]
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
REGISTRY_IMAGE: misskey/misskey
|
||||
TAGS: |
|
||||
type=edge
|
||||
type=ref,event=pr
|
||||
type=ref,event=branch
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
|
||||
jobs:
|
||||
# see https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
|
||||
build:
|
||||
name: Build
|
||||
push_to_registry:
|
||||
name: Push Docker image to Docker Hub
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform:
|
||||
- linux/amd64
|
||||
- linux/arm64
|
||||
|
||||
steps:
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
- name: Check out the repo
|
||||
uses: actions/checkout@v6.0.1
|
||||
uses: actions/checkout@v3.3.0
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2.3.0
|
||||
with:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
uses: docker/metadata-action@v4
|
||||
with:
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
tags: ${{ env.TAGS }}
|
||||
images: misskey/misskey
|
||||
tags: |
|
||||
type=edge
|
||||
type=ref,event=pr
|
||||
type=ref,event=branch
|
||||
type=semver,pattern={{version}}
|
||||
type=semver,pattern={{major}}.{{minor}}
|
||||
type=semver,pattern={{major}}
|
||||
- name: Log in to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Build and Push to Docker Hub
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@v4
|
||||
with:
|
||||
builder: ${{ steps.buildx.outputs.name }}
|
||||
context: .
|
||||
push: true
|
||||
platforms: ${{ matrix.platform }}
|
||||
platforms: ${{ steps.buildx.outputs.platforms }}
|
||||
provenance: false
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
merge:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build
|
||||
steps:
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v7
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
tags: ${{ env.TAGS }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
|
||||
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.version }}
|
||||
|
||||
49
.github/workflows/dockle.yml
vendored
@@ -11,43 +11,20 @@ on:
|
||||
jobs:
|
||||
dockle:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
DOCKER_CONTENT_TRUST: 1
|
||||
DOCKLE_VERSION: 0.4.15
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
|
||||
- name: Download and install dockle v${{ env.DOCKLE_VERSION }}
|
||||
run: |
|
||||
set -eux
|
||||
curl -L -o dockle.deb "https://github.com/goodwithtech/dockle/releases/download/v${DOCKLE_VERSION}/dockle_${DOCKLE_VERSION}_Linux-64bit.deb"
|
||||
- uses: actions/checkout@v3.2.0
|
||||
- run: |
|
||||
curl -L -o dockle.deb "https://github.com/goodwithtech/dockle/releases/download/v0.4.10/dockle_0.4.10_Linux-64bit.deb"
|
||||
sudo dpkg -i dockle.deb
|
||||
|
||||
- name: Build web image (docker build)
|
||||
run: |
|
||||
set -eux
|
||||
docker build -t "misskey-web:ci" .
|
||||
docker image ls
|
||||
|
||||
- name: Mount tmpfs for Dockle tar
|
||||
env:
|
||||
TMPFS_SIZE: 8G
|
||||
run: |
|
||||
set -eux
|
||||
sudo mkdir -p /mnt/dockle-tmp
|
||||
sudo mount -t tmpfs -o size=${{ env.TMPFS_SIZE }} tmpfs /mnt/dockle-tmp
|
||||
free -h
|
||||
df -h
|
||||
|
||||
- name: Save image tar into tmpfs
|
||||
run: |
|
||||
set -eux
|
||||
docker save misskey-web:ci -o /mnt/dockle-tmp/misskey-web.tar
|
||||
ls -lh /mnt/dockle-tmp/misskey-web.tar
|
||||
|
||||
- name: Run Dockle Scan (tar input)
|
||||
run: |
|
||||
set -eux
|
||||
dockle --exit-code 1 --input /mnt/dockle-tmp/misskey-web.tar
|
||||
- run: |
|
||||
cp .config/docker_example.env .config/docker.env
|
||||
cp ./docker-compose.yml.example ./docker-compose.yml
|
||||
- run: |
|
||||
docker compose up -d web
|
||||
docker tag "$(docker compose images web | awk 'OFS=":" {print $4}' | tail -n +2)" misskey-web:latest
|
||||
- run: |
|
||||
cmd="dockle --exit-code 1 misskey-web:latest ${image_name}"
|
||||
echo "> ${cmd}"
|
||||
eval "${cmd}"
|
||||
|
||||
67
.github/workflows/get-api-diff.yml
vendored
@@ -1,67 +0,0 @@
|
||||
# this name is used in report-api-diff.yml so be careful when change name
|
||||
name: Get api.json from Misskey
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
paths:
|
||||
- packages/backend/**
|
||||
- .github/workflows/get-api-diff.yml
|
||||
jobs:
|
||||
get-from-misskey:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
api-json-name: [api-base.json, api-head.json]
|
||||
include:
|
||||
- api-json-name: api-base.json
|
||||
ref: ${{ github.base_ref }}
|
||||
- api-json-name: api-head.json
|
||||
ref: refs/pull/${{ github.event.number }}/merge
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
ref: ${{ matrix.ref }}
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Copy Configure
|
||||
run: cp .config/example.yml .config/default.yml
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Generate API JSON
|
||||
run: pnpm --filter backend generate-api-json
|
||||
- name: Copy API.json
|
||||
run: cp packages/backend/built/api.json ${{ matrix.api-json-name }}
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: api-artifact-${{ matrix.api-json-name }}
|
||||
path: ${{ matrix.api-json-name }}
|
||||
|
||||
save-pr-number:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Save PR number
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.number }}
|
||||
run: |
|
||||
echo "$PR_NUMBER" > ./pr_number
|
||||
- uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: api-artifact-pr-number
|
||||
path: pr_number
|
||||
87
.github/workflows/get-backend-memory.yml
vendored
@@ -1,87 +0,0 @@
|
||||
# this name is used in report-backend-memory.yml so be careful when change name
|
||||
name: Get backend memory usage
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
paths:
|
||||
- packages/backend/**
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/get-backend-memory.yml
|
||||
|
||||
jobs:
|
||||
get-memory-usage:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
memory-json-name: [memory-base.json, memory-head.json]
|
||||
include:
|
||||
- memory-json-name: memory-base.json
|
||||
ref: ${{ github.base_ref }}
|
||||
- memory-json-name: memory-head.json
|
||||
ref: refs/pull/${{ github.event.number }}/merge
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:7
|
||||
ports:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
ref: ${{ matrix.ref }}
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Copy Configure
|
||||
run: cp .github/misskey/test.yml .config/default.yml
|
||||
- name: Compile Configure
|
||||
run: pnpm compile-config
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Run migrations
|
||||
run: pnpm --filter backend migrate
|
||||
- name: Measure memory usage
|
||||
run: |
|
||||
# Start the server and measure memory usage
|
||||
node packages/backend/scripts/measure-memory.mjs > ${{ matrix.memory-json-name }}
|
||||
- name: Upload Artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: memory-artifact-${{ matrix.memory-json-name }}
|
||||
path: ${{ matrix.memory-json-name }}
|
||||
|
||||
save-pr-number:
|
||||
runs-on: ubuntu-latest
|
||||
permissions: {}
|
||||
steps:
|
||||
- name: Save PR number
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.number }}
|
||||
run: |
|
||||
echo "$PR_NUMBER" > ./pr_number
|
||||
- uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: memory-artifact-pr-number
|
||||
path: pr_number
|
||||
2
.github/workflows/labeler.yml
vendored
@@ -11,6 +11,6 @@ jobs:
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/labeler@v6
|
||||
- uses: actions/labeler@v4
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
|
||||
86
.github/workflows/lint.yml
vendored
@@ -5,47 +5,25 @@ on:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
paths:
|
||||
- packages/backend/**
|
||||
- packages/frontend/**
|
||||
- packages/frontend-shared/**
|
||||
- packages/frontend-builder/**
|
||||
- packages/frontend-embed/**
|
||||
- packages/icons-subsetter/**
|
||||
- packages/sw/**
|
||||
- packages/misskey-js/**
|
||||
- packages/misskey-bubble-game/**
|
||||
- packages/misskey-reversi/**
|
||||
- packages/shared/eslint.config.js
|
||||
- .github/workflows/lint.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/backend/**
|
||||
- packages/frontend/**
|
||||
- packages/frontend-shared/**
|
||||
- packages/frontend-builder/**
|
||||
- packages/frontend-embed/**
|
||||
- packages/icons-subsetter/**
|
||||
- packages/sw/**
|
||||
- packages/misskey-js/**
|
||||
- packages/misskey-bubble-game/**
|
||||
- packages/misskey-reversi/**
|
||||
- packages/shared/eslint.config.js
|
||||
- .github/workflows/lint.yml
|
||||
|
||||
jobs:
|
||||
pnpm_install:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
- uses: actions/checkout@v3.3.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.1.0
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
version: 7
|
||||
run_install: false
|
||||
- uses: actions/setup-node@v3.6.0
|
||||
with:
|
||||
node-version: 18.x
|
||||
cache: 'pnpm'
|
||||
- run: corepack enable
|
||||
- run: pnpm i --frozen-lockfile
|
||||
|
||||
lint:
|
||||
@@ -57,36 +35,24 @@ jobs:
|
||||
workspace:
|
||||
- backend
|
||||
- frontend
|
||||
- frontend-shared
|
||||
- frontend-builder
|
||||
- frontend-embed
|
||||
- icons-subsetter
|
||||
- sw
|
||||
- misskey-js
|
||||
- misskey-bubble-game
|
||||
- misskey-reversi
|
||||
env:
|
||||
eslint-cache-version: v1
|
||||
eslint-cache-path: ${{ github.workspace }}/node_modules/.cache/eslint-${{ matrix.workspace }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
- uses: actions/checkout@v3.3.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.1.0
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
version: 7
|
||||
run_install: false
|
||||
- uses: actions/setup-node@v3.6.0
|
||||
with:
|
||||
node-version: 18.x
|
||||
cache: 'pnpm'
|
||||
- run: corepack enable
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Restore eslint cache
|
||||
uses: actions/cache@v4.3.0
|
||||
with:
|
||||
path: ${{ env.eslint-cache-path }}
|
||||
key: eslint-${{ env.eslint-cache-version }}-${{ matrix.workspace }}-${{ hashFiles('**/pnpm-lock.yaml') }}-${{ github.ref_name }}-${{ github.sha }}
|
||||
restore-keys: eslint-${{ env.eslint-cache-version }}-${{ matrix.workspace }}-${{ hashFiles('**/pnpm-lock.yaml') }}-
|
||||
- run: pnpm --filter ${{ matrix.workspace }} run eslint --cache --cache-location ${{ env.eslint-cache-path }} --cache-strategy content
|
||||
- run: pnpm --filter ${{ matrix.workspace }} run eslint
|
||||
|
||||
typecheck:
|
||||
needs: [pnpm_install]
|
||||
@@ -96,20 +62,20 @@ jobs:
|
||||
matrix:
|
||||
workspace:
|
||||
- backend
|
||||
- frontend
|
||||
- sw
|
||||
- misskey-js
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
- uses: actions/checkout@v3.3.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.1.0
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
version: 7
|
||||
run_install: false
|
||||
- uses: actions/setup-node@v3.6.0
|
||||
with:
|
||||
node-version: 18.x
|
||||
cache: 'pnpm'
|
||||
- run: corepack enable
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- run: pnpm --filter "${{ matrix.workspace }}^..." run build
|
||||
- run: pnpm --filter ${{ matrix.workspace }} run typecheck
|
||||
|
||||
33
.github/workflows/locale.yml
vendored
@@ -1,33 +0,0 @@
|
||||
name: Lint
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- packages/i18n/**
|
||||
- locales/**
|
||||
- .github/workflows/locale.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/i18n/**
|
||||
- locales/**
|
||||
- .github/workflows/locale.yml
|
||||
jobs:
|
||||
locale_verify:
|
||||
runs-on: ubuntu-latest
|
||||
continue-on-error: true
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: ".node-version"
|
||||
cache: "pnpm"
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- run: pnpm --filter i18n build
|
||||
- name: Verify Locales
|
||||
working-directory: ./packages/i18n
|
||||
run: pnpm run verify
|
||||
36
.github/workflows/ok-to-test.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
# If someone with write access comments "/ok-to-test" on a pull request, emit a repository_dispatch event
|
||||
name: Ok To Test
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
ok-to-test:
|
||||
runs-on: ubuntu-latest
|
||||
# Only run for PRs, not issue comments
|
||||
if: ${{ github.event.issue.pull_request }}
|
||||
steps:
|
||||
# Generate a GitHub App installation access token from an App ID and private key
|
||||
# To create a new GitHub App:
|
||||
# https://developer.github.com/apps/building-github-apps/creating-a-github-app/
|
||||
# See app.yml for an example app manifest
|
||||
- name: Generate token
|
||||
id: generate_token
|
||||
uses: tibdex/github-app-token@v1
|
||||
with:
|
||||
app_id: ${{ secrets.DEPLOYBOT_APP_ID }}
|
||||
private_key: ${{ secrets.DEPLOYBOT_PRIVATE_KEY }}
|
||||
|
||||
- name: Slash Command Dispatch
|
||||
uses: peter-evans/slash-command-dispatch@v1
|
||||
env:
|
||||
TOKEN: ${{ steps.generate_token.outputs.token }}
|
||||
with:
|
||||
token: ${{ env.TOKEN }} # GitHub App installation access token
|
||||
# token: ${{ secrets.PERSONAL_ACCESS_TOKEN }} # PAT or OAuth token will also work
|
||||
reaction-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-type: pull-request
|
||||
commands: deploy
|
||||
named-args: true
|
||||
permission: write
|
||||
38
.github/workflows/on-release-created.yml
vendored
@@ -1,38 +0,0 @@
|
||||
name: On Release Created (Publish misskey-js)
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
publish-misskey-js:
|
||||
name: Publish misskey-js
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
# see https://docs.github.com/actions/use-cases-and-examples/publishing-packages/publishing-nodejs-packages#publishing-packages-to-the-npm-registry
|
||||
registry-url: 'https://registry.npmjs.org'
|
||||
- name: Publish package
|
||||
run: |
|
||||
pnpm i --frozen-lockfile
|
||||
pnpm build
|
||||
pnpm --filter misskey-js publish --access public --no-git-checks --provenance
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NODE_AUTH_TOKEN }}
|
||||
92
.github/workflows/pr-preview-deploy.yml
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
# Run secret-dependent integration tests only after /deploy approval
|
||||
on:
|
||||
repository_dispatch:
|
||||
types: [deploy-command]
|
||||
|
||||
name: Deploy preview environment
|
||||
|
||||
jobs:
|
||||
# Repo owner has commented /deploy on a (fork-based) pull request
|
||||
deploy-preview-environment:
|
||||
runs-on: ubuntu-latest
|
||||
if:
|
||||
github.event.client_payload.slash_command.sha != '' &&
|
||||
contains(github.event.client_payload.pull_request.head.sha, github.event.client_payload.slash_command.sha)
|
||||
steps:
|
||||
- uses: actions/github-script@v6.3.3
|
||||
id: check-id
|
||||
env:
|
||||
number: ${{ github.event.client_payload.pull_request.number }}
|
||||
job: ${{ github.job }}
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
result-encoding: string
|
||||
script: |
|
||||
const { data: pull } = await github.rest.pulls.get({
|
||||
...context.repo,
|
||||
pull_number: process.env.number
|
||||
});
|
||||
const ref = pull.head.sha;
|
||||
|
||||
const { data: checks } = await github.rest.checks.listForRef({
|
||||
...context.repo,
|
||||
ref
|
||||
});
|
||||
|
||||
const check = checks.check_runs.filter(c => c.name === process.env.job);
|
||||
|
||||
return check[0].id;
|
||||
|
||||
- uses: actions/github-script@v6.3.3
|
||||
env:
|
||||
check_id: ${{ steps.check-id.outputs.result }}
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/runs/${{ github.run_id }}
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
await github.rest.checks.update({
|
||||
...context.repo,
|
||||
check_run_id: process.env.check_id,
|
||||
status: 'in_progress',
|
||||
details_url: process.env.details_url
|
||||
});
|
||||
|
||||
# Check out merge commit
|
||||
- name: Fork based /deploy checkout
|
||||
uses: actions/checkout@v3.3.0
|
||||
with:
|
||||
ref: 'refs/pull/${{ github.event.client_payload.pull_request.number }}/merge'
|
||||
|
||||
# <insert integration tests needing secrets>
|
||||
- name: Context
|
||||
uses: okteto/context@latest
|
||||
with:
|
||||
token: ${{ secrets.OKTETO_TOKEN }}
|
||||
|
||||
- name: Deploy preview environment
|
||||
uses: ikuradon/deploy-preview@latest
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
name: pr-${{ github.event.client_payload.pull_request.number }}-syuilo
|
||||
timeout: 15m
|
||||
|
||||
# Update check run called "integration-fork"
|
||||
- uses: actions/github-script@v6.3.3
|
||||
id: update-check-run
|
||||
if: ${{ always() }}
|
||||
env:
|
||||
# Conveniently, job.status maps to https://developer.github.com/v3/checks/runs/#update-a-check-run
|
||||
conclusion: ${{ job.status }}
|
||||
check_id: ${{ steps.check-id.outputs.result }}
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const { data: result } = await github.rest.checks.update({
|
||||
...context.repo,
|
||||
check_run_id: process.env.check_id,
|
||||
status: 'completed',
|
||||
conclusion: process.env.conclusion
|
||||
});
|
||||
|
||||
return result;
|
||||
54
.github/workflows/pr-preview-destroy.yml
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
# file: .github/workflows/preview-closed.yaml
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
|
||||
name: Destroy preview environment
|
||||
|
||||
jobs:
|
||||
destroy-preview-environment:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/github-script@v6.3.3
|
||||
id: check-conclusion
|
||||
env:
|
||||
number: ${{ github.event.number }}
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
result-encoding: string
|
||||
script: |
|
||||
const { data: pull } = await github.rest.pulls.get({
|
||||
...context.repo,
|
||||
pull_number: process.env.number
|
||||
});
|
||||
const ref = pull.head.sha;
|
||||
|
||||
const { data: checks } = await github.rest.checks.listForRef({
|
||||
...context.repo,
|
||||
ref
|
||||
});
|
||||
|
||||
const check = checks.check_runs.filter(c => c.name === 'deploy-preview-environment');
|
||||
|
||||
if (check.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { data: result } = await github.rest.checks.get({
|
||||
...context.repo,
|
||||
check_run_id: check[0].id,
|
||||
});
|
||||
|
||||
return result.conclusion;
|
||||
- name: Context
|
||||
if: steps.check-conclusion.outputs.result == 'success'
|
||||
uses: okteto/context@latest
|
||||
with:
|
||||
token: ${{ secrets.OKTETO_TOKEN }}
|
||||
|
||||
- name: Destroy preview environment
|
||||
if: steps.check-conclusion.outputs.result == 'success'
|
||||
uses: okteto/destroy-preview@latest
|
||||
with:
|
||||
name: pr-${{ github.event.number }}-syuilo
|
||||
48
.github/workflows/release-edit-with-push.yml
vendored
@@ -1,48 +0,0 @@
|
||||
name: "Release Manager: sync changelog with PR"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
paths:
|
||||
- 'CHANGELOG.md'
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
edit:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
# headã$GITHUB_REF_NAME, baseã$STABLE_BRANCHãã¤openãŽPRã1ã¤ååž
|
||||
- name: Get PR
|
||||
run: |
|
||||
echo "pr_number=$(gh pr list --limit 1 --search "head:$GITHUB_REF_NAME base:$STABLE_BRANCH is:open" --json number --jq '.[] | .number')" >> $GITHUB_OUTPUT
|
||||
id: get_pr
|
||||
env:
|
||||
STABLE_BRANCH: ${{ vars.STABLE_BRANCH }}
|
||||
- name: Get target version
|
||||
if: steps.get_pr.outputs.pr_number != ''
|
||||
uses: misskey-dev/release-manager-actions/.github/actions/get-target-version@v2
|
||||
id: v
|
||||
# CHANGELOG.mdãŽå
厚ãååž
|
||||
- name: Get changelog
|
||||
if: steps.get_pr.outputs.pr_number != ''
|
||||
uses: misskey-dev/release-manager-actions/.github/actions/get-changelog@v2
|
||||
with:
|
||||
version: ${{ steps.v.outputs.target_version }}
|
||||
id: changelog
|
||||
# PRãŽnotesãæ´æ°
|
||||
- name: Update PR
|
||||
if: steps.get_pr.outputs.pr_number != ''
|
||||
run: |
|
||||
gh pr edit "$PR_NUMBER" --body "$CHANGELOG"
|
||||
env:
|
||||
PR_NUMBER: ${{ steps.get_pr.outputs.pr_number }}
|
||||
CHANGELOG: ${{ steps.changelog.outputs.changelog }}
|
||||
136
.github/workflows/release-with-dispatch.yml
vendored
@@ -1,136 +0,0 @@
|
||||
name: "Release Manager [Dispatch]"
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
## Specify the type of the next release.
|
||||
#version_increment_type:
|
||||
# type: choice
|
||||
# description: 'VERSION INCREMENT TYPE'
|
||||
# default: 'patch'
|
||||
# required: false
|
||||
# options:
|
||||
# - 'major'
|
||||
# - 'minor'
|
||||
# - 'patch'
|
||||
merge:
|
||||
type: boolean
|
||||
description: 'MERGE RELEASE BRANCH TO MAIN'
|
||||
default: false
|
||||
start-rc:
|
||||
type: boolean
|
||||
description: 'Start Release Candidate'
|
||||
default: false
|
||||
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
get-pr:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
pr_number: ${{ steps.get_pr.outputs.pr_number }}
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
# headã$GITHUB_REF_NAME, baseã$STABLE_BRANCHãã¤openãŽPRã1ã¤ååž
|
||||
- name: Get PRs
|
||||
run: |
|
||||
echo "pr_number=$(gh pr list --limit 1 --search "head:$GITHUB_REF_NAME base:$STABLE_BRANCH is:open" --json number --jq '.[] | .number')" >> $GITHUB_OUTPUT
|
||||
id: get_pr
|
||||
env:
|
||||
STABLE_BRANCH: ${{ vars.STABLE_BRANCH }}
|
||||
|
||||
merge:
|
||||
uses: misskey-dev/release-manager-actions/.github/workflows/merge.yml@v2
|
||||
needs: get-pr
|
||||
if: ${{ needs.get-pr.outputs.pr_number != '' && inputs.merge == true }}
|
||||
with:
|
||||
pr_number: ${{ needs.get-pr.outputs.pr_number }}
|
||||
user: 'github-actions[bot]'
|
||||
package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }}
|
||||
# Text to prepend to the changelog
|
||||
# The first line must be `## Unreleased`
|
||||
changes_template: |
|
||||
## Unreleased
|
||||
|
||||
### General
|
||||
-
|
||||
|
||||
### Client
|
||||
-
|
||||
|
||||
### Server
|
||||
-
|
||||
|
||||
use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
|
||||
indent: ${{ vars.INDENT }}
|
||||
secrets:
|
||||
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
|
||||
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
|
||||
|
||||
create-prerelease:
|
||||
uses: misskey-dev/release-manager-actions/.github/workflows/create-prerelease.yml@v2
|
||||
needs: get-pr
|
||||
if: ${{ needs.get-pr.outputs.pr_number != '' && inputs.merge != true }}
|
||||
with:
|
||||
pr_number: ${{ needs.get-pr.outputs.pr_number }}
|
||||
user: 'github-actions[bot]'
|
||||
package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }}
|
||||
use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
|
||||
indent: ${{ vars.INDENT }}
|
||||
draft_prerelease_channel: alpha
|
||||
ready_start_prerelease_channel: beta
|
||||
prerelease_channel: ${{ inputs.start-rc && 'rc' || '' }}
|
||||
reset_number_on_channel_change: true
|
||||
secrets:
|
||||
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
|
||||
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
|
||||
|
||||
create-target:
|
||||
uses: misskey-dev/release-manager-actions/.github/workflows/create-target.yml@v2
|
||||
needs: get-pr
|
||||
if: ${{ needs.get-pr.outputs.pr_number == '' }}
|
||||
with:
|
||||
user: 'github-actions[bot]'
|
||||
# The script for version increment.
|
||||
# process.env.CURRENT_VERSION: The current version.
|
||||
#
|
||||
# Misskey calender versioning (yyyy.MM.patch) example
|
||||
version_increment_script: |
|
||||
const now = new Date();
|
||||
const year = now.toLocaleDateString('en-US', { year: 'numeric', timeZone: 'Asia/Tokyo' });
|
||||
const month = now.toLocaleDateString('en-US', { month: 'numeric', timeZone: 'Asia/Tokyo' });
|
||||
const [major, minor, _patch] = process.env.CURRENT_VERSION.split('.');
|
||||
const patch = Number(_patch.split('-')[0]);
|
||||
if (Number.isNaN(patch)) {
|
||||
console.error('Invalid patch version', year, month, process.env.CURRENT_VERSION, major, minor, _patch);
|
||||
throw new Error('Invalid patch version');
|
||||
}
|
||||
if (year !== major || month !== minor) {
|
||||
return `${year}.${month}.0`;
|
||||
} else {
|
||||
return `${major}.${minor}.${patch + 1}`;
|
||||
}
|
||||
##Semver example
|
||||
#version_increment_script: |
|
||||
# const [major, minor, patch] = process.env.CURRENT_VERSION.split('.');
|
||||
# if ("${{ inputs.version_increment_type }}" === "major") {
|
||||
# return `${Number(major) + 1}.0.0`;
|
||||
# } else if ("${{ inputs.version_increment_type }}" === "minor") {
|
||||
# return `${major}.${Number(minor) + 1}.0`;
|
||||
# } else {
|
||||
# return `${major}.${minor}.${Number(patch) + 1}`;
|
||||
# }
|
||||
package_jsons_to_rewrite: ${{ vars.PACKAGE_JSONS_TO_REWRITE }}
|
||||
use_external_app_to_release: ${{ vars.USE_RELEASE_APP == 'true' }}
|
||||
indent: ${{ vars.INDENT }}
|
||||
stable_branch: ${{ vars.STABLE_BRANCH }}
|
||||
draft_prerelease_channel: alpha
|
||||
secrets:
|
||||
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
|
||||
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}
|
||||
104
.github/workflows/report-api-diff.yml
vendored
@@ -1,104 +0,0 @@
|
||||
name: Report API Diff
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
types: [completed]
|
||||
workflows:
|
||||
- Get api.json from Misskey # get-api-diff.yml
|
||||
|
||||
jobs:
|
||||
compare-diff:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
# api-artifact
|
||||
steps:
|
||||
- name: Download artifact
|
||||
uses: actions/github-script@v8.0.0
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: context.payload.workflow_run.id,
|
||||
});
|
||||
let matchArtifacts = allArtifacts.data.artifacts.filter((artifact) => {
|
||||
return artifact.name.startsWith("api-artifact-") || artifact.name == "api-artifact"
|
||||
});
|
||||
await Promise.all(matchArtifacts.map(async (artifact) => {
|
||||
let download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: artifact.id,
|
||||
archive_format: 'zip',
|
||||
});
|
||||
await fs.promises.writeFile(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data));
|
||||
}));
|
||||
- name: Extract all artifacts
|
||||
run: |
|
||||
find . -mindepth 1 -maxdepth 1 -type f -name '*.zip' -exec unzip {} -d artifacts ';'
|
||||
ls -la
|
||||
- name: Load PR Number
|
||||
id: load-pr-num
|
||||
run: echo "pr-number=$(cat artifacts/pr_number)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Output base
|
||||
run: cat ./artifacts/api-base.json
|
||||
- name: Output head
|
||||
run: cat ./artifacts/api-head.json
|
||||
- name: Arrange json files
|
||||
run: |
|
||||
jq '.' ./artifacts/api-base.json > ./api-base.json
|
||||
jq '.' ./artifacts/api-head.json > ./api-head.json
|
||||
- name: Get diff of 2 files
|
||||
run: diff -u --label=base --label=head ./api-base.json ./api-head.json | cat > api.json.diff
|
||||
- name: Get full diff
|
||||
run: diff --label=base --label=head --new-line-format='+%L' --old-line-format='-%L' --unchanged-line-format=' %L' ./api-base.json ./api-head.json | cat > api-full.json.diff
|
||||
- name: Echo full diff
|
||||
run: cat ./api-full.json.diff
|
||||
- name: Upload full diff to Artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: api-artifact
|
||||
path: |
|
||||
api-full.json.diff
|
||||
api-base.json
|
||||
api-head.json
|
||||
- id: out-diff
|
||||
name: Build diff Comment
|
||||
run: |
|
||||
HEADER="ããŽPRãĢããapi.jsonãŽåˇŽå"
|
||||
FOOTER="[Get diff files from Workflow Page](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})"
|
||||
DIFF_BYTES="$(stat ./api.json.diff -c '%s' | tr -d '\n')"
|
||||
|
||||
echo "$HEADER" > ./output.md
|
||||
|
||||
if (( "$DIFF_BYTES" <= 1 )); then
|
||||
echo 'åˇŽåã¯ãããžããã' >> ./output.md
|
||||
else
|
||||
echo '<details>' >> ./output.md
|
||||
echo '<summary>åˇŽåã¯ããĄã</summary>' >> ./output.md
|
||||
echo >> ./output.md
|
||||
echo '```diff' >> ./output.md
|
||||
cat ./api.json.diff >> ./output.md
|
||||
echo '```' >> ./output.md
|
||||
echo '</details>' >> .output.md
|
||||
fi
|
||||
|
||||
echo "$FOOTER" >> ./output.md
|
||||
- uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment-tag: show_diff
|
||||
file-path: ./output.md
|
||||
- name: Tell error to PR
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
if: failure() && steps.load-pr-num.outputs.pr-number
|
||||
with:
|
||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment-tag: show_diff_error
|
||||
message: |
|
||||
api.jsonãŽåˇŽåäŊæä¸ãĢã¨ãŠãŧãįēįããžãããčŠŗį´°ã¯[WorkflowãŽãã°](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})ãįĸēčĒããĻãã ããã
|
||||
122
.github/workflows/report-backend-memory.yml
vendored
@@ -1,122 +0,0 @@
|
||||
name: Report backend memory
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
types: [completed]
|
||||
workflows:
|
||||
- Get backend memory usage # get-backend-memory.yml
|
||||
|
||||
jobs:
|
||||
compare-memory:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Download artifact
|
||||
uses: actions/github-script@v8.0.0
|
||||
with:
|
||||
script: |
|
||||
const fs = require('fs');
|
||||
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
run_id: context.payload.workflow_run.id,
|
||||
});
|
||||
let matchArtifacts = allArtifacts.data.artifacts.filter((artifact) => {
|
||||
return artifact.name.startsWith("memory-artifact-") || artifact.name == "memory-artifact"
|
||||
});
|
||||
await Promise.all(matchArtifacts.map(async (artifact) => {
|
||||
let download = await github.rest.actions.downloadArtifact({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
artifact_id: artifact.id,
|
||||
archive_format: 'zip',
|
||||
});
|
||||
await fs.promises.writeFile(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data));
|
||||
}));
|
||||
- name: Extract all artifacts
|
||||
run: |
|
||||
find . -mindepth 1 -maxdepth 1 -type f -name '*.zip' -exec unzip {} -d artifacts ';'
|
||||
ls -la artifacts/
|
||||
- name: Load PR Number
|
||||
id: load-pr-num
|
||||
run: echo "pr-number=$(cat artifacts/pr_number)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Output base
|
||||
run: cat ./artifacts/memory-base.json
|
||||
- name: Output head
|
||||
run: cat ./artifacts/memory-head.json
|
||||
- name: Compare memory usage
|
||||
id: compare
|
||||
run: |
|
||||
BASE_MEMORY=$(cat ./artifacts/memory-base.json)
|
||||
HEAD_MEMORY=$(cat ./artifacts/memory-head.json)
|
||||
|
||||
BASE_RSS=$(echo "$BASE_MEMORY" | jq -r '.memory.rss // 0')
|
||||
HEAD_RSS=$(echo "$HEAD_MEMORY" | jq -r '.memory.rss // 0')
|
||||
|
||||
# Calculate difference
|
||||
if [ "$BASE_RSS" -gt 0 ] && [ "$HEAD_RSS" -gt 0 ]; then
|
||||
DIFF=$((HEAD_RSS - BASE_RSS))
|
||||
DIFF_PERCENT=$(echo "scale=2; ($DIFF * 100) / $BASE_RSS" | bc)
|
||||
|
||||
# Convert to MB for readability
|
||||
BASE_MB=$(echo "scale=2; $BASE_RSS / 1048576" | bc)
|
||||
HEAD_MB=$(echo "scale=2; $HEAD_RSS / 1048576" | bc)
|
||||
DIFF_MB=$(echo "scale=2; $DIFF / 1048576" | bc)
|
||||
|
||||
echo "base_mb=$BASE_MB" >> "$GITHUB_OUTPUT"
|
||||
echo "head_mb=$HEAD_MB" >> "$GITHUB_OUTPUT"
|
||||
echo "diff_mb=$DIFF_MB" >> "$GITHUB_OUTPUT"
|
||||
echo "diff_percent=$DIFF_PERCENT" >> "$GITHUB_OUTPUT"
|
||||
echo "has_data=true" >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Determine if this is a significant change (more than 5% increase)
|
||||
if [ "$(echo "$DIFF_PERCENT > 5" | bc)" -eq 1 ]; then
|
||||
echo "significant_increase=true" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "significant_increase=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
else
|
||||
echo "has_data=false" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- id: build-comment
|
||||
name: Build memory comment
|
||||
run: |
|
||||
HEADER="## Backend Memory Usage Comparison"
|
||||
FOOTER="[See workflow logs for details](https://github.com/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID})"
|
||||
|
||||
echo "$HEADER" > ./output.md
|
||||
echo >> ./output.md
|
||||
|
||||
if [ "${{ steps.compare.outputs.has_data }}" == "true" ]; then
|
||||
echo "| Metric | base | head | Diff |" >> ./output.md
|
||||
echo "|--------|------|------|------|" >> ./output.md
|
||||
echo "| RSS | ${{ steps.compare.outputs.base_mb }} MB | ${{ steps.compare.outputs.head_mb }} MB | ${{ steps.compare.outputs.diff_mb }} MB (${{ steps.compare.outputs.diff_percent }}%) |" >> ./output.md
|
||||
echo >> ./output.md
|
||||
|
||||
if [ "${{ steps.compare.outputs.significant_increase }}" == "true" ]; then
|
||||
echo "â ī¸ **Warning**: Memory usage has increased by more than 5%. Please verify this is not an unintended change." >> ./output.md
|
||||
echo >> ./output.md
|
||||
fi
|
||||
else
|
||||
echo "Could not retrieve memory usage data." >> ./output.md
|
||||
echo >> ./output.md
|
||||
fi
|
||||
|
||||
echo "$FOOTER" >> ./output.md
|
||||
- uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment-tag: show_memory_diff
|
||||
file-path: ./output.md
|
||||
- name: Tell error to PR
|
||||
uses: thollander/actions-comment-pull-request@v3
|
||||
if: failure() && steps.load-pr-num.outputs.pr-number
|
||||
with:
|
||||
pr-number: ${{ steps.load-pr-num.outputs.pr-number }}
|
||||
comment-tag: show_memory_diff_error
|
||||
message: |
|
||||
An error occurred while comparing backend memory usage. See [workflow logs](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) for details.
|
||||
51
.github/workflows/request-release-review.yml
vendored
@@ -1,51 +0,0 @@
|
||||
name: Request release review
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
reply:
|
||||
if: github.event.comment.body == '/request-release-review'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Reply
|
||||
uses: actions/github-script@v8
|
||||
with:
|
||||
script: |
|
||||
const body = `To dev team (@misskey-dev/dev):
|
||||
|
||||
ãĒãĒãŧãšãææĄãããĻããžã :rocket:
|
||||
|
||||
GOãŽå ´åã¯approveãNO GOãŽå ´åã¯ããŽæ¨ãŗãĄãŗãããéĄãããããžãã
|
||||
|
||||
夿ãĢãããŖãĻčæ
ŽããšãčĻŗįšã¯ã
|
||||
|
||||
- ããæŽãããã¨ã¯ãĒããīŧ
|
||||
- CHANGELOGã¯éä¸čļŗãĒããīŧ
|
||||
- ããŧã¸ã§ãŗãĢåéĄã¯ãĒããīŧ(æčˇ¨ãã§ãããŽãĢæ´æ°åŋããĻãããĒãŠ)
|
||||
- åčããšãäģæ§ãģåŽčŖ
ã¯ãĒããīŧ
|
||||
- ããŧãŋįãæ¤č¨ŧãããĩãŧããŧããä¸å
ˇåãŽå ąåįã¯ä¸ããŖãĻãĒããīŧ
|
||||
- (ãģããĨãĒããŖãŽäŋŽæŖãéčĻãĒãã°äŋŽæŖãĒãŠãŽãã)ãĒãĒãŧãšãæĨãã æšãč¯ããīŧããã§ã¯ãĒããīŧ
|
||||
- ActionsãčŊãĄãĻããĒããīŧ
|
||||
|
||||
ãĒãŠãæããããžãã
|
||||
|
||||
ãååãããã¨ãããããžã :sparkles:
|
||||
`
|
||||
|
||||
const issue_number = context.payload.issue ? context.payload.issue.number : (context.payload.pull_request && context.payload.pull_request.number)
|
||||
if (!issue_number) {
|
||||
console.log('No issue or PR number found in payload; skipping')
|
||||
} else {
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number,
|
||||
body,
|
||||
})
|
||||
}
|
||||
13
.github/workflows/reviewer_lottery.yml
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
name: "Reviewer lottery"
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, ready_for_review, reopened]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: uesteibar/reviewer-lottery@v2
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
108
.github/workflows/storybook.yml
vendored
@@ -1,108 +0,0 @@
|
||||
name: Storybook
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
pull_request_target:
|
||||
branches-ignore:
|
||||
# Since pull requests targets master mostly is the "develop" branch.
|
||||
# Storybook CI is checked on the "push" event of "develop" branch so it would cause a duplicate build.
|
||||
# This is a waste of chromatic build quota, so we don't run storybook CI on pull requests targets master.
|
||||
- master
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# Chromatic is not likely to be available for fork repositories, so we disable for fork repositories.
|
||||
if: github.repository == 'misskey-dev/misskey'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
env:
|
||||
NODE_OPTIONS: "--max_old_space_size=7168"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
if: github.event_name != 'pull_request_target'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
- uses: actions/checkout@v6.0.1
|
||||
if: github.event_name == 'pull_request_target'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: true
|
||||
ref: "refs/pull/${{ github.event.number }}/merge"
|
||||
- name: Checkout actual HEAD
|
||||
if: github.event_name == 'pull_request_target'
|
||||
run: git checkout "$(git rev-list --parents -n1 HEAD | cut -d" " -f3)"
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Build dependent packages
|
||||
run: pnpm -F misskey-js -F misskey-bubble-game -F misskey-reversi build
|
||||
- name: Build storybook
|
||||
run: pnpm --filter frontend build-storybook
|
||||
- name: Publish to Chromatic
|
||||
if: github.event_name != 'pull_request_target' && github.ref == 'refs/heads/master'
|
||||
run: pnpm --filter frontend chromatic --exit-once-uploaded -d storybook-static
|
||||
env:
|
||||
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||
- name: Publish to Chromatic
|
||||
if: github.event_name != 'pull_request_target' && github.ref != 'refs/heads/master'
|
||||
id: chromatic_push
|
||||
run: |
|
||||
DIFF="${{ github.event.before }} HEAD"
|
||||
if [ "$DIFF" = "0000000000000000000000000000000000000000 HEAD" ]; then
|
||||
DIFF="HEAD"
|
||||
fi
|
||||
CHROMATIC_PARAMETER="$(node packages/frontend/.storybook/changes.js $(git diff-tree --no-commit-id --name-only -r $(echo "$DIFF") | xargs))"
|
||||
if [ "$CHROMATIC_PARAMETER" = " --skip" ]; then
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
if pnpm --filter frontend chromatic -d storybook-static $(echo "$CHROMATIC_PARAMETER"); then
|
||||
echo "success=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "success=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
env:
|
||||
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||
- name: Publish to Chromatic
|
||||
if: github.event_name == 'pull_request_target'
|
||||
id: chromatic_pull_request
|
||||
run: |
|
||||
CHROMATIC_PARAMETER="$(node packages/frontend/.storybook/changes.js $(git diff --name-only origin/${GITHUB_BASE_REF}...origin/${GITHUB_HEAD_REF} | xargs))"
|
||||
if [ "$CHROMATIC_PARAMETER" = " --skip" ]; then
|
||||
echo "skip=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
BRANCH="${{ github.event.pull_request.head.user.login }}:$GITHUB_HEAD_REF"
|
||||
if [ "$BRANCH" = "misskey-dev:$GITHUB_HEAD_REF" ]; then
|
||||
BRANCH="$GITHUB_HEAD_REF"
|
||||
fi
|
||||
pnpm --filter frontend chromatic --exit-once-uploaded -d storybook-static --branch-name "$BRANCH" $(echo "$CHROMATIC_PARAMETER")
|
||||
env:
|
||||
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
|
||||
- name: Notify that Chromatic detects changes
|
||||
uses: actions/github-script@v8.0.0
|
||||
if: github.event_name != 'pull_request_target' && steps.chromatic_push.outputs.success == 'false'
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
github.rest.repos.createCommitComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
commit_sha: context.sha,
|
||||
body: 'Chromatic detects changes. Please [review the changes on Chromatic](https://www.chromatic.com/builds?appId=6428f7d7b962f0b79f97d6e4).'
|
||||
})
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: storybook
|
||||
path: packages/frontend/storybook-static
|
||||
181
.github/workflows/test-backend.yml
vendored
@@ -5,98 +5,44 @@ on:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
paths:
|
||||
- packages/backend/**
|
||||
# for permissions
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/test-backend.yml
|
||||
- .github/misskey/test.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/backend/**
|
||||
# for permissions
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/test-backend.yml
|
||||
- .github/misskey/test.yml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
force_ffmpeg_cache_update:
|
||||
description: 'Force update ffmpeg cache'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
unit:
|
||||
name: Unit tests (backend)
|
||||
jest:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version-file:
|
||||
- .node-version
|
||||
- .github/min.node-version
|
||||
node-version: [18.x]
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
image: postgres:13
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:7
|
||||
image: redis:6
|
||||
ports:
|
||||
- 56312:6379
|
||||
meilisearch:
|
||||
image: getmeili/meilisearch:v1.3.4
|
||||
ports:
|
||||
- 57712:7700
|
||||
env:
|
||||
MEILI_NO_ANALYTICS: true
|
||||
MEILI_ENV: development
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
- uses: actions/checkout@v3.3.0
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Setup and Restore ffmpeg/ffprobe Cache
|
||||
id: cache-ffmpeg
|
||||
uses: actions/cache@v4
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
path: |
|
||||
/usr/local/bin/ffmpeg
|
||||
/usr/local/bin/ffprobe
|
||||
# daily cache
|
||||
key: ${{ runner.os }}-ffmpeg-${{ steps.current-date.outputs.today }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-ffmpeg-${{ steps.current-date.outputs.today }}
|
||||
- name: Install FFmpeg
|
||||
if: steps.cache-ffmpeg.outputs.cache-hit != 'true' || github.event.inputs.force_ffmpeg_cache_update == true
|
||||
run: |
|
||||
for i in {1..3}; do
|
||||
echo "Attempt $i: Installing FFmpeg..."
|
||||
curl -s -L https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz -o ffmpeg.tar.xz && \
|
||||
tar -xf ffmpeg.tar.xz && \
|
||||
mv ffmpeg-*-static/ffmpeg /usr/local/bin/ && \
|
||||
mv ffmpeg-*-static/ffprobe /usr/local/bin/ && \
|
||||
rm -rf ffmpeg.tar.xz ffmpeg-*-static/ && \
|
||||
break || sleep 10
|
||||
if [ $i -eq 3 ]; then
|
||||
echo "Failed to install FFmpeg after 3 attempts"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
version: 7
|
||||
run_install: false
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3.6.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- run: corepack enable
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
@@ -105,102 +51,9 @@ jobs:
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Test
|
||||
run: pnpm --filter backend test-and-coverage
|
||||
- name: Upload to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
run: pnpm jest-and-coverage
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/backend/coverage/coverage-final.json
|
||||
|
||||
e2e:
|
||||
name: E2E tests (backend)
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version-file:
|
||||
- .node-version
|
||||
- .github/min.node-version
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:7
|
||||
ports:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Copy Configure
|
||||
run: cp .github/misskey/test.yml .config
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Test
|
||||
run: pnpm --filter backend test-and-coverage:e2e
|
||||
- name: Upload to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/backend/coverage/coverage-final.json
|
||||
|
||||
migration:
|
||||
name: Migration tests (backend)
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version-file:
|
||||
- .node-version
|
||||
#- .github/min.node-version
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Copy Configure
|
||||
run: cp .github/misskey/test.yml .config
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
- name: Run migrations
|
||||
run: MISSKEY_CONFIG_YML=test.yml pnpm --filter backend migrate
|
||||
- name: Check no migrations are remaining
|
||||
run: MISSKEY_CONFIG_YML=test.yml pnpm --filter backend check-migrations
|
||||
|
||||
111
.github/workflows/test-federation.yml
vendored
@@ -1,111 +0,0 @@
|
||||
name: Test (federation)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
paths:
|
||||
- packages/backend/**
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/test-federation.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/backend/**
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/test-federation.yml
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
force_ffmpeg_cache_update:
|
||||
description: 'Force update ffmpeg cache'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Federation test
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
node-version-file:
|
||||
- .node-version
|
||||
- .github/min.node-version
|
||||
steps:
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Get current date
|
||||
id: current-date
|
||||
run: echo "today=$(date +'%Y-%m-%d')" >> $GITHUB_OUTPUT
|
||||
- name: Setup and Restore ffmpeg/ffprobe Cache
|
||||
id: cache-ffmpeg
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
/usr/local/bin/ffmpeg
|
||||
/usr/local/bin/ffprobe
|
||||
# daily cache
|
||||
key: ${{ runner.os }}-ffmpeg-${{ steps.current-date.outputs.today }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-ffmpeg-${{ steps.current-date.outputs.today }}
|
||||
- name: Install FFmpeg
|
||||
if: steps.cache-ffmpeg.outputs.cache-hit != 'true' || github.event.inputs.force_ffmpeg_cache_update == true
|
||||
run: |
|
||||
for i in {1..3}; do
|
||||
echo "Attempt $i: Installing FFmpeg..."
|
||||
curl -s -L https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz -o ffmpeg.tar.xz && \
|
||||
tar -xf ffmpeg.tar.xz && \
|
||||
mv ffmpeg-*-static/ffmpeg /usr/local/bin/ && \
|
||||
mv ffmpeg-*-static/ffprobe /usr/local/bin/ && \
|
||||
rm -rf ffmpeg.tar.xz ffmpeg-*-static/ && \
|
||||
break || sleep 10
|
||||
if [ $i -eq 3 ]; then
|
||||
echo "Failed to install FFmpeg after 3 attempts"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: ${{ matrix.node-version-file }}
|
||||
cache: 'pnpm'
|
||||
- name: Build Misskey
|
||||
run: |
|
||||
pnpm i --frozen-lockfile
|
||||
pnpm build
|
||||
- name: Setup
|
||||
run: |
|
||||
echo "NODE_VERSION=$(cat ${{ matrix.node-version-file }})" >> $GITHUB_ENV
|
||||
cd packages/backend/test-federation
|
||||
bash ./setup.sh
|
||||
sudo chmod 644 ./certificates/*.test.key
|
||||
- name: Start servers
|
||||
id: start_servers
|
||||
continue-on-error: true
|
||||
# https://github.com/docker/compose/issues/1294#issuecomment-374847206
|
||||
run: |
|
||||
cd packages/backend/test-federation
|
||||
docker compose up -d --scale tester=0
|
||||
- name: Print start_servers error
|
||||
if: ${{ steps.start_servers.outcome == 'failure' }}
|
||||
run: |
|
||||
cd packages/backend/test-federation
|
||||
docker compose logs | tail -n 300
|
||||
exit 1
|
||||
- name: Test
|
||||
run: |
|
||||
cd packages/backend/test-federation
|
||||
docker compose run --no-deps tester
|
||||
- name: Log
|
||||
if: always()
|
||||
run: |
|
||||
cd packages/backend/test-federation
|
||||
docker compose logs
|
||||
- name: Stop servers
|
||||
if: always()
|
||||
run: |
|
||||
cd packages/backend/test-federation
|
||||
docker compose down
|
||||
71
.github/workflows/test-frontend.yml
vendored
@@ -5,39 +5,31 @@ on:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
paths:
|
||||
- packages/frontend/**
|
||||
# for permissions
|
||||
- packages/misskey-js/**
|
||||
# for e2e
|
||||
- packages/backend/**
|
||||
- .github/workflows/test-frontend.yml
|
||||
- .github/misskey/test.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/frontend/**
|
||||
# for permissions
|
||||
- packages/misskey-js/**
|
||||
# for e2e
|
||||
- packages/backend/**
|
||||
- .github/workflows/test-frontend.yml
|
||||
- .github/misskey/test.yml
|
||||
|
||||
jobs:
|
||||
vitest:
|
||||
name: Unit tests (frontend)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
- uses: actions/checkout@v3.3.0
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
version: 7
|
||||
run_install: false
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3.6.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- run: corepack enable
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
@@ -48,35 +40,35 @@ jobs:
|
||||
- name: Test
|
||||
run: pnpm --filter frontend test-and-coverage
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@v5
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/frontend/coverage/coverage-final.json
|
||||
|
||||
e2e:
|
||||
name: E2E tests (frontend)
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node-version: [18.x]
|
||||
browser: [chrome]
|
||||
|
||||
services:
|
||||
postgres:
|
||||
image: postgres:18
|
||||
image: postgres:13
|
||||
ports:
|
||||
- 54312:5432
|
||||
env:
|
||||
POSTGRES_DB: test-misskey
|
||||
POSTGRES_HOST_AUTH_METHOD: trust
|
||||
redis:
|
||||
image: redis:7
|
||||
image: redis:6
|
||||
ports:
|
||||
- 56312:6379
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
- uses: actions/checkout@v3.3.0
|
||||
with:
|
||||
submodules: true
|
||||
# https://github.com/cypress-io/cypress-docker-images/issues/150
|
||||
@@ -85,13 +77,17 @@ jobs:
|
||||
# if: ${{ matrix.browser == 'firefox' }}
|
||||
#- uses: browser-actions/setup-firefox@latest
|
||||
# if: ${{ matrix.browser == 'firefox' }}
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v2
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
version: 7
|
||||
run_install: false
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3.6.0
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
- run: corepack enable
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Copy Configure
|
||||
run: cp .github/misskey/test.yml .config
|
||||
@@ -105,20 +101,19 @@ jobs:
|
||||
- name: Cypress install
|
||||
run: pnpm exec cypress install
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v6
|
||||
timeout-minutes: 15
|
||||
uses: cypress-io/github-action@v5
|
||||
with:
|
||||
install: false
|
||||
start: pnpm start:test
|
||||
wait-on: 'http://localhost:61812'
|
||||
headed: true
|
||||
headless: false
|
||||
browser: ${{ matrix.browser }}
|
||||
- uses: actions/upload-artifact@v6
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: failure()
|
||||
with:
|
||||
name: ${{ matrix.browser }}-cypress-screenshots
|
||||
path: cypress/screenshots
|
||||
- uses: actions/upload-artifact@v6
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: always()
|
||||
with:
|
||||
name: ${{ matrix.browser }}-cypress-videos
|
||||
|
||||
26
.github/workflows/test-misskey-js.yml
vendored
@@ -6,31 +6,29 @@ name: Test (misskey.js)
|
||||
on:
|
||||
push:
|
||||
branches: [ develop ]
|
||||
paths:
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/test-misskey-js.yml
|
||||
pull_request:
|
||||
branches: [ develop ]
|
||||
paths:
|
||||
- packages/misskey-js/**
|
||||
- .github/workflows/test-misskey-js.yml
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Unit tests (misskey.js)
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [18.x]
|
||||
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6.0.1
|
||||
uses: actions/checkout@v3.3.0
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- run: corepack enable
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
- name: Setup Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3.6.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
node-version: ${{ matrix.node-version }}
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
@@ -48,7 +46,7 @@ jobs:
|
||||
CI: true
|
||||
|
||||
- name: Upload Coverage
|
||||
uses: codecov/codecov-action@v5
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
files: ./packages/misskey-js/coverage/coverage-final.json
|
||||
|
||||
35
.github/workflows/test-production.yml
vendored
@@ -1,35 +0,0 @@
|
||||
name: Test (production install and build)
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
NODE_ENV: production
|
||||
|
||||
jobs:
|
||||
production:
|
||||
name: Production build
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Copy Configure
|
||||
run: cp .github/misskey/test.yml .config/default.yml
|
||||
- name: Build
|
||||
run: pnpm build
|
||||
40
.github/workflows/validate-api-json.yml
vendored
@@ -1,40 +0,0 @@
|
||||
name: api.json validation
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
paths:
|
||||
- packages/backend/**
|
||||
- .github/workflows/validate-api-json.yml
|
||||
pull_request:
|
||||
paths:
|
||||
- packages/backend/**
|
||||
- .github/workflows/validate-api-json.yml
|
||||
jobs:
|
||||
validate-api-json:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v6.0.1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4.2.0
|
||||
- name: Use Node.js
|
||||
uses: actions/setup-node@v6.1.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
cache: 'pnpm'
|
||||
- name: Install Redocly CLI
|
||||
run: npm i -g @redocly/cli
|
||||
- run: pnpm i --frozen-lockfile
|
||||
- name: Check pnpm-lock.yaml
|
||||
run: git diff --exit-code pnpm-lock.yaml
|
||||
- name: Copy Configure
|
||||
run: cp .config/example.yml .config/default.yml
|
||||
- name: Build and generate
|
||||
run: pnpm build && pnpm --filter backend generate-api-json
|
||||
- name: Validation
|
||||
run: npx @redocly/cli lint --extends=minimal ./packages/backend/built/api.json
|
||||
22
.gitignore
vendored
@@ -35,22 +35,16 @@ coverage
|
||||
!/.config/example.yml
|
||||
!/.config/docker_example.yml
|
||||
!/.config/docker_example.env
|
||||
!/.config/cypress-devcontainer.yml
|
||||
docker-compose.yml
|
||||
./compose.yml
|
||||
.devcontainer/compose.yml
|
||||
!/.devcontainer/compose.yml
|
||||
!/.devcontainer/docker-compose.yml
|
||||
|
||||
# misskey
|
||||
/build
|
||||
built
|
||||
built-test
|
||||
js-built
|
||||
src-js
|
||||
/data
|
||||
/.cache-loader
|
||||
/db
|
||||
/meili_data
|
||||
/elasticsearch
|
||||
npm-debug.log
|
||||
*.pem
|
||||
run.bat
|
||||
@@ -62,15 +56,6 @@ api-docs.json
|
||||
/files
|
||||
ormconfig.json
|
||||
temp
|
||||
/packages/frontend/src/**/*.stories.ts
|
||||
tsdoc-metadata.json
|
||||
misskey-assets
|
||||
|
||||
# Vite temporary files
|
||||
vite.config.js.timestamp-*
|
||||
vite.config.ts.timestamp-*
|
||||
vite.config.local-dev.js.timestamp-*
|
||||
vite.config.local-dev.ts.timestamp-*
|
||||
|
||||
# blender backups
|
||||
*.blend1
|
||||
@@ -78,6 +63,3 @@ vite.config.local-dev.ts.timestamp-*
|
||||
*.blend3
|
||||
*.blend4
|
||||
*.blend5
|
||||
|
||||
# VSCode addon
|
||||
.favorites.json
|
||||
|
||||
3
.gitmodules
vendored
@@ -1,3 +1,6 @@
|
||||
[submodule "misskey-assets"]
|
||||
path = misskey-assets
|
||||
url = https://github.com/misskey-dev/assets.git
|
||||
[submodule "fluent-emojis"]
|
||||
path = fluent-emojis
|
||||
url = https://github.com/misskey-dev/emojis.git
|
||||
|
||||
@@ -1 +1 @@
|
||||
22.15.0
|
||||
v18.13.0
|
||||
|
||||
2
.vscode/extensions.json
vendored
@@ -3,7 +3,9 @@
|
||||
"editorconfig.editorconfig",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"Vue.volar",
|
||||
"Vue.vscode-typescript-vue-plugin",
|
||||
"Orta.vscode-jest",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"mrmlnc.vscode-json5"
|
||||
]
|
||||
}
|
||||
|
||||
28
.vscode/settings.json
vendored
@@ -1,20 +1,10 @@
|
||||
{
|
||||
"search.exclude": {
|
||||
"**/node_modules": true
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true,
|
||||
"files.associations": {
|
||||
"*.test.ts": "typescript"
|
||||
},
|
||||
"jest.runMode": "on-demand",
|
||||
"jest.virtualFolders": [
|
||||
{ "name": "backend unit", "jestCommandLine": "pnpm -F backend run test" },
|
||||
{ "name": "backend e2e", "jestCommandLine": "pnpm -F backend run test:e2e"},
|
||||
{ "name": "misskey-js", "jestCommandLine": "pnpm -F misskey-js run jest" }
|
||||
],
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll": "explicit"
|
||||
},
|
||||
"editor.formatOnSave": false
|
||||
}
|
||||
"search.exclude": {
|
||||
"**/node_modules": true
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"files.associations": {
|
||||
"*.test.ts": "typescript"
|
||||
},
|
||||
"jest.autoRun": "off"
|
||||
}
|
||||
2207
CHANGELOG.md
@@ -2,131 +2,45 @@
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, caste, color, religion, or sexual
|
||||
identity and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the overall
|
||||
community
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or advances of
|
||||
any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email address,
|
||||
without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
## Our Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
<syuilotan@yahoo.co.jp>.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at syuilotan@yahoo.co.jp. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series of
|
||||
actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or permanent
|
||||
ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within the
|
||||
community.
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.1, available at
|
||||
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
Community Impact Guidelines were inspired by
|
||||
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
||||
[https://www.contributor-covenant.org/translations][translations].
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
||||
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||
[FAQ]: https://www.contributor-covenant.org/faq
|
||||
[translations]: https://www.contributor-covenant.org/translations
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
|
||||
437
CONTRIBUTING.md
@@ -1,7 +1,7 @@
|
||||
# Contribution guide
|
||||
We're glad you're interested in contributing Misskey! In this document you will find the information you need to contribute to the project.
|
||||
|
||||
> [!NOTE]
|
||||
> **Note**
|
||||
> This project uses Japanese as its major language, **but you do not need to translate and write the Issues/PRs in Japanese.**
|
||||
> Also, you might receive comments on your Issue/PR in Japanese, but you do not need to reply to them in Japanese as well.\
|
||||
> The accuracy of machine translation into Japanese is not high, so it will be easier for us to understand if you write it in the original language.
|
||||
@@ -15,33 +15,18 @@ Before creating an issue, please check the following:
|
||||
- To avoid duplication, please search for similar issues before creating a new issue.
|
||||
- Do not use Issues to ask questions or troubleshooting.
|
||||
- Issues should only be used to feature requests, suggestions, and bug tracking.
|
||||
- Please ask questions or troubleshooting in [GitHub Discussions](https://github.com/misskey-dev/misskey/discussions) or [Discord](https://discord.gg/Wp8gVStHW3).
|
||||
- Please ask questions or troubleshooting in ~~the [Misskey Forum](https://forum.misskey.io/)~~ [GitHub Discussions](https://github.com/misskey-dev/misskey/discussions) or [Discord](https://discord.gg/Wp8gVStHW3).
|
||||
|
||||
> [!WARNING]
|
||||
> **Warning**
|
||||
> Do not close issues that are about to be resolved. It should remain open until a commit that actually resolves it is merged.
|
||||
|
||||
### Recommended discussing before implementation
|
||||
We welcome your proposal.
|
||||
|
||||
## Before implementation
|
||||
When you want to add a feature or fix a bug, **first have the design and policy reviewed in an Issue** (if it is not there, please make one). Without this step, there is a high possibility that the PR will not be merged even if it is implemented.
|
||||
|
||||
At this point, you also need to clarify the goals of the PR you will create, and make sure that the other members of the team are aware of them.
|
||||
PRs that do not have a clear set of do's and don'ts tend to be bloated and difficult to review.
|
||||
|
||||
Also, when you start implementation, assign yourself to the Issue (if you cannot do it yourself, ask Committer to assign you).
|
||||
By expressing your intention to work on the Issue, you can prevent conflicts in the work.
|
||||
|
||||
To the Committers: you should not assign someone on it before the Final Decision.
|
||||
|
||||
### How issues are triaged
|
||||
|
||||
The Committers may:
|
||||
* close an issue that is not reproducible on latest stable release,
|
||||
* merge an issue into another issue,
|
||||
* split an issue into multiple issues,
|
||||
* or re-open that has been closed for some reason which is not applicable anymore.
|
||||
|
||||
@syuilo reserves the Final Decision rights including whether the project will implement feature and how to implement, these rights are not always exercised.
|
||||
Also, when you start implementation, assign yourself to the Issue (if you cannot do it yourself, ask another member to assign you). By expressing your intention to work the Issue, you can prevent conflicts in the work.
|
||||
|
||||
## Well-known branches
|
||||
- **`master`** branch is tracking the latest release and used for production purposes.
|
||||
@@ -52,45 +37,25 @@ The Committers may:
|
||||
## Creating a PR
|
||||
Thank you for your PR! Before creating a PR, please check the following:
|
||||
- If possible, prefix the title with a keyword that identifies the type of this PR, as shown below.
|
||||
- `fix` / `refactor` / `feat` / `enhance` / `perf` / `chore` etc
|
||||
- Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR.
|
||||
- `fix` / `refactor` / `feat` / `enhance` / `perf` / `chore` etc
|
||||
- Also, make sure that the granularity of this PR is appropriate. Please do not include more than one type of change or interest in a single PR.
|
||||
- If there is an Issue which will be resolved by this PR, please include a reference to the Issue in the text.
|
||||
- Please add the summary of the changes to [`CHANGELOG.md`](/CHANGELOG.md). However, this is not necessary for changes that do not affect the users, such as refactoring.
|
||||
- Check if there are any documents that need to be created or updated due to this change.
|
||||
- If you have added a feature or fixed a bug, please add a test case if possible.
|
||||
- Please make sure that tests and Lint are passed in advance.
|
||||
- You can run it with `pnpm test` and `pnpm lint`. [See more info](#testing)
|
||||
- You can run it with `pnpm test` and `pnpm lint`. [See more info](#testing)
|
||||
- If this PR includes UI changes, please attach a screenshot in the text.
|
||||
|
||||
Thanks for your cooperation đ¤
|
||||
|
||||
### Additional things for ActivityPub payload changes
|
||||
*This section is specific to misskey-dev implementation. Other fork or implementation may take different way. A significant difference is that non-"misskey-dev" extension is not described in the misskey-hub's document.*
|
||||
|
||||
If PR includes changes to ActivityPub payload, please reflect it in [misskey-hub's document](https://github.com/misskey-dev/misskey-hub-next/blob/master/content/ns.md) by sending PR.
|
||||
|
||||
The name of purporsed extension property (referred as "extended property" in later) to ActivityPub shall be prefixed by `_misskey_`. (i.e. `_misskey_quote`)
|
||||
|
||||
The extended property in `packages/backend/src/core/activitypub/type.ts` **must** be declared as optional because ActivityPub payloads that comes from older Misskey or other implementation may not contain it.
|
||||
|
||||
The extended property must be included in the context definition. Context is defined in `packages/backend/src/core/activitypub/misc/contexts.ts`.
|
||||
The key shall be same as the name of extended property, and the value shall be same as "short IRI".
|
||||
|
||||
"Short IRI" is defined in misskey-hub's document, but usually takes form of `misskey:<name of extended property>`. (i.e. `misskey:_misskey_quote`)
|
||||
|
||||
One should not add property that has defined before by other implementation, or add custom variant value to "well-known" property.
|
||||
|
||||
## Reviewers guide
|
||||
Be willing to comment on the good points and not just the things you want fixed đ¯
|
||||
|
||||
čĒãã§ããã¨ãããã¤
|
||||
- https://blog.lacolaco.net/posts/1e2cf439b3c2/
|
||||
- https://konifar-zatsu.hatenadiary.jp/entry/2024/11/05/192421
|
||||
|
||||
### Review perspective
|
||||
- Scope
|
||||
- Are the goals of the PR clear?
|
||||
- Is the granularity of the PR appropriate?
|
||||
- Are the goals of the PR clear?
|
||||
- Is the granularity of the PR appropriate?
|
||||
- Security
|
||||
- Does merging this PR create a vulnerability?
|
||||
- Performance
|
||||
@@ -101,22 +66,6 @@ Be willing to comment on the good points and not just the things you want fixed
|
||||
- Are there any omissions or gaps?
|
||||
- Does it check for anomalies?
|
||||
|
||||
## Security Advisory
|
||||
### For reporter
|
||||
Thank you for your reporting!
|
||||
|
||||
If you can also create a patch to fix the vulnerability, please create a PR on the private fork.
|
||||
|
||||
> [!note]
|
||||
> There is a GitHub bug that prevents merging if a PR not following the develop branch of upstream, so please keep follow the develop branch.
|
||||
|
||||
### For misskey-dev member
|
||||
äŋŽæŖPRãdevelopãĢčŋŊåžãããĻããĒãã¨ããŧã¸ã§ããĒããŽã§ãããŧã¸ã§ããĒããŖãã
|
||||
|
||||
> Could you merge or rebase onto upstream develop branch?
|
||||
|
||||
ãĒãŠã¨äŧããã
|
||||
|
||||
## Deploy
|
||||
The `/deploy` command by issue comment can be used to deploy the contents of a PR to the preview environment.
|
||||
```
|
||||
@@ -128,7 +77,7 @@ An actual domain will be assigned so you can test the federation.
|
||||
|
||||
## Release
|
||||
### Release Instructions
|
||||
1. Commit version changes in the `develop` branch ([package.json](package.json))
|
||||
1. Commit version changes in the `develop` branch ([package.json](https://github.com/misskey-dev/misskey/blob/develop/package.json))
|
||||
2. Create a release PR.
|
||||
- Into `master` from `develop` branch.
|
||||
- The title must be in the format `Release: x.y.z`.
|
||||
@@ -139,7 +88,7 @@ An actual domain will be assigned so you can test the federation.
|
||||
- The target branch must be `master`
|
||||
- The tag name must be the version
|
||||
|
||||
> [!NOTE]
|
||||
> **Note**
|
||||
> Why this instruction is necessary:
|
||||
> - To perform final QA checks
|
||||
> - To distribute responsibility
|
||||
@@ -152,30 +101,26 @@ You can improve our translations with your Crowdin account.
|
||||
Your changes in Crowdin are automatically submitted as a PR (with the title "New Crowdin translations") to the repository.
|
||||
The owner [@syuilo](https://github.com/syuilo) merges the PR into the develop branch before the next release.
|
||||
|
||||
If your language is not listed in Crowdin, please open an issue. We will add it to Crowdin.
|
||||
For newly added languages, once the translation progress per language exceeds 70%, it will be officially introduced into Misskey and made available to users.
|
||||
If your language is not listed in Crowdin, please open an issue.
|
||||
|
||||

|
||||
|
||||
## Development
|
||||
### Setup
|
||||
Before developing, you have to set up environment. Misskey requires Redis, PostgreSQL, and FFmpeg.
|
||||
During development, it is useful to use the
|
||||
|
||||
You would want to install Meilisearch to experiment related features. Technically, meilisearch is not strict requirement, but some features and tests require it.
|
||||
```
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
There are a few ways to proceed.
|
||||
command.
|
||||
|
||||
#### Use system-wide software
|
||||
You could install them in system-wide (such as from package manager).
|
||||
|
||||
#### Use `docker compose`
|
||||
You could obtain middleware container by typing `docker compose -f $PROJECT_ROOT/compose.local-db.yml up -d`.
|
||||
|
||||
#### Use Devcontainer
|
||||
Devcontainer also has necessary setting. This method can be done by connecting from VSCode.
|
||||
- Server-side source files and automatically builds them if they are modified. Automatically start the server process(es).
|
||||
- Vite HMR (just the `vite` command) is available. The behavior may be different from production.
|
||||
- Service Worker is watched by esbuild.
|
||||
|
||||
### Dev Container
|
||||
Instead of running `pnpm` locally, you can use Dev Container to set up your development environment.
|
||||
To use Dev Container, open the project directory on VSCode with Dev Containers installed.
|
||||
To use Dev Container, open the project directory on VSCode with Dev Containers installed.
|
||||
**Note:** If you are using Windows, please clone the repository with WSL. Using Git for Windows will result in broken files due to the difference in how newlines are handled.
|
||||
|
||||
It will run the following command automatically inside the container.
|
||||
@@ -187,66 +132,38 @@ pnpm build
|
||||
pnpm migrate
|
||||
```
|
||||
|
||||
After finishing the migration, you can proceed.
|
||||
After finishing the migration, run the `pnpm dev` command to start the development server.
|
||||
|
||||
### Start developing
|
||||
During development, it is useful to use the
|
||||
```
|
||||
``` bash
|
||||
pnpm dev
|
||||
```
|
||||
command.
|
||||
|
||||
- Server-side source files and automatically builds them if they are modified. Automatically start the server process(es).
|
||||
- Service Worker is watched by esbuild.
|
||||
- Vite HMR (just the `vite` command) is available. The behavior may be different from production.
|
||||
- Vite runs behind the backend (the backend will proxy Vite at /vite and /embed_vite except for websocket used for HMR).
|
||||
- You can see Misskey by accessing `http://localhost:3000` (Replace `3000` with the port configured with `port` in .config/default.yml).
|
||||
|
||||
## Testing
|
||||
You can run non-backend tests by executing following commands:
|
||||
```sh
|
||||
pnpm --filter frontend test
|
||||
pnpm --filter misskey-js test
|
||||
- Test codes are located in [`/packages/backend/test`](/packages/backend/test).
|
||||
|
||||
### Run test
|
||||
Create a config file.
|
||||
```
|
||||
|
||||
Backend tests require manual preparation of servers. See the next section for more on this.
|
||||
|
||||
### Backend
|
||||
There are three types of test codes for the backend:
|
||||
- Unit tests: [`/packages/backend/test/unit`](/packages/backend/test/unit)
|
||||
- Single-server E2E tests: [`/packages/backend/test/e2e`](/packages/backend/test/e2e)
|
||||
- Multiple-server E2E tests: [`/packages/backend/test-federation`](/packages/backend/test-federation)
|
||||
|
||||
#### Running Unit Tests or Single-server E2E Tests
|
||||
1. Create a config file:
|
||||
```sh
|
||||
cp .github/misskey/test.yml .config/
|
||||
```
|
||||
|
||||
2. Start DB and Redis servers for testing:
|
||||
```sh
|
||||
docker compose -f packages/backend/test/compose.yml up
|
||||
Prepare DB/Redis for testing.
|
||||
```
|
||||
Instead, you can prepare an empty (data can be erased) DB and edit `.config/test.yml` appropriately.
|
||||
|
||||
3. Run all tests:
|
||||
```sh
|
||||
pnpm --filter backend test # unit tests
|
||||
pnpm --filter backend test:e2e # single-server E2E tests
|
||||
docker compose -f packages/backend/test/docker-compose.yml up
|
||||
```
|
||||
If you want to run a specific test, run as a following command:
|
||||
```sh
|
||||
pnpm --filter backend test -- packages/backend/test/unit/activitypub.ts
|
||||
pnpm --filter backend test:e2e -- packages/backend/test/e2e/nodeinfo.ts
|
||||
Alternatively, prepare an empty (data can be erased) DB and edit `.config/test.yml`.
|
||||
|
||||
Run all test.
|
||||
```
|
||||
pnpm test
|
||||
```
|
||||
|
||||
#### Running Multiple-server E2E Tests
|
||||
See [`/packages/backend/test-federation/README.md`](/packages/backend/test-federation/README.md).
|
||||
#### Run specify test
|
||||
```
|
||||
pnpm jest -- foo.ts
|
||||
```
|
||||
|
||||
## Environment Variable
|
||||
|
||||
- `MISSKEY_CONFIG_YML`: Specify the file path of config.yml instead of default.yml (e.g. `2nd.yml`).
|
||||
- `MISSKEY_WEBFINGER_USE_HTTP`: If it's set true, WebFinger requests will be http instead of https, useful for testing federation between servers in localhost. NEVER USE IN PRODUCTION.
|
||||
### e2e tests
|
||||
TODO
|
||||
|
||||
## Continuous integration
|
||||
Misskey uses GitHub Actions for executing automated tests.
|
||||
@@ -258,12 +175,6 @@ Misskey uses Vue(v3) as its front-end framework.
|
||||
- **When creating a new component, please use the Composition API (with [setup sugar](https://v3.vuejs.org/api/sfc-script-setup.html) and [ref sugar](https://github.com/vuejs/rfcs/discussions/369)) instead of the Options API.**
|
||||
- Some of the existing components are implemented in the Options API, but it is an old implementation. Refactors that migrate those components to the Composition API are also welcome.
|
||||
|
||||
## Tabler Icons
|
||||
ãĸã¤ãŗãŗã¯ãProduction BuildæãĢäŊŋį¨ãããĻããĒãããŽãåé¤ããããããĢãĒãŖãĻããžãã
|
||||
|
||||
**ãĸã¤ãŗãŗãåįãĢč¨åŽããéãĢã¯ã `ti-${someVal}` ãŽãããĒããĸã¤ãŗãŗåãŽãŋãåįãĢå¤åãããåŽčŖ
ãčĄããĒãã§ãã ããã**
|
||||
åŋ
ã `ti-xxx` ãŽãããĒåŽå
¨ãĒã¯ãŠãšåãåĢãããããĢããĻãã ããã
|
||||
|
||||
## nirax
|
||||
niraxã¯ãMisskeyã§äŊŋį¨ããĻãããĒãĒã¸ããĢãŽãããŗãã¨ãŗããĢãŧããŖãŗã°ãˇãšãã ã§ãã
|
||||
**vue-routerããåŊąéŋãå¤å¤§ãĢåããĻãããŽã§ããžãã¯vue-routerãĢã¤ããĻåĻãļãã¨ããå§ãããžãã**
|
||||
@@ -271,7 +182,7 @@ niraxã¯ãMisskeyã§äŊŋį¨ããĻãããĒãĒã¸ããĢãŽãããŗãã¨ãŗã
|
||||
### ãĢãŧãåŽįžŠ
|
||||
ãĢãŧãåŽįžŠã¯ãäģĨä¸ãŽåŊĸåŧãŽãĒãã¸ã§ã¯ããŽé
åã§ãã
|
||||
|
||||
```ts
|
||||
``` ts
|
||||
{
|
||||
name?: string;
|
||||
path: string;
|
||||
@@ -279,11 +190,12 @@ niraxã¯ãMisskeyã§äŊŋį¨ããĻãããĒãĒã¸ããĢãŽãããŗãã¨ãŗã
|
||||
query?: Record<string, string>;
|
||||
loginRequired?: boolean;
|
||||
hash?: string;
|
||||
globalCacheKey?: string;
|
||||
children?: RouteDef[];
|
||||
}
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> **Warning**
|
||||
> įžįļããĢãŧãã¯åŽįžŠãããé ãĢčŠäžĄãããžãã
|
||||
> ãã¨ãã°ã`/foo/:id`ãĢãŧãåŽįžŠãŽæŦĄãĢ`/foo/bar`ãĢãŧãåŽįžŠããããĻããå ´åãåžč
ãããããããã¨ã¯ãããžããã
|
||||
|
||||
@@ -291,201 +203,7 @@ niraxã¯ãMisskeyã§äŊŋį¨ããĻãããĒãĒã¸ããĢãŽãããŗãã¨ãŗã
|
||||
vue-routerã¨ã޿大ãŽéãã¯ãniraxã¯č¤æ°ãŽãĢãŧãŋãŧãåå¨ãããã¨ã訹å¯ããĻããįšã§ãã
|
||||
ãããĢããããĸããĒå
ãĻãŖãŗããĻã§ããŠãĻãļã¨ã¯ååĨãĢãĢãŧããŖãŗã°ãããã¨ãĒãŠãå¯čŊãĢãĒããžãã
|
||||
|
||||
## Storybook
|
||||
|
||||
Misskey uses [Storybook](https://storybook.js.org/) for UI development.
|
||||
|
||||
### Setup & Run
|
||||
|
||||
#### Setup
|
||||
|
||||
```bash
|
||||
pnpm --filter misskey-js build
|
||||
```
|
||||
|
||||
#### Run
|
||||
|
||||
```bash
|
||||
pnpm --filter frontend storybook-dev
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
When you create a new component (in this example, `MyComponent.vue`), the story file (`MyComponent.stories.ts`) will be automatically generated by the `.storybook/generate.js` script.
|
||||
You can override the default story by creating a impl story file (`MyComponent.stories.impl.ts`).
|
||||
|
||||
```ts
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
import { StoryObj } from '@storybook/vue3';
|
||||
import MyComponent from './MyComponent.vue';
|
||||
export const Default = {
|
||||
render(args) {
|
||||
return {
|
||||
components: {
|
||||
MyComponent,
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
args,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
props() {
|
||||
return {
|
||||
...this.args,
|
||||
};
|
||||
},
|
||||
},
|
||||
template: '<MyComponent v-bind="props" />',
|
||||
};
|
||||
},
|
||||
args: {
|
||||
foo: 'bar',
|
||||
},
|
||||
parameters: {
|
||||
layout: 'centered',
|
||||
},
|
||||
} satisfies StoryObj<typeof MyComponent>;
|
||||
```
|
||||
|
||||
If you want to opt-out from the automatic generation, create a `MyComponent.stories.impl.ts` file and add the following line to the file.
|
||||
|
||||
```ts
|
||||
import MyComponent from './MyComponent.vue';
|
||||
void MyComponent;
|
||||
```
|
||||
|
||||
You can override the component meta by creating a meta story file (`MyComponent.stories.meta.ts`).
|
||||
|
||||
```ts
|
||||
export const argTypes = {
|
||||
scale: {
|
||||
control: {
|
||||
type: 'range',
|
||||
min: 1,
|
||||
max: 4,
|
||||
},
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
Also, you can use msw to mock API requests in the storybook. Creating a `MyComponent.stories.msw.ts` file to define the mock handlers.
|
||||
|
||||
```ts
|
||||
import { HttpResponse, http } from 'msw';
|
||||
export const handlers = [
|
||||
http.post('/api/notes/timeline', ({ request }) => {
|
||||
return HttpResponse.json([]);
|
||||
}),
|
||||
];
|
||||
```
|
||||
|
||||
Don't forget to re-run the `.storybook/generate.js` script after adding, editing, or removing the above files.
|
||||
|
||||
## Nest
|
||||
|
||||
### Nest Service Circular dependency / Nestã§ãĩãŧããšãŽåžĒį°åį
§ã§ã¨ãŠãŧãčĩˇããå ´å
|
||||
|
||||
#### forwardRef
|
||||
ãžãã¯į°ĄåãĢ`forwardRef`ãčŠĻããĻãŋã
|
||||
|
||||
```typescript
|
||||
export class FooService {
|
||||
constructor(
|
||||
@Inject(forwardRef(() => BarService))
|
||||
private barService: BarService
|
||||
) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### OnModuleInit
|
||||
ã§ããĒããã°`OnModuleInit`ãäŊŋã
|
||||
|
||||
```typescript
|
||||
import { Injectable, OnModuleInit } from '@nestjs/common';
|
||||
import { ModuleRef } from '@nestjs/core';
|
||||
import { BarService } from '@/core/BarService';
|
||||
|
||||
@Injectable()
|
||||
export class FooService implements OnModuleInit {
|
||||
private barService: BarService // constructorããį§ģåããĻãã
|
||||
|
||||
constructor(
|
||||
private moduleRef: ModuleRef,
|
||||
) {
|
||||
}
|
||||
|
||||
async onModuleInit() {
|
||||
this.barService = this.moduleRef.get(BarService.name);
|
||||
}
|
||||
|
||||
public async niceMethod() {
|
||||
return await this.barService.incredibleMethod({ hoge: 'fuga' });
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
##### Service Unit Test
|
||||
ããšãã§`onModuleInit`ãåŧãŗåēãåŋ
čĻããã
|
||||
|
||||
```typescript
|
||||
// import ...
|
||||
|
||||
describe('test', () => {
|
||||
let app: TestingModule;
|
||||
let fooService: FooService; // for test case
|
||||
let barService: BarService; // for test case
|
||||
|
||||
beforeEach(async () => {
|
||||
app = await Test.createTestingModule({
|
||||
imports: ...,
|
||||
providers: [
|
||||
FooService,
|
||||
{ // mockãã (mockã¯åŋ
é ã§ã¯ãĒããããããĒã)
|
||||
provide: BarService,
|
||||
useFactory: () => ({
|
||||
incredibleMethod: jest.fn(),
|
||||
}),
|
||||
},
|
||||
{ // ProvideãĢãã
|
||||
provide: BarService.name,
|
||||
useExisting: BarService,
|
||||
},
|
||||
],
|
||||
})
|
||||
.useMocker(...
|
||||
.compile();
|
||||
|
||||
fooService = app.get<FooService>(FooService);
|
||||
barService = app.get<BarService>(BarService) as jest.Mocked<BarService>;
|
||||
|
||||
// onModuleInitãåŽčĄãã
|
||||
await fooService.onModuleInit();
|
||||
});
|
||||
|
||||
test('nice', () => {
|
||||
await fooService.niceMethod();
|
||||
|
||||
expect(barService.incredibleMethod).toHaveBeenCalled();
|
||||
expect(barService.incredibleMethod.mock.lastCall![0])
|
||||
.toEqual({ hoge: 'fuga' });
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
### MisskeyãŽããĄã¤ãŗåēæãŽæĻåŋĩã¯`Mi`ãprefixãã
|
||||
äžãã°GoogleãčĒį¤žãĩãŧããšãMapãEarthãDriveã§ã¯ãĒãGoogle MapãGoogle EarthãGoogle DriveãŽãããĢåŊåãããŽã¨åã
|
||||
ãŗãŧãä¸ã§MisskeyãŽããĄã¤ãŗåēæãŽæĻåŋĩãĢã¯`Mi`ãprefixãããã¨ã§ãäģãŽããĄã¤ãŗãŽåæ§ãŽæĻåŋĩã¨åēåĨã§ãããģããååãŽčĄįĒãé˛ãã
|
||||
ãã ããæčä¸MisskeyãŽããŽãæããã¨ãæããã§ãããååãŽčĄįĒãŽæãããĒãå ´åã¯ã䏿įãĒããŧãĢãĢ夿°ãĢéãŖãĻ`Mi`ãįįĨããĻãããã
|
||||
|
||||
### Misskey.jsãŽåįæ
|
||||
```bash
|
||||
pnpm build-misskey-js-with-types
|
||||
```
|
||||
|
||||
### How to resolve conflictions occurred at pnpm-lock.yaml?
|
||||
|
||||
Just execute `pnpm` to fix it.
|
||||
@@ -581,6 +299,27 @@ pnpm dlx typeorm migration:generate -d ormconfig.js -o <migration name>
|
||||
- įæåžãããĄã¤ãĢãmigrationä¸ãĢį§ģããĻãã ãã
|
||||
- äŊæããããšã¯ãĒããã¯ä¸åŋ
čĻãĒ夿´ãåĢãããé¤åģããĻãã ãã
|
||||
|
||||
### JSON SchemaãŽobjectã§anyOfãäŊŋãã¨ã
|
||||
JSON Schemaã§ãobjectãĢ寞ããĻanyOfãäŊŋãå ´åãanyOfãŽä¸ã§propertiesãåŽįžŠããĒããã¨ã
|
||||
ããĒããŧãˇã§ãŗãåšããĒããããīŧSchemaTypeãããŽãããĢäŊãããĻãããobjectãŽanyOfå
ãŽpropertiesã¯æ¨ãĻãããžãīŧ
|
||||
https://github.com/misskey-dev/misskey/pull/10082
|
||||
|
||||
ãããšãhogeãããŗfugaãĢã¤ããĻãįæšãåŋ
é ã¨ãã¤ã¤ä¸ĄæšãŽæåŽãããããå ´å:
|
||||
|
||||
```
|
||||
export const paramDef = {
|
||||
type: 'object',
|
||||
properties: {
|
||||
hoge: { type: 'string', minLength: 1 },
|
||||
fuga: { type: 'string', minLength: 1 },
|
||||
},
|
||||
anyOf: [
|
||||
{ required: ['hoge'] },
|
||||
{ required: ['fuga'] },
|
||||
],
|
||||
} as const;
|
||||
```
|
||||
|
||||
### ãŗãã¯ãˇã§ãŗãĢã¯`markRaw`ãã
|
||||
**VueãŽãŗãŗããŧããŗããŽdataãĒããˇã§ãŗã¨ããĻ**misskey.jsãŽãŗãã¯ãˇã§ãŗãč¨åŽããã¨ããåŋ
ã`markRaw`ã§ãŠããããĻãã ãããã¤ãŗãšãŋãŗãšãä¸åŋ
čĻãĢãĒãĸã¯ããŖãåããããã¨ã§ãmisskey.jså
ãŽåĻįã§ä¸å
ˇåãįēįããã¨ã¨ããĢããããŠãŧããŗãšä¸ãŽåéĄãĢãįšããããĒããComposition APIãäŊŋãå ´åã¯ããŽéãã§ã¯ãĒã(ãĒãĸã¯ããŖãåã¯ãããĨãĸãĢãĒãã)ã
|
||||
|
||||
@@ -594,47 +333,3 @@ marginã¯ããŽãŗãŗããŧããŗããäŊŋãå´ãč¨åŽãã
|
||||
## ããŽäģ
|
||||
### HTMLãŽã¯ãŠãšåã§ follow ã¨ããåčĒã¯äŊŋããĒã
|
||||
åēåããããĢãŧã§čǤãŖãĻãããã¯ããã
|
||||
|
||||
### indexã¨ããããĄã¤ãĢåãäŊŋããĒ
|
||||
ESMã§ã¯ããŖãŦã¯ããĒã¤ãŗããŧãã¯åģæĸãããĻãããŽã¨ãããŖãŦã¯ããĒã¤ãŗããŧãããã¨ãããĄã¤ãĢåã index ã ã¨äŊæ
ãä¸é¨ãŽãŠã¤ããŠãĒīŧã§ããŖãŦã¯ããĒã¤ãŗããŧãã ã¨čĻåãããĻã¨ãŠãŧãĢãĒã
|
||||
|
||||
## CSS Recipe
|
||||
|
||||
### Lighten CSS vars
|
||||
|
||||
``` css
|
||||
color: hsl(from var(--MI_THEME-accent) h s calc(l + 10));
|
||||
```
|
||||
|
||||
### Darken CSS vars
|
||||
|
||||
``` css
|
||||
color: hsl(from var(--MI_THEME-accent) h s calc(l - 10));
|
||||
```
|
||||
|
||||
### Add alpha to CSS vars
|
||||
|
||||
``` css
|
||||
color: color(from var(--MI_THEME-accent) srgb r g b / 0.5);
|
||||
```
|
||||
|
||||
## čãæš
|
||||
### DRYãĢåããããĒ
|
||||
åŋ
čĻãĒãŽã¯ä¸čŦåã§ã¯ãĒãæŊ蹥åã¨čããžãã
|
||||
į˛äŋĄãããčǤãŖããģä¸åŋ
čĻãĒå
ąéåã¯éŋãããããčĒįļã ã¨æããå ´åã¯éč¤ãããåæ°ãæãĄãžãããã
|
||||
|
||||
### Misskeyãč¤éãĢããĒãåŽčŖ
|
||||
ããããããč¤éã§ããŖãĻããMisskeyåēæãŽãŗãŗãããšãã¨éĸåŋãåéĸãããĻãã(ãããã¯äēåŽä¸åéĸãããĻããã¨čĻåããã¨ãã§ãã)åŽčŖ
ã§ããã°ãããã¯MisskeyãŽãŗãŧãããŧãšãĢ寞ããč¤éæ§ãĢåŊąéŋãä¸ããĒãã¨čããžãã
|
||||
|
||||
äžãããĒããVueãAiScriptã¨ããŖãMisskeyãäŊŋį¨ããĻãããŠã¤ããŠãĒãŽå
é¨åŽčŖ
ããããč¤éã ãŖãã¨ããĻããããããäŊŋį¨ããĻããããMisskeyãŽåŽčŖ
ã¯č¤éã§ãããã¨ãããã¨ãĢã¯ãĒããĒããŽã¨åãã§ãã
|
||||
|
||||
MisskeyãŽããĄã¤ãŗįĨčããéĸåŋãåéĸãããĻããã¨ãããã¨ã¯ãMisskeyãŽåŽčŖ
ãĢã¤ããĻčããæãĢããããŽå
é¨åŽčŖ
ãčæ
Žããåŋ
čĻãįĄããčĒįĨč˛ čˇãåĸãããĒãããã§ãã
|
||||
|
||||
ãžãéčĻãĒįšã¯ãããŽåŽčŖ
ããMisskeyãĒãã¸ããĒãŽå¤é¨ãĢããããģå
é¨ãĢãããã¨ãããã¨ããMisskeyããĄãŗãããŗãšããããŽããģįŦŦä¸č
ããĄãŗãããŗãšããããŽãã¨ããŖããã¨ã¯č¤éæ§ãčããä¸ã§ã¯ãģã¨ããŠįĄčĻã§ããã¨ããįšã§ãã
|
||||
|
||||
ããĄããããŽåŽčŖ
ãMisskeyãĒãã¸ããĒãĢãããMisskeyããĄãŗãããŗãšããĒããã°ãĒããĒãããŽã¯ãäŋåŽãŽãŗãšãã¯ããããžãã
|
||||
ããããMisskeyãŽæŦčŗĒįãĒč¨č¨ãģåŽčŖ
ã¨ããčĻŗįšã§čĻãã¨ãã¯ãããŽåŽčŖ
ã¯åŽčŗĒįãĢå¤é¨ãŠã¤ããŠãĒãŽãããĢæ¯ãčããžãã
|
||||
æč¨ããã°ãããžããžMisskeyãŽéįēč
ã¨åãäēēããĄããĄãŗãããŗãšããĻããããããžããžMisskeyãŽãĒãã¸ããĒå
ãĢįŊŽããĻããã ããŽå¤é¨ãŠã¤ããŠãĒãã§ãã
|
||||
|
||||
ããŽãããåŽčŖ
ããĒããšãMisskeyãŽããĄã¤ãŗįĨčããįŦįĢããããŽãĢããã°ãMisskeyãŽãŗãŧãããŧãšãŽč¤éæ§ãä¸ãããã¨ãĒãæŠčŊåŽčŖ
ãčĄããã¨ãã§ãããåžã§ããã¨č¨ããžãã
|
||||
ããĄãããããĢãã ããŖãĻãäēį´°ãĒåŽčŖ
ã§ãããŽãããĢåéĸããĻããžãã¨ãããŖãĻčĒįĨč˛ čˇãåĸããããåŽčŖ
éãåĸããĻãĄãĒãããããĄãĒãããä¸åãå ´åããããŽã§ããąãŧãšãã¤ãąãŧãšã§ã¯ãããžãã
|
||||
|
||||
2
COPYING
@@ -1,5 +1,5 @@
|
||||
Unless otherwise stated this repository is
|
||||
Copyright Š 2014-2026 syuilo and contributors
|
||||
Copyright Š 2014-2023 syuilo and contributers
|
||||
|
||||
And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE.
|
||||
|
||||
|
||||
49
Dockerfile
@@ -1,6 +1,6 @@
|
||||
# syntax = docker/dockerfile:1.4
|
||||
|
||||
ARG NODE_VERSION=22.15.0-bookworm
|
||||
ARG NODE_VERSION=18.13.0-bullseye
|
||||
|
||||
# build assets & compile TypeScript
|
||||
|
||||
@@ -14,32 +14,24 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
&& apt-get install -yqq --no-install-recommends \
|
||||
build-essential
|
||||
|
||||
RUN corepack enable
|
||||
|
||||
WORKDIR /misskey
|
||||
|
||||
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
|
||||
COPY --link ["scripts", "./scripts"]
|
||||
COPY --link ["patches", "./patches"]
|
||||
COPY --link ["packages/backend/package.json", "./packages/backend/"]
|
||||
COPY --link ["packages/frontend-shared/package.json", "./packages/frontend-shared/"]
|
||||
COPY --link ["packages/frontend/package.json", "./packages/frontend/"]
|
||||
COPY --link ["packages/frontend-embed/package.json", "./packages/frontend-embed/"]
|
||||
COPY --link ["packages/frontend-builder/package.json", "./packages/frontend-builder/"]
|
||||
COPY --link ["packages/i18n/package.json", "./packages/i18n/"]
|
||||
COPY --link ["packages/icons-subsetter/package.json", "./packages/icons-subsetter/"]
|
||||
COPY --link ["packages/sw/package.json", "./packages/sw/"]
|
||||
COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
|
||||
COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"]
|
||||
COPY --link ["packages/misskey-bubble-game/package.json", "./packages/misskey-bubble-game/"]
|
||||
|
||||
ARG NODE_ENV=production
|
||||
|
||||
RUN node -e "console.log(JSON.parse(require('node:fs').readFileSync('./package.json')).packageManager)" | xargs npm install -g
|
||||
|
||||
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
|
||||
pnpm i --frozen-lockfile --aggregate-output
|
||||
|
||||
COPY --link . ./
|
||||
|
||||
ARG NODE_ENV=production
|
||||
|
||||
RUN git submodule update --init
|
||||
RUN pnpm build
|
||||
RUN rm -rf .git/
|
||||
@@ -52,19 +44,13 @@ RUN apt-get update \
|
||||
&& apt-get install -yqq --no-install-recommends \
|
||||
build-essential
|
||||
|
||||
RUN corepack enable
|
||||
|
||||
WORKDIR /misskey
|
||||
|
||||
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
|
||||
COPY --link ["scripts", "./scripts"]
|
||||
COPY --link ["patches", "./patches"]
|
||||
COPY --link ["packages/backend/package.json", "./packages/backend/"]
|
||||
COPY --link ["packages/misskey-js/package.json", "./packages/misskey-js/"]
|
||||
COPY --link ["packages/misskey-reversi/package.json", "./packages/misskey-reversi/"]
|
||||
COPY --link ["packages/misskey-bubble-game/package.json", "./packages/misskey-bubble-game/"]
|
||||
|
||||
ARG NODE_ENV=production
|
||||
|
||||
RUN node -e "console.log(JSON.parse(require('node:fs').readFileSync('./package.json')).packageManager)" | xargs npm install -g
|
||||
|
||||
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
|
||||
pnpm i --frozen-lockfile --aggregate-output
|
||||
@@ -76,38 +62,25 @@ ARG GID="991"
|
||||
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
ffmpeg tini curl libjemalloc-dev libjemalloc2 \
|
||||
&& ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so \
|
||||
ffmpeg tini curl \
|
||||
&& corepack enable \
|
||||
&& groupadd -g "${GID}" misskey \
|
||||
&& useradd -l -u "${UID}" -g "${GID}" -m -d /misskey misskey \
|
||||
&& find / -type d -path /sys -prune -o -type d -path /proc -prune -o -type f -perm /u+s -ignore_readdir_race -exec chmod u-s {} \; \
|
||||
&& find / -type d -path /sys -prune -o -type d -path /proc -prune -o -type f -perm /g+s -ignore_readdir_race -exec chmod g-s {} \; \
|
||||
&& find / -type d -path /proc -prune -o -type f -perm /u+s -ignore_readdir_race -exec chmod u-s {} \; \
|
||||
&& find / -type d -path /proc -prune -o -type f -perm /g+s -ignore_readdir_race -exec chmod g-s {} \; \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists
|
||||
|
||||
# add package.json to add pnpm
|
||||
COPY ./package.json ./package.json
|
||||
RUN node -e "console.log(JSON.parse(require('node:fs').readFileSync('./package.json')).packageManager)" | xargs npm install -g
|
||||
|
||||
USER misskey
|
||||
WORKDIR /misskey
|
||||
|
||||
COPY --chown=misskey:misskey --from=target-builder /misskey/node_modules ./node_modules
|
||||
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/backend/node_modules ./packages/backend/node_modules
|
||||
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-js/node_modules ./packages/misskey-js/node_modules
|
||||
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-reversi/node_modules ./packages/misskey-reversi/node_modules
|
||||
COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-bubble-game/node_modules ./packages/misskey-bubble-game/node_modules
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/built ./built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-js/built ./packages/misskey-js/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-reversi/built ./packages/misskey-reversi/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/misskey-bubble-game/built ./packages/misskey-bubble-game/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/built ./packages/backend/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/src-js ./packages/backend/src-js
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/packages/i18n/built ./packages/i18n/built
|
||||
COPY --chown=misskey:misskey --from=native-builder /misskey/fluent-emojis /misskey/fluent-emojis
|
||||
COPY --chown=misskey:misskey . ./
|
||||
|
||||
ENV LD_PRELOAD=/usr/local/lib/libjemalloc.so
|
||||
ENV NODE_ENV=production
|
||||
HEALTHCHECK --interval=5s --retries=20 CMD ["/bin/bash", "/misskey/healthcheck.sh"]
|
||||
ENTRYPOINT ["/usr/bin/tini", "--"]
|
||||
|
||||
56
README.md
@@ -1,18 +1,16 @@
|
||||
<div align="center">
|
||||
<a href="https://misskey-hub.net">
|
||||
<img src="./assets/title_float.svg" alt="Misskey logo" style="border-radius:50%" width="300"/>
|
||||
<img src="./assets/title_float.svg" alt="Misskey logo" style="border-radius:50%" width="400"/>
|
||||
</a>
|
||||
|
||||
**đ **Misskey** is an open source, federated social media platform that's free forever! đ**
|
||||
|
||||
[Learn more](https://misskey-hub.net/)
|
||||
|
||||
|
||||
**đ **[Misskey](https://misskey-hub.net/)** is an open source, decentralized social media platform that's free forever! đ**
|
||||
|
||||
---
|
||||
|
||||
<a href="https://misskey-hub.net/servers/">
|
||||
<a href="https://misskey-hub.net/instances.html">
|
||||
<img src="https://custom-icon-badges.herokuapp.com/badge/find_an-instance-acea31?logoColor=acea31&style=for-the-badge&logo=misskey&labelColor=363B40" alt="find an instance"/></a>
|
||||
|
||||
<a href="https://misskey-hub.net/docs/for-admin/install/guides/">
|
||||
<a href="https://misskey-hub.net/docs/install.html">
|
||||
<img src="https://custom-icon-badges.herokuapp.com/badge/create_an-instance-FBD53C?logoColor=FBD53C&style=for-the-badge&logo=server&labelColor=363B40" alt="create an instance"/></a>
|
||||
|
||||
<a href="./CONTRIBUTING.md">
|
||||
@@ -23,31 +21,39 @@
|
||||
|
||||
<a href="https://www.patreon.com/syuilo">
|
||||
<img src="https://custom-icon-badges.herokuapp.com/badge/become_a-patron-F96854?logoColor=F96854&style=for-the-badge&logo=patreon&labelColor=363B40" alt="become a patron"/></a>
|
||||
|
||||
---
|
||||
|
||||
[](https://deepwiki.com/misskey-dev/misskey)
|
||||
|
||||
<a href="https://flatt.tech/oss/gmo/trampoline" target="_blank"><img src="https://flatt.tech/assets/images/badges/gmo-oss.svg" height="24px"/></a>
|
||||
[](https://codecov.io/gh/misskey-dev/misskey)
|
||||
|
||||
</div>
|
||||
|
||||
## Thanks
|
||||
<div>
|
||||
|
||||
<a href="https://sentry.io/"><img src="https://github.com/misskey-dev/misskey/assets/4439005/98576556-222f-467a-94be-e98dbda1d852" height="30" alt="Sentry" /></a>
|
||||
<a href="https://xn--931a.moe/"><img src="https://github.com/misskey-dev/misskey/blob/develop/assets/ai.png?raw=true" align="right" height="320px"/></a>
|
||||
|
||||
Thanks to [Sentry](https://sentry.io/) for providing the error tracking platform that helps us catch unexpected errors.
|
||||
## ⨠Features
|
||||
- **ActivityPub support**\
|
||||
Not on Misskey? No problem! Not only can Misskey instances talk to each other, but you can make friends with people on other networks like Mastodon and Pixelfed!
|
||||
- **Reactions**\
|
||||
You can add emoji reactions to any post! No longer are you bound by a like button, show everyone exactly how you feel with the tap of a button.
|
||||
- **Drive**\
|
||||
With Misskey's built in drive, you get cloud storage right in your social media, where you can upload any files, make folders, and find media from posts you've made!
|
||||
- **Rich Web UI**\
|
||||
Misskey has a rich and easy to use Web UI!
|
||||
It is highly customizable, from changing the layout and adding widgets to making custom themes.
|
||||
Furthermore, plugins can be created using AiScript, an original programming language.
|
||||
- And much more...
|
||||
|
||||
<a href="https://www.chromatic.com/"><img src="https://user-images.githubusercontent.com/321738/84662277-e3db4f80-af1b-11ea-88f5-91d67a5e59f6.png" height="30" alt="Chromatic" /></a>
|
||||
</div>
|
||||
|
||||
Thanks to [Chromatic](https://www.chromatic.com/) for providing the visual testing platform that helps us review UI changes and catch visual regressions.
|
||||
<div style="clear: both;"></div>
|
||||
|
||||
<a href="https://about.codecov.io/for/open-source/"><img src="https://about.codecov.io/wp-content/themes/codecov/assets/brand/sentry-cobranding/logos/codecov-by-sentry-logo.svg" height="30" alt="Codecov" /></a>
|
||||
## Documentation
|
||||
|
||||
Thanks to [Codecov](https://about.codecov.io/for/open-source/) for providing the code coverage platform that helps us improve our test coverage.
|
||||
Misskey Documentation can be found at [Misskey Hub](https://misskey-hub.net/), some of the links and graphics above also lead to specific portions of it.
|
||||
|
||||
<a href="https://crowdin.com/"><img src="https://user-images.githubusercontent.com/20679825/230709597-1299a011-171a-4294-a91e-355a9b37c672.svg" height="30" alt="Crowdin" /></a>
|
||||
|
||||
Thanks to [Crowdin](https://crowdin.com/) for providing the localization platform that helps us translate Misskey into many languages.
|
||||
|
||||
<a href="https://hub.docker.com/"><img src="https://user-images.githubusercontent.com/20679825/230148221-f8e73a32-a49b-47c3-9029-9a15c3824f92.png" height="30" alt="Docker" /></a>
|
||||
|
||||
Thanks to [Docker](https://hub.docker.com/) for providing the container platform that helps us run Misskey in production.
|
||||
## Sponsors
|
||||
<div align="center">
|
||||
<a class="rss3" title="RSS3" href="https://rss3.io/" target="_blank"><img src="https://rss3.mypinata.cloud/ipfs/QmUG6H3Z7D5P511shn7sB4CPmpjH5uZWu4m5mWX7U3Gqbu" alt="RSS3" height="60"></a>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,6 @@ Also, the later tasks are more indefinite and are subject to change as developme
|
||||
This is the phase we are at now. We need to make a high-maintenance environment that can withstand future development.
|
||||
|
||||
- ~~Make the number of type errors zero (backend)~~ â Done âī¸
|
||||
- ~~Make the number of type errors zero (frontend)~~ â Done âī¸
|
||||
- Improve CI
|
||||
- ~~Fix tests~~ â Done âī¸
|
||||
- Fix random test failures - https://github.com/misskey-dev/misskey/issues/7985 and https://github.com/misskey-dev/misskey/issues/7986
|
||||
@@ -23,7 +22,7 @@ This is the phase we are at now. We need to make a high-maintenance environment
|
||||
Once Phase 1 is complete and an environment conducive to the development of a stable system is in place, the implementation of new functions can begin gradually.
|
||||
|
||||
- Improve features for moderation
|
||||
- ~~OAuth2 support https://github.com/misskey-dev/misskey/issues/8262~~ â Done âī¸
|
||||
- OAuth2 support https://github.com/misskey-dev/misskey/issues/8262
|
||||
- GraphQL support?
|
||||
|
||||
## (3) Improve scalability
|
||||
|
||||
15
SECURITY.md
@@ -1,20 +1,9 @@
|
||||
# Reporting Security Issues
|
||||
|
||||
If you discover a security issue in Misskey, please report it by **[this form](https://github.com/misskey-dev/misskey/security/advisories/new)**.
|
||||
If you discover a security issue in Misskey, please report it by sending an
|
||||
email to [syuilotan@yahoo.co.jp](mailto:syuilotan@yahoo.co.jp).
|
||||
|
||||
This will allow us to assess the risk, and make a fix available before we add a
|
||||
bug report to the GitHub repository.
|
||||
|
||||
Thanks for helping make Misskey safe for everyone.
|
||||
|
||||
> [!note]
|
||||
> CNA [requires](https://www.cve.org/ResourcesSupport/AllResources/CNARules#section_5-2_Description) that CVEs include a description in English for inclusion in the CVE Catalog.
|
||||
>
|
||||
> When creating a security advisory, all content must be written in English (it is acceptable to include a non-English description along with the English one).
|
||||
|
||||
## When create a patch
|
||||
|
||||
If you can also create a patch to fix the vulnerability, please create a PR on the private fork.
|
||||
|
||||
> [!note]
|
||||
> There is a GitHub bug that prevents merging if a PR not following the develop branch of upstream, so please keep follow the develop branch.
|
||||
|
||||
BIN
assets/about/drive.png
Normal file
|
After Width: | Height: | Size: 94 KiB |
BIN
assets/about/post.png
Normal file
|
After Width: | Height: | Size: 317 KiB |
BIN
assets/about/reaction.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
assets/about/ui.png
Normal file
|
After Width: | Height: | Size: 95 KiB |
BIN
assets/ss/explore.jpg
Normal file
|
After Width: | Height: | Size: 238 KiB |
BIN
assets/ss/user.jpg
Normal file
|
After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 6.1 KiB After Width: | Height: | Size: 6.1 KiB |
@@ -72,75 +72,25 @@ db:
|
||||
#extra:
|
||||
# ssl: true
|
||||
|
||||
dbReplications: false
|
||||
|
||||
# You can configure any number of replicas here
|
||||
#dbSlaves:
|
||||
# -
|
||||
# host:
|
||||
# port:
|
||||
# db:
|
||||
# user:
|
||||
# pass:
|
||||
# -
|
||||
# host:
|
||||
# port:
|
||||
# db:
|
||||
# user:
|
||||
# pass:
|
||||
|
||||
# âââââââââââââââââââââââ
|
||||
#ââââ Redis configuration ââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
#family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
#pass: example-pass
|
||||
#prefix: example-prefix
|
||||
#db: 1
|
||||
|
||||
#redisForPubsub:
|
||||
# âââââââââââââââââââââââââââââââ
|
||||
#ââââ Elasticsearch configuration ââââââââââââââââââââââââââââââ
|
||||
|
||||
#elasticsearch:
|
||||
# host: localhost
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForJobQueue:
|
||||
# host: localhost
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForTimelines:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
#redisForReactions:
|
||||
# host: redis
|
||||
# port: 6379
|
||||
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6
|
||||
# #pass: example-pass
|
||||
# #prefix: example-prefix
|
||||
# #db: 1
|
||||
|
||||
# âââââââââââââââââââââââââââââ
|
||||
#ââââ MeiliSearch configuration ââââââââââââââââââââââââââââââ
|
||||
|
||||
#meilisearch:
|
||||
# host: localhost
|
||||
# port: 7700
|
||||
# apiKey: ''
|
||||
# ssl: true
|
||||
# index: ''
|
||||
# port: 9200
|
||||
# ssl: false
|
||||
# user:
|
||||
# pass:
|
||||
|
||||
# âââââââââââââââââ
|
||||
#ââââ ID generation ââââââââââââââââââââââââââââââââââââââââââââ
|
||||
@@ -151,7 +101,6 @@ redis:
|
||||
|
||||
# Available methods:
|
||||
# aid ... Short, Millisecond accuracy
|
||||
# aidx ... Millisecond accuracy
|
||||
# meid ... Similar to ObjectID, Millisecond accuracy
|
||||
# ulid ... Millisecond accuracy
|
||||
# objectid ... This is left for backward compatibility
|
||||
@@ -159,28 +108,7 @@ redis:
|
||||
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
|
||||
# ID SETTINGS AFTER THAT!
|
||||
|
||||
id: "aidx"
|
||||
|
||||
# ââââââââââââââââââ
|
||||
#ââââ Error tracking âââââââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
# Sentry is available for error tracking.
|
||||
# See the Sentry documentation for more details on options.
|
||||
|
||||
#sentryForBackend:
|
||||
# enableNodeProfiling: true
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
#sentryForFrontend:
|
||||
# vueIntegration:
|
||||
# tracingOptions:
|
||||
# trackComponents: true
|
||||
# browserTracingIntegration:
|
||||
# replayIntegration:
|
||||
# options:
|
||||
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
|
||||
|
||||
id: "aid"
|
||||
# âââââââââââââââââââââââ
|
||||
#ââââ Other configuration ââââââââââââââââââââââââââââââââââââââ
|
||||
|
||||
@@ -196,7 +124,7 @@ id: "aidx"
|
||||
|
||||
# Job rate limiter
|
||||
# deliverJobPerSec: 128
|
||||
# inboxJobPerSec: 32
|
||||
# inboxJobPerSec: 16
|
||||
|
||||
# Job attempts
|
||||
# deliverJobMaxAttempts: 12
|
||||
@@ -221,6 +149,9 @@ id: "aidx"
|
||||
# Media Proxy
|
||||
#mediaProxy: https://example.com/proxy
|
||||
|
||||
# Sign to ActivityPub GET request (default: true)
|
||||
signToActivityPubGet: true
|
||||
|
||||
#allowedPrivateNetworks: [
|
||||
# '127.0.0.1/32'
|
||||
#]
|
||||
|
||||
@@ -27,7 +27,7 @@ spec:
|
||||
ports:
|
||||
- containerPort: 3000
|
||||
- name: postgres
|
||||
image: postgres:18-alpine
|
||||
image: postgres:14-alpine
|
||||
env:
|
||||
- name: POSTGRES_USER
|
||||
value: "example-misskey-user"
|
||||
@@ -38,7 +38,7 @@ spec:
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
- name: redis
|
||||
image: redis:7-alpine
|
||||
image: redis:alpine
|
||||
ports:
|
||||
- containerPort: 6379
|
||||
volumes:
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
# ããŽconfigã¯ã dockerã§MisskeyæŦäŊãčĩˇåããã redisã¨postgresql ãĒãŠã ããčĩˇåããžã
|
||||
|
||||
services:
|
||||
redis:
|
||||
restart: always
|
||||
image: redis:7-alpine
|
||||
ports:
|
||||
- "6379:6379"
|
||||
volumes:
|
||||
- ./redis:/data
|
||||
healthcheck:
|
||||
test: "redis-cli ping"
|
||||
interval: 5s
|
||||
retries: 20
|
||||
|
||||
db:
|
||||
restart: always
|
||||
image: postgres:18-alpine
|
||||
ports:
|
||||
- "5432:5432"
|
||||
env_file:
|
||||
- .config/docker.env
|
||||
volumes:
|
||||
- ./db:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
||||
interval: 5s
|
||||
retries: 20
|
||||
|
||||
# meilisearch:
|
||||
# restart: always
|
||||
# image: getmeili/meilisearch:v1.3.4
|
||||
# environment:
|
||||
# - MEILI_NO_ANALYTICS=true
|
||||
# - MEILI_ENV=production
|
||||
# env_file:
|
||||
# - .config/meilisearch.env
|
||||
# volumes:
|
||||
# - ./meili_data:/meili_data
|
||||
|
||||
@@ -1,98 +0,0 @@
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
restart: always
|
||||
links:
|
||||
- db
|
||||
- redis
|
||||
# - mcaptcha
|
||||
# - meilisearch
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "3000:3000"
|
||||
networks:
|
||||
- internal_network
|
||||
- external_network
|
||||
# env_file:
|
||||
# - .config/docker.env
|
||||
volumes:
|
||||
- ./files:/misskey/files
|
||||
- ./.config:/misskey/.config:ro
|
||||
|
||||
redis:
|
||||
restart: always
|
||||
image: redis:7-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
volumes:
|
||||
- ./redis:/data
|
||||
healthcheck:
|
||||
test: "redis-cli ping"
|
||||
interval: 5s
|
||||
retries: 20
|
||||
|
||||
db:
|
||||
restart: always
|
||||
image: postgres:18-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
env_file:
|
||||
- .config/docker.env
|
||||
volumes:
|
||||
- ./db:/var/lib/postgresql
|
||||
healthcheck:
|
||||
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
||||
interval: 5s
|
||||
retries: 20
|
||||
|
||||
# mcaptcha:
|
||||
# restart: always
|
||||
# image: mcaptcha/mcaptcha:latest
|
||||
# networks:
|
||||
# internal_network:
|
||||
# external_network:
|
||||
# aliases:
|
||||
# - localhost
|
||||
# ports:
|
||||
# - 7493:7493
|
||||
# env_file:
|
||||
# - .config/docker.env
|
||||
# environment:
|
||||
# PORT: 7493
|
||||
# MCAPTCHA_redis_URL: "redis://mcaptcha_redis/"
|
||||
# depends_on:
|
||||
# db:
|
||||
# condition: service_healthy
|
||||
# mcaptcha_redis:
|
||||
# condition: service_healthy
|
||||
#
|
||||
# mcaptcha_redis:
|
||||
# image: mcaptcha/cache:latest
|
||||
# networks:
|
||||
# - internal_network
|
||||
# healthcheck:
|
||||
# test: "redis-cli ping"
|
||||
# interval: 5s
|
||||
# retries: 20
|
||||
|
||||
# meilisearch:
|
||||
# restart: always
|
||||
# image: getmeili/meilisearch:v1.3.4
|
||||
# environment:
|
||||
# - MEILI_NO_ANALYTICS=true
|
||||
# - MEILI_ENV=production
|
||||
# env_file:
|
||||
# - .config/meilisearch.env
|
||||
# networks:
|
||||
# - internal_network
|
||||
# volumes:
|
||||
# - ./meili_data:/meili_data
|
||||
|
||||
networks:
|
||||
internal_network:
|
||||
internal: true
|
||||
external_network:
|
||||
@@ -2,6 +2,11 @@ import { defineConfig } from 'cypress'
|
||||
|
||||
export default defineConfig({
|
||||
e2e: {
|
||||
// We've imported your old cypress plugins here.
|
||||
// You may want to clean this up later by importing these.
|
||||
setupNodeEvents(on, config) {
|
||||
return require('./cypress/plugins/index.js')(on, config)
|
||||
},
|
||||
baseUrl: 'http://localhost:61812',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
describe('Before setup instance', () => {
|
||||
beforeEach(() => {
|
||||
cy.resetState();
|
||||
@@ -23,7 +18,6 @@ describe('Before setup instance', () => {
|
||||
|
||||
cy.intercept('POST', '/api/admin/accounts/create').as('signup');
|
||||
|
||||
cy.get('[data-cy-admin-initial-password] input').type('example_password_please_change_this_or_you_will_get_hacked');
|
||||
cy.get('[data-cy-admin-username] input').type('admin');
|
||||
cy.get('[data-cy-admin-password] input').type('admin1234');
|
||||
cy.get('[data-cy-admin-ok]').click();
|
||||
@@ -31,14 +25,6 @@ describe('Before setup instance', () => {
|
||||
// ãĒããåããĒã
|
||||
//cy.wait('@signup').should('have.property', 'response.statusCode');
|
||||
cy.wait('@signup');
|
||||
|
||||
cy.intercept('POST', '/api/admin/update-meta').as('update-meta');
|
||||
|
||||
cy.get('[data-cy-next]').click();
|
||||
cy.get('[data-cy-server-name] input').type('Testskey');
|
||||
cy.get('[data-cy-server-setup-wizard-apply]').click();
|
||||
|
||||
cy.wait('@update-meta');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -66,20 +52,12 @@ describe('After setup instance', () => {
|
||||
cy.intercept('POST', '/api/signup').as('signup');
|
||||
|
||||
cy.get('[data-cy-signup]').click();
|
||||
cy.get('[data-cy-signup-rules-continue]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-rules-notes-agree] [data-cy-switch-toggle]').click();
|
||||
cy.get('[data-cy-modal-dialog-ok]').click();
|
||||
cy.get('[data-cy-signup-rules-continue]').should('not.be.disabled');
|
||||
cy.get('[data-cy-signup-rules-continue]').click();
|
||||
|
||||
cy.get('[data-cy-signup-submit]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-username] input').type('alice');
|
||||
cy.get('[data-cy-signup-submit]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-password] input').type('alice1234');
|
||||
cy.get('[data-cy-signup-submit]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-password-retype] input').type('alice1234');
|
||||
cy.get('[data-cy-signup-submit]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-invitation-code] input').type('test-invitation-code');
|
||||
cy.get('[data-cy-signup-submit]').should('not.be.disabled');
|
||||
cy.get('[data-cy-signup-submit]').click();
|
||||
|
||||
@@ -93,12 +71,6 @@ describe('After setup instance', () => {
|
||||
|
||||
// ãĻãŧãļãŧåãéč¤ããĻããå ´åãŽæåįĸēčĒ
|
||||
cy.get('[data-cy-signup]').click();
|
||||
cy.get('[data-cy-signup-rules-continue]').should('be.disabled');
|
||||
cy.get('[data-cy-signup-rules-notes-agree] [data-cy-switch-toggle]').click();
|
||||
cy.get('[data-cy-modal-dialog-ok]').click();
|
||||
cy.get('[data-cy-signup-rules-continue]').should('not.be.disabled');
|
||||
cy.get('[data-cy-signup-rules-continue]').click();
|
||||
|
||||
cy.get('[data-cy-signup-username] input').type('alice');
|
||||
cy.get('[data-cy-signup-password] input').type('alice1234');
|
||||
cy.get('[data-cy-signup-password-retype] input').type('alice1234');
|
||||
@@ -130,16 +102,11 @@ describe('After user signup', () => {
|
||||
it('signin', () => {
|
||||
cy.visitHome();
|
||||
|
||||
cy.intercept('POST', '/api/signin-flow').as('signin');
|
||||
cy.intercept('POST', '/api/signin').as('signin');
|
||||
|
||||
cy.get('[data-cy-signin]').click();
|
||||
|
||||
cy.get('[data-cy-signin-page-input]').should('be.visible', { timeout: 1000 });
|
||||
// Enterããŧã§įļčĄã§ããããŽįĸēčĒãå
ŧãã
|
||||
cy.get('[data-cy-signin-username] input').type('alice{enter}');
|
||||
|
||||
cy.get('[data-cy-signin-page-password]').should('be.visible', { timeout: 10000 });
|
||||
// Enterããŧã§įļčĄã§ããããŽįĸēčĒãå
ŧãã
|
||||
cy.get('[data-cy-signin-username] input').type('alice');
|
||||
// Enterããŧã§ãĩã¤ãŗã¤ãŗã§ããããŽįĸēčĒãå
ŧãã
|
||||
cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
|
||||
|
||||
cy.wait('@signin');
|
||||
@@ -154,9 +121,8 @@ describe('After user signup', () => {
|
||||
cy.visitHome();
|
||||
|
||||
cy.get('[data-cy-signin]').click();
|
||||
|
||||
cy.get('[data-cy-signin-page-input]').should('be.visible', { timeout: 1000 });
|
||||
cy.get('[data-cy-signin-username] input').type('alice{enter}');
|
||||
cy.get('[data-cy-signin-username] input').type('alice');
|
||||
cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
|
||||
|
||||
// TODO: cypressãĢããŠãĻãļãŽč¨čĒæåŽã§ããæŠčŊãåŽčŖ
ããæŦĄįŦŦčąčĒãŽãŋããšããããããĢãã
|
||||
cy.contains(/ãĸãĢãĻãŗããåįĩãããĻããžã|This account has been suspended due to/gi);
|
||||
@@ -183,67 +149,15 @@ describe('After user signed in', () => {
|
||||
});
|
||||
|
||||
it('successfully loads', () => {
|
||||
// 襨į¤ēãĢæéãããããŽã§ãããŠãĢãį§æ°ã ã¨ãŋã¤ã ãĸãĻããã
|
||||
cy.get('[data-cy-user-setup-continue]', { timeout: 30000 }).should('be.visible');
|
||||
cy.get('[data-cy-open-post-form]').should('be.visible');
|
||||
});
|
||||
|
||||
it('account setup wizard', () => {
|
||||
// 襨į¤ēãĢæéãããããŽã§ãããŠãĢãį§æ°ã ã¨ãŋã¤ã ãĸãĻããã
|
||||
cy.get('[data-cy-user-setup-continue]', { timeout: 30000 }).click();
|
||||
|
||||
cy.get('[data-cy-user-setup-user-name] input').type('ããã');
|
||||
cy.get('[data-cy-user-setup-user-description] textarea').type('ãģã');
|
||||
// TODO: ãĸã¤ãŗãŗč¨åŽããšã
|
||||
|
||||
cy.get('[data-cy-user-setup-continue]').click();
|
||||
|
||||
// ããŠã¤ããˇãŧč¨åŽ
|
||||
|
||||
cy.get('[data-cy-user-setup-continue]').click();
|
||||
|
||||
// ããŠããŧã¯ãšããã
|
||||
|
||||
cy.get('[data-cy-user-setup-continue]').click();
|
||||
|
||||
// ãããˇãĨéįĨč¨åŽã¯ãšããã
|
||||
|
||||
cy.get('[data-cy-user-setup-continue]').click();
|
||||
|
||||
cy.get('[data-cy-user-setup-continue]').click();
|
||||
});
|
||||
});
|
||||
|
||||
describe('After user setup', () => {
|
||||
beforeEach(() => {
|
||||
cy.resetState();
|
||||
|
||||
// ã¤ãŗãšãŋãŗãšåæãģãããĸãã
|
||||
cy.registerUser('admin', 'pass', true);
|
||||
|
||||
// ãĻãŧãļãŧäŊæ
|
||||
cy.registerUser('alice', 'alice1234');
|
||||
|
||||
cy.login('alice', 'alice1234');
|
||||
|
||||
// ãĸãĢãĻãŗãåæč¨åŽãĻãŖãļãŧã
|
||||
// 襨į¤ēãĢæéãããããŽã§ãããŠãĢãį§æ°ã ã¨ãŋã¤ã ãĸãĻããã
|
||||
cy.get('[data-cy-user-setup] [data-cy-modal-window-close]', { timeout: 30000 }).click();
|
||||
cy.get('[data-cy-modal-dialog-ok]').click();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
// ããšãįĩäēį´åãĢããŧã¸éˇį§ģãããããĒããšããąãŧãš(äžãã°ãĸãĢãĻãŗãäŊæ)ã ã¨ãããļãCypressãŽãã°ã§ããŠãĻãļãŽå
厚ãæŦĄãŽããšããąãŧãšãĢåŧãįļãããĻããžã(äžãã°ãĸãĢãĻãŗããäŊæãįĩããŖãæŽĩéããããšããå§ãžã)ã
|
||||
// waitãå
Ĩãããã¨ã§ããã鞿ĸã§ãã
|
||||
cy.wait(1000);
|
||||
});
|
||||
|
||||
it('note', () => {
|
||||
cy.get('[data-cy-open-post-form]').should('be.visible');
|
||||
cy.get('[data-cy-open-post-form]').click();
|
||||
cy.get('[data-cy-post-form-text]').type('Hello, Misskey!');
|
||||
cy.get('[data-cy-open-post-form-submit]').click();
|
||||
|
||||
cy.contains('Hello, Misskey!', { timeout: 15000 });
|
||||
cy.contains('Hello, Misskey!');
|
||||
});
|
||||
|
||||
it('open note form with hotkey', () => {
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
describe('Router transition', () => {
|
||||
describe('Redirect', () => {
|
||||
// ãĩãŧããŽåæåããĢãŧããŽããšããĢéĸããĻã¯ådescribeãã¨ãĢ1åēĻã ãåŽčĄã§ååã ã¨æãīŧäŊŋããžãããæšãæŠãīŧ
|
||||
before(() => {
|
||||
cy.resetState();
|
||||
|
||||
// ã¤ãŗãšãŋãŗãšåæãģãããĸãã
|
||||
cy.registerUser('admin', 'pass', true);
|
||||
|
||||
// ãĻãŧãļãŧäŊæ
|
||||
cy.registerUser('alice', 'alice1234');
|
||||
|
||||
cy.login('alice', 'alice1234');
|
||||
|
||||
// ãĸãĢãĻãŗãåæč¨åŽãĻãŖãļãŧã
|
||||
// 襨į¤ēãĢæéãããããŽã§ãããŠãĢãį§æ°ã ã¨ãŋã¤ã ãĸãĻããã
|
||||
cy.get('[data-cy-user-setup] [data-cy-modal-window-close]', { timeout: 30000 }).click();
|
||||
cy.wait(500);
|
||||
cy.get('[data-cy-modal-dialog-ok]').click();
|
||||
});
|
||||
|
||||
it('redirect to user profile', () => {
|
||||
// ããšããŽããã ããĢ፿ããããĒãã¤ãŦã¯ãį¨ãĢãŧããĢéŖãļ
|
||||
cy.visit('/redirect-test');
|
||||
|
||||
// ããããŖãŧãĢããŧã¸ãŽURLã§ãããã¨ãįĸēčĒãã
|
||||
cy.url().should('include', '/@alice')
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,9 +1,3 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
/* flaky
|
||||
describe('After user signed in', () => {
|
||||
beforeEach(() => {
|
||||
cy.resetState();
|
||||
@@ -16,10 +10,6 @@ describe('After user signed in', () => {
|
||||
cy.registerUser('alice', 'alice1234');
|
||||
|
||||
cy.login('alice', 'alice1234');
|
||||
|
||||
// ãĸãĢãĻãŗãåæč¨åŽãĻãŖãļãŧã
|
||||
cy.get('[data-cy-user-setup] [data-cy-modal-window-close]').click();
|
||||
cy.get('[data-cy-modal-dialog-ok]').click();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -29,26 +19,26 @@ describe('After user signed in', () => {
|
||||
});
|
||||
|
||||
it('widget edit toggle is visible', () => {
|
||||
cy.get('[data-cy-widget-edit]').should('be.visible');
|
||||
cy.get('.mk-widget-edit').should('be.visible');
|
||||
});
|
||||
|
||||
it('widget select should be visible in edit mode', () => {
|
||||
cy.get('[data-cy-widget-edit]').click();
|
||||
cy.get('[data-cy-widget-select]').should('be.visible');
|
||||
cy.get('.mk-widget-edit').click();
|
||||
cy.get('.mk-widget-select').should('be.visible');
|
||||
});
|
||||
|
||||
it('first widget should be removed', () => {
|
||||
cy.get('[data-cy-widget-edit]').click();
|
||||
cy.get('.mk-widget-edit').click();
|
||||
cy.get('[data-cy-customize-container]:first-child [data-cy-customize-container-remove]._button').click();
|
||||
cy.get('[data-cy-customize-container]').should('have.length', 2);
|
||||
});
|
||||
|
||||
function buildWidgetTest(widgetName) {
|
||||
it(`${widgetName} widget should get added`, () => {
|
||||
cy.get('[data-cy-widget-edit]').click();
|
||||
cy.get('[data-cy-widget-select] select').select(widgetName, { force: true });
|
||||
cy.get('.mk-widget-edit').click();
|
||||
cy.get('.mk-widget-select select').select(widgetName, { force: true });
|
||||
cy.get('[data-cy-bg]._modalBg[data-cy-transparent]').click({ multiple: true, force: true });
|
||||
cy.get('[data-cy-widget-add]').click({ force: true });
|
||||
cy.get('.mk-widget-add').click({ force: true });
|
||||
cy.get(`[data-cy-mkw-${widgetName}]`).should('exist');
|
||||
});
|
||||
}
|
||||
@@ -73,4 +63,3 @@ describe('After user signed in', () => {
|
||||
buildWidgetTest('aiscript');
|
||||
buildWidgetTest('aichan');
|
||||
});
|
||||
*/
|
||||
22
cypress/plugins/index.js
Normal file
@@ -0,0 +1,22 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
module.exports = (on, config) => {
|
||||
// `on` is used to hook into various events Cypress emits
|
||||
// `config` is the resolved Cypress config
|
||||
}
|
||||
@@ -30,13 +30,9 @@ Cypress.Commands.add('visitHome', () => {
|
||||
})
|
||||
|
||||
Cypress.Commands.add('resetState', () => {
|
||||
// iframe.contentWindow.indexedDB.deleteDatabase() ãchromeãŽãã°ã§äŊŋį¨ã§ããĒããããindexedDBãįĄåšåããĻããã
|
||||
// see https://github.com/misskey-dev/misskey/issues/13605#issuecomment-2053652123
|
||||
/*
|
||||
cy.window().then(win => {
|
||||
cy.window(win => {
|
||||
win.indexedDB.deleteDatabase('keyval-store');
|
||||
});
|
||||
*/
|
||||
cy.request('POST', '/api/reset-db', {}).as('reset');
|
||||
cy.get('@reset').its('status').should('equal', 204);
|
||||
cy.reload(true);
|
||||
@@ -48,19 +44,16 @@ Cypress.Commands.add('registerUser', (username, password, isAdmin = false) => {
|
||||
cy.request('POST', route, {
|
||||
username: username,
|
||||
password: password,
|
||||
...(isAdmin ? { setupPassword: 'example_password_please_change_this_or_you_will_get_hacked' } : {}),
|
||||
}).its('body').as(username);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('login', (username, password) => {
|
||||
cy.visitHome();
|
||||
|
||||
cy.intercept('POST', '/api/signin-flow').as('signin');
|
||||
cy.intercept('POST', '/api/signin').as('signin');
|
||||
|
||||
cy.get('[data-cy-signin]').click();
|
||||
cy.get('[data-cy-signin-page-input]').should('be.visible', { timeout: 1000 });
|
||||
cy.get('[data-cy-signin-username] input').type(`${username}{enter}`);
|
||||
cy.get('[data-cy-signin-page-password]').should('be.visible', { timeout: 10000 });
|
||||
cy.get('[data-cy-signin-username] input').type(username);
|
||||
cy.get('[data-cy-signin-password] input').type(`${password}{enter}`);
|
||||
|
||||
cy.wait('@signin').as('signedIn');
|
||||
@@ -21,8 +21,6 @@ import './commands'
|
||||
|
||||
Cypress.on('uncaught:exception', (err, runnable) => {
|
||||
if ([
|
||||
'The source image cannot be decoded',
|
||||
|
||||
// Chrome
|
||||
'ResizeObserver loop limit exceeded',
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
declare global {
|
||||
namespace Cypress {
|
||||
interface Chainable {
|
||||
login(username: string, password: string): Chainable<void>;
|
||||
|
||||
registerUser(
|
||||
username: string,
|
||||
password: string,
|
||||
isAdmin?: boolean
|
||||
): Chainable<void>;
|
||||
|
||||
resetState(): Chainable<void>;
|
||||
|
||||
visitHome(): Chainable<void>;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export {}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["dom", "es5"],
|
||||
"target": "es5",
|
||||
"types": ["cypress", "node"]
|
||||
},
|
||||
"include": ["./**/*.ts"]
|
||||
}
|
||||
65
docker-compose.yml.example
Normal file
@@ -0,0 +1,65 @@
|
||||
version: "3"
|
||||
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
restart: always
|
||||
links:
|
||||
- db
|
||||
- redis
|
||||
# - es
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
redis:
|
||||
condition: service_healthy
|
||||
ports:
|
||||
- "3000:3000"
|
||||
networks:
|
||||
- internal_network
|
||||
- external_network
|
||||
volumes:
|
||||
- ./files:/misskey/files
|
||||
- ./.config:/misskey/.config:ro
|
||||
|
||||
redis:
|
||||
restart: always
|
||||
image: redis:7-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
volumes:
|
||||
- ./redis:/data
|
||||
healthcheck:
|
||||
test: "redis-cli ping"
|
||||
interval: 5s
|
||||
retries: 20
|
||||
|
||||
db:
|
||||
restart: always
|
||||
image: postgres:15-alpine
|
||||
networks:
|
||||
- internal_network
|
||||
env_file:
|
||||
- .config/docker.env
|
||||
volumes:
|
||||
- ./db:/var/lib/postgresql/data
|
||||
healthcheck:
|
||||
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
|
||||
interval: 5s
|
||||
retries: 20
|
||||
|
||||
# es:
|
||||
# restart: always
|
||||
# image: docker.elastic.co/elasticsearch/elasticsearch-oss:6.4.2
|
||||
# environment:
|
||||
# - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
|
||||
# - "TAKE_FILE_OWNERSHIP=111"
|
||||
# networks:
|
||||
# - internal_network
|
||||
# volumes:
|
||||
# - ./elasticsearch:/usr/share/elasticsearch/data
|
||||
|
||||
networks:
|
||||
internal_network:
|
||||
internal: true
|
||||
external_network:
|
||||
25
docs/DONATORS.md
Normal file
@@ -0,0 +1,25 @@
|
||||
DONATORS
|
||||
========
|
||||
The list of people who have sent donation for Misskey.
|
||||
|
||||
(In random order, honorific titles are omitted.)
|
||||
|
||||
* ããĩã
|
||||
* äŋēæ§
|
||||
* ãĒããã
|
||||
* ãšãĢãĄ https://surume.tk/
|
||||
* č
|
||||
* éŗčš https://otofune.me/
|
||||
* aqz https://misskey.xyz/aqz
|
||||
* kotodu "čįĄåĩäŊä¸"
|
||||
* Maya Minatsuki
|
||||
* Knzk https://knzk.me/@Knzk
|
||||
* ããããããŗ https://knzk.me/@y
|
||||
* NCLS https://knzk.me/@imncls]
|
||||
* ãããž @skoji@sandbox.skoji.jp
|
||||
|
||||
:heart: Thanks for donating, guys!
|
||||
|
||||
---
|
||||
|
||||
If your name is missing, please contact us!
|
||||
65
gulpfile.js
Normal file
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Gulp tasks
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
const gulp = require('gulp');
|
||||
const replace = require('gulp-replace');
|
||||
const terser = require('gulp-terser');
|
||||
const cssnano = require('gulp-cssnano');
|
||||
|
||||
const locales = require('./locales');
|
||||
const meta = require('./package.json');
|
||||
|
||||
gulp.task('copy:backend:views', () =>
|
||||
gulp.src('./packages/backend/src/server/web/views/**/*').pipe(gulp.dest('./packages/backend/built/server/web/views'))
|
||||
);
|
||||
|
||||
gulp.task('copy:frontend:fonts', () =>
|
||||
gulp.src('./packages/frontend/node_modules/three/examples/fonts/**/*').pipe(gulp.dest('./built/_frontend_dist_/fonts/'))
|
||||
);
|
||||
|
||||
gulp.task('copy:frontend:tabler-icons', () =>
|
||||
gulp.src('./packages/frontend/node_modules/@tabler/icons-webfont/**/*').pipe(gulp.dest('./built/_frontend_dist_/tabler-icons/'))
|
||||
);
|
||||
|
||||
gulp.task('copy:frontend:locales', cb => {
|
||||
fs.mkdirSync('./built/_frontend_dist_/locales', { recursive: true });
|
||||
|
||||
const v = { '_version_': meta.version };
|
||||
|
||||
for (const [lang, locale] of Object.entries(locales)) {
|
||||
fs.writeFileSync(`./built/_frontend_dist_/locales/${lang}.${meta.version}.json`, JSON.stringify({ ...locale, ...v }), 'utf-8');
|
||||
}
|
||||
|
||||
cb();
|
||||
});
|
||||
|
||||
gulp.task('build:backend:script', () => {
|
||||
return gulp.src(['./packages/backend/src/server/web/boot.js', './packages/backend/src/server/web/bios.js', './packages/backend/src/server/web/cli.js'])
|
||||
.pipe(replace('LANGS', JSON.stringify(Object.keys(locales))))
|
||||
.pipe(terser({
|
||||
toplevel: true
|
||||
}))
|
||||
.pipe(gulp.dest('./packages/backend/built/server/web/'));
|
||||
});
|
||||
|
||||
gulp.task('build:backend:style', () => {
|
||||
return gulp.src(['./packages/backend/src/server/web/style.css', './packages/backend/src/server/web/bios.css', './packages/backend/src/server/web/cli.css'])
|
||||
.pipe(cssnano({
|
||||
zindex: false
|
||||
}))
|
||||
.pipe(gulp.dest('./packages/backend/built/server/web/'));
|
||||
});
|
||||
|
||||
gulp.task('build', gulp.parallel(
|
||||
'copy:frontend:locales', 'copy:backend:views', 'build:backend:script', 'build:backend:style', 'copy:frontend:fonts', 'copy:frontend:tabler-icons'
|
||||
));
|
||||
|
||||
gulp.task('default', gulp.task('build'));
|
||||
|
||||
gulp.task('watch', () => {
|
||||
gulp.watch([
|
||||
'./packages/*/src/**/*',
|
||||
], { ignoreInitial: false }, gulp.task('build'));
|
||||
});
|
||||
@@ -1,7 +1,4 @@
|
||||
#!/bin/bash
|
||||
|
||||
# SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
# SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
PORT=$(grep '^port:' /misskey/.config/default.yml | awk 'NR==1{print $2; exit}')
|
||||
curl -Sfso/dev/null "http://localhost:${PORT}/healthz"
|
||||
curl -s -S -o /dev/null "http://localhost:${PORT}"
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
||||
import { action } from 'storybook/actions';
|
||||
import type { StoryObj } from '@storybook/vue3';
|
||||
import { HttpResponse, http } from 'msw';
|
||||
import { abuseUserReport } from '../packages/frontend/.storybook/fakes.js';
|
||||
import { commonHandlers } from '../packages/frontend/.storybook/mocks.js';
|
||||
import MkAbuseReport from './MkAbuseReport.vue';
|
||||
export const Default = {
|
||||
render(args) {
|
||||
return {
|
||||
components: {
|
||||
MkAbuseReport,
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
args,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
props() {
|
||||
return {
|
||||
...this.args,
|
||||
};
|
||||
},
|
||||
events() {
|
||||
return {
|
||||
resolved: action('resolved'),
|
||||
};
|
||||
},
|
||||
},
|
||||
template: '<MkAbuseReport v-bind="props" v-on="events" />',
|
||||
};
|
||||
},
|
||||
args: {
|
||||
report: abuseUserReport(),
|
||||
},
|
||||
parameters: {
|
||||
layout: 'fullscreen',
|
||||
msw: {
|
||||
handlers: [
|
||||
...commonHandlers,
|
||||
http.post('/api/admin/resolve-abuse-user-report', async ({ request }) => {
|
||||
action('POST /api/admin/resolve-abuse-user-report')(await request.json());
|
||||
return HttpResponse.json({});
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
} satisfies StoryObj<typeof MkAbuseReport>;
|
||||
@@ -1,232 +0,0 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<canvas ref="canvasEl" style="display: block; width: 100%; height: 100%; pointer-events: none;"></canvas>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, useTemplateRef } from 'vue';
|
||||
import isChromatic from 'chromatic/isChromatic';
|
||||
import { initShaderProgram } from '@/utility/webgl.js';
|
||||
|
||||
const VERTEX_SHADER = `#version 300 es
|
||||
in vec2 position;
|
||||
out vec2 in_uv;
|
||||
|
||||
void main() {
|
||||
in_uv = (position + 1.0) / 2.0;
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const FRAGMENT_SHADER = `#version 300 es
|
||||
precision mediump float;
|
||||
|
||||
const float PI = 3.141592653589793;
|
||||
const float TWO_PI = 6.283185307179586;
|
||||
const float HALF_PI = 1.5707963267948966;
|
||||
|
||||
in vec2 in_uv;
|
||||
uniform vec2 in_resolution;
|
||||
uniform float u_scale;
|
||||
uniform float u_time;
|
||||
uniform float u_seed;
|
||||
uniform float u_angle;
|
||||
uniform float u_radius;
|
||||
uniform vec3 u_color;
|
||||
uniform vec2 u_ripplePositions[16];
|
||||
uniform float u_rippleRadiuses[16];
|
||||
out vec4 out_color;
|
||||
|
||||
float getRipple(vec2 uv) {
|
||||
float strength = 0.0;
|
||||
float thickness = 0.05;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if (u_rippleRadiuses[i] <= 0.0) continue;
|
||||
|
||||
float d = distance(uv, u_ripplePositions[i]);
|
||||
|
||||
// ãã
|
||||
if (d < u_rippleRadiuses[i] + thickness && d > u_rippleRadiuses[i] - thickness) {
|
||||
float gradate = abs(d - u_rippleRadiuses[i] + thickness) / thickness;
|
||||
strength += (1.0 - u_rippleRadiuses[i]) * gradate;
|
||||
}
|
||||
|
||||
// å
å´
|
||||
if (d < u_rippleRadiuses[i] + thickness) {
|
||||
strength += 0.25 * (1.0 - u_rippleRadiuses[i]);
|
||||
}
|
||||
}
|
||||
return strength;
|
||||
}
|
||||
|
||||
void main() {
|
||||
float x_ratio = min(in_resolution.x / in_resolution.y, 1.0);
|
||||
float y_ratio = min(in_resolution.y / in_resolution.x, 1.0);
|
||||
|
||||
float angle = -(u_angle * PI);
|
||||
vec2 centeredUv = (in_uv - vec2(0.5, 0.5)) * vec2(x_ratio, y_ratio);
|
||||
vec2 rotatedUV = vec2(
|
||||
centeredUv.x * cos(angle) - centeredUv.y * sin(angle),
|
||||
centeredUv.x * sin(angle) + centeredUv.y * cos(angle)
|
||||
);
|
||||
vec2 uv = rotatedUV;
|
||||
|
||||
float time = u_time * 0.00025;
|
||||
|
||||
float size = 1.0 / u_scale;
|
||||
float size_half = size / 2.0;
|
||||
float modX = mod(uv.x, size);
|
||||
float modY = mod(uv.y, size);
|
||||
|
||||
vec2 pixelated_uv = vec2(
|
||||
(size * (floor((uv.x - 0.5 - size) / size) + 0.5)),
|
||||
(size * (floor((uv.y - 0.5 - size) / size) + 0.5))
|
||||
) + vec2(0.5 + size, 0.5 + size);
|
||||
|
||||
float strength = getRipple(pixelated_uv);
|
||||
|
||||
float opacity = min(max(strength, 0.0), 1.0);
|
||||
|
||||
float threshold = ((u_radius / 2.0) / u_scale);
|
||||
if (length(vec2(modX - size_half, modY - size_half)) < threshold) {
|
||||
out_color = vec4(u_color.r, u_color.g, u_color.b, opacity);
|
||||
//out_color = vec4(1.0);
|
||||
return;
|
||||
}
|
||||
|
||||
// debug
|
||||
//float a = min(max(getRipple(uv), 0.0), 1.0);
|
||||
//out_color = vec4(u_color.r, u_color.g, u_color.b, (opacity + a) / 2.0);
|
||||
|
||||
out_color = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const canvasEl = useTemplateRef('canvasEl');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
scale?: number;
|
||||
}>(), {
|
||||
scale: 48,
|
||||
});
|
||||
|
||||
let handle: ReturnType<typeof window['requestAnimationFrame']> | null = null;
|
||||
|
||||
onMounted(() => {
|
||||
const canvas = canvasEl.value!;
|
||||
let width = canvas.offsetWidth;
|
||||
let height = canvas.offsetHeight;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
const maybeGl = canvas.getContext('webgl2', { preserveDrawingBuffer: false, alpha: true, premultipliedAlpha: false, antialias: true });
|
||||
if (maybeGl == null) return;
|
||||
|
||||
const gl = maybeGl;
|
||||
|
||||
const VERTICES = new Float32Array([-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1]);
|
||||
const vertexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, VERTICES, gl.STATIC_DRAW);
|
||||
|
||||
//gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
//gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
const shaderProgram = initShaderProgram(gl, VERTEX_SHADER, FRAGMENT_SHADER);
|
||||
|
||||
gl.useProgram(shaderProgram);
|
||||
|
||||
const positionLocation = gl.getAttribLocation(shaderProgram, 'position');
|
||||
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(positionLocation);
|
||||
|
||||
const in_resolution = gl.getUniformLocation(shaderProgram, 'in_resolution');
|
||||
gl.uniform2fv(in_resolution, [canvas.width, canvas.height]);
|
||||
|
||||
const u_time = gl.getUniformLocation(shaderProgram, 'u_time');
|
||||
const u_seed = gl.getUniformLocation(shaderProgram, 'u_seed');
|
||||
const u_scale = gl.getUniformLocation(shaderProgram, 'u_scale');
|
||||
const u_angle = gl.getUniformLocation(shaderProgram, 'u_angle');
|
||||
const u_radius = gl.getUniformLocation(shaderProgram, 'u_radius');
|
||||
const u_color = gl.getUniformLocation(shaderProgram, 'u_color');
|
||||
gl.uniform1f(u_seed, Math.random() * 1000);
|
||||
gl.uniform1f(u_scale, props.scale);
|
||||
gl.uniform1f(u_angle, 0.0);
|
||||
gl.uniform1f(u_radius, 0.15);
|
||||
gl.uniform3fv(u_color, [0.5, 1.0, 0]);
|
||||
|
||||
if (isChromatic()) {
|
||||
gl.uniform1f(u_time, 0);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
} else {
|
||||
let ripples = [] as { position: [number, number]; startTime: number; }[];
|
||||
const LIFE_TIME = 1000 * 4;
|
||||
|
||||
function render(timeStamp: number) {
|
||||
let sizeChanged = false;
|
||||
if (Math.abs(height - canvas.offsetHeight) > 2) {
|
||||
height = canvas.offsetHeight;
|
||||
canvas.height = height;
|
||||
sizeChanged = true;
|
||||
}
|
||||
if (Math.abs(width - canvas.offsetWidth) > 2) {
|
||||
width = canvas.offsetWidth;
|
||||
canvas.width = width;
|
||||
sizeChanged = true;
|
||||
}
|
||||
if (sizeChanged && gl) {
|
||||
gl.uniform2fv(in_resolution, [width, height]);
|
||||
gl.viewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
gl.uniform1f(u_time, timeStamp);
|
||||
|
||||
if (Math.random() < 0.01 && ripples.length < 16) {
|
||||
ripples.push({ position: [(Math.random() * 2) - 1, (Math.random() * 2) - 1], startTime: timeStamp });
|
||||
}
|
||||
|
||||
for (let i = 0; i < 16; i++) {
|
||||
const o = gl.getUniformLocation(shaderProgram, `u_ripplePositions[${i.toString()}]`);
|
||||
const r = gl.getUniformLocation(shaderProgram, `u_rippleRadiuses[${i.toString()}]`);
|
||||
const ripple = ripples[i];
|
||||
if (ripple == null) {
|
||||
gl.uniform2f(o, 0, 0);
|
||||
gl.uniform1f(r, 0.0);
|
||||
continue;
|
||||
}
|
||||
|
||||
const delta = timeStamp - ripple.startTime;
|
||||
|
||||
gl.uniform2f(o, ripple.position[0], ripple.position[1]);
|
||||
gl.uniform1f(r, delta / LIFE_TIME);
|
||||
}
|
||||
|
||||
ripples = ripples.filter(r => (timeStamp - r.startTime) < LIFE_TIME);
|
||||
if (ripples.length === 0) {
|
||||
ripples.push({ position: [(Math.random() * 2) - 1, (Math.random() * 2) - 1], startTime: timeStamp });
|
||||
}
|
||||
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
|
||||
handle = window.requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
handle = window.requestAnimationFrame(render);
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (handle) {
|
||||
window.cancelAnimationFrame(handle);
|
||||
}
|
||||
|
||||
// TODO: WebGLãĒãŊãŧãšãŽč§Ŗæž
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
</style>
|
||||
@@ -1,190 +0,0 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<canvas ref="canvasEl" style="display: block; width: 100%; height: 100%; pointer-events: none;"></canvas>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { onMounted, onUnmounted, useTemplateRef } from 'vue';
|
||||
import isChromatic from 'chromatic/isChromatic';
|
||||
import { GLSL_LIB_SNOISE, initShaderProgram } from '@/utility/webgl.js';
|
||||
|
||||
const VERTEX_SHADER = `#version 300 es
|
||||
in vec2 position;
|
||||
out vec2 in_uv;
|
||||
|
||||
void main() {
|
||||
in_uv = (position + 1.0) / 2.0;
|
||||
gl_Position = vec4(position, 0.0, 1.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const FRAGMENT_SHADER = `#version 300 es
|
||||
precision mediump float;
|
||||
|
||||
const float PI = 3.141592653589793;
|
||||
const float TWO_PI = 6.283185307179586;
|
||||
const float HALF_PI = 1.5707963267948966;
|
||||
|
||||
${GLSL_LIB_SNOISE}
|
||||
|
||||
in vec2 in_uv;
|
||||
uniform vec2 in_resolution;
|
||||
uniform float u_scale;
|
||||
uniform float u_time;
|
||||
uniform float u_seed;
|
||||
uniform float u_angle;
|
||||
uniform float u_radius;
|
||||
uniform vec3 u_color;
|
||||
out vec4 out_color;
|
||||
|
||||
void main() {
|
||||
float x_ratio = min(in_resolution.x / in_resolution.y, 1.0);
|
||||
float y_ratio = min(in_resolution.y / in_resolution.x, 1.0);
|
||||
|
||||
float size = 1.0 / u_scale;
|
||||
float size_half = size / 2.0;
|
||||
|
||||
float angle = -(u_angle * PI);
|
||||
vec2 centeredUv = (in_uv - vec2(0.5, 0.5)) * vec2(x_ratio, y_ratio);
|
||||
vec2 rotatedUV = vec2(
|
||||
centeredUv.x * cos(angle) - centeredUv.y * sin(angle),
|
||||
centeredUv.x * sin(angle) + centeredUv.y * cos(angle)
|
||||
);
|
||||
vec2 uv = rotatedUV;
|
||||
|
||||
float modX = mod(uv.x, size);
|
||||
float modY = mod(uv.y, size);
|
||||
|
||||
vec2 pixelated_uv = vec2(
|
||||
(size * (floor((uv.x - 0.5 - size) / size) + 0.5)),
|
||||
(size * (floor((uv.y - 0.5 - size) / size) + 0.5))
|
||||
) + vec2(0.5 + size, 0.5 + size);
|
||||
|
||||
float time = u_time * 0.00025;
|
||||
|
||||
float noiseAScale = 1.0;
|
||||
float noiseAX = (pixelated_uv.x + u_seed) * (u_scale / noiseAScale);
|
||||
float noiseAY = (pixelated_uv.y + u_seed) * (u_scale / noiseAScale);
|
||||
float noiseA = snoise(vec3(noiseAX, noiseAY, time * 2.0));
|
||||
|
||||
float noiseBScale = 32.0;
|
||||
float noiseBX = (pixelated_uv.x + u_seed) * (u_scale / noiseBScale);
|
||||
float noiseBY = (pixelated_uv.y + u_seed) * (u_scale / noiseBScale);
|
||||
float noiseB = snoise(vec3(noiseBX, noiseBY, time));
|
||||
|
||||
float strength = 0.0;
|
||||
strength += noiseA * 0.2;
|
||||
strength += noiseB * 0.8;
|
||||
|
||||
float opacity = min(max(strength, 0.0), 1.0);
|
||||
|
||||
float threshold = ((u_radius / 2.0) / u_scale);
|
||||
if (length(vec2(modX - size_half, modY - size_half)) < threshold) {
|
||||
out_color = vec4(u_color.r, u_color.g, u_color.b, opacity);
|
||||
return;
|
||||
}
|
||||
|
||||
out_color = vec4(0.0, 0.0, 0.0, 0.0);
|
||||
}
|
||||
`;
|
||||
|
||||
const canvasEl = useTemplateRef('canvasEl');
|
||||
|
||||
const props = withDefaults(defineProps<{
|
||||
scale?: number;
|
||||
}>(), {
|
||||
scale: 48,
|
||||
});
|
||||
|
||||
let handle: ReturnType<typeof window['requestAnimationFrame']> | null = null;
|
||||
|
||||
onMounted(() => {
|
||||
const canvas = canvasEl.value!;
|
||||
let width = canvas.offsetWidth;
|
||||
let height = canvas.offsetHeight;
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
const maybeGl = canvas.getContext('webgl2', { preserveDrawingBuffer: false, alpha: true, premultipliedAlpha: false, antialias: true });
|
||||
if (maybeGl == null) return;
|
||||
|
||||
const gl = maybeGl;
|
||||
|
||||
const VERTICES = new Float32Array([-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1]);
|
||||
const vertexBuffer = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, VERTICES, gl.STATIC_DRAW);
|
||||
|
||||
//gl.clearColor(0.0, 0.0, 0.0, 0.0);
|
||||
//gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
|
||||
const shaderProgram = initShaderProgram(gl, VERTEX_SHADER, FRAGMENT_SHADER);
|
||||
|
||||
gl.useProgram(shaderProgram);
|
||||
|
||||
const positionLocation = gl.getAttribLocation(shaderProgram, 'position');
|
||||
gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
|
||||
gl.enableVertexAttribArray(positionLocation);
|
||||
|
||||
const in_resolution = gl.getUniformLocation(shaderProgram, 'in_resolution');
|
||||
gl.uniform2fv(in_resolution, [canvas.width, canvas.height]);
|
||||
|
||||
const u_time = gl.getUniformLocation(shaderProgram, 'u_time');
|
||||
const u_seed = gl.getUniformLocation(shaderProgram, 'u_seed');
|
||||
const u_scale = gl.getUniformLocation(shaderProgram, 'u_scale');
|
||||
const u_angle = gl.getUniformLocation(shaderProgram, 'u_angle');
|
||||
const u_radius = gl.getUniformLocation(shaderProgram, 'u_radius');
|
||||
const u_color = gl.getUniformLocation(shaderProgram, 'u_color');
|
||||
gl.uniform1f(u_seed, Math.random() * 1000);
|
||||
gl.uniform1f(u_scale, props.scale);
|
||||
gl.uniform1f(u_angle, 0.0);
|
||||
gl.uniform1f(u_radius, 0.15);
|
||||
gl.uniform3fv(u_color, [0.5, 1.0, 0]);
|
||||
|
||||
if (isChromatic()) {
|
||||
gl.uniform1f(u_time, 0);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
} else {
|
||||
function render(timeStamp: number) {
|
||||
let sizeChanged = false;
|
||||
if (Math.abs(height - canvas.offsetHeight) > 2) {
|
||||
height = canvas.offsetHeight;
|
||||
canvas.height = height;
|
||||
sizeChanged = true;
|
||||
}
|
||||
if (Math.abs(width - canvas.offsetWidth) > 2) {
|
||||
width = canvas.offsetWidth;
|
||||
canvas.width = width;
|
||||
sizeChanged = true;
|
||||
}
|
||||
if (sizeChanged && gl) {
|
||||
gl.uniform2fv(in_resolution, [width, height]);
|
||||
gl.viewport(0, 0, width, height);
|
||||
}
|
||||
|
||||
gl.uniform1f(u_time, timeStamp);
|
||||
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
||||
|
||||
handle = window.requestAnimationFrame(render);
|
||||
}
|
||||
|
||||
handle = window.requestAnimationFrame(render);
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => {
|
||||
if (handle) {
|
||||
window.cancelAnimationFrame(handle);
|
||||
}
|
||||
|
||||
// TODO: WebGLãĒãŊãŧãšãŽč§Ŗæž
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
</style>
|
||||
@@ -1 +0,0 @@
|
||||
äŊŋãããĒããĒãŖãããŠæļããŽã¯åŋäŊãĒã(å°æĨäŊŋãããããããĒã)ãŗãŧããå
ĨããĻããã¨ã
|
||||
@@ -2,7 +2,6 @@
|
||||
_lang_: "Ø§ŲØšØąØ¨ŲØŠ"
|
||||
headlineMisskey: "Ø´Ø¨ŲØŠ Ų
ØąØĒØ¨ØˇØŠ باŲŲ
ŲØ§ØØ¸Ø§ØĒ"
|
||||
introMisskey: "اŲŲØ§ بŲ! Ų
ŲØŗŲŲ ŲŲ Ų
ŲØĩØŠ ØĒدŲŲŲ Ų
ØĩØēØą ŲØ§ Ų
ØąŲØ˛ŲØŠ ŲŲ
ŲØĒŲØØŠ اŲŲ
ØĩØ¯Øą.\nŲŲ
ŲŲŲ Ų
Ø´Ø§ØąŲØŠ \"Ų
ŲØ§ØØ¸Ø§ØĒ\" ØšŲ Ų
ا ŲØŦØąŲ ØŲŲŲØ ŲØĨØŽØ¨Ø§Øą Ø§ŲØŦŲ
ŲØš ØšŲ ŲŲØŗŲ đĄ\nØĒØŗŲ
Ø ŲŲ \"Ø§ŲØ§ŲŲØšØ§ŲاØĒ\" بØĒØšØ¨ŲØą ØšŲ Ø´ØšŲØąŲ ØŲŲ Ų
ŲØ§ØØ¸Ø§ØĒ Ø§ŲØĸØŽØąŲŲ đ\nØ§ŲØĒØ´Ų ؚاŲŲ
ŲØ§ ØŦØ¯ŲØ¯Ųا đ"
|
||||
poweredByMisskeyDescription: "{name} ŲŲ ØĨØØ¯Ų Ø§ŲØŽŲدŲ
اØĒ Ø§ŲØĒŲ ØĒØŗØĒ؎دŲ
اŲŲ
ŲØĩØŠ Ų
ŲØĒŲØØŠ اŲŲ
ØĩØ¯Øą <b>Ų
ŲØŗŲŲ</b> (ŲØ´Ø§Øą ØĨŲŲŲ ŲŲ
ØĢŲŲ Ų
ŲØŗŲŲ)"
|
||||
monthAndDay: "{day}/{month}"
|
||||
search: "Ø§ŲØ¨ØØĢ"
|
||||
notifications: "Ø§ŲØĨØ´ØšØ§ØąØ§ØĒ"
|
||||
@@ -20,7 +19,6 @@ noNotes: "ŲŲ
ŲŲØšØĢØą ØšŲŲ ØŖŲØŠ Ų
ŲØ§ØØ¸Ø§ØĒ"
|
||||
noNotifications: "ŲŲØŗ ŲŲØ§Ų ØŖŲØŠ Ø§Ø´ØšØ§ØąØ§ØĒ"
|
||||
instance: "Ų
ØĢŲŲ Ø§ŲØŽØ§Ø¯Ų
"
|
||||
settings: "Ø§ŲØ§ØšØ¯Ø§Ø¯Ø§ØĒ"
|
||||
notificationSettings: "ØĨؚداداØĒ Ø§ŲØĨØ´ØšØ§ØąØ§ØĒ"
|
||||
basicSettings: "Ø§ŲØ§ØšØ¯Ø§Ø¯Ø§ØĒ Ø§ŲØŖØŗØ§ØŗŲØŠ"
|
||||
otherSettings: "ØĨؚداداØĒ ØŖØŽØąŲ"
|
||||
openInWindow: "Ø§ŲØĒØ ŲŲ ŲØ§Ųذ؊ ØŦØ¯ŲØ¯ØŠ"
|
||||
@@ -41,23 +39,16 @@ unfavorite: "ØĨØ˛Ø§ŲØŠ Ų
Ų Ø§ŲŲ
ŲØļŲØŠ"
|
||||
favorited: "ØŖŲØļŲŲ ØĨŲŲ Ø§ŲŲ
ŲØļŲØŠ."
|
||||
alreadyFavorited: "ØĒŲ
ØĒ ØĨØļØ§ŲØĒŲ Ø¨Ø§ŲŲØšŲ ØĨŲŲ Ø§ŲŲ
ŲØļŲØŠ."
|
||||
cantFavorite: "ØĒØšØ°ØąØĒ Ø§ŲØĨØļØ§ŲØŠ ØĨŲŲ Ø§ŲŲ
ŲØļŲØŠ."
|
||||
pin: "ØĢبØĒŲØ§ ØšŲŲ Ø§ŲØĩŲØØŠ Ø§ŲØ´ØŽØĩŲØŠ"
|
||||
unpin: "ŲŲŲØ§ Ų
Ų Ų
ŲŲŲ Ø§ŲØ´ØŽØĩŲ"
|
||||
pin: "Ø¯Ø¨ŲØŗŲا ØšŲŲ Ø§ŲØĩŲØØŠ Ø§ŲØ´ØŽØĩŲØŠ"
|
||||
unpin: "ØŖŲØē ØĒØ¯Ø¨ŲØŗŲØ§ Ų
Ų Ų
ŲŲŲ Ø§ŲØ´ØŽØĩŲ"
|
||||
copyContent: "Ø§ŲØŗØŽ اŲŲ
ØØĒŲŲ"
|
||||
copyLink: "Ø§ŲØŗØŽ Ø§ŲØąØ§Ø¨Øˇ"
|
||||
delete: "ØØ°Ų"
|
||||
deleteAndEdit: "ØĨØ˛Ø§ŲØŠ ŲØĨؚاد؊ Ø§ŲØĩŲØ§ØēØŠ"
|
||||
deleteAndEditConfirm: "ØŖŲ
ØĒØŖŲØ¯ Ų
Ų ØØ°Ų اŲŲ
ŲØ§ØØ¸ØŠØ ØŗØĒŲŲØ¯ ŲŲ Ų
Ø´Ø§ØąŲØ§ØĒŲØ§Ø ŲØ§ŲØĒŲØ§ØšŲاØĒØ ŲØ§ŲØąØ¯ŲØ¯ ØšŲŲŲØ§."
|
||||
addToList: "ØŖØļŲŲ ØĨŲŲ ŲØ§ØĻŲ
ØŠ"
|
||||
addToAntenna: "ØŖØļŲ ØĨŲŲ ŲŲØ§ØĻŲ"
|
||||
sendMessage: "ØŖØąØŗŲ ØąØŗØ§ŲØŠ"
|
||||
copyRSS: "Ø§ŲØŗØŽ ØąØ§Ø¨Øˇ RSS"
|
||||
copyUsername: "Ø§ŲØŗØŽ Ø§ØŗŲ
اŲŲ
ØŗØĒ؎دŲ
"
|
||||
copyUserId: "Ø§ŲØŗØŽ Ų
ØšØąŲ Ø§ŲŲ
ØŗØĒ؎دŲ
"
|
||||
copyNoteId: "Ø§ŲØŗØŽ Ų
ØšØąŲ Ø§ŲŲ
ŲØ§ØØ¸ØŠ"
|
||||
copyFileId: "Ø§ŲØŗØŽ Ų
ØšØąŲŲ Ø§ŲŲ
ŲŲ"
|
||||
copyFolderId: "Ø§ŲØŗØŽ Ų
ØšØąŲŲ Ø§ŲŲ
ØŦŲØ¯"
|
||||
copyProfileUrl: "Ø§ŲØŗØŽ ØąØ§Ø¨Øˇ اŲŲ
ŲŲ Ø§ŲØ´ØŽØĩŲ"
|
||||
searchUser: "Ø§Ø¨ØØĢ ØšŲ Ų
ØŗØĒ؎دŲ
ŲŲ"
|
||||
reply: "ØąØ¯"
|
||||
loadMore: "ØšØąØļ اŲŲ
Ø˛ŲØ¯"
|
||||
@@ -68,7 +59,7 @@ receiveFollowRequest: "ØĒŲŲŲØĒ ØˇŲØ¨ Ų
ØĒابؚ؊"
|
||||
followRequestAccepted: "ŲŲØ¨Ų ØˇŲØ¨ اŲŲ
ØĒابؚ؊"
|
||||
mention: "ØŖØ´Øą اŲŲ"
|
||||
mentions: "Ø§ŲØĨØ´Ø§ØąØ§ØĒ"
|
||||
directNotes: "ØąØŗØ§ŲØŠ ØŽØ§ØĩØŠ"
|
||||
directNotes: "اŲŲ
ŲØ§ØØ¸Ø§ØĒ اŲŲ
Ø¨Ø§Ø´ØąØŠ"
|
||||
importAndExport: "ØĨØŗØĒبਝ / ØĩØ¯Øą"
|
||||
import: "Ø§ØŗØĒŲØąØ§Ø¯"
|
||||
export: "ØĒØĩØ¯ŲØą"
|
||||
@@ -110,27 +101,23 @@ renoted: "ØŖŲØšŲد ŲØ´ØąŲ"
|
||||
cantRenote: "ŲØ§ ŲŲ
ŲŲ ØĨؚاد؊ ŲØ´Øą اŲŲ
ŲØ§ØØ¸ØŠ"
|
||||
cantReRenote: "ŲØ§ ŲŲ
ŲŲŲ ØĨؚاد؊ ŲØ´Øą Ų
ŲØ§ØØ¸ØŠ Ų
ؚاد ŲØ´ØąŲا"
|
||||
quote: "Ø§ŲØĒØ¨Øŗ"
|
||||
inChannelRenote: "ØĨؚاد؊ ŲØ´Øą ŲŲ ŲŲØ§ØŠ"
|
||||
inChannelQuote: "Ø§ŲØĒØ¨Ø§Øŗ ŲŲ ŲŲØ§ØŠ"
|
||||
pinnedNote: "Ų
ŲØ§ØØ¸ØŠ Ų
ØĢبØĒØŠ"
|
||||
pinned: "ØĢبØĒŲØ§ ØšŲŲ Ø§ŲØĩŲØØŠ Ø§ŲØ´ØŽØĩŲØŠ"
|
||||
pinnedNote: "Ų
ŲØ§ØØ¸ØŠ Ų
Ø¯Ø¨ØŗØŠ"
|
||||
pinned: "Ø¯Ø¨ŲØŗŲا ØšŲŲ Ø§ŲØĩŲØØŠ Ø§ŲØ´ØŽØĩŲØŠ"
|
||||
you: "ØŖŲØĒ"
|
||||
clickToShow: "اØļØēØˇ ŲŲØšØąØļ"
|
||||
sensitive: "Ų
ØØĒŲŲ ØØŗØ§Øŗ"
|
||||
add: "ØĨØļØ§ŲØŠ"
|
||||
reaction: "Ø§ŲØĒŲØ§ØšŲاØĒ"
|
||||
reactions: "Ø§ŲØĒŲØ§ØšŲاØĒ"
|
||||
reactionSetting: "Ø§ŲØĒŲØ§ØšŲاØĒ اŲŲ
ØąØ§Ø¯ ØšØąØļŲØ§ ŲŲ Ų
ŲØĒŲŲ Ø§ŲØĒŲØ§ØšŲاØĒ."
|
||||
reactionSettingDescription2: "Ø§ØŗØØ¨ ŲØĒØąØĒŲØ¨ Ø Ø§ŲŲØą ŲŲØØ°Ų Ø Ø§ØŗØĒ؎دŲ
\"+\" ŲŲØĨØļØ§ŲØŠ."
|
||||
rememberNoteVisibility: "ØĒØ°ŲØą ØĨؚدادØĒ Ų
Ø¯Ų ØąØ¤ŲØŠ Ø§ŲŲ
ŲØ§ØØ¸Ø§ØĒ"
|
||||
attachCancel: "ØŖØ˛Ų Ø§ŲŲ
ØąŲŲ"
|
||||
deleteFile: "ØŲØ°Ų Ø§ŲŲ
ŲŲ"
|
||||
markAsSensitive: "ØšŲŲŲ
Ų ŲŲ
ØØĒŲŲ ØØŗØ§Øŗ"
|
||||
unmarkAsSensitive: "ØŖŲØē ØĒØšŲŲŲŲ ŲŲ
ØØĒŲŲ ØØŗØ§Øŗ"
|
||||
enterFileName: "Ø§Ø¯ØŽŲ Ø§ØŗŲ
اŲŲ
ŲŲ"
|
||||
mute: "Ø§ŲØĒŲ
"
|
||||
unmute: "ØĨŲØēØ§ØĄ اŲŲØĒŲ
"
|
||||
renoteMute: "Ø§ŲØĒŲ
ØĨؚاد؊ اŲŲØ´Øą"
|
||||
renoteUnmute: "Ø§ØąŲØš Ø§ŲŲØĒŲ
ØšŲ ØĨؚاد؊ اŲŲØ´Øą"
|
||||
block: "Ø§ØØŦب"
|
||||
unblock: "ØĨŲØēØ§ØĄ Ø§ŲØØŦب"
|
||||
suspend: "ØšŲŲŲ"
|
||||
@@ -140,10 +127,7 @@ unblockConfirm: "ØŖŲ
ØĒØŖŲØ¯ Ų
Ų ØĨŲØēØ§ØĄ ØØŦب ŲØ°Ø§ Ø§ŲØØŗØ§Ø¨Ø"
|
||||
suspendConfirm: "ØŖŲ
ØĒØŖŲØ¯ Ų
Ų ØĒØšŲŲŲ Ø§ŲØØŗØ§Ø¨Ø"
|
||||
unsuspendConfirm: "ØŖŲ
ØĒØŖŲØ¯ Ų
Ų ØĨŲØēØ§ØĄ ØĒØšŲŲŲØ"
|
||||
selectList: "ا؎ØĒØą ŲØ§ØĻŲ
ØŠ"
|
||||
editList: "ؚدŲŲ Ø§ŲŲØ§ØĻŲ
ØŠ"
|
||||
selectChannel: "ا؎ØĒØą ŲŲØ§ØŠ"
|
||||
selectAntenna: "ا؎ØĒØą ŲŲØ§ØĻŲŲØ§"
|
||||
editAntenna: "ؚدŲŲ Ø§ŲŲŲØ§ØĻŲ"
|
||||
selectWidget: "ا؎ØĒØą ŲØ¯ØŦØŠ"
|
||||
editWidgets: "ؚدŲŲ Ø§ŲŲØ¯ØŦاØĒ"
|
||||
editWidgetsExit: "ØĒŲ
"
|
||||
@@ -155,7 +139,6 @@ emojiUrl: "ØąØ§Ø¨Øˇ Ø§ŲØĨŲŲ
ŲØŦŲ"
|
||||
addEmoji: "ØĨØļØ§ŲØŠ ØĨŲŲ
ŲØŦŲ"
|
||||
settingGuide: "Ø§ŲØĨؚداداØĒ اŲŲ
ØŗØĒØØŗŲØŠ"
|
||||
cacheRemoteFiles: "ØŽØ˛Ų Ų
Ø¤ŲØĒØ§ اŲŲ
ŲŲØ§ØĒ Ø§ŲØ¨ØšŲد؊"
|
||||
cacheRemoteFilesDescription: "ØĨذا ØšŲØˇŲ ŲØ°Ø§ Ø§ŲØĨØšØ¯Ø§Ø¯Ø ØŗØĒŲØŲ
Ų Ø§ŲŲ
ŲŲØ§ØĒ Ų
Ų Ø§ŲŲ
ØĢŲŲ Ø§ŲØ¨ØšŲØ¯Ø ŲØ°Ø§ ØŗŲŲŲŲ Ų
Ų Ø§ŲŲ
ØŗØ§ØØŠ Ø§ŲŲ
ØŗØĒØēŲØŠ ØšŲŲ Ø§ŲŲØąØĩ ŲŲŲ ØŗŲØ˛Ųد ØØŦŲ
ØĒدŲŲ Ø§ŲØ¨ŲØ§ŲØ§ØĒ ŲŲØ°Ø§ ŲØŖŲ Ø§ŲØĩŲØą Ø§ŲŲ
ØĩØēØąØŠ ŲŲ ØĒŲŲŲØ¯."
|
||||
flagAsBot: "ØšŲŲŲ
Ų ŲØØŗØ§Ø¨ ØĸŲŲ"
|
||||
flagAsBotDescription: "ŲØšŲŲ ŲØ°Ø§ Ø§ŲØŽŲØ§Øą ØĨذا ŲØ§Ų ŲØ°Ø§ Ø§ŲØØŗØ§Ø¨ ŲŲØ¯Ø§Øą ØšØ¨Øą Ø¨ØąŲ
ØŦŲØŠ. ØĨذا ŲŲØšŲ ŲØŗŲŲŲŲ Ø¨Ų
ØĢاب؊ ØšŲØ§Ų
ØŠ ŲŲŲ
ØˇŲØąŲŲ Ø§ŲØĸØŽØąŲŲ ŲØĒØŦŲØ¨ ØŗŲØ§ØŗŲ ŲØ§ Ų
ØĒŲØ§ŲŲØŠ Ų
Ų Ø§ŲØĒŲØ§ØšŲ بŲŲ ØØŗØ§Ø¨Ø§ØĒ Ø§ŲØĸŲŲØŠ ŲØļØ¨Øˇ ØŖŲØ¸Ų
ØŠ Ų
ŲØŗŲŲ ŲŲØĒØšØ§Ų
Ų Ų
Øš ŲØ°Ø§ Ø§ŲØØŗØ§Ø¨ ŲØĸŲŲ."
|
||||
flagAsCat: "ØšŲŲŲ
ŲØ°Ø§ Ø§ŲØØŗØ§Ø¨ ŲØØŗØ§Ø¨ ŲØˇ"
|
||||
@@ -214,7 +197,8 @@ blockedUsers: "Ø§ŲØØŗØ§Ø¨Ø§ØĒ اŲŲ
ØØŦŲØ¨ØŠ"
|
||||
noUsers: "ŲŲØŗ ŲŲØ§Ų Ų
ØŗØĒ؎دŲ
ŲŲ"
|
||||
editProfile: "ØĒؚدŲŲ Ø§ŲŲ
ŲŲ Ø§ŲØĒØšØąŲŲŲ"
|
||||
noteDeleteConfirm: "ŲŲ ØĒØąŲØ¯ ØØ°Ų ŲØ°Ų اŲŲ
ŲØ§ØØ¸ØŠØ"
|
||||
pinLimitExceeded: "ŲØ§ ŲŲ
ŲŲŲ ØĒØĢØ¨ŲØĒ Ø§ŲŲ
ŲØ§ØØ¸Ø§ØĒ بؚد Ø§ŲØĸŲ."
|
||||
pinLimitExceeded: "ŲØ§ ŲŲ
ŲŲŲ ØĒØ¯Ø¨ŲØŗ اŲŲ
ŲØ§ØØ¸Ø§ØĒ بؚد Ø§ŲØĸŲ."
|
||||
intro: "ŲŲØ¯ Ø§ŲØĒŲØĒ ØšŲ
ŲŲØŠ ØĒŲØĩŲØ¨ Misskey. Ø§ŲØąØŦØ§ØĄ ØĨŲØ´Ø§ØĄ ØØŗØ§Ø¨ ØĨØ¯Ø§ØąŲ."
|
||||
done: "ØĒŲ
Ų"
|
||||
processing: "اŲŲ
ØšØ§ŲØŦØŠ ØŦØ§ØąŲØŠ"
|
||||
preview: "Ų
ؚاŲŲØŠ"
|
||||
@@ -250,6 +234,7 @@ removeAreYouSure: "Ų
ØĒØŖŲØ¯ Ų
Ų ØŖŲŲ ØĒØąŲØ¯ ØØ°Ų {x}Ø"
|
||||
deleteAreYouSure: "Ų
ØĒØŖŲØ¯ Ų
Ų ØŖŲŲ ØĒØąŲØ¯ ØØ°Ų {x}Ø"
|
||||
resetAreYouSure: "ŲŲ ØĒØąŲØ¯ ØĨؚاد؊ Ø§ŲØĒØšŲŲŲØ"
|
||||
saved: "ØŲŲØ¸"
|
||||
messaging: "اŲŲ
ØØ§Ø¯ØĢØŠ"
|
||||
upload: "Ø§ØąŲØš"
|
||||
keepOriginalUploading: "Ø§Ø¨Ų Ø§ŲØĩŲØąØŠ Ø§ŲØŖØĩŲŲØŠ"
|
||||
keepOriginalUploadingDescription: "ŲØŲØ¸ Ø§ŲØĩŲØą Ø§ŲŲ
ØąŲŲØšØŠ ØšŲŲ ØØ§ŲØĒŲØ§ Ø§ŲØŖØĩŲŲØŠØ ŲØ§Ų ØšØˇŲŲ ØŗØĒŲŲØ¯ ŲØŗØŽØŠ Ų
ØŽØĩØĩØŠ Ų
Ų Ø§ŲØĩŲØąØŠ."
|
||||
@@ -262,18 +247,15 @@ uploadFromUrlMayTakeTime: "ØŗŲØŗØĒØēØąŲ Ø¨ØšØļ اŲŲŲØĒ ŲØ§ØĒŲ
اŲ
Ø§ŲØą
|
||||
explore: "Ø§ØŗØĒŲØ´Ø§Ų"
|
||||
messageRead: "Ų
ŲØąŲØĄØŠ"
|
||||
noMoreHistory: "ŲØ§ ŲŲØŦد اŲŲ
Ø˛ŲØ¯ Ų
Ų Ø§ŲØĒØ§ØąŲØŽ"
|
||||
startMessaging: "Ø§Ø¨Ø¯ØŖ Ų
ØØ§Ø¯ØĢØŠ"
|
||||
nUsersRead: "ŲØąØŖŲ {n}"
|
||||
agreeTo: "Ø§ŲØ§ŲŲ ØšŲŲ {0}"
|
||||
agree: "ØŖŲØ¨Ų"
|
||||
agreeBelow: "ØŖŲØ¨Ų Ų
ا ŲŲŲ"
|
||||
basicNotesBeforeCreateAccount: "Ų
ŲØ§ØØ¸Ø§ØĒ Ų
ŲŲ
ØŠ"
|
||||
termsOfService: "Ø´ØąŲØˇ Ø§ŲØŽØ¯Ų
ØŠ"
|
||||
tos: "Ø´ØąŲØˇ Ø§ŲØŽØ¯Ų
ØŠ"
|
||||
start: "Ø§ŲØ¨Ø¯Ø§ŲØŠ"
|
||||
home: "Ø§ŲØąØĻŲØŗŲ"
|
||||
remoteUserCaution: "ŲØ°Ų اŲŲ
ØšŲŲŲ
اØĒ ŲØ¯ ŲØ§ ØĒŲŲŲ Ų
ŲØĒŲ
ŲØŠ Ø¨Ų
ا ØŖŲ Ø§ŲŲ
ØŗØĒ؎دŲ
Ų
Ų Ų
ØĢŲŲ Ø¨ØšŲØ¯."
|
||||
activity: "اŲŲØ´Ø§Øˇ"
|
||||
images: "ØĩŲØą"
|
||||
image: "ØĩŲØą"
|
||||
images: "Ø§ŲØĩŲØą"
|
||||
birthday: "ØĒØ§ØąŲØŽ Ø§ŲŲ
ŲŲØ§Ø¯"
|
||||
yearsOld: "{age} ØŗŲØŠ"
|
||||
registeredDate: "Ø§ŲØļŲ
ŲŲ"
|
||||
@@ -310,7 +292,7 @@ copyUrl: "Ø§ŲØŗØŽ Ø§ŲØąØ§Ø¨Øˇ"
|
||||
rename: "ØĨؚاد؊ Ø§ŲØĒØŗŲ
ŲØŠ"
|
||||
avatar: "Ø§ŲØĩŲØąØŠ Ø§ŲØąŲ
Ø˛ŲØŠ"
|
||||
banner: "Ø§ŲØĩŲØąØŠ Ø§ŲØąØŖØŗŲØŠ"
|
||||
displayOfSensitiveMedia: "ØšØąØļ اŲŲ
ØØĒŲŲ Ø§ŲØØŗØ§Øŗ"
|
||||
nsfw: "Ų
ØØĒŲŲ ØØŗØ§Øŗ"
|
||||
whenServerDisconnected: "ØšŲØ¯ ŲŲØ¯Ø§Ų Ø§ŲØ§ØĒØĩØ§Ų Ø¨Ø§ŲØŽØ§Ø¯Ų
"
|
||||
disconnectedFromServer: "ŲŲØˇŲØš Ø§ŲØĨØĒØĩØ§Ų Ø¨Ø§ŲØŽØ§Ø¯Ų
"
|
||||
reload: "Ø§ŲØšØ´"
|
||||
@@ -340,25 +322,25 @@ enableLocalTimeline: "ØĒŲØšŲŲ Ø§ŲØŽŲØˇ اŲŲ
ØŲŲ"
|
||||
enableGlobalTimeline: "ØĒŲØšŲŲ Ø§ŲØŽŲØˇ Ø§ŲØ˛Ų
ŲŲ Ø§ŲØ´Ø§Ų
Ų"
|
||||
disablingTimelinesInfo: "ØŗŲØĒŲ
ŲŲ Ø§ŲŲ
Ø¯ŲØąŲŲ ŲØ§ŲŲ
Ø´ØąŲŲŲ Ų
Ų Ø§ŲŲØĩŲŲ ØĨŲŲ ŲŲ Ø§ŲØŽŲŲØˇ Ø§ŲØ˛Ų
ŲŲØŠ ØØĒŲ ŲØĨŲ ŲŲ
ØĒŲØšŲŲ."
|
||||
registration: "ØĨŲØ´Ø§ØĄ ØØŗØ§Ø¨"
|
||||
enableRegistration: "ØĒŲØšŲŲ ØĨŲØ´Ø§ØĄ Ø§ŲØØŗØ§Ø¨Ø§ØĒ Ø§ŲØŦØ¯ŲØ¯ØŠ"
|
||||
invite: "Ø¯ØšŲØŠ"
|
||||
driveCapacityPerLocalAccount: "ØØĩØŠ Ø§ŲØĒØŽØ˛ŲŲ ŲŲŲ Ų
ØŗØĒ؎دŲ
Ų
ØŲŲ"
|
||||
driveCapacityPerRemoteAccount: "ØØĩØŠ Ø§ŲØĒØŽØ˛ŲŲ ŲŲŲ Ų
ØŗØĒ؎دŲ
Ø¨ØšŲØ¯"
|
||||
inMb: "باŲŲ
ŲØēØ§Ø¨Ø§ŲØĒ"
|
||||
iconUrl: "ØąØ§Ø¨Øˇ Ø§ŲØŖŲŲŲŲØŠ"
|
||||
bannerUrl: "ØąØ§Ø¨Øˇ ØĩŲØąØŠ اŲŲØ§ŲØĒØŠ"
|
||||
backgroundImageUrl: "ØąØ§Ø¨Øˇ ØĩŲØąØŠ Ø§ŲØŽŲŲŲØŠ"
|
||||
basicInfo: "اŲŲ
ØšŲŲŲ
اØĒ Ø§ŲØŖØŗØ§ØŗŲØŠ "
|
||||
pinnedUsers: "اŲŲ
ØŗØĒ؎دŲ
ŲŲ Ø§ŲŲ
ØĢبØĒŲŲ"
|
||||
pinnedUsersDescription: "ŲØ§ØĻŲ
ØŠ اŲŲ
ØŗØĒ؎دŲ
ŲŲ Ø§ŲŲ
ØĢبØĒŲŲ ŲŲ ŲØŗØ§Ų \"Ø§ØŗØĒŲØ´Ų\" Ø Ø§ØŦØšŲ ŲŲ Ø§ØŗŲ
Ų
ØŗØĒ؎دŲ
ŲŲ ØŗØˇØą ŲŲØØ¯Ų."
|
||||
pinnedPages: "Ø§ŲØĩŲØØ§ØĒ اŲŲ
ØĢبØĒØŠ"
|
||||
pinnedPagesDescription: "ØŖØ¯ØŽŲ Ų
ØŗØ§Øą Ø§ŲØĩŲØØ§ØĒ Ø§ŲØĒŲ ØĒØąŲØ¯ ØĒØĢØ¨ŲØĒŲØ§ ŲŲ ØŖØšŲŲ ŲØ°Ø§ اŲŲ
Ųب𨠨§ØŦØšŲ ŲŲ Ų
ØŗØ§Øą ŲŲ ØŗØˇØą ŲŲØØ¯Ų."
|
||||
pinnedClipId: "Ų
ØšØąŲŲ Ø§ŲŲ
Ø´Ø¨Ų Ø§ŲŲ
ØĢبØĒ"
|
||||
pinnedNotes: "Ų
ŲØ§ØØ¸ØŠ Ų
ØĢبØĒØŠ"
|
||||
pinnedUsers: "اŲŲ
ØŗØĒ؎دŲ
ŲŲ Ø§ŲŲ
Ø¯Ø¨ØŗŲŲ"
|
||||
pinnedUsersDescription: "ŲØ§ØĻŲ
ØŠ اŲŲ
ØŗØĒ؎دŲ
ŲŲ Ø§ŲŲ
Ø¯Ø¨ØŗŲŲ ŲŲ ŲØŗØ§Ų \"Ø§ØŗØĒŲØ´Ų\" Ø Ø§ØŦØšŲ ŲŲ Ø§ØŗŲ
Ų
ØŗØĒ؎دŲ
ŲŲ ØŗØˇØą ŲŲØØ¯Ų."
|
||||
pinnedPages: "Ø§ŲØĩŲØØ§ØĒ اŲŲ
Ø¯Ø¨ØŗØŠ"
|
||||
pinnedPagesDescription: "ØŖØ¯ØŽŲ Ų
ØŗØ§Øą Ø§ŲØĩŲØØ§ØĒ Ø§ŲØĒŲ ØĒØąŲØ¯ ØĒØ¯Ø¨ŲØŗŲا ŲŲ ØŖØšŲŲ ŲØ°Ø§ اŲŲ
Ųب𨠨§ØŦØšŲ ŲŲ Ų
ØŗØ§Øą ŲŲ ØŗØˇØą ŲŲØØ¯Ų."
|
||||
pinnedClipId: "Ų
ØšØąŲŲ Ø§ŲŲ
Ø´Ø¨Ų Ø§ŲŲ
Ø¯Ø¨Øŗ"
|
||||
pinnedNotes: "Ų
ŲØ§ØØ¸ØŠ Ų
Ø¯Ø¨ØŗØŠ"
|
||||
hcaptcha: "hCaptcha"
|
||||
enableHcaptcha: "ŲØšŲŲ hCaptcha"
|
||||
hcaptchaSiteKey: "Ų
ŲØĒØ§Ø اŲŲ
ŲŲØš"
|
||||
hcaptchaSecretKey: "اŲŲ
ŲØĒØ§Ø Ø§ŲØŗØąŲ"
|
||||
mcaptchaSiteKey: "Ų
ŲØĒØ§Ø اŲŲ
ŲŲØš"
|
||||
mcaptchaSecretKey: "اŲŲ
ŲØĒØ§Ø Ø§ŲØŗØąŲ"
|
||||
recaptcha: "reCAPTCHA"
|
||||
enableRecaptcha: "ØĒŲ
ŲŲŲ reCAPTCHA"
|
||||
recaptchaSiteKey: "Ų
ŲØĒØ§Ø اŲŲ
ŲŲØš"
|
||||
@@ -375,7 +357,6 @@ antennaExcludeKeywords: "اŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ اŲŲ
ØŗØĒØĢŲØ§ØŠ"
|
||||
antennaKeywordsDescription: "Ø§ŲØĩŲ Ø¨ŲŲŲŲ
بŲ
ØŗØ§ŲØŠ ŲØ§ØŗØĒ؎داŲ
Ų
ؚاŲ
Ų \"Ų\" ØŖŲ Ø¨ØŗØˇØą ŲØ§ØŗØĒ؎داŲ
Ų
ؚاŲ
Ų \"ØŖŲ\""
|
||||
notifyAntenna: "ŲØ¨ŲŲŲ Ø¨ØĩŲŲ Ų
ŲØ§ØØ¸Ø§ØĒ ØŦØ¯ŲØ¯ØŠ"
|
||||
withFileAntenna: "Ų
ŲØ§ØØ¸Ø§ØĒ ØĒØŲŲ Ų
ŲŲØ§ØĒ ŲŲØˇ"
|
||||
enableServiceworker: "ŲØšŲŲ ØĨØąØŗØ§Ų Ø§ŲØĨØ´ØšØ§ØąØ§ØĒ ŲŲŲ
ØĒØĩŲØ"
|
||||
antennaUsersDescription: "Ø§ŲØĒØ¨ Ø§ØŗŲ
Ų
ØŗØĒ؎دŲ
ŲŲŲ ØŗØˇØą"
|
||||
caseSensitive: "ØØŗØ§ØŗŲØŠ ØØ§ŲØŠ Ø§ŲØŖØØąŲ"
|
||||
withReplies: "Ø¨Ø§ŲØąØ¯ŲØ¯"
|
||||
@@ -398,15 +379,11 @@ about: "ØšŲ"
|
||||
aboutMisskey: "ØšŲ Misskey"
|
||||
administrator: "اŲŲ
Ø¯ŲØą"
|
||||
token: "Ø§ŲØąŲ
Ø˛ اŲŲ
Ų
ŲØ˛"
|
||||
2fa: "Ø§ŲØ§ØŗØĒŲØĢØ§Ų بؚاŲ
ŲŲŲŲŲ"
|
||||
totp: "ØĒØˇØ¨ŲŲ Ø§ØŗØĒŲØĢØ§Ų"
|
||||
moderator: "Ų
Ø´ØąŲŲ"
|
||||
moderation: "Ø§ŲØĨØ´ØąØ§Ų"
|
||||
nUsersMentioned: "{n} Ų
ØŗØĒ؎دŲ
ŲŲ ØŖŲØ´ŲØą ØĨŲŲŲŲ
"
|
||||
securityKeyAndPasskey: "Ø§ŲØŖŲ
Ų ŲŲ
ŲØ§ØĒŲØ Ø§ŲØŖŲ
اŲ"
|
||||
securityKey: "Ų
ŲØĒØ§Ø Ø§ŲØŖŲ
اŲ"
|
||||
lastUsed: "ØĸØŽØą Ø§ØŗØĒ؎داŲ
"
|
||||
lastUsedAt: "ØĸØŽØą Ø§ØŗØĒ؎داŲ
: {t}"
|
||||
unregister: "ØĨŲØēØ§ØĄ Ø§ŲØĒØŗØŦŲŲ"
|
||||
passwordLessLogin: "ŲŲØŦ Ų
ŲŲ Ø¯ŲŲ ŲŲŲ
ØŠ ØŗØąŲØŠ"
|
||||
resetPassword: "ØŖØšØ¯ ØĒØšŲŲŲ ŲŲŲ
ØĒŲ Ø§ŲØŗØąŲØŠ"
|
||||
@@ -416,6 +393,7 @@ share: "Ø´Ø§ØąŲŲ"
|
||||
notFound: "ØēŲØą Ų
ŲØŦŲØ¯"
|
||||
notFoundDescription: "ØĒØšØ°Øą Ø§ŲØšØĢŲØą ØšŲŲ ØĩŲØØŠ ŲŲŲØ¯ ØĨŲŲŲØ§ ŲØ°Ø§ Ø§ŲØąØ§Ø¨Øˇ."
|
||||
uploadFolder: "اŲŲ
ØŦŲØ¯ Ø§ŲØ§ŲØĒØąØ§ØļŲ ŲŲØąŲØš"
|
||||
cacheClear: "Ų
ØŗØ Ø°Ø§ŲØąØŠ Ø§ŲØĒØŽØ˛ŲŲ Ø§ŲŲ
Ø¤ŲØĒ"
|
||||
markAsReadAllNotifications: "ŲØļØš ØŦŲ
ب𠨧بĨØ´ØšØ§ØąØ§ØĒ ŲØŖŲŲØ§ Ų
ŲØąŲØĄØŠ"
|
||||
markAsReadAllUnreadNotes: "ØšŲŲŲ
ØŦŲ
ب𠨧ŲŲ
ŲØ§ØØ¸Ø§ØĒ ŲŲ
ŲØąŲØĄØŠ"
|
||||
markAsReadAllTalkMessages: "ØšŲŲŲ
ØŦŲ
ŲØš Ø§ŲØąØŗØ§ØĻŲ ŲŲ
ŲØąŲØĄØŠ"
|
||||
@@ -433,6 +411,8 @@ retype: "ØŖØšØ¯ اŲŲØĒØ§Ø¨ØŠ"
|
||||
noteOf: "Ų
ŲØ§ØØ¸Ø§ØĒ {user}"
|
||||
quoteAttached: "اŲŲØĒŲØ¨ØŗŲ"
|
||||
quoteQuestion: "ØŖØĒØąŲØ¯ ØĒØļŲ
ŲŲŲØ§ ŲØ§ŲØĒØ¨Ø§Øŗ"
|
||||
noMessagesYet: "ŲŲØŗ ŲŲØ§Ų ØąØŗØ§ØĻŲ Ø¨ØšØ¯"
|
||||
newMessageExists: "ŲŲØ¯ ØĒŲŲŲØĒ ØąØŗØ§ŲØŠ ØŦØ¯ŲØ¯ØŠ"
|
||||
onlyOneFileCanBeAttached: "ŲŲ
ŲŲŲ ØĨØąŲØ§Ų Ų
ŲŲ ŲØ§ØØ¯ Ø¨Ø§ŲØąØŗØ§ŲØŠ"
|
||||
signinRequired: "ØąØŦØ§ØĄŲ ŲŲØŦ"
|
||||
invitations: "Ø¯ØšŲØŠ"
|
||||
@@ -454,8 +434,6 @@ or: "ØŖŲ"
|
||||
language: "اŲŲØēØŠ"
|
||||
uiLanguage: "ŲØēØŠ ŲØ§ØŦŲØŠ Ø§ŲŲ
ØŗØĒ؎دŲ
"
|
||||
aboutX: "ØšŲ {x}"
|
||||
emojiStyle: "ŲŲ
Øˇ اŲŲØŦŲŲ Ø§ŲØĒØšØ¨ŲØąŲØŠ"
|
||||
showNoteActionsOnlyHover: "ØŖØ¸ŲØą Ø§ŲØĨØŦØąØ§ØĄØ§ØĒ ØšŲØ¯ Ø§ŲØĒŲ
ØąŲØą ŲŲŲ Ø§ŲŲ
ŲØ§ØØ¸ØŠ"
|
||||
noHistory: "Ø§ŲØŗØŦŲ ŲØ§ØąØē"
|
||||
signinHistory: "ØĒØ§ØąŲØŽ ØĒØŗØŦŲŲ Ø§ŲØ¯ØŽŲŲ"
|
||||
doing: "Ø§ŲØĒØ¸Øą ŲØØ¸ØŠ"
|
||||
@@ -466,7 +444,6 @@ createAccount: "ØŖŲØ´ØĻ ØØŗØ§Ø¨Ųا"
|
||||
existingAccount: "Ø§ŲØØŗØ§Ø¨Ø§ØĒ اŲŲ
ŲØŦŲØ¯ØŠ"
|
||||
regenerate: "ØŖØšŲØ¯ Ø§ŲØĒŲŲŲØ¯"
|
||||
fontSize: "ØØŦŲ
Ø§ŲØŽØˇ"
|
||||
limitTo: "ØŗŲŲŲŲ ŲŲ{x}"
|
||||
noFollowRequests: "ŲŲØŗ ŲØ¯ŲŲ ØˇŲØ¨Ø§ØĒ Ų
ØĒابؚ؊ Ų
ØšŲŲØŠ"
|
||||
openImageInNewTab: "ØĨŲØĒØ Ø§ŲØĩŲØąØŠ بØĩŲØØŠ ØŦØ¯ŲØ¯ØŠ"
|
||||
dashboard: "ŲŲØØŠ Ø§ŲØĒØŲŲ
"
|
||||
@@ -488,16 +465,13 @@ objectStoragePrefix: "Ø§ŲØ¨Ø§Ø¯ØĻØŠ"
|
||||
objectStoragePrefixDesc: "ØŗØĒŲØŲØ¸ اŲŲ
ŲŲØ§ØĒ ŲŲ Ų
ØŦŲØ¯Ø§ØĒ ØĒØŲŲ Ø§ØŗŲ
Ø§ØĄŲØ§ ŲØ°Ų Ø§ŲØ¨Ø§Ø¯ØĻØŠ."
|
||||
objectStorageEndpoint: "ŲŲØˇØŠ اŲŲŲØ§ŲØŠ"
|
||||
objectStorageRegion: "اŲŲ
ŲØˇŲØŠ"
|
||||
objectStorageRegionDesc: "ØØ¯Ø¯ Ų
ŲØˇŲØŠ Ų
ØĢŲ \"xx-east-1\". ØĨذا ŲØ§ŲØĒ ؎دŲ
ØĒŲ ŲØ§ ØĒŲ
ŲØ˛ بŲŲ Ø§ŲŲ
ŲØ§ØˇŲ Ø§ØŗØĒ؎دŲ
\"us-east-1\" ØŖŲ Ø§ØĒØąŲŲØ§ ŲØ§ØąØēØŠ ØĨذا ŲŲØĒ ØĒØŗØĒ؎دŲ
Ų
ØĒØēبਧØĒ Ø§ŲØ¨ŲØĻØŠ ØŖŲ Ų
ŲŲØ§ØĒ ØļØ¨Øˇ AWS."
|
||||
objectStorageUseSSL: "Ø§ØŗØĒ؎دŲ
SSL"
|
||||
objectStorageUseSSLDesc: "ØšØˇŲ ŲØ°Ø§ Ø§ŲØŽŲØ§Øą ØĨذا ŲŲ
ØĒØąØ¯ Ø§ØŗØĒ؎داŲ
API ØšØ¨Øą HTTPS"
|
||||
objectStorageUseProxy: "اØĒØĩŲ ØšØ¨Øą ŲŲŲŲ"
|
||||
objectStorageUseProxyDesc: "ØšØˇŲ ŲØ°Ø§ Ø§ŲØŽŲØ§Øą ØĨذا ŲŲ
ØĒØąØ¯ Ø§ØŗØĒ؎داŲ
API ØšØ¨Øą ŲŲŲŲ"
|
||||
objectStorageSetPublicRead: "ØšŲŲŲØ§ Ų\"ØšŲŲŲØŠ\" ØšŲØ¯ Ø§ŲØąŲØš"
|
||||
serverLogs: "ØŗØŦŲØ§ØĒ Ø§ŲØŽØ§Ø¯Ų
"
|
||||
deleteAll: "ØØ°Ų اŲŲŲ"
|
||||
showFixedPostForm: "ØŖØ¸ŲØą ŲŲ
ŲØ°ØŦ اŲŲØĒØ§Ø¨ØŠ ŲŲ ØŖØšŲŲ Ø§ŲØĩŲØØŠ"
|
||||
showFixedPostFormInChannel: "ØŖØ¸ŲØą ŲŲ
ŲØ°ØŦ اŲŲØĒØ§Ø¨ØŠ ŲŲ ØŖØšŲŲ Ø§ŲØŽØˇ Ø§ŲØ˛Ų
ŲŲ (ŲŲŲØ§ØĒ)"
|
||||
newNoteRecived: "ŲŲØ§Ų Ų
ŲØ§ØØ¸Ø§ØĒ ØŦØ¯ŲØ¯ØŠ"
|
||||
sounds: "Ø§ŲØąŲاØĒ"
|
||||
sound: "Ø§ŲØąŲاØĒ"
|
||||
@@ -532,12 +506,9 @@ userSuspended: "ØšŲŲŲ ŲØ°Ø§ اŲŲ
ØŗØĒ؎دŲ
."
|
||||
userSilenced: "ŲŲØĒŲ
ŲØ°Ø§ اŲŲ
ØŗØĒ؎دŲ
."
|
||||
yourAccountSuspendedTitle: "ŲØ°Ø§ Ø§ŲØØŗØ§Ø¨ Ų
ØšŲŲ"
|
||||
yourAccountSuspendedDescription: "ØšŲŲŲ Ø§ŲØØŗØ§Ø¨ Ø¨ØŗØ¨Ø¨ Ø§ŲØĒŲØ§Ų Ø´ØąŲØˇ ؎دŲ
ØŠ اŲŲ
ØĢŲŲ Ų Ų
ا شابŲ. ØĨذا ØŖØąØ¯ØĒ Ų
ØšØąŲØŠ Ø§ŲØĒŲØĩŲŲ ØĒŲØ§ØĩŲ Ų
Øš Ų
Ø¯ŲØą Ø§ŲŲ
ØĢŲŲ. ØąØŦØ§ØĄŲ ŲØ§ ØĒŲØ´ØĻ ØØŗØ§Ø¨ ØŦØ¯ŲØ¯."
|
||||
accountDeleted: "ØŲØ°Ų Ø§ŲØØŗØ§Ø¨"
|
||||
accountDeletedDescription: "ØŲØ°Ų ŲØ°Ø§ Ø§ŲØØŗØ§Ø¨."
|
||||
menu: "اŲŲØ§ØĻŲ
ØŠ"
|
||||
divider: "ŲØ§ØĩŲ"
|
||||
addItem: "ØĨØļØ§ŲØŠ ØšŲØĩØą"
|
||||
rearrange: "ØŖØšØ¯ Ø§ŲØĒØąØĒŲØ¨"
|
||||
relays: "اŲŲ
ŲØąŲØŲاØĒ"
|
||||
addRelay: "ØĨØļØ§ŲØŠ Ų
ŲØąØŲŲ"
|
||||
inboxUrl: "ØąØ§Ø¨Øˇ ØĩŲØ¯ŲŲ Ø§ŲŲØ§ØąØ¯"
|
||||
@@ -560,8 +531,6 @@ author: "اŲŲØ§ØĒب"
|
||||
leaveConfirm: "ŲØ¯ŲŲ ØĒØēŲبਧØĒ ØēŲØą Ų
ØŲŲØ¸ØŠ. ØŖØĒØąŲØ¯ اŲŲ
ØĒابؚ؊ دŲŲ ØŲØ¸ŲØ§Ø"
|
||||
manage: "ØĨØ¯Ø§ØąØŠ "
|
||||
plugins: "Ø§ŲØĨØļØ§ŲØ§ØĒ"
|
||||
preferencesBackups: "اŲŲŲØŗØŽ Ø§ŲØ§ØØĒŲØ§ØˇŲØŠ ŲŲØĨؚداداØĒ"
|
||||
useBlurEffectForModal: "Ø§ØŗØĒ؎دŲ
ØĒØŖØĢŲØą Ø§ŲØˇŲ
Øŗ ŲŲ Ø§ŲŲ
Ø´ØąŲØˇ"
|
||||
useFullReactionPicker: "Ø§ØŗØĒ؎دŲ
Ø§ŲØØŦŲ
اŲŲØ§Ų
Ų ŲŲ
ŲØĒŲŲ Ø§ŲØĒŲØ§ØšŲاØĒ"
|
||||
width: "Ø§ŲØšØąØļ"
|
||||
height: "Ø§ŲØĨØąØĒŲØ§Øš"
|
||||
@@ -620,7 +589,10 @@ abuseReported: "ØŖŲØąØŗŲ Ø§ŲØ¨ŲاØēØ Ø´ŲØąŲا ŲŲ"
|
||||
reporter: "اŲŲ
ŲØ¨ŲŲØē"
|
||||
reporteeOrigin: "ØŖØĩŲ Ø§ŲØ¨ŲاØē"
|
||||
reporterOrigin: "ØŖØĩŲ Ø§ŲŲ
ŲØ¨ŲŲØē"
|
||||
forwardReport: "ŲØŦŲŲ Ø§ŲØ¨ŲاØē ØĨŲŲ Ø§ŲŲ
ØĢŲŲ Ø§ŲØ¨ØšŲد"
|
||||
forwardReportIsAnonymous: "ŲŲ Ø§ŲŲ
ØĢŲŲ Ø§ŲØ¨ØšŲد ØŗŲØ¸ŲØą اŲŲ
بŲŲØē ŲØØŗØ§Ø¨ Ų
ØŦŲŲŲ."
|
||||
send: "ØŖØąØŗŲ"
|
||||
abuseMarkAsResolved: "ØšŲŲŲ
Ø§ŲØ¨ŲاØē ŲŲ
ØŲŲŲ"
|
||||
openInNewTab: "Ø§ŲØĒØ ŲŲ ŲØŗØ§Ų ØŦØ¯ŲØ¯"
|
||||
defaultNavigationBehaviour: "ØŗŲŲŲ Ø§ŲŲ
ŲØ§ØØŠ Ø§ŲØ§ŲØĒØąØ§ØļŲ"
|
||||
editTheseSettingsMayBreakAccount: "ØĒؚدŲŲ ŲØ°Ų Ø§ŲØĨؚداداØĒ ŲØ¯ ŲØŗØ¨Ø¨ ØšØˇØ¨ŲØ§ ŲØØŗØ§Ø¨Ų"
|
||||
@@ -634,9 +606,7 @@ clip: "Ų
ŲØ´Ø¨Ų"
|
||||
createNew: "ØŖŲØ´ŲØĻ ØŦØ¯ŲØ¯"
|
||||
optional: "ا؎ØĒŲØ§ØąŲ"
|
||||
createNewClip: "ØŖŲØ´ØĻ Ų
ŲØ´Ø¨ŲŲØ§ ØŦØ¯ŲØ¯Ųا"
|
||||
confirmToUnclipAlreadyClippedNote: "ŲØ°Ų اŲŲ
ŲØ§ØØ¸ØŠ ØĒŲØĒŲ
Ų ŲŲŲ
Ø´Ø¨Ų {name} ØŗŲŲŲØ§Ø ØŖØĒØąŲØ¯ ØØ°ŲŲØ§ Ų
ŲŲ⸎"
|
||||
public: "ØšŲŲŲ"
|
||||
private: "؎اØĩ"
|
||||
i18nInfo: "ŲØĒØąØŦŲ
Ų
ØĒØˇŲØšŲŲ Ų
ŲØŗŲŲ ØĨŲŲ ØšØ¯ØŠ ب稧ØĒØ ŲŲ
ŲŲŲ Ø§ŲŲ
ØŗØ§ØšØ¯ØŠ ØšØ¨Øą {link}"
|
||||
manageAccessTokens: "ØĨØ¯Ø§ØąØŠ ØąŲ
ŲØ˛ اŲŲØĩŲŲ"
|
||||
accountInfo: "Ų
ØšŲŲŲ
اØĒ Ø§ŲØØŗØ§Ø¨"
|
||||
@@ -657,7 +627,6 @@ driveFilesCount: "ؚدد اŲŲ
ŲŲØ§ØĒ ŲŲ ŲØąØĩ Ø§ŲØĒØŽØ˛ŲŲ"
|
||||
driveUsage: "اŲŲ
ØŗØĒØēŲ Ų
Ų ŲØąØĩ Ø§ŲØĒØŽØ˛ŲŲ"
|
||||
noCrawle: "Ø§ØąŲØļ ŲŲØąØŗØŠ Ø˛Ø§ØŲ اŲŲŲØ¨"
|
||||
noCrawleDescription: "ŲØˇŲب Ų
Ų Ų
ØØąŲاØĒ Ø§ŲØ¨ØØĢ ØŖŲŲØ§ ŲŲŲب਺ب§ Ų
ŲŲŲ Ø§ŲØ´ØŽØĩŲ ŲŲ
ŲØ§ØØ¸Ø§ØĒ ŲØĩŲØØ§ØĒŲ ŲŲ
ا شابŲ."
|
||||
lockedAccountInfo: "ØŗØĒŲŲŲ ŲØ°Ų اŲŲ
ŲØ§ØØ¸ØŠ Ų
ØąØĻŲØŠ ŲŲØŦŲ
ŲØš Ų
اŲŲ
ØĒØØ¯Ø¯ Ų
ØąØĻØĒŲŲØ§ ØĨŲŲ \"ŲŲŲ
ØĒابؚŲŲ ŲŲØˇ\""
|
||||
alwaysMarkSensitive: "ØšŲŲŲ
Ø§ŲØĒØąØ§ØļŲŲØ§ ØŦŲ
ŲØš Ų
ŲØ§ØØ¸Ø§ØĒŲ ŲØ°Ø§ØĒ Ų
ØØĒŲŲ ØØŗØ§Øŗ"
|
||||
loadRawImages: "ØŲ
ŲŲ Ø§ŲØĩŲØą Ø§ŲØŖØĩŲŲØŠ Ø¨Ø¯ŲŲØ§ Ų
Ų Ø§ŲŲ
ØĩØēØąØ§ØĒ"
|
||||
disableShowingAnimatedImages: "ŲØ§ ØĒØ´ØēŲŲ Ø§ŲØĩŲØą Ø§ŲŲ
ØĒØØąŲØŠ"
|
||||
@@ -671,12 +640,10 @@ contact: "Ø§ŲØĒŲØ§ØĩŲ"
|
||||
useSystemFont: "Ø§ØŗØĒ؎دŲ
Ø§ŲØŽØˇ Ø§ŲØ§ŲØĒØąØ§ØļŲØŠ ŲŲŲØ¸Ø§Ų
"
|
||||
clips: "Ų
شابŲ"
|
||||
experimentalFeatures: "Ų
ŲŲØ˛Ø§ØĒ ا؎ØĒØ¨Ø§ØąŲØŠ"
|
||||
experimental: "ا؎ØĒØ¨Ø§ØąŲ"
|
||||
developer: "اŲŲ
ØˇŲØą"
|
||||
makeExplorable: "ØŖØ¸ŲØą Ø§ŲØØŗØ§Ø¨ ŲŲ ØĩŲØØŠ \"Ø§ØŗØĒŲØ´Ø§Ų\""
|
||||
makeExplorableDescription: "بØĒØšØˇŲŲ ŲØ°Ø§ Ø§ŲØŽŲØ§Øą ŲŲ ŲØ¸ŲØą ØØŗØ§Ø¨Ų ŲŲ ØĩŲØØŠ \"Ø§ØŗØĒŲØ´Ø§Ų\""
|
||||
left: "ŲØŗØ§Øą"
|
||||
center: "ŲØŗØˇ"
|
||||
showGapBetweenNotesInTimeline: "ØŖØ¸ŲØą ŲØŦŲØ§ØĒ بŲŲ Ø§ŲŲ
Ø´Ø§ØąŲØ§ØĒ ŲŲ Ø§ŲØŽŲØˇ Ø§ŲØ˛Ų
ŲŲ"
|
||||
wide: "ØšØąŲØļ"
|
||||
narrow: "ØąŲŲØš"
|
||||
reloadToApplySetting: "ØŗŲŲØˇØ¨Ų ŲØ°Ø§ Ø§ŲØĨؚداد بؚد ØĨؚاد؊ ØĒØŲ
ŲŲ Ø§ŲØĩŲØØŠØ ØŖØĒØąŲØ¯ ØĨؚاد؊ ØĒØŲ
ŲŲŲØ§ Ø§ŲØĸŲØ"
|
||||
@@ -694,7 +661,6 @@ accentColor: "ØˇØ§Ø¨Øš ŲŲŲŲ"
|
||||
textColor: "ŲŲŲ Ø§ŲŲØĩ"
|
||||
saveAs: "اØŲظ ŲŲ..."
|
||||
advanced: "Ų
ØĒŲØ¯Ų
"
|
||||
advancedSettings: "ØĨؚداداØĒ Ų
ØĒŲØ¯Ų
ØŠ"
|
||||
value: "اŲŲŲŲ
ØŠ"
|
||||
createdAt: "ØŖŲŲØ´ØĻ ŲŲ"
|
||||
updatedAt: "ØŲØ¯ŲØĢ ŲŲ"
|
||||
@@ -714,7 +680,6 @@ editCode: "ØØąØą Ø§ŲØ´ŲØąØŠ"
|
||||
apply: "ØĒØˇØ¨ŲŲ"
|
||||
receiveAnnouncementFromInstance: "Ø§ØŗØĒŲŲ
ØĨØ´ØšØ§ØąØ§ØĒ Ų
Ų ŲØ°Ø§ اŲŲ
ØĢŲŲ"
|
||||
emailNotification: "ØĨØ´ØšØ§ØąØ§ØĒ Ø§ŲØ¨ØąŲد اŲŲØĒØąŲŲŲ"
|
||||
publish: "ØšŲŲŲ"
|
||||
inChannelSearch: "Ø§Ø¨ØØĢ ØšŲ ŲŲØ§ØŠ"
|
||||
useReactionPickerForContextMenu: "Ø§ŲØĒØ Ų
ŲØĒŲŲ Ø§ŲØĒŲØ§ØšŲاØĒ ØšŲØ¯ اŲŲŲØą Ø¨Ø§ŲØ˛Øą Ø§ŲØŖŲŲ
Ų"
|
||||
typingUsers: "{users} ŲŲØĒØ¨(ŲŲ)..."
|
||||
@@ -727,7 +692,7 @@ unlikeConfirm: "ØŖØĒØąŲØ¯ ØĨŲØēØ§ØĄ ØĨØšØŦØ§Ø¨ŲØ"
|
||||
fullView: "Ų
ŲØĄ Ø§ŲØ´Ø§Ø´ØŠ"
|
||||
quitFullView: "Ø§ØŽØąØŦ Ų
Ų ŲØļØš Ų
ŲØĄ ŲŲØ´Ø§Ø´ØŠ"
|
||||
addDescription: "ØŖØļŲ ŲØĩŲŲØ§"
|
||||
userPagePinTip: "ŲØšØąØļ Ų
ŲØ§ØØ¸ØŠ ŲŲØ§ ا؎ØĒØą \"ØĢبØĒŲØ§ ØšŲŲ Ø§ŲØĩŲØØŠ Ø§ŲØ´ØŽØĩŲØŠ\" Ų
Ų ŲØ§ØĻŲ
ØŠ ØĒŲŲ Ø§ŲŲ
ŲØ§ØØ¸ØŠ."
|
||||
userPagePinTip: "ŲØšØąØļ Ų
ŲØ§ØØ¸ØŠ ŲŲØ§ ا؎ØĒØą \"Ø¯Ø¨ØŗŲØ§ ØšŲŲ Ø§ŲØĩŲØØŠ Ø§ŲØ´ØŽØĩŲØŠ\" Ų
Ų ŲØ§ØĻŲ
ØŠ ØĒŲŲ Ø§ŲŲ
ŲØ§ØØ¸ØŠ."
|
||||
notSpecifiedMentionWarning: "ŲŲ Ø§ŲŲ
ŲØ§ØØ¸ØŠ Ø°ŲØą ŲŲ
ØŗØĒ؎دŲ
ŲŲ ŲŲ ŲØŗØĒŲŲ
ŲŲØ§."
|
||||
info: "ØšŲ"
|
||||
userInfo: "Ų
ØšŲŲŲ
اØĒ اŲŲ
ØŗØĒ؎دŲ
"
|
||||
@@ -754,14 +719,12 @@ noMaintainerInformationWarning: "ŲŲ
ØĒŲØļØ¨Øˇ Ų
ØšŲŲŲ
اØĒ اŲŲ
Ø¯ŲØą"
|
||||
noBotProtectionWarning: "ŲŲ
ØĒØļØ¨Øˇ Ø§ŲØŲ
Ø§ŲØŠ Ų
Ų Ø§ŲØØŗØ§Ø¨Ø§ØĒ Ø§ŲØĸŲŲØŠ"
|
||||
configure: "اØļØ¨Øˇ"
|
||||
postToGallery: "Ø§ŲØ´Øą ŲŲ Ø§ŲŲ
ØšØąØļ"
|
||||
postToHashtag: "Ø§ŲØ´Øą Ø¨ŲØ°Ø§ اŲŲØŗŲ
"
|
||||
gallery: "اŲŲ
ØšØąØļ"
|
||||
recentPosts: "اŲŲ
Ø´Ø§ØąŲØ§ØĒ Ø§ŲØØ¯ŲØĢØŠ"
|
||||
popularPosts: "اŲŲ
Ø´Ø§ØąŲØ§ØĒ اŲŲ
ØĒداŲŲØŠ"
|
||||
shareWithNote: "Ø´Ø§ØąŲŲ ŲŲ Ų
ŲØ§ØØ¸ØŠ"
|
||||
ads: "Ø§ŲØĨØšŲØ§ŲاØĒ"
|
||||
expiration: "ŲŲØĒŲŲ Ø§ØŗØĒØˇŲØ§Øš Ø§ŲØąØŖŲ ŲŲ"
|
||||
startingperiod: "Ø§Ø¨Ø¯ØŖ"
|
||||
memo: "ØĒذŲŲØą"
|
||||
priority: "Ø§ŲØŖŲŲŲŲØŠ"
|
||||
high: "ؚاŲŲØŠ"
|
||||
@@ -787,18 +750,13 @@ translate: "ØĒØąØŦŲ
"
|
||||
translatedFrom: "ØĒŲØąØŦŲ
Ų
Ų {x}"
|
||||
accountDeletionInProgress: "ØØ°Ų Ø§ŲØØŗØ§Ø¨ ØŦØ§ØąŲ"
|
||||
usernameInfo: "Ø§ŲØ§ØŗŲ
Ø§ŲØ°Ų ŲŲ
ŲØ˛Ų ØšŲ Ø¨Ø§ŲŲ Ų
ØŗØĒ؎دŲ
Ų ŲØ°Ø§ Ø§ŲØŽØ§Ø¯Ų
Ø ŲŲ
ŲŲŲ Ø§ØŗØĒ؎داŲ
Ø§ŲØØąŲŲ Ø§ŲŲØ§ØĒŲŲŲØŠ (a~z, A~Z) ŲØ§ŲØŖØąŲØ§Ų
(0~9) ŲØ§ŲØ´ØąØˇØŠ Ø§ŲØŗŲŲŲØŠ (_). ŲØ§ ŲŲ
ŲŲŲ ØĒØēŲŲØąŲ بؚد ØĒØŗØŦŲŲŲ."
|
||||
devMode: "ŲØļØš اŲŲ
ŲØˇŲŲØą"
|
||||
keepCw: "ØŖØ¨ŲŲ ØšŲŲ ØĒØØ°ŲØąØ§ØĒ اŲŲ
ØØĒŲŲ"
|
||||
pubSub: "ØØŗØ§Ø¨Ø§ØĒ Pub/Sub"
|
||||
lastCommunication: "ØĸØŽØą ØĒŲØ§ØĩŲ"
|
||||
resolved: "ØšŲŲØŦ"
|
||||
unresolved: "ŲŲ
ŲØšØ§ŲØŦ"
|
||||
breakFollow: "ØĨŲØēØ§ØĄ Ø§ŲØ§Ø´ØĒØąØ§Ų"
|
||||
breakFollowConfirm: "ØŖŲ
ØĒØŖŲØ¯ Ų
Ų ØĨØ˛Ø§ŲØŠ Ø§ŲŲ
ØĒØ§Ø¨ŲØš Ø"
|
||||
itsOn: "Ų
ŲØšŲŲ"
|
||||
itsOff: "Ų
ØšØˇŲŲ"
|
||||
on: "Ų
ŲØšŲ"
|
||||
off: "Ų
ØšØˇŲ"
|
||||
emailRequiredForSignup: "ØšŲŲØ§Ų Ø§ŲØ¨ØąŲد Ø§ŲØĨŲŲØĒØąŲŲŲ ØĨŲØ˛Ø§Ų
Ų ŲŲØĒØŗØŦŲŲ"
|
||||
unread: "ØēŲØą Ų
ŲØąŲØĄØŠ"
|
||||
filter: "ØąØ´ŲØ"
|
||||
@@ -809,7 +767,8 @@ makeReactionsPublicDescription: "ŲØ°Ø§ ØŗŲØŦØšŲ ŲØ§ØĻŲ
ØŠ ØĒŲØ§ØšŲاØĒŲ
|
||||
classic: "ØĒŲŲŲØ¯Ų"
|
||||
muteThread: "Ø§ŲØĒŲ
اŲŲŲØ§Ø´"
|
||||
unmuteThread: "Ø§ØąŲØš Ø§ŲŲØĒŲ
ØšŲ Ø§ŲŲŲØ§Ø´"
|
||||
continueThread: "Ø§ØšØąØļ بŲŲØŠ Ø§ŲŲŲØ§Ø´"
|
||||
ffVisibility: "Ų
ØąØĻŲØŠ Ø§ŲŲ
ØĒØ§Ø¨ŲØšŲŲ/اŲŲ
ØĒØ§Ø¨ŲØšŲŲ"
|
||||
ffVisibilityDescription: "ŲØŗŲ
Ø ŲŲ Ø¨ØĒØØ¯Ųد Ų
Ų ŲŲ
ŲŲŲŲ
ØąØ¤ŲØŠ Ų
ØĒØ§Ø¨ŲØšŲŲ ŲŲ
ØĒØ§Ø¨ŲØšŲŲ."
|
||||
deleteAccountConfirm: "ØŗŲØØ°Ų ØØŗØ§Ø¨Ų ŲŲØ§ØĻŲŲØ§Ø ØŖØĒØąŲØ¯ اŲŲ
ØĒابؚ؊Ø"
|
||||
incorrectPassword: "ŲŲŲ
ØŠ Ø§ŲØŗØą ØŽØ§ØˇØĻØŠ."
|
||||
voteConfirm: "Ų
ØĒŲŲŲŲŲ Ų
Ų ØĒØĩŲŲØĒŲ ŲŲ {choice}Ø"
|
||||
@@ -831,301 +790,23 @@ tenMinutes: "10 Ø¯ŲØ§ØĻŲ"
|
||||
oneHour: "ØŗØ§ØšØŠ"
|
||||
oneDay: "ŲŲŲ
"
|
||||
oneWeek: "ØŖØŗØ¨ŲØš"
|
||||
oneMonth: "Ø´ŲØą"
|
||||
failedToFetchAccountInformation: "ØĒØšØ°Øą ØŦŲØ¨ Ų
ØšŲŲŲ
اØĒ Ø§ŲØØŗØ§Ø¨"
|
||||
cropImage: "Ø§ŲØĒØĩاØĩ Ø§ŲØĩŲØąØŠ"
|
||||
cropImageAsk: "ØŖØĒØąŲØ¯ Ø§ŲØĒØĩاØĩ ŲØ°Ų Ø§ŲØĩŲØąØŠ"
|
||||
cropYes: "Ø§ŲØĒØĩ"
|
||||
cropNo: "Ø§ØŗØĒ؎دŲ
ŲØ§ ŲŲ
ا ŲŲ"
|
||||
file: "اŲŲ
ŲŲØ§ØĒ"
|
||||
recentNHours: "ØĸØŽØą {n} ØŗØ§ØšØŠ"
|
||||
recentNDays: "ØĸØŽØą {n} ØŖŲØ§Ų
"
|
||||
noEmailServerWarning: "؎ادŲ
Ø§ŲØ¨ØąŲد ØēŲØą Ų
ØļØ¨ŲØˇ."
|
||||
thereIsUnresolvedAbuseReportWarning: "ØĒŲØŦد Ø¨ŲØ§ØēاØĒ ØēŲØą Ų
ØšØ§ŲØŦØŠ."
|
||||
recommended: "Ų
ŲØĒØąØ"
|
||||
check: "Ø§ŲØĒØŲŲ"
|
||||
driveCapOverrideLabel: "ØēŲŲØą ØØŦŲ
ŲØąØĩ Ø§ŲØĒØŽØ˛ŲŲ ŲŲØ°Ø§ اŲŲ
ØŗØĒ؎دŲ
"
|
||||
driveCapOverrideCaption: "ØŖØšØ¯ Ø§ŲØØŦŲ
ØĨŲŲ Ø§ŲŲŲŲ
ØŠ Ø§ŲØ§ŲØĒØąØ§ØļŲØŠ Ø¨ØĨØ¯ØŽØ§Ų 0 ØŖŲ ØŖŲŲ."
|
||||
requireAdminForView: "ŲØ§ØŗØĒØšØąØ§Øļ ŲØ°Ų Ø§ŲØĩŲØØŠ ŲØŦب ØšŲŲŲ Ø§ŲŲŲŲØŦ ŲŲ
Ø¯ŲØą."
|
||||
isSystemAccount: "ØØŗØ§Ø¨ ØŖŲØ´ØŖŲ اŲŲØ¸Ø§Ų
ŲŲŲØ¯Ø§Øą Ų
Ų ŲŲØ¨ŲŲ."
|
||||
typeToConfirm: "ØŖØ¯ØŽŲ {x} ŲŲØĒØŖŲŲØ¯"
|
||||
deleteAccount: "Ø§ØØ°Ų Ø§ŲØØŗØ§Ø¨"
|
||||
document: "Ø§ŲØĒŲØĢŲŲ"
|
||||
numberOfPageCache: "ؚدد Ø§ŲØĩŲØØ§ØĒ اŲŲ
ØŽØ˛ŲØŠ Ų
Ø¤ŲØĒŲØ§"
|
||||
numberOfPageCacheDescription: "ØąŲØš Ø§ŲØąŲŲ
ØŗŲØŗØŲ ØĒØŦØąØ¨ØŠ اŲŲ
ØŗØĒ؎دŲ
ŲŲŲ ØŗŲØąŲØš Ø§ØŗØĒŲŲØ§Ų Ø§ŲØ°Ø§ŲØąØŠ."
|
||||
logoutConfirm: "ØŖØĒØąŲØ¯ Ø§ŲØŽØąŲØŦØ"
|
||||
lastActiveDate: "ØĸØŽØą Ø§ØŗØĒ؎داŲ
"
|
||||
statusbar: "Ø´ØąŲØˇ Ø§ŲØØ§ŲØŠ"
|
||||
pleaseSelect: "ØØ¯Ø¯ ØŽŲØ§ØąŲا"
|
||||
reverse: "اŲŲØ¨"
|
||||
colored: "Ų
ŲŲŲŲ"
|
||||
refreshInterval: "Ų
ŲŲØŠ Ø§ŲØĒØØ¯ŲØĢ"
|
||||
label: "Ø§ŲØĒØŗŲ
ŲØŠ"
|
||||
type: "ŲŲØš"
|
||||
speed: "ØŗØąØšØŠ"
|
||||
slow: "Ø¨ØˇŲØĄ"
|
||||
fast: "ØŗØąŲØš"
|
||||
sensitiveMediaDetection: "Ø§ŲØĒØšØąŲ ØšŲŲ Ø§ŲŲ
ØØĒŲŲ Ø§ŲØØŗØ§Øŗ"
|
||||
localOnly: "اŲŲ
ØŲŲ ŲŲØˇ"
|
||||
remoteOnly: "Ø¨ŲØšØ¯Ų ŲŲØˇ"
|
||||
failedToUpload: "ŲØ´Ų Ø§ŲØąŲØš"
|
||||
cannotUploadBecauseInappropriate: "ØĒØšØ°Øą ØąŲØš Ø§ŲŲ
ŲŲ ŲŲØŦŲØ¯ Ų
ØØĒŲŲ ØØŗØ§Øŗ ŲŲŲ."
|
||||
cannotUploadBecauseNoFreeSpace: "ØĒØšØ°Øą ØąŲØš Ø§ŲŲ
ŲŲ ŲŲŲØĩ Ų
ØŗØ§ØØŠ Ø§ŲØĒØŽØ˛ŲŲ."
|
||||
cannotUploadBecauseExceedsFileSizeLimit: "ØĒØšØ°Øą ØąŲØš Ø§ŲŲ
ŲŲ Ø¨ØŗØ¨Ø¨ ØĒØŦØ§ŲØ˛ ØØŦŲ
Ų ŲŲØØ¯ اŲŲ
ØŗŲ
ŲØ"
|
||||
beta: "Ø¨ŲØĒØ§"
|
||||
enableAutoSensitive: "ØĒØšŲŲŲ ØĒŲŲØ§ØĻŲ ŲŲ
ØØĒŲŲ ØØŗØ§Øŗ NSFW"
|
||||
enableAutoSensitiveDescription: "ØšŲØ¯ Ø§ŲØ§ØŗØĒØˇØ§ØšØŠ ŲØŗŲ
Ø Ø¨Ø§ŲØĒØ´Ø§Ų اŲŲ
ØØĒŲŲ ØØŗØ§Øŗ NSFW ØĒŲŲØ§ØĻŲŲØ§ ŲŲ Ø§ŲŲØŗØ§ØĻØˇ Ø¨Ø§ØŗØĒ؎داŲ
ØĒØšŲŲ
Ø§ŲØĸŲØŠ ŲŲØŗŲ
ŲØ§ ØĒØ¨ØšŲØ§ ŲØ°ŲŲ. ŲØ¯ ŲŲŲŲ ŲØ°Ø§ Ø§ŲØŽŲØ§Øą Ų
ŲØšŲا Ų
Ų ØŦŲØŠ Ø§ŲØŽØ§Ø¯Ų
ŲØŗŲØšŲ
Ų ØØĒŲ ŲØ§Ų ØšŲØˇŲ."
|
||||
activeEmailValidationDescription: "ŲØĒØŲŲ Ų
Ų ØĩØØŠ ØšŲŲØ§Ų Ø§ŲØ¨ØąŲد Ø§ŲØĨŲŲØĒØąŲŲŲ Ø¨Ø´ŲŲ ØŖŲØĢØą ØØ˛Ų
ŲØ§ ŲØ°ŲŲ ØšØ¨Øą ØĒØØ¯Ųد Ų
ا ØĨذا ŲØ§Ų ØšŲŲØ§Ų Ø¨ØąŲØ¯ ØĨŲŲØĒØąŲŲŲ Ų
Ø¤ŲØĒ ŲØĨŲ
ŲØ§ŲŲØŠ Ø§ŲØĒŲØ§ØĩŲ Ų
ØšŲ. ØĨذا ŲŲ
ŲØØ¯Ø¯ ŲØ°Ø§ Ø§ŲØŽŲØ§Øą ŲØŗŲØĒØŲŲ Ų
Ų ŲØŗŲ ØšŲŲØ§Ų Ø§ŲØ¨ØąŲد Ø§ŲØĨŲŲØĒØąŲŲŲ."
|
||||
navbar: "Ø´ØąŲØˇ Ø§ŲØĒŲŲŲ"
|
||||
shuffle: "ØŽŲØˇ"
|
||||
account: "Ø§ŲØØŗØ§Ø¨Ø§ØĒ"
|
||||
move: "ØŖŲŲŲ"
|
||||
pushNotification: "ØĨØąØŗØ§Ų Ø§ŲØĨØ´ØšØ§ØąØ§ØĒ"
|
||||
subscribePushNotification: "ŲØšŲŲ ØĨØąØŗØ§Ų Ø§ŲØĨØ´ØšØ§ØąØ§ØĒ"
|
||||
unsubscribePushNotification: "ØšØˇŲ ØĨØąØŗØ§Ų Ø§ŲØĨØ´ØšØ§ØąØ§ØĒ"
|
||||
pushNotificationAlreadySubscribed: "ØĨØąØŗØ§Ų Ø§ŲØĨØ´ØšØ§ØąØ§ØĒ Ų
ŲØšŲ ØŗŲŲŲØ§"
|
||||
pushNotificationNotSupported: "Ų
ØĒØĩŲØŲ ŲØ§ ŲØ¯ØšŲ
ØĨØąØŗØ§Ų Ø§ŲØĨØ´ØšØ§ØąØ§ØĒ ØŖŲ Ø§ŲŲ
ØĢŲŲ ŲØ§ ŲØ¯ØšŲ
ŲØ§."
|
||||
sendPushNotificationReadMessage: "Ø§ØØ°Ų Ø§ŲØĨØ´ØšØ§ØąØ§ØĒ ŲŲØą ŲØąØ§ØĄØĒŲØ§"
|
||||
sendPushNotificationReadMessageCaption: "ŲØ°Ø§ ŲØ¯ ŲØ˛Ųد Ų
Ų Ų
ØšØ¯Ų Ø§ØŗØĒŲŲØ§Ų Ø§ŲØˇØ§ŲØŠ ŲØŦŲØ§Ø˛Ų."
|
||||
windowMaximize: "اŲ
ŲØŖ Ø§ŲØ´Ø§Ø´ØŠ"
|
||||
windowRestore: "Ø§ØŗØĒØąØŦاؚ"
|
||||
caption: "Ø§ŲØĒØšŲŲŲ Ø§ŲØĒŲØļŲØŲ"
|
||||
loggedInAsBot: "ŲØ§ŲØŦ ŲØĸŲŲ"
|
||||
tools: "ØŖØ¯ŲØ§ØĒ"
|
||||
cannotLoad: "ØĒØšØ°Øą Ø§ŲØĒØŲ
ŲŲ"
|
||||
numberOfProfileView: "Ų
Ø´Ø§ŲØ¯Ø§ØĒ اŲŲ
ŲŲ Ø§ŲØ´ØŽØĩŲ"
|
||||
like: "ØŖØšØŦبŲŲ"
|
||||
unlike: "ØŖŲØēŲ Ø§ŲØĨØšØŦاب"
|
||||
numberOfLikes: "Ø§ŲØĨØšØŦاباØĒ"
|
||||
show: "اŲŲ
Ø¸ŲØą"
|
||||
neverShow: "ŲØ§ ØĒØ¸ŲØąŲ Ų
ØŦØ¯Ø¯ŲØ§"
|
||||
remindMeLater: "ØąØ¨Ų
ا ŲØ§ØŲا"
|
||||
didYouLikeMisskey: "ŲŲ ØŖØšØŦØ¨Ų Ų
ŲØŗŲŲØ"
|
||||
pleaseDonate: "ŲØŗØĒ؎دŲ
{host} Ø§ŲØ¨ØąŲ
ØŦŲØŠ Ø§ŲØØąØŠ Ų
ŲØŗŲŲ. ŲØĒŲ
ŲŲ ØŖŲ ØĒØĒØ¨ØąØšŲØ§ ŲŲŲ
Ø´ØąŲØš Ų
Ų
ا ØŗŲØŗŲ
Ø ŲŲØ§ Ų
ØĒابؚ؊ ØĒØˇŲŲØąŲ!"
|
||||
roles: "Ø§ŲØŖØ¯ŲØ§Øą"
|
||||
role: "Ø§ŲØ¯ŲØą"
|
||||
noRole: "ŲŲ
ŲŲØšØĢØą ØšŲŲ Ø¯ŲØą"
|
||||
normalUser: "Ų
ØŗØĒ؎دŲ
ؚادŲ"
|
||||
undefined: "ØēŲØą Ų
ØšØąŲŲ"
|
||||
assign: "ØŖØŗŲØ¯"
|
||||
unassign: "ØŖŲØē Ø§ŲØĨØŗŲØ§Ø¯"
|
||||
color: "اŲŲŲŲ"
|
||||
manageCustomEmojis: "ØĨØ¯Ø§ØąØŠ Ø§ŲØĨŲŲ
ŲØŦŲ Ø§ŲŲ
ØŽØĩØĩØŠ"
|
||||
youCannotCreateAnymore: "ŲØĩŲØĒ ŲØŗŲŲ Ø§ŲØĨŲØ´Ø§ØĄ."
|
||||
cannotPerformTemporary: "ØēŲØą Ų
ØĒØ§Ø Ų
Ø¤ŲØĒØ§Ų"
|
||||
invalidParamError: "Ų
ؚاŲ
ŲØ§ØĒ ØēŲØą ØĩØ§ŲØØŠ"
|
||||
permissionDeniedError: "ØąŲŲØļØŠ Ø§ŲØšŲ
ŲŲØŠ"
|
||||
preset: "ØĨؚداداØĒ Ų
ØŗØ¨ŲØŠ"
|
||||
selectFromPresets: "ا؎ØĒØą Ų
Ų Ø§ŲØĨؚداداØĒ اŲŲ
ØŗØ¨ŲØŠ"
|
||||
achievements: "Ø§ŲØĨŲØŦØ§Ø˛Ø§ØĒ"
|
||||
gotInvalidResponseError: "Ø§ØŗØĒØŦاب؊ ØēŲØą Ų
ØĒŲŲØšØŠ Ų
Ų Ø§ŲØŽØ§Ø¯Ų
"
|
||||
gotInvalidResponseErrorDescription: "ŲØĒØšØ°Øą Ø§ŲŲØĩŲŲ ØĨŲŲ Ø§ŲØŽØ§Ø¯Ų
ØŖŲØŖŲŲ ŲŲØĩØ§ŲØ ØąØŦØ§ØĄŲ ØØ§ŲŲ ŲØ§ØŲŲØ§."
|
||||
thisPostMayBeAnnoying: "ŲØ°Ø§ ŲØ¯ ŲØ˛ØšØŦ Ø§ŲØĸØŽØąŲŲ."
|
||||
thisPostMayBeAnnoyingHome: "ØŖŲØ´Øą ŲŲ Ø§ŲØŽØˇ Ø§ŲØ˛Ų
ŲŲ Ø§ŲØąØĻŲØŗ"
|
||||
thisPostMayBeAnnoyingCancel: "ØŖŲØēŲ"
|
||||
internalServerError: "ØŽØˇØŖ دا؎ŲŲ ŲŲ Ø§ŲØŽØ§Ø¯Ų
"
|
||||
internalServerErrorDescription: "ŲØ§ØŦŲ Ø§ŲØŽØ§Ø¯Ų
ØŽØˇØŖ ØēŲ Ų
ØĒŲŲØš."
|
||||
copyErrorInfo: "Ø§ŲØŗØŽ ØĒŲØ§ØĩŲŲ Ø§ŲØŽØˇØŖ"
|
||||
joinThisServer: "ØŗØŦŲ ŲŲ ŲØ°Ø§ اŲŲ
ØĢŲŲ"
|
||||
exploreOtherServers: "اؚØĢØą ØšŲŲ Ų
ØĢŲŲ ØĸØŽØą"
|
||||
disableFederationOk: "ØšØˇŲŲ"
|
||||
invitationRequiredToRegister: "ŲØ°Ø§ اŲŲ
ØĢŲŲ ŲŲŲ
دؚŲŲŲ ŲŲØˇ. ŲØĒØŗØŦŲŲ ŲŲŲ ØĒØØĒØ§ØŦ ØąŲ
Ø˛ŲØ§ ØĩØ§ŲØŲØ§."
|
||||
postToTheChannel: "Ø§ŲØ´Øą ŲŲ ŲŲØ§ØŠ"
|
||||
cannotBeChangedLater: "ŲØ§ ŲŲ
ŲŲ ØĒØēŲŲØąŲ ŲØ§ØŲŲØ§."
|
||||
reactionAcceptance: "ŲØ¨ŲŲ Ø§ŲØĒŲØ§ØšŲاØĒ"
|
||||
rolesAssignedToMe: "Ø§ŲØŖØ¯ŲØ§Øą اŲŲ
ØŗŲØ¯ØŠ ØĨŲŲ"
|
||||
resetPasswordConfirm: "ŲŲ ØĒØąŲØ¯ ØĨؚاد؊ ØĒØšŲŲŲ ŲŲŲ
ØŠ Ø§ŲØŗØąØ"
|
||||
license: "Ø§ŲØąØŽØĩØŠ"
|
||||
unfavoriteConfirm: "ØŖØĒØąŲØ¯ ØĨØ˛Ø§ŲØĒŲØ§ Ų
Ų Ø§ŲŲ
ŲØļŲØŠØ"
|
||||
reactionsDisplaySize: "ØØŦŲ
Ø§ŲØĒŲØ§ØšŲاØĒ"
|
||||
limitWidthOfReaction: "ØĒØĩØēŲØą ØØŦŲ
Ø§ŲØĒŲØ§ØšŲاØĒ"
|
||||
noteIdOrUrl: "Ų
ØšØąŲ Ø§ŲŲ
ŲØ§ØØ¸ØŠ ØŖŲ ØąØ§Ø¨ØˇŲØ§"
|
||||
video: "ŲŲØ¯ŲŲ"
|
||||
videos: "ŲŲØ¯ŲŲŲØ§ØĒ"
|
||||
dataSaver: "Ų
ŲŲØą Ø§ŲØ¨ŲØ§ŲاØĒ"
|
||||
accountMigration: "ØĒØąØŲŲ Ø§ŲØØŗØ§Ø¨"
|
||||
accountMoved: "ŲŲŲ ŲØ°Ø§ اŲŲ
ØŗØĒ؎دŲ
ØØŗØ§Ø¨Ų:"
|
||||
accountMovedShort: "ØąŲØŲ ŲØ°Ø§ Ø§ŲØØŗØ§Ø¨."
|
||||
operationForbidden: "ØšŲ
ŲŲØŠ Ų
Ų
ŲŲØšØŠ"
|
||||
forceShowAds: "ØŖØ¸ŲØą Ø§ŲØĨØšŲØ§ŲاØĒ Ø§ŲØĒØŦØ§ØąŲØŠ Ø¯Ø§ØĻŲ
ا"
|
||||
reactionsList: "Ø§ŲØĒŲØ§ØšŲاØĒ"
|
||||
renotesList: "ØĨؚاداØĒ اŲŲØ´Øą"
|
||||
notificationDisplay: "ØĨØ´ØšØ§ØąØ§ØĒ"
|
||||
leftTop: "ØŖØšŲŲ Ø§ŲŲØŗØ§Øą"
|
||||
rightTop: "ØŖØšŲŲ Ø§ŲŲŲ
ŲŲ"
|
||||
leftBottom: "ØŖØŗŲŲ Ø§ŲŲØŗØ§Øą"
|
||||
rightBottom: "ØŖØŗŲŲ Ø§ŲŲŲ
ŲŲ"
|
||||
stackAxis: "اØĒØŦØ§Ų Ø§ŲØĒŲØ¯ŲØŗ"
|
||||
vertical: "ØšŲ
ŲØ¯Ų"
|
||||
horizontal: "ØŦØ§ŲØ¨Ų"
|
||||
position: "اŲŲ
ŲØļØš"
|
||||
serverRules: "ŲŲØ§ŲŲŲ Ø§ŲØŽØ§Ø¯Ų
"
|
||||
pleaseConfirmBelowBeforeSignup: "ØąØŦØ§ØĄŲ ŲØ§ŲŲ ØšŲŲ Ų
ا ŲŲŲ ŲØ¨Ų Ø§ŲØĒØŗØŦŲŲ."
|
||||
pleaseAgreeAllToContinue: "ŲŲŲ
ØĒابؚ؊ ŲØ§ŲŲ ØšŲŲ Ø§ŲØŲŲŲ ØŖØšŲØ§Ų."
|
||||
continue: "Ų
ØĒابؚ؊"
|
||||
preservedUsernames: "ØŖØŗŲ
Ø§ØĄ اŲŲ
ØŗØĒ؎دŲ
ŲŲ Ø§ŲŲ
ØØŦŲØ˛ØŠ"
|
||||
preservedUsernamesDescription: "ŲØ§ØĻŲ
ØŠ Ø¨ØŖØŗŲ
Ø§ØĄ اŲŲ
ØŗØĒ؎دŲ
ŲŲ Ø§ŲŲ
ØØŦŲØ˛ØŠ ŲŲŲ ŲŲ ØŗØˇØą. ŲŲ ŲŲŲØ¨Ų Ø§ŲØĒØŗØŦŲŲ Ø¨ŲØ°Ų Ø§ŲØŖØŗŲ
Ø§ØĄ ŲØŗØĒبŲŲ Ų
ØØĩŲØąØŠ ØšŲŲ Ø§ŲØĒØŗØŦŲŲ Ø§ŲŲØ¯ŲŲ Ø¨ŲØ§ØŗØˇØŠ اŲŲ
Ø¯ŲØąŲŲ. ŲŲ ŲØĒØŖØĢØą اŲŲ
ØŗØĒ؎دŲ
ŲŲ Ø§ŲØ°ŲŲ ŲŲ
ŲŲŲŲ ŲØ°Ų Ø§ŲØŖØŗŲ
Ø§ØĄ ØŗŲŲŲØ§."
|
||||
createNoteFromTheFile: "ØŖŲØ´ØĻ Ų
ŲØ§ØØ¸ØŠ Ų
Ų ŲØ°Ø§ اŲŲ
ŲŲ"
|
||||
archive: "Ø§ŲØŖØąØ´ŲŲ"
|
||||
channelArchiveConfirmTitle: "ØŖØĒØąŲØ¯ ØŖØąØ´ŲØĒ {name}Ø"
|
||||
channelArchiveConfirmDescription: "ŲŲ ŲŲ
ŲŲŲ ŲØ´Øą Ų
ŲØ§ØØ¸Ø§ØĒ ŲŲ Ø§ŲŲŲØ§ØŠ اŲŲ
ØŖØąØ´ŲØŠ ŲŲŲ ØĒØ¸ŲØą ŲŲ ŲØ§ØĻŲ
ØŠ اŲŲŲŲØ§ØĒ ŲŲØ§ ŲŲ ŲØĒØ§ØĻØŦ Ø§ŲØ¨ØØĢ."
|
||||
thisChannelArchived: "ØŖŲØąØ´ŲØĒ ŲØ°Ų اŲŲŲØ§ØŠ."
|
||||
displayOfNote: "ØšØąØļ اŲŲ
ŲØ§ØØ¸ØŠ"
|
||||
initialAccountSetting: "ØĨؚداد اŲŲ
ŲŲ Ø§ŲØ´ØŽØĩŲ"
|
||||
youFollowing: "Ų
ØĒØ§Ø¨ŲØš"
|
||||
preventAiLearning: "Ų
ŲØš Ø§ØŗØĒ؎داŲ
Ø§ŲØ¨ŲØ§ŲØ§ØĒ ŲŲ ØĒØšŲŲŲ
Ø§ŲØĸŲØŠ"
|
||||
options: "ØŽŲØ§ØąØ§ØĒ"
|
||||
specifyUser: "Ų
ØŗØĒ؎دŲ
Ų
ØØ¯Ø¯"
|
||||
failedToPreviewUrl: "ØĒØĒØšØ°Øą اŲŲ
ؚاŲŲØŠ"
|
||||
update: "ØØ¯ŲŲØĢ"
|
||||
rolesThatCanBeUsedThisEmojiAsReaction: "Ø§ŲØŖØ¯ŲØ§Øą Ø§ŲØĒŲ ŲŲØŗŲ
Ø ŲØŖØĩØØ§Ø¨Ųا Ø§ØŗØĒ؎داŲ
ŲØ°Ø§ اØĨŲŲ
ŲØŦŲ ŲŲ Ø§ŲŲØĒŲØ§ØšŲ"
|
||||
rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "ØĨذا ŲŲ
ØĒØØ¯Ø¯ Ø¯ŲØąŲا ŲŲ
ŲŲ ŲŲØŦŲ
ŲØš Ø§ØŗØĒ؎داŲ
ŲØ°Ø§ Ø§ŲØĨŲŲ
ŲØŦŲ ŲŲ Ø§ŲØĒŲØ§ØšŲ."
|
||||
rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "ŲØŦب ØŖŲ ØĒŲŲŲ Ø§ŲØŖØ¯ŲØ§Øą ØšŲŲŲØŠ."
|
||||
cancelReactionConfirm: "ØŖØĒØąŲØ¯ ØØ°Ų ØĒŲØ§ØšŲŲØ"
|
||||
changeReactionConfirm: "ØŖØĒØąŲØ¯ ØĒؚدŲŲ ØĒŲØ§ØšŲŲØ"
|
||||
later: "ŲØ§ØŲاŲ"
|
||||
goToMisskey: "ŲŲ
ŲØŗŲŲ"
|
||||
additionalEmojiDictionary: "ŲŲØ§Ų
ŲØŗ ØĨŲŲ
ŲØŦŲ ØĨØļاŲŲØŠ"
|
||||
installed: "Ų
ŲØĢØ¨ØĒ"
|
||||
enableServerMachineStats: "ŲØ´Øą ØĨØØĩاØĻŲØ§ØĒ ØšØĒاد Ø§ŲØŽØ§Ø¯Ų
"
|
||||
turnOffToImprovePerformance: "ØĒŲØšŲŲŲ ŲØ¯ ŲØ˛Ųد Ø§ŲØŖØ¯Ø§ØĄ."
|
||||
createInviteCode: "ŲŲŲŲØ¯ Ø¯ØšŲØŠ"
|
||||
inviteCodeCreated: "ŲŲŲŲØ¯ØĒ Ø¯ØšŲØŠ"
|
||||
inviteLimitExceeded: "ŲØĩŲØĒŲ ŲØØ¯ ؚدد Ø§ŲØ¯ØšŲاØĒ اŲŲ
ØŗŲ
ŲØ ŲŲ ØĒŲŲŲØ¯Ųا."
|
||||
createLimitRemaining: "ØØ¯ ؚدد Ø§ŲØ¯ØšŲاØĒ: {limit} Ø¯ØšŲØŠ"
|
||||
expirationDate: "ØĒØ§ØąŲØŽ Ø§ŲØĒŲØ§ØĄ Ø§ŲØĩŲØ§ØŲØŠ"
|
||||
noExpirationDate: "ŲØ§ ŲŲØ§ŲØŠ ŲØĩŲØ§ØŲØĒŲØ§"
|
||||
inviteCodeUsedAt: "Ø§ŲØŗØĒ؎دŲ
ØąŲ
Ø˛ Ø§ŲØ¯ØšŲØŠ ŲŲ"
|
||||
registeredUserUsingInviteCode: "Ø§ŲØŗØĒ؎دŲ
ØąŲ
Ø˛ Ø§ŲØ¯ØšŲØŠ"
|
||||
unused: "ØēŲØą Ų
ØŗØĒØšŲ
ŲŲ"
|
||||
expired: "Ų
ŲØĒŲŲØŠ ØĩŲØ§ØŲØĒŲ"
|
||||
icon: "Ø§ŲØĩŲØąØŠ Ø§ŲØąŲ
Ø˛ŲØŠ"
|
||||
replies: "ØąØ¯"
|
||||
renotes: "ØŖØšØ¯ اŲŲØ´Øą"
|
||||
sourceCode: "Ø§ŲØ´ŲØąØŠ اŲŲ
ØĩØ¯ØąŲØŠ"
|
||||
flip: "اŲŲØ¨"
|
||||
lastNDays: "ØĸØŽØą {n} ØŖŲØ§Ų
"
|
||||
surrender: "ØŖŲØēŲ"
|
||||
postForm: "ØŖŲØ´ØĻ Ų
ŲØ§ØØ¸ØŠ"
|
||||
information: "ØšŲ"
|
||||
inMinutes: "د"
|
||||
inDays: "Ų"
|
||||
widgets: "Ø§ŲØĒØˇØ¨ŲŲØ§ØĒ اŲŲ
ŲØĩØēŲØąØŠ"
|
||||
presets: "ØĨؚداداØĒ Ų
ØŗØ¨ŲØŠ"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
filename: "Ø§ØŗŲ
اŲŲ
ŲŲ"
|
||||
_imageFrameEditor:
|
||||
font: "Ø§ŲØŽØˇ"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
_chat:
|
||||
invitations: "Ø¯ØšŲØŠ"
|
||||
noHistory: "Ø§ŲØŗØŦŲ ŲØ§ØąØē"
|
||||
members: "Ø§ŲØŖØšØļØ§ØĄ"
|
||||
home: "Ø§ŲØąØĻŲØŗŲ"
|
||||
send: "ØŖØąØŗŲ"
|
||||
_delivery:
|
||||
stop: "Ų
ŲØšŲŲŲ"
|
||||
_initialAccountSetting:
|
||||
accountCreated: "ŲØŦØ ØĨŲØ´Ø§ØĄ ØØŗØ§Ø¨Ų!"
|
||||
letsStartAccountSetup: "ØĨذا ŲŲØĒ ØŦØ¯ŲØ¯Ųا ŲŲØšØ¯Ų ØØŗØ§Ø¨Ų Ø§ŲØ´ØŽØĩŲ."
|
||||
letsFillYourProfile: "ØŖŲŲŲØ§ Ųب𨝠Ų
ŲŲŲ Ø§ŲØ´ØŽØĩŲ."
|
||||
profileSetting: "ØĨؚداداØĒ اŲŲ
ŲŲ Ø§ŲØ´ØŽØĩŲ"
|
||||
privacySetting: "ØĨؚداداØĒ Ø§ŲØŽØĩŲØĩŲØŠ"
|
||||
theseSettingsCanEditLater: "ŲŲ
ŲŲŲ ØĒØēŲŲØą ŲØ°Ų Ø§ŲØĨؚداداØĒ ŲØ§ØŲŲØ§."
|
||||
skipAreYouSure: "ØŖØĒØąŲØ¯ ØĒØŽØˇŲ ØĨؚداد اŲŲ
ŲŲ Ø§ŲØ´ØŽØĩŲØ"
|
||||
laterAreYouSure: "ØŖØĒØąŲØ¯ ØĨؚداد اŲŲ
ŲŲ Ø§ŲØ´ØŽØĩŲ ŲØ§ØŲŲØ§Ø"
|
||||
_serverRules:
|
||||
description: "Ų
ØŦŲ
ŲØšØŠ Ų
Ų Ø§ŲŲŲØ§ØšØ¯ ŲØšØąØļŲØ§ ØšŲØ¯ Ø§ŲØĒØŗØŦŲŲØ Ų
Ų Ø§ŲŲ
ØŗØĒØØŗŲ ŲØĒØ§Ø¨ØŠ Ų
ŲØŽØĩŲ ŲŲØ´ØąŲØˇ Ø§ŲØŽØ¯Ų
ØŠ."
|
||||
_accountMigration:
|
||||
moveFrom: "اŲŲŲ ØØŗØ§Ø¨Ųا ØĸØŽØą ŲŲØ°Ø§ Ø§ŲØØŗØ§Ø¨"
|
||||
moveFromLabel: "Ø§ŲØØŗØ§Ø¨ Ø§ŲØŖØĩŲŲ #{n}"
|
||||
moveTo: "اŲŲŲ ŲØ°Ø§ Ø§ŲØØŗØ§Ø¨ ŲØØŗØ§Ø¨ ØĸØŽØą"
|
||||
moveToLabel: "Ø§ŲØØŗØ§Ø¨ اŲŲØŦŲØŠ:"
|
||||
moveCannotBeUndone: "ŲØ§ ŲŲ
ŲŲ Ø§ŲØĒØąØ§ØŦØš ØšŲ ŲŲŲ Ø§ŲØØŗØ§Ø¨."
|
||||
movedTo: "Ø§ŲØØŗØ§Ø¨ اŲŲØŦŲØŠ:"
|
||||
_achievements:
|
||||
_types:
|
||||
_notes1:
|
||||
description: "Ø§ŲØ´Øą Ų
ŲØ§ØØ¸ØĒŲ Ø§ŲØŖŲŲŲ"
|
||||
flavor: "ØĒŲ
ØĒØš Ø¨Ø§ØŗØĒ؎داŲ
Ų
ŲØŗŲŲ!"
|
||||
_notes10:
|
||||
title: "بؚØļ اŲŲ
ŲØ§ØØ¸Ø§ØĒ"
|
||||
description: "Ø§ŲØ´Øą 10 Ų
ŲØ§ØØ¸Ø§ØĒ"
|
||||
_notes100:
|
||||
title: "ŲØĢŲØą Ų
Ų Ø§ŲŲ
ŲØ§ØØ¸Ø§ØĒ"
|
||||
description: "Ø§ŲØ´Øą 100 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes500:
|
||||
description: "Ø§ŲØ´Øą 500 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes1000:
|
||||
title: "ØŦØ¨Ų Ų
ŲØ§ØØ¸Ø§ØĒ"
|
||||
description: "Ø§ŲØ´Øą 1000 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes5000:
|
||||
description: "Ø§ŲØ´Øą 5000 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes10000:
|
||||
description: "Ø§ŲØ´Øą 10000 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes20000:
|
||||
title: "ØŖØąŲØ¯...Ų
ŲØ§ØØ¸Ø§ØĒ...ØŖŲØĢØą"
|
||||
description: "Ø§ŲØ´Øą 20000 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes30000:
|
||||
title: "Ų
ŲØ§ØØ¸Ø§ØĒ ŲŲ
ŲØ§ØØ¸Ø§ØĒ ŲŲ
ŲØ§ØØ¸Ø§ØĒ"
|
||||
description: "Ø§ŲØ´Øą 30000 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes40000:
|
||||
title: "Ų
ØĩŲØš Ų
ŲØ§ØØ¸Ø§ØĒ"
|
||||
description: "Ø§ŲØ´Øą 40000 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes50000:
|
||||
title: "ŲŲŲØ¨ Ų
ŲØ§ØØ¸Ø§ØĒ"
|
||||
description: "Ø§ŲØ´Øą 50000 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes60000:
|
||||
title: "ŲØŦŲ
Ų
ŲØ§ØØ¸Ø§ØĒ"
|
||||
description: "Ø§ŲØ´Øą 60000 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes70000:
|
||||
title: "ØĢŲØ¨ ØŖØŗŲØ¯ ŲŲŲ
ŲØ§ØØ¸Ø§ØĒ"
|
||||
description: "Ø§ŲØ´Øą 70000 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes80000:
|
||||
title: "Ų
ØŦØąØŠ Ų
ŲØ§ØØ¸Ø§ØĒ"
|
||||
description: "Ø§ŲØ´Øą 80000 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes90000:
|
||||
title: "ŲŲŲŲ Ų
ŲØ§ØØ¸Ø§ØĒ"
|
||||
description: "Ø§ŲØ´Øą 90000 Ų
ŲØ§ØØ¸ØŠ"
|
||||
_notes100000:
|
||||
title: "ŲŲ Ų
ŲØ§ØØ¸Ø§ØĒŲ ŲŲØ§"
|
||||
description: "Ø§ŲØ´Øą 100000 Ų
ŲØ§ØØ¸ØŠ"
|
||||
flavor: "ØŲŲØ§ ŲØ¯ŲŲ Ø§ŲŲØĢŲØą Ų
Ų Ø§ŲŲØĩØĩ"
|
||||
_login3:
|
||||
title: "Ų
بØĒØ¯ØŖ I"
|
||||
_noteFavorited1:
|
||||
description: "ŲØļŲŲŲ Ų
ŲØ§ØØ¸ØĒŲ Ø§ŲØŖŲŲŲ"
|
||||
_myNoteFavorited1:
|
||||
title: "ØŗØ§ØšŲ ŲŲŲØŦŲŲ
"
|
||||
description: "ØŖØšØŦب Ø´ØŽØĩ ØĸØŽØą بØĨØØ¯Ų Ų
ŲØ§ØØ¸Ø§ØĒŲ"
|
||||
_profileFilled:
|
||||
title: "Ų
ØŗØĒؚد"
|
||||
description: "ØŖØšØ¯Ų ØØŗØ§Ø¨Ų"
|
||||
_markedAsCat:
|
||||
title: "ØŖŲØ§ ŲØˇ"
|
||||
_role:
|
||||
new: "Ø¯ŲØą ØŦØ¯ŲØ¯"
|
||||
edit: "ØØąØą Ø§ŲØŖØ¯ŲØ§Øą"
|
||||
name: "Ø§ØŗŲ
Ø§ŲØ¯ŲØą"
|
||||
description: "ŲØĩŲ Ø§ŲØ¯ŲØą"
|
||||
permission: "ØŖØ°ŲŲØ§ØĒ Ø§ŲØ¯ŲØą"
|
||||
assignTarget: "Ųب𠨧بĨØŗŲØ§Ø¯"
|
||||
condition: "Ø§ŲØ´ØąØˇ"
|
||||
options: "ØŽŲØ§ØąØ§ØĒ"
|
||||
policies: "Ø§ŲØŗŲØ§ØŗØŠ Ø§ŲØšØ§Ų
ØŠ"
|
||||
priority: "Ø§ŲØŖŲŲŲŲØŠ"
|
||||
_priority:
|
||||
low: "Ų
ŲØŽŲØļØŠ"
|
||||
middle: "Ų
ØĒŲØŗØˇ"
|
||||
high: "ؚاŲŲØŠ"
|
||||
_options:
|
||||
canManageCustomEmojis: "ØĨØ¯Ø§ØąØŠ Ø§ŲØĨŲŲ
ŲØŦŲ Ø§ŲŲ
ØŽØĩØĩØŠ"
|
||||
pinMax: "ØØ¯ ؚدد اŲŲ
ŲØ§ØØ¸Ø§ØĒ اŲŲ
ØĢبØĒØŠ"
|
||||
_condition:
|
||||
isLocal: "Ų
ØŗØĒ؎دŲ
Ų
ØŲŲ"
|
||||
isRemote: "Ų
ØŗØĒ؎دŲ
Ø¨ØšŲØ¯"
|
||||
_emailUnavailable:
|
||||
used: "ŲØ°Ø§ Ø§ŲØ¨ØąŲد Ø§ŲØĨŲŲØĒØąŲŲŲ Ų
ØŗØĒ؎دŲ
"
|
||||
format: "ØĩŲØēØŠ Ø§ŲØ¨ØąŲد Ø§ŲØĨŲŲØĒØąŲŲŲ ØēŲØą ØĩØ§ŲØØŠ"
|
||||
@@ -1168,10 +849,6 @@ _plugin:
|
||||
install: "ØĢØ¨ŲØĒ ØĨØļØ§ŲØ§ØĒ"
|
||||
installWarn: "ØąØŦØ§ØĄŲ ŲØ§ ØĒØĢبØĒ ØĨØļØ§ŲØ§ØĒ ØēŲØą Ų
ŲØĢŲŲØŠ."
|
||||
manage: "ØĨØ¯Ø§ØąØŠ Ø§ŲØĨØļØ§ŲØ§ØĒ"
|
||||
viewSource: "Ø§Ø¸ŲØą Ø§ŲŲ
ØĩØ¯Øą"
|
||||
_preferencesBackups:
|
||||
createdAt: "ØĒŲ
ØĨŲØ´Ø§Ø¤Ų: {date} {time}"
|
||||
updatedAt: "ØĸØŽØą ØĒØØ¯ŲØĢ: {date} {time}"
|
||||
_registry:
|
||||
scope: "Ø§ŲØŲŲØ˛"
|
||||
key: "Ų
ŲØĒØ§Ø"
|
||||
@@ -1187,6 +864,10 @@ _aboutMisskey:
|
||||
donate: "ØĒØ¨ØąØš ŲŲ
ŲØŗŲŲ"
|
||||
morePatrons: "ŲØŲ ŲŲØ¯Øą Ø§ŲØ¯ØšŲ
Ø§ŲØ°Ų ŲØ¯Ų
Ų Ø§ŲØšØ¯Ųد Ų
Ų Ø§ŲØŖØ´ØŽØ§Øĩ Ø§ŲØ°ŲŲ ŲŲ
ŲØ°ŲØąŲŲ
. Ø´ŲØąŲا ŲŲŲ
đĨ°"
|
||||
patrons: "Ø§ŲØ¯Ø§ØšŲ
ŲŲ"
|
||||
_nsfw:
|
||||
respect: "Ø§ØŽŲ Ø§ŲŲØŗØ§ØĻØˇ ذاØĒ اŲŲ
ØØĒŲŲ Ø§ŲØØŗØ§Øŗ"
|
||||
ignore: "Ø§ØšØąØļ اŲŲØŗØ§ØĻØˇ ذاØĒ اŲŲ
ØØĒŲŲ Ø§ŲØØŗØ§Øŗ"
|
||||
force: "Ø§ØŽŲ ŲŲ Ø§ŲŲØŗØ§ØĻØˇ"
|
||||
_instanceTicker:
|
||||
none: "ŲØ§ ØĒØ¸ŲØąŲ بØĒاØĒŲØ§"
|
||||
remote: "ØŖØ¸ŲØą ŲŲŲ
ØŗØĒ؎دŲ
ŲŲ Ø§ŲØ¨Ųؚاد"
|
||||
@@ -1212,6 +893,11 @@ _wordMute:
|
||||
muteWords: "اŲŲŲŲ
اØĒ اŲŲ
ØØ¸ŲØąØŠ"
|
||||
muteWordsDescription: "Ø§ŲØĩŲ Ø¨ŲŲŲŲ
بŲ
ØŗØ§ŲØŠ ŲØ§ØŗØĒ؎داŲ
Ų
ؚاŲ
Ų \"Ų\" ØŖŲ Ø¨ØŗØˇØą ŲØ§ØŗØĒ؎داŲ
Ų
ؚاŲ
Ų \"ØŖŲ\"."
|
||||
muteWordsDescription2: "Ø§ØØĩØą اŲŲŲŲ
اØĒ اŲŲ
ŲØĒØ§ØŲØŠ بŲŲ Ø¨ŲŲ Ø´ØąØˇØĒŲŲ Ų
اØĻŲØĒŲŲ ŲØ§ØŗØĒ؎داŲ
ŲØ§ بǨ𨧨¨ŲØą ŲŲ
ØˇŲØŠ"
|
||||
softDescription: "Ø§ØŽŲ Ø§ŲŲ
ŲØ§ØØ¸Ø§ØĒ Ø§ŲØĒŲ ØĒØŗØĒŲŲ Ø§ŲØ´ØąŲØˇ Ų
Ų Ø§ŲØŽŲØˇ Ø§ŲØ˛Ų
ŲŲ."
|
||||
hardDescription: "Ø§ØŽŲ Ø§ŲŲ
ŲØ§ØØ¸Ø§ØĒ Ø§ŲØĒŲ ØĒØŗØĒŲŲ Ø§ŲØ´ØąŲØˇ Ų
Ų Ø§ŲØŽŲØˇ Ø§ŲØ˛Ų
ŲŲ.Ø¨Ø§ŲØĨØļØ§ŲØŠ ØĨŲŲ ØŖŲ ŲØ°Ų اŲŲ
ŲØ§ØØ¸Ø§ØĒ ØŗØĒبŲŲ Ų
ØŽŲŲØŠ ØØĒŲ ŲØĨŲ ØĒØēŲØąØĒ Ø§ŲØ´ØąŲØˇ."
|
||||
soft: "ŲŲŲØŠ"
|
||||
hard: "ŲØ§ØŗŲØŠ"
|
||||
mutedNotes: "اŲŲ
ŲØ§ØØ¸Ø§ØĒ اŲŲ
ŲØĒŲŲ
ØŠ"
|
||||
_instanceMute:
|
||||
instanceMuteDescription: "ŲØ°Ų ØŗŲØØŦب ŲŲ Ų
ŲØ§ØØ¸Ø§ØĒ Ø§ŲØŽŲادŲ
اŲŲ
ØØŦŲØ¨ØŠ ŲŲ
Ø´Ø§ØąŲØ§ØĒŲØ§ ŲØ§ŲØąØ¯ŲØ¯ ØšŲŲ ØĒŲŲ Ø§ŲŲ
ŲØ§ØØ¸Ø§ØĒ ØØĒŲ ŲØĨŲ ŲØ§ŲØĒ Ų
Ų ØŽØ§Ø¯Ų
ØēŲØą Ų
ØØŦŲØ¨."
|
||||
instanceMuteDescription2: "Ų
Ø¯ØŽŲØŠ ŲŲŲ ØŗØˇØą"
|
||||
@@ -1249,6 +935,7 @@ _theme:
|
||||
shadow: "Ø§ŲØ¸Ų"
|
||||
navBg: "ØŽŲŲŲØŠ Ø§ŲØ´ØąŲØˇ Ø§ŲØŦØ§ŲØ¨Ų"
|
||||
navFg: "ŲØĩ Ø§ŲØ´ØąŲØˇ Ø§ŲØŦØ§ŲØ¨Ų"
|
||||
navHoverFg: "ŲØĩ Ø§ŲØ´ØąŲØˇ Ø§ŲØŦØ§ŲØ¨Ų (ØšŲØ¯ Ø§ŲØĒŲ
ØąŲØą ŲŲŲŲ)"
|
||||
link: "ØąØ§Ø¨Øˇ"
|
||||
hashtag: "ŲØŗŲ
"
|
||||
mention: "ØŖØ´Øą اŲŲ"
|
||||
@@ -1263,11 +950,17 @@ _theme:
|
||||
buttonBg: "ØŽŲŲŲØŠ Ø§ŲØŖØ˛ØąØ§Øą"
|
||||
buttonHoverBg: "ØŽŲŲŲØŠ Ø§ŲØŖØ˛ØąØ§Øą (ØšŲØ¯ Ø§ŲØĒŲ
ØąŲØą ŲŲŲŲØ§)"
|
||||
inputBorder: "ØŲØ§Ų ØŲŲ Ø§ŲØĨد؎اŲ"
|
||||
listItemHoverBg: "ØŽŲŲŲØŠ ØšŲØ§ØĩØą اŲŲØ§ØĻŲ
ØŠ (ØšŲØ¯ Ø§ŲØĒŲ
ØąŲØą ŲŲŲŲØ§)"
|
||||
driveFolderBg: "ØŽŲŲŲØŠ Ų
ØŦŲØ¯ ŲØąØĩ Ø§ŲØĒØŽØ˛ŲŲ"
|
||||
messageBg: "ØŽŲŲŲØŠ Ø§ŲŲ
ØØ§Ø¯ØĢØŠ"
|
||||
_sfx:
|
||||
note: "اŲŲ
ŲØ§ØØ¸Ø§ØĒ"
|
||||
noteMy: "Ų
ŲØ§ØØ¸ØĒŲ"
|
||||
notification: "Ø§ŲØĨØ´ØšØ§ØąØ§ØĒ"
|
||||
chat: "اŲŲ
ØØ§Ø¯ØĢØŠ"
|
||||
chatBg: "اŲŲ
ØØ§Ø¯ØĢØŠ (Ø§ŲØŽŲŲŲØŠ)"
|
||||
antenna: "اŲŲŲØ§ØĻŲØ§ØĒ"
|
||||
channel: "ØĨØ´ØšØ§ØąØ§ØĒ اŲŲŲØ§ØĒ"
|
||||
_ago:
|
||||
future: "اŲŲ
ØŗØĒŲØ¨ŲŲ"
|
||||
justNow: "اŲŲØØ¸ØŠ"
|
||||
@@ -1284,6 +977,29 @@ _time:
|
||||
minute: "د"
|
||||
hour: "ØŗØ§"
|
||||
day: "Ų"
|
||||
_tutorial:
|
||||
title: "ŲŲŲ ØĒØŗØĒ؎دŲ
Misskey"
|
||||
step1_1: "Ų
ØąØØ¨Ųا!"
|
||||
step1_2: "ØĒØ¯ØšŲ ŲØ°Ų Ø§ŲØĩŲØØŠ 'Ø§ŲØŽŲØˇ Ø§ŲØ˛Ų
ŲŲ' ŲŲŲ ØĒØŲŲ Ų
ŲØ§ØØ¸Ø§ØĒ Ø§ŲØŖØ´ØŽØ§Øĩ Ø§ŲØ°Ų ØĒØĒابؚŲŲ
Ų
ØąØĒب؊ ØØŗØ¨ ØĒØ§ØąŲØŽ ŲØ´ØąŲا."
|
||||
step1_3: "ØŽŲØˇŲ Ø§ŲØ˛Ų
ŲŲ ŲØ§ØąØē ØØ§ŲŲŲØ§ بŲ
ا ØŖŲŲ ŲØ§ ØĒØĒابؚ ØŖŲ Ø´ØŽØĩ ŲŲŲ
ØĒŲØ´Øą ØŖŲ Ų
ŲØ§ØØ¸ØŠ."
|
||||
step2_1: "ŲŲŲŲŲ ØĨؚداد Ų
ŲŲŲ Ø§ŲØ´ØŽØĩŲ ŲØ¨Ų ŲØĒØ§Ø¨ØŠ Ų
ŲØ§ØØ¸ØŠ ØŖŲ Ų
ØĒابؚ؊ ØŖØ´ØŽØ§Øĩ."
|
||||
step2_2: "ØŖØšØˇØ§ØĄ Ų
ØšŲŲŲ
اØĒ ØšŲ Ø´ØŽØĩŲØĒŲ ŲŲ
ŲØ Ų
Ų ŲŲ ŲŲØŗ ØĨŲØĒŲ
اŲ
اØĒŲ ŲØąØĩØŠ Ų
ØĒابؚØĒŲ ŲØ§ŲØĒŲØ§ØšŲ Ų
Øš Ų
ŲØ§ØØ¸Ø§ØĒŲ."
|
||||
step3_1: "ŲŲ ØŖŲŲŲØĒ ØĨؚداد ØØŗØ§Ø¨ŲØ"
|
||||
step3_2: "ØĨذا ØĒاŲŲŲØ§ ŲØĒŲØ´Øą Ų
ŲØ§ØØ¸ØŠ. ØŖŲŲØą ØšŲŲ ØŖŲŲŲŲØŠ Ø§ŲŲŲŲ
ŲŲ ØŖØšŲŲ Ø§ŲØ´Ø§Ø´ØŠ"
|
||||
step3_3: "اŲ
ŲØŖ اŲŲŲ
ŲØ°ØŦ ŲØ§ŲŲØą Ø§ŲØ˛ØąŲ Ø§ŲŲ
ŲØŦŲØ¯ ŲŲ ØŖØšŲŲ Ø§ŲŲŲ
ŲŲ ŲŲØĨØąØŗØ§Ų."
|
||||
step3_4: "ŲŲØŗ ŲØ¯ŲŲ Ų
ا ØĒŲŲŲŲØ ØĨذا Ø§ŲØĒØ¨ \"Ø¨Ø¯ØŖØĒŲ Ø§ØŗØĒ؎دŲ
Ų
ŲØŗŲŲ\"."
|
||||
step4_1: "ŲŲ ŲØ´ØąØĒ Ų
ŲØ§ØØ¸ØĒŲ Ø§ŲØŖŲŲŲØ"
|
||||
step4_2: "Ų
ØąØŲ! ŲŲ
ŲŲŲ Ø§ŲØĸŲ ØąØ¤ŲØŠ Ų
ŲØ§ØØ¸ØĒŲ ŲŲ Ø§ŲØŽŲØˇ Ø§ŲØ˛Ų
ŲŲ."
|
||||
step5_1: "ŲØ§ŲØĸŲØ ŲŲØŦØšŲ Ø§ŲØŽŲØˇ Ø§ŲØ˛Ų
ŲŲ ØŖŲØĢØą ØŲŲŲØŠ ŲØ°ŲŲ Ø¨Ų
ØĒابؚ؊ بؚØļ اŲŲ
ØŗØĒ؎دŲ
ŲŲ."
|
||||
step5_2: "ØĒØšØąØļ ØĩŲØØŠ {features} اŲŲ
ŲØ§ØØ¸Ø§ØĒ اŲŲ
ØĒداŲŲØŠ ŲŲ ŲØ°Ø§ اŲŲ
ØĢŲŲ ŲŲØĒŲØ ŲŲ {Explore} Ø§ŲØšØĢŲØą ØšŲŲ Ø§ŲŲ
ØŗØĒ؎دŲ
ŲŲ Ø§ŲØąØ§ØĻدŲŲ. اؚØĢØą ØšŲŲ Ø§ŲØŖØ´ØŽØ§Øĩ Ø§ŲØ°ŲŲ ŲØĢŲØąŲŲ ØĨŲØĒŲ
اŲ
Ų ŲØĒØ§Ø¨ØšŲŲ
!"
|
||||
step5_3: "ŲŲ
ØĒابؚ؊ Ų
ØŗØĒ؎دŲ
ŲŲ Ø§Ø¯ØŽŲ Ų
ŲŲŲŲ
Ø§ŲØ´ØŽØĩŲ Ø¨Ø§ŲŲŲØą ØšŲŲ ØĩŲØąØĒŲŲ
Ø§ŲØ´ØŽØĩŲØŠ ØĢŲ
اØļØēØˇ Ø˛Øą 'ØĒابؚ'."
|
||||
step5_4: "ØĨذا ŲØ§Ų ŲØ¯Ų اŲŲ
ØŗØĒ؎دŲ
ØąŲ
Ø˛ ŲŲŲ Ø¨ØŦŲØ§Øą Ø§ØŗŲ
Ų Ø ŲØŦب ØšŲŲŲ Ø§ŲØĒØ¸Ø§ØąŲ ŲŲŲØ¨Ų ØˇŲØ¨ اŲŲ
ØĒابؚ؊ ŲØ¯ŲŲŲØ§."
|
||||
step6_1: "Ø§ŲØĸŲ ØŗØĒØĒŲ
ŲŲ Ų
Ų ØąØ¤ŲØŠ Ų
ŲØ§ØØ¸Ø§ØĒ اŲŲ
ØŗØĒ؎دŲ
ŲŲ Ø§ŲŲ
ØĒØ§Ø¨ŲØšŲŲ ŲŲ Ø§ŲØŽŲØˇ Ø§ŲØ˛Ų
ŲŲ."
|
||||
step6_2: "ŲŲ
ŲŲŲ Ø§ŲØĒŲØ§ØšŲ Ø¨ØŗØąØšØŠ Ų
Øš اŲŲ
ŲØ§ØØ¸Ø§ØĒ ØšŲ ØˇØąŲŲ ØĨØļØ§ŲØŠ \"ØĒŲØ§ØšŲ\"."
|
||||
step6_3: "ŲØĨØļØ§ŲØŠ ØĒŲØ§ØšŲ ŲŲ
ŲØ§ØØ¸ØŠ Ø Ø§ŲŲØą ŲŲŲ ØšŲØ§Ų
ØŠ \"+\" ØŖØŗŲŲ ŲŲŲ
ŲØ§ØØ¸ØŠ ŲØ§ØŽØĒØą Ø§ŲØĨŲŲ
ŲØŦŲ Ø§ŲŲ
ØˇŲŲØ¨."
|
||||
step7_1: "Ų
Ø¨Ø§ØąŲ ! ØŖŲŲŲØĒ Ø§ŲØ¯ŲØąØŠ Ø§ŲØĒØšŲŲŲ
ŲØŠ Ø§ŲØŖØŗØ§ØŗŲØŠ ŲØ§ØŗØĒ؎داŲ
Ų
ŲØŗŲŲ."
|
||||
step7_2: "ØĨذا ØŖØąØ¯ØĒ Ų
ØšØąŲØŠ Ø§ŲŲ
Ø˛ŲØ¯ ØšŲ Ų
ŲØŗŲŲ Ø˛Øą {help}."
|
||||
step7_3: "ØØ¸Ųا ØŗØšŲØ¯Ųا ŲØ§ØŗØĒŲ
ØĒØš بŲŲØĒŲ Ų
Øš Ų
ŲØŗŲŲ! đ"
|
||||
_2fa:
|
||||
alreadyRegistered: "ØŗØŦŲØĒ ØŗŲŲŲØ§ ØŦŲØ§Ø˛Ųا ŲŲØ§ØŗØĒŲØĢØ§Ų بؚاŲ
ŲŲŲ."
|
||||
step1: "ØŖŲŲŲØ§ ØĢØ¨ŲØĒ ØĒØˇØ¨ŲŲ Ø§ØŗØĒŲØĢØ§Ų ØšŲŲ ØŦŲØ§Ø˛Ų (Ų
ØĢŲ {a} Ų{b})."
|
||||
@@ -1322,7 +1038,6 @@ _permissions:
|
||||
"read:gallery": "Ø§ØšØąØļ اŲŲ
ØšØąØļ"
|
||||
"write:gallery": "ؚدŲŲ Ø§ŲŲ
ØšØąØļ"
|
||||
"read:gallery-likes": "ŲØšØąØļ Ų
ا ØŖØšØŦØ¨Ų Ų
Ų Ų
Ø´Ø§ØąŲØ§ØĒ اŲŲ
ØšØąØļ"
|
||||
"write:chat": "Ø§ŲØĒØ¨ ØŖŲ Ø§ØØ°Ų ØąØŗØ§ØĻŲ Ų
ØØ§Ø¯ØĢØŠ"
|
||||
_auth:
|
||||
shareAccess: "ØŖØĒØąŲØ¯ Ø§ŲØĒŲŲŲØļ ŲŲ \"{name}\" باŲŲØĩŲŲ ŲØØŗØ§Ø¨ŲØ"
|
||||
shareAccessAsk: "ŲŲ ØĒØŽŲŲ ŲŲØ°Ø§ Ø§ŲØĒØˇØ¨ŲŲ Ø§ŲŲØĩŲŲ ŲØØŗØ§Ø¨ŲØ"
|
||||
@@ -1362,7 +1077,6 @@ _widgets:
|
||||
onlineUsers: "اŲŲ
ØĒŲØĩŲŲŲ"
|
||||
jobQueue: "ŲØ§ØĻŲ
ØŠ Ø§ŲØ§ŲØĒØ¸Ø§Øą"
|
||||
serverMetric: "ØĨØØĩاØĻŲØ§ØĒ Ø§ŲØŽØ§Ø¯Ų
"
|
||||
userList: "ŲØ§ØĻŲ
ØŠ اŲŲ
ØŗØĒ؎دŲ
ŲŲ"
|
||||
_userList:
|
||||
chooseList: "ا؎ØĒØą ŲØ§ØĻŲ
ØŠ"
|
||||
_cw:
|
||||
@@ -1405,9 +1119,6 @@ _postForm:
|
||||
replyPlaceholder: "ØąØ¯ ØšŲŲ ŲØ°Ų اŲŲ
ŲØ§ØØ¸ØŠâĻ"
|
||||
quotePlaceholder: "Ø§ŲØĒØ¨Øŗ ŲØ°Ų اŲŲ
ŲØ§ØØ¸ØŠâĻ"
|
||||
channelPlaceholder: "Ø§ŲØ´Øą ŲŲ ŲŲØ§ØŠ..."
|
||||
_howToUse:
|
||||
visibility_title: "Ø§ŲØ¸ŲŲØą"
|
||||
menu_title: "اŲŲØ§ØĻŲ
ØŠ"
|
||||
_placeholders:
|
||||
a: "Ų
ا Ø§ŲØ°Ų ØĒŲŲŲ ŲØšŲŲØ"
|
||||
b: "Ų
اذا ŲØØ¯ØĢ ØŲŲŲ Ø"
|
||||
@@ -1429,8 +1140,6 @@ _profile:
|
||||
changeBanner: "ØēŲŲØą Ø§ŲŲØ§ŲØĒØŠ"
|
||||
_exportOrImport:
|
||||
allNotes: "ŲŲ Ø§ŲŲ
ŲØ§ØØ¸Ø§ØĒ"
|
||||
favoritedNotes: " اŲŲ
ŲØ§ØØ¸Ø§ØĒ اŲŲ
ŲØļŲØŠ"
|
||||
clips: "Ų
ŲØ´Ø¨Ų"
|
||||
followingList: "اŲŲ
ØĒØ§Ø¨ŲØšŲŲ"
|
||||
muteList: "اŲŲ
ØŗØĒ؎دŲ
ŲŲ Ø§ŲŲ
ŲØĒŲŲ
ŲŲ"
|
||||
blockingList: "اŲŲ
ØŗØĒ؎دŲ
ŲŲ Ø§ŲŲ
ØØŦŲØ¨ŲŲ"
|
||||
@@ -1449,8 +1158,6 @@ _charts:
|
||||
notesTotal: "ØĨØŦŲ
اŲŲ Ø§ŲŲ
ŲØ§ØØ¸Ø§ØĒ"
|
||||
filesIncDec: "ØĒباŲŲ ØšØ¯Ø¯ اŲŲ
ŲŲØ§ØĒ"
|
||||
filesTotal: "Ø§ŲØšØ¯Ø¯ Ø§ŲØĨØŦŲ
اŲŲ ŲŲŲ
ŲŲØ§ØĒ"
|
||||
storageUsageIncDec: "Ø§ŲØĒØ¨Ø§ŲŲ ŲŲ Ø§ØŗØĒØēŲØ§Ų Ų
ØŗØ§ØØŠ Ø§ŲØĒØŽØ˛ŲŲ"
|
||||
storageUsageTotal: "اØŦŲ
اŲŲ Ų
ØŗØ§ØØŠ Ø§ŲØĒØŽØ˛ŲŲ Ø§ŲŲ
ØŗØĒØēŲØŠ"
|
||||
_instanceCharts:
|
||||
requests: "Ø§ŲØˇŲباØĒ"
|
||||
users: "ØĒباŲŲ ØšØ¯Ø¯ اŲŲ
ØŗØĒ؎دŲ
ŲŲ"
|
||||
@@ -1475,6 +1182,9 @@ _pages:
|
||||
newPage: "ØŖŲØ´ØĻ ØĩŲØØŠ ØŦØ¯ŲØ¯ØŠ"
|
||||
editPage: "ؚدŲŲ Ø§ŲØĩŲØØŠ"
|
||||
readPage: "ŲŲØ´ŲØˇ ØšØąØļ اŲŲ
ØĩØ¯Øą"
|
||||
created: "ŲØŦØ ØĨŲØ´Ø§ØĄ Ø§ŲØĩŲØØŠ"
|
||||
updated: "ŲØŦØ ØĒؚدŲŲ Ø§ŲØĩŲØØŠ"
|
||||
deleted: "ŲØŦØ ØØ°Ų Ø§ŲØĩŲØØŠ"
|
||||
pageSetting: "ØĨؚداداØĒ Ø§ŲØĩŲØØŠ"
|
||||
nameAlreadyExists: "ØąØ§Ø¨Øˇ Ø§ŲØĩŲØØŠ Ų
ŲØŦŲØ¯ Ų
ØŗØ¨ŲŲØ§"
|
||||
invalidNameTitle: "ØąØ§Ø¨Øˇ Ø§ŲØĩŲØØŠ ŲŲØŗ ØĩØ§ŲØŲØ§"
|
||||
@@ -1493,7 +1203,7 @@ _pages:
|
||||
url: "ØąØ§Ø¨Øˇ Ø§ŲØĩŲØØŠ"
|
||||
summary: "Ų
ŲØŽØĩ Ø§ŲØĩŲØØŠ"
|
||||
alignCenter: "ØĒŲØŗŲØˇ Ø§ŲØšŲاØĩØą"
|
||||
hideTitleWhenPinned: "Ø§ØŽŲ ØšŲŲØ§Ų Ø§ŲØĩŲØØŠ ØšŲØ¯ ØĒØĢØ¨ŲØĒŲØ§ ŲŲ Ų
ŲŲ Ø§ŲØ´ØŽØĩŲ"
|
||||
hideTitleWhenPinned: "Ø§ØŽŲ ØšŲŲØ§Ų Ø§ŲØĩŲØØŠ ØšŲØ¯ ØĒØ¯Ø¨ŲØŗŲا ŲŲ Ų
ŲŲ Ø§ŲØ´ØŽØĩŲ"
|
||||
font: "Ø§ŲØŽØˇ"
|
||||
fontSerif: "Serif"
|
||||
fontSansSerif: "Sans Serif"
|
||||
@@ -1508,7 +1218,7 @@ _pages:
|
||||
text: "ŲØĩ"
|
||||
textarea: "ØŲŲ ŲØĩŲ"
|
||||
section: "ŲØŗŲ
"
|
||||
image: "ØĩŲØą"
|
||||
image: "Ø§ŲØĩŲØą"
|
||||
button: "Ø˛ØąŲ"
|
||||
note: "Ų
ŲØ§ØØ¸ØŠ Ų
ØļŲ
ŲŲØŠ"
|
||||
_note:
|
||||
@@ -1523,101 +1233,48 @@ _notification:
|
||||
fileUploaded: "ŲØŦØ ØąŲØš Ø§ŲŲ
ŲŲ"
|
||||
youGotMention: "{name} ØŖØ´Ø§Øą ØĨŲŲŲ"
|
||||
youGotReply: "ØąØ¯Ų ØšŲŲŲ {name}"
|
||||
youGotQuote: "Ø§ŲØĒØ¨Øŗ {name} Ų
ŲØ´ŲØąŲ"
|
||||
youRenoted: "ØŖØšØ§Ø¯ {name} ŲØ´Øą Ų
ŲØ´ŲØąŲ"
|
||||
youGotQuote: "Ø§ŲØĒØ¨Øŗ Ų
ŲŲ {name}"
|
||||
youRenoted: "ØĨؚادØĒ ŲØ´Øą Ų
Ų {name}"
|
||||
youWereFollowed: "ŲØĒØ§Ø¨ØšŲ"
|
||||
youReceivedFollowRequest: "ØĒŲŲŲØĒŲ ØˇŲØ¨ Ų
ØĒابؚ؊"
|
||||
yourFollowRequestAccepted: "ŲŲØ¨Ų ØˇŲØ¨ اŲŲ
ØĒابؚ؊"
|
||||
pollEnded: "Ø§ŲØĒŲŲ Ø§ŲØ§ØŗØĒØˇŲØ§Øš"
|
||||
pollEnded: "Ø¸ŲØąØĒ ŲØĒØ§ØĻØŦ Ø§ŲØ§ØŗØĒØˇŲØ§Øš"
|
||||
unreadAntennaNote: "ŲŲØ§ØĻŲ {name}"
|
||||
_types:
|
||||
all: "اŲŲŲ"
|
||||
follow: "Ų
ØĒØ§Ø¨ŲØšŲŲ ØŦدد"
|
||||
mention: "Ø§ŲØĨØ´Ø§ØąØ§ØĒ"
|
||||
reply: "Ø§ŲØąØ¯ŲØ¯"
|
||||
renote: "ØŖØšØ§Ø¯ اŲŲØ´Øą"
|
||||
renote: "ØŖØšØ¯ اŲŲØ´Øą"
|
||||
quote: "Ø§ŲØ§ŲØĒØ¨Ø§ØŗØ§ØĒ"
|
||||
reaction: "Ø§ŲØĒŲØ§ØšŲ"
|
||||
receiveFollowRequest: "ØˇŲØ¨Ø§ØĒ اŲŲ
ØĒابؚ؊"
|
||||
reaction: "Ø§ŲØĒŲØ§ØšŲاØĒ"
|
||||
receiveFollowRequest: "ØˇŲØ¨Ø§ØĒ اŲŲ
ØĒابؚ؊ اŲŲ
ØĒŲŲØ§ØŠ"
|
||||
followRequestAccepted: "ØˇŲØ¨Ø§ØĒ اŲŲ
ØĒابؚ؊ اŲŲ
ŲØ¨ŲŲØŠ"
|
||||
login: "ŲŲØŦ"
|
||||
app: "ØĨØ´ØšØ§ØąØ§ØĒ Ø§ŲØĒØˇØ¨ŲŲØ§ØĒ اŲŲ
ØąØĒØ¨ØˇØŠ"
|
||||
_actions:
|
||||
followBack: "ØĒØ§Ø¨ØšŲ Ø¨Ø§ŲŲ
ØĢŲ"
|
||||
reply: "ØąØ¯"
|
||||
renote: "ØŖØšØ¯ اŲŲØ´Øą"
|
||||
_deck:
|
||||
alwaysShowMainColumn: "ØŖØ¸ŲØą Ø§ŲØšŲ
ŲØ¯ Ø§ŲØŖØŗØ§ØŗŲ داØĻŲ
ŲØ§"
|
||||
columnAlign: "Ų
ØØ§Ø°Ø§ØŠ Ø§ŲØŖØšŲ
د؊"
|
||||
addColumn: "ØĨØļØ§ŲØŠ ØšŲ
ŲØ¯"
|
||||
swapLeft: "Ø§ŲØĒØØąŲŲ ØĨŲŲ Ø§ŲŲØŗØ§Øą"
|
||||
swapRight: "Ø§ŲØĒØØąŲŲ ØĨŲŲ Ø§ŲŲŲ
ŲŲ"
|
||||
swapUp: "Ø§ŲØĒØØąŲŲ ØĨŲŲ Ø§ŲØŖØšŲŲ"
|
||||
swapDown: "Ø§ŲØĒØØąŲŲ ØĨŲŲ Ø§ŲØŖØŗŲŲ"
|
||||
profile: "ØØŗØ§Ø¨Ų Ø§ŲØ´ØŽØĩŲ"
|
||||
newProfile: "Ų
ŲŲ ØĒØšØąŲŲŲ ØŦØ¯ŲØ¯"
|
||||
deleteProfile: "ØØ°Ų اŲŲ
ŲŲ Ø§ŲØĒØšØąŲŲŲ"
|
||||
alwaysShowMainColumn: "ØŖØ¸ŲØą Ø§ŲØšŲ
ŲØ¯ Ø§ŲØąØĻŲØŗŲ داØĻŲ
ŲØ§"
|
||||
columnAlign: "ØØ§Ø°Ų Ø§ŲØŖØšŲ
د؊"
|
||||
addColumn: "ØŖØļŲ ØšŲ
ŲØ¯Ųا"
|
||||
swapLeft: "ØØąŲŲ ŲŲŲØŗØ§Øą"
|
||||
swapRight: "ØØąŲŲ ŲŲŲŲ
ŲŲ"
|
||||
swapUp: "ØØąŲŲ ŲØŖØšŲŲ"
|
||||
swapDown: "ØØąŲŲ ŲØŖØŗŲŲ"
|
||||
profile: "اŲŲ
ŲŲ Ø§ŲØ´ØŽØĩŲ"
|
||||
_columns:
|
||||
main: "Ø§ŲØąØĻŲØŗŲØŠ"
|
||||
widgets: "Ø§ŲØĒØˇØ¨ŲŲØ§ØĒ اŲŲ
ŲØĩØēŲØąØŠ"
|
||||
main: "Ø§ŲØąØĻŲØŗŲ"
|
||||
widgets: "اŲŲØ¯ØŦاØĒ"
|
||||
notifications: "Ø§ŲØĨØ´ØšØ§ØąØ§ØĒ"
|
||||
tl: "Ø§ŲØŽØˇ Ø§ŲØ˛Ų
ŲŲ"
|
||||
tl: "Ø§ŲØŽŲØˇ Ø§ŲØ˛Ų
ŲŲ"
|
||||
antenna: "اŲŲŲØ§ØĻŲØ§ØĒ"
|
||||
list: "اŲŲŲØ§ØĻŲ
"
|
||||
channel: "اŲŲŲŲØ§ØĒ"
|
||||
mentions: "Ø§ŲØĨØ´Ø§ØąØ§ØĒ"
|
||||
direct: "Ų
Ø¨Ø§Ø´ØąØŠ"
|
||||
_webhookSettings:
|
||||
name: "Ø§ŲØ§ØŗŲ
"
|
||||
active: "Ų
ŲŲØšŲŲ"
|
||||
_events:
|
||||
reaction: "ØšŲØ¯ Ø§ŲØĒŲØ§ØšŲ"
|
||||
_abuseReport:
|
||||
_notificationRecipient:
|
||||
_recipientType:
|
||||
mail: "Ø§ŲØ¨ØąŲد Ø§ŲØĨŲŲØĒØąŲŲŲ "
|
||||
_moderationLogTypes:
|
||||
suspend: "ØšŲŲŲ"
|
||||
deleteDriveFile: "ØŲØ°Ų Ø§ŲŲ
ŲŲ"
|
||||
deleteNote: "ØŲØ°ŲØĒ Ø§ŲŲ
ŲØ§ØØ¸ØŠ"
|
||||
createGlobalAnnouncement: "ØŖŲŲØ´ØĻ ØĨØšŲØ§Ų ؚاŲ
"
|
||||
createUserAnnouncement: "ØŖŲŲØ´ØĻ ØĨØšŲØ§Ų Ų
ØŗØĒ؎دŲ
"
|
||||
updateGlobalAnnouncement: "ØŲدØĢ ØĨØšŲØ§Ų ؚاŲ
"
|
||||
updateUserAnnouncement: "ØŲدØĢ ØĨØšŲØ§Ų Ų
ØŗØĒ؎دŲ
"
|
||||
resetPassword: "ØŖØšØ¯ ØĒØšŲŲŲ ŲŲŲ
ØĒŲ Ø§ŲØŗØąŲØŠ"
|
||||
createInvitation: "ŲŲŲŲØ¯ Ø¯ØšŲØŠ"
|
||||
_reversi:
|
||||
total: "اŲŲ
ØŦŲ
ŲØš"
|
||||
lookingForPlayer: "ŲØ¨ØØĢ ØšŲ ØŽØĩŲ
..."
|
||||
gameCanceled: "ØŖŲŲØēŲØĒ Ø§Ųب𨍨Š."
|
||||
opponentHasSettingsChanged: "ØēŲŲØą Ø§ŲØŽØĩŲ
ØĨؚدادØĒŲ."
|
||||
showBoardLabels: "Ø§ØšØąØļ ØĒØąŲŲŲ
Ø§ŲØĩŲŲŲ ŲØ§ŲØŖØšŲ
د؊ ØšŲŲ Ø§ŲŲŲØ"
|
||||
useAvatarAsStone: "ØŲŲŲ Ø§ŲØØŦØ§ØąØŠ ØĨŲŲ ØĩŲØą Ų
ØŗØĒ؎دŲ
ŲŲ"
|
||||
_offlineScreen:
|
||||
title: "ØēŲØą Ų
ØĒØĩŲ - ŲØĒØšØ°Øą Ø§ŲاØĒØĩØ§Ų Ø¨Ø§ŲØŽØ§Ø¯Ų
"
|
||||
header: "ŲØĒØšØ°Øą Ø§ŲاØĒØĩØ§Ų Ø¨Ø§ŲØŽØ§Ø¯Ų
"
|
||||
_remoteLookupErrors:
|
||||
_noSuchObject:
|
||||
title: "ØēŲØą Ų
ŲØŦŲØ¯"
|
||||
_search:
|
||||
searchScopeAll: "اŲŲŲ"
|
||||
searchScopeLocal: "اŲŲ
ØŲŲ"
|
||||
searchScopeUser: "Ų
ØŗØĒ؎دŲ
Ų
ØØ¯Ø¯"
|
||||
_watermarkEditor:
|
||||
opacity: "Ø§ŲØ´ŲاŲŲØŠ"
|
||||
scale: "Ø§ŲØØŦŲ
"
|
||||
text: "ŲØĩ"
|
||||
position: "اŲŲ
ŲØļØš"
|
||||
type: "ŲŲØš"
|
||||
image: "ØĩŲØą"
|
||||
advanced: "Ų
ØĒŲØ¯Ų
"
|
||||
_imageEffector:
|
||||
_fxProps:
|
||||
scale: "Ø§ŲØØŦŲ
"
|
||||
size: "Ø§ŲØØŦŲ
"
|
||||
offset: "اŲŲ
ŲØļØš"
|
||||
color: "اŲŲŲŲ"
|
||||
opacity: "Ø§ŲØ´ŲاŲŲØŠ"
|
||||
_qr:
|
||||
showTabTitle: "اŲŲ
Ø¸ŲØą"
|
||||
raw: "ŲØĩ"
|
||||
name: "Ø§ŲØĨØŗŲ
"
|
||||
active: "Ų
ŲØšŲŲ"
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
_lang_: "āĻŦāĻžāĻāϞāĻž"
|
||||
headlineMisskey: "āύā§āĻ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ āĻāϰ⧠āϏāĻāϝā§āĻā§āϤ āύā§āĻāĻā§āĻžāϰā§āĻ"
|
||||
introMisskey: "āϏā§āĻŦāĻžāĻāϤāĻŽ! āĻŽāĻŋāϏāĻāĻŋ āĻāĻāĻāĻŋ āĻāĻĒā§āύ āϏā§āϰā§āϏ, āĻĄāĻŋāϏā§āύā§āĻā§āϰāĻžāϞāĻžāĻāĻāĻĄ āĻŽāĻžāĻāĻā§āϰā§āĻŦā§āϞāĻāĻŋāĻ āĻĒāϰāĻŋāώā§āĻŦāĻžāĨ¤ \n\"āύā§āĻ\" āϤā§āϰāĻŋāϰ āĻŽāĻžāϧā§āϝāĻŽā§ āϝāĻž āĻāĻāĻā§ āϤāĻž āϏāĻŦāĻžāϰ āϏāĻžāĻĨā§ āĻļā§ā§āĻžāϰ āĻāϰā§āύ đĄ\n\"āϰāĻŋāĻ
ā§āϝāĻžāĻāĻļāύ\" āĻā§āϞāĻŋāϰ āĻŽāĻžāϧā§āϝāĻŽā§ āϝā§āĻā§āύ⧠āύā§āĻ āϏāĻŽā§āĻĒāϰā§āĻā§ āĻāĻĒāύāĻžāϰ āĻ
āύā§āĻā§āϤāĻŋ āĻŦā§āϝāĻžāĻā§āϤ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ đ\nāĻāĻāĻāĻŋ āύāϤā§āύ āĻĻā§āύāĻŋā§āĻž āĻā§āϰ⧠āĻĻā§āĻā§āύ đ\n"
|
||||
poweredByMisskeyDescription: "{name} āĻšāϞ āĻāĻĒā§āύ āϏā§āϰā§āϏ āĻĒā§āϞā§āϝāĻžāĻāĻĢāϰā§āĻŽ <b>Misskey</b>-āĻāϰ āϏāĻžāϰā§āĻāĻžāϰāĻā§āϞāĻŋāϰ āĻāĻāĻāĻŋ⧎"
|
||||
monthAndDay: "{day}/{month}"
|
||||
search: "āĻā§āĻāĻā§āύ"
|
||||
notifications: "āĻŦāĻŋāĻā§āĻāĻĒā§āϤāĻŋ"
|
||||
@@ -13,14 +12,12 @@ fetchingAsApObject: "āĻĢā§āĻĄāĻŋāĻāĻžāϰā§āϏ āĻĨā§āĻā§ āĻāĻŦāϰ āĻāύ
|
||||
ok: "āĻ āĻŋāĻ"
|
||||
gotIt: "āĻŦā§āĻā§āĻāĻŋ"
|
||||
cancel: "āĻŦāĻžāϤāĻŋāϞ"
|
||||
noThankYou: "āύāĻž, āϧāύā§āϝāĻŦāĻžāĻĻ"
|
||||
enterUsername: "āĻāĻāĻāĻžāϰāύā§āĻŽ āϞāĻŋāĻā§āύ"
|
||||
renotedBy: "{user} āϰāĻŋāύā§āĻ āĻāϰā§āĻā§āύ"
|
||||
noNotes: "āĻā§āύ āύā§āĻ āύā§āĻ"
|
||||
noNotifications: "āĻā§āύ⧠āĻŦāĻŋāĻā§āĻāĻĒā§āϤāĻŋ āύā§āĻ"
|
||||
instance: "āĻāύā§āϏāĻā§āϝāĻžāύā§āϏ"
|
||||
settings: "āϏā§āĻāĻŋāĻāϏ"
|
||||
notificationSettings: "āĻŦāĻŋāĻā§āĻāĻĒā§āϤāĻŋāϰ āϏā§āĻāĻŋāĻāϏ"
|
||||
basicSettings: "āϏāĻžāϧāĻžāϰāĻŖ āϏā§āĻāĻŋāĻāϏ"
|
||||
otherSettings: "āĻ
āύā§āϝāĻžāύā§āϝ āϏā§āĻāĻŋāĻāϏ"
|
||||
openInWindow: "āύāϤā§āύ āĻāĻāύā§āĻĄā§āϤ⧠āĻā§āϞāĻž"
|
||||
@@ -45,20 +42,12 @@ pin: "āĻĒāĻŋāύ āĻāϰāĻž"
|
||||
unpin: "āĻĒāĻŋāύ āϏāϰāĻžāύ"
|
||||
copyContent: "āĻŦāĻŋāώā§āĻŦāϏā§āϤ⧠āĻāĻĒāĻŋ āĻāϰā§āύ"
|
||||
copyLink: "āϞāĻŋāĻā§āĻ āĻāĻĒāĻŋ āĻāϰā§āύ"
|
||||
copyLinkRenote: "āϰāĻŋāύā§āĻ āϞāĻŋāĻā§āĻ āĻāĻĒāĻŋ āĻāϰā§āύ"
|
||||
delete: "āĻŽā§āĻā§āύ"
|
||||
deleteAndEdit: "āĻŽā§āĻā§āύ āĻāĻŦāĻ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰā§āύ"
|
||||
deleteAndEditConfirm: "āĻāĻĒāύāĻŋ āĻāĻŋ āĻāĻ āύā§āĻāĻāĻŋ āĻŽā§āĻā§ āĻāĻāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰāĻžāϰ āĻŦāĻŋāώāϝāĻŧā§ āύāĻŋāĻļā§āĻāĻŋāϤ? āĻāĻĒāύāĻŋ āĻāĻāĻŋāϰ āϏāĻŽāϏā§āϤ āϰāĻŋāĻ
ā§āϝāĻžāĻāĻļāύ, āϰāĻŋāύā§āĻ āĻāĻŦāĻ āĻāĻŦāĻžāĻŦ āĻšāĻžāϰāĻžāĻŦā§āύāĨ¤"
|
||||
addToList: "āϞāĻŋāϏā§āĻ āĻ āϝā§āĻ āĻāϰā§āύ"
|
||||
addToAntenna: "āĻ
ā§āϝāĻžāύā§āĻā§āύāĻž āĻ āϝā§āĻ āĻāϰā§āύ"
|
||||
sendMessage: "āĻāĻāĻāĻŋ āĻŦāĻžāϰā§āϤāĻž āĻĒāĻžāĻ āĻžāύ"
|
||||
copyRSS: "RSS āĻāĻĒāĻŋ āĻāϰā§āύ"
|
||||
copyUsername: "āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āύāĻžāĻŽ āĻāĻĒāĻŋ āĻāϰā§āύ"
|
||||
copyUserId: "āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ ID āĻāĻĒāĻŋ āĻāϰā§āύ"
|
||||
copyNoteId: "āύā§āĻā§āϰ ID āĻāĻĒāĻŋ āĻāϰā§āύ"
|
||||
copyFileId: "āĻĢāĻžāĻāϞ ID āĻāĻĒāĻŋ āĻāϰā§āύ"
|
||||
copyFolderId: "āĻĢā§āϞā§āĻĄāĻžāϰ ID āĻāĻĒāĻŋ āĻāϰā§āύ"
|
||||
copyProfileUrl: "āĻĒā§āϰā§āĻĢāĻžāĻāϞ URL āĻāĻĒāĻŋ āĻāϰā§āύ"
|
||||
searchUser: "āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰ⧠āĻā§āĻāĻā§āύ..."
|
||||
reply: "āĻāĻŦāĻžāĻŦ"
|
||||
loadMore: "āĻāϰāĻ āĻĻā§āĻā§āύ"
|
||||
@@ -111,8 +100,6 @@ renoted: "āϰāĻŋāύā§āĻ āĻāϰāĻž āĻšā§ā§āĻā§"
|
||||
cantRenote: "āĻāĻ āύā§āĻāĻāĻŋ āϰāĻŋāύā§āĻ āĻāϰāĻž āϝāĻžāĻŦā§ āύāĻžāĨ¤"
|
||||
cantReRenote: "āϰāĻŋāύā§āĻāĻā§ āϰāĻŋāύā§āĻ āĻāϰāĻž āϝāĻžāĻŦā§ āύāĻžāĨ¤"
|
||||
quote: "āĻāĻĻā§āϧā§āϤāĻŋ"
|
||||
inChannelRenote: "āĻā§āϝāĻžāύā§āϞ⧠āϰāĻŋāύā§āĻ"
|
||||
inChannelQuote: "āĻā§āϝāĻžāύā§āϞ⧠āĻāĻĻā§āϧā§āϤāĻŋ"
|
||||
pinnedNote: "āĻĒāĻŋāύ āĻāϰāĻž āύā§āĻ"
|
||||
pinned: "āĻĒāĻŋāύ āĻāϰāĻž"
|
||||
you: "āĻāĻĒāύāĻŋ"
|
||||
@@ -121,10 +108,7 @@ sensitive: "āϏāĻāĻŦā§āĻĻāύāĻļā§āϞ āĻŦāĻŋāώā§āĻŦāϏā§āϤā§"
|
||||
add: "āϝā§āĻā§āϤ āĻāϰā§āύ"
|
||||
reaction: "āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž"
|
||||
reactions: "āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž"
|
||||
emojiPicker: "āĻāĻŽā§āĻāĻŋ āĻĒāĻŋāĻāĻžāϰ"
|
||||
pinnedEmojisForReactionSettingDescription: "āϰāĻŋāĻ
ā§āϝāĻžāĻāĻļāύ āĻĻā§ā§āĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻĒāύāĻŋ āĻāĻŽā§āĻāĻŋāĻāĻŋāĻā§ āĻĒāĻŋāύ āĻāϰāĻž āĻāĻŦāĻ āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻšāĻāϝāĻŧāĻžāϰ āĻāύā§āϝ āϏā§āĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤"
|
||||
pinnedEmojisSettingDescription: "āĻāĻŽā§āĻāĻŋ āĻāύāĻĒā§āĻ āĻĻā§ā§āĻžāϰ āϏāĻŽāϝāĻŧ āĻāĻĒāύāĻŋ āĻāĻŽā§āĻāĻŋāĻāĻŋāĻā§ āĻĒāĻŋāύ āĻāϰāĻž āĻāĻŦāĻ āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻšāĻāϝāĻŧāĻžāϰ āĻāύā§āϝ āϏā§āĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤"
|
||||
emojiPickerDisplay: "āĻĒāĻŋāĻāĻžāϰ āĻĄāĻŋāϏāĻĒā§āϞā§"
|
||||
reactionSetting: "āϰāĻŋāĻ
ā§āϝāĻžāĻāĻļāύ āĻĒāĻŋāĻāĻžāϰ⧠āϝā§āϏāĻāϞ āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋā§āĻž āĻĻā§āĻāĻžāύ⧠āĻšāĻŦā§"
|
||||
reactionSettingDescription2: "āĻĒā§āύāϰāĻžāϝāĻŧ āϏāĻžāĻāĻžāϤ⧠āĻā§āύ⧠āĻāύā§āύ, āĻŽā§āĻāϤ⧠āĻā§āϞāĻŋāĻ āĻāϰā§āύ, āϝā§āĻ āĻāϰāϤ⧠+ āĻāĻŋāĻĒā§āύāĨ¤"
|
||||
rememberNoteVisibility: "āύā§āĻā§āϰ āĻĻā§āĻļā§āϝāĻŽāĻžāύā§āϝāϤāĻžāϰ āϏā§āĻāĻŋāĻāϏ āĻŽāύ⧠āϰāĻžāĻā§āύ"
|
||||
attachCancel: "āĻ
ā§āϝāĻžāĻāĻžāĻāĻŽā§āύā§āĻ āϏāϰāĻžāύ "
|
||||
@@ -215,6 +199,7 @@ noUsers: "āĻā§āύ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻāĻžāϰ⧠āύā§āĻ"
|
||||
editProfile: "āĻĒā§āϰā§āĻĢāĻžāĻāϞ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰā§āύ"
|
||||
noteDeleteConfirm: "āĻāĻĒāύāĻŋ āĻāĻŋ āύā§āĻ āĻĄāĻŋāϞāĻŋāĻ āĻāϰāĻžāϰ āĻŦā§āϝāĻžāĻĒāĻžāϰ⧠āύāĻŋāĻļā§āĻāĻŋāϤ?"
|
||||
pinLimitExceeded: "āĻāĻĒāύāĻŋ āĻāϰ āĻā§āύ āύā§āĻ āĻĒāĻŋāύ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŦā§āύ āύāĻž"
|
||||
intro: "Misskey āĻāϰ āĻāύā§āϏāĻāϞā§āĻļāύ āϏāĻŽā§āĻĒāύā§āύ āĻšā§ā§āĻā§īŧāĻĻā§āĻž āĻāϰ⧠āĻ
ā§āϝāĻžāĻĄāĻŽāĻŋāύ āĻāĻāĻāĻžāϰ āϤā§āϰāĻŋ āĻāϰā§āύāĨ¤"
|
||||
done: "āϏāĻŽā§āĻĒāύā§āύ"
|
||||
processing: "āĻĒā§āϰāĻā§āϰāĻŋā§āĻžāϧā§āύ..."
|
||||
preview: "āĻĒā§āϰā§āĻŦāϰā§āĻĒ āĻĻā§āĻā§āύ"
|
||||
@@ -251,6 +236,7 @@ removeAreYouSure: "āĻāĻĒāύāĻŋ āĻāĻŋ \"{x}\" āϏāϰāĻžāύā§āϰ āĻŦā§āϝāĻž
|
||||
deleteAreYouSure: "āĻāĻĒāύāĻŋ āĻāĻŋ \"{x}\" āϏāϰāĻžāύā§āϰ āĻŦā§āϝāĻžāĻĒāĻžāϰ⧠āύāĻŋāĻļā§āĻāĻŋāϤ?"
|
||||
resetAreYouSure: "āϰāĻŋāϏā§āĻ āĻāϰāĻžāϰ āĻŦā§āϝāĻžāĻĒāĻžāϰ⧠āύāĻŋāĻļā§āĻāĻŋāϤ?"
|
||||
saved: "āϏāĻāϰāĻā§āώāĻŋāϤ āĻšā§ā§āĻā§"
|
||||
messaging: "āĻā§āϝāĻžāĻ"
|
||||
upload: "āĻāĻĒāϞā§āĻĄ"
|
||||
keepOriginalUploading: "āĻāϏāϞ āĻāĻŦāĻŋ āϰāĻžāĻā§āύ"
|
||||
keepOriginalUploadingDescription: "āĻāĻŦāĻŋāĻāĻŋ āĻāĻĒāϞā§āĻĄ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ āĻāϏāϞ āϏāĻāϏā§āĻāϰāĻŖāĻāĻŋ āϰāĻžāĻā§āύāĨ¤ āĻ
āĻĒāĻļāύāĻāĻŋ āĻŦāύā§āϧ āĻĨāĻžāĻāϞā§, āĻāĻĒāϞā§āĻĄā§āϰ āϏāĻŽāϝāĻŧ āĻāϝāĻŧā§āĻŦ āĻĒā§āϰāĻāĻžāĻļāύāĻžāϰ āĻāύā§āϝ āĻāĻŦāĻŋ āĻŦā§āϰāĻžāĻāĻāĻžāϰ⧠āϤā§āϰāĻŋ āĻāϰāĻž āĻšāĻŦā§āĨ¤"
|
||||
@@ -263,14 +249,15 @@ uploadFromUrlMayTakeTime: "URL āĻšāϤ⧠āĻāĻĒāϞā§āĻĄ āĻšāϤ⧠āĻāĻŋāĻā§
|
||||
explore: "āĻā§āϰ⧠āĻĻā§āĻā§āύ"
|
||||
messageRead: "āĻĒāĻĄāĻŧāĻž"
|
||||
noMoreHistory: "āĻāϰ āĻā§āύ āĻāϤāĻŋāĻšāĻžāϏ āύā§āĻ"
|
||||
startMessaging: "āĻā§āϝāĻžāĻ āĻļā§āϰ⧠āĻāϰā§āύ"
|
||||
nUsersRead: "{n} āĻāύ āĻĒā§ā§āĻā§āύ"
|
||||
agreeTo: "{0} āĻāϰ āĻĒā§āϰāϤāĻŋ āĻāĻŽāĻŋ āϏāĻŽā§āĻŽāϤ"
|
||||
tos: "āĻĒāϰāĻŋāώā§āĻŦāĻžāϰ āĻļāϰā§āϤāĻžāĻĻāĻŋ"
|
||||
start: "āĻļā§āϰ⧠āĻāϰā§āύ"
|
||||
home: "āĻŽā§āϞ āĻĒāĻžāϤāĻž"
|
||||
remoteUserCaution: "āĻāĻ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻāĻžāϰ⧠āϰāĻŋāĻŽā§āĻ āĻāύā§āϏāĻā§āϝāĻžāύā§āϏā§āϰ, āύāĻŋāĻŽā§āύāĻā§āϤ āϤāĻĨā§āϝ āĻ
āϏāĻŽā§āĻĒā§āϰā§āĻŖ āĻšāϤ⧠āĻĒāĻžāϰā§āĨ¤"
|
||||
activity: "āĻāĻžāϰā§āϝāĻāϞāĻžāĻĒ"
|
||||
images: "āĻāĻŦāĻŋ"
|
||||
image: "āĻāĻŦāĻŋ"
|
||||
birthday: "āĻāύā§āĻŽāĻĻāĻŋāύ"
|
||||
yearsOld: "{age} āĻŦāĻāϰ"
|
||||
registeredDate: "āϝā§āĻāĻĻāĻžāύā§āϰ āϤāĻžāϰāĻŋāĻ"
|
||||
@@ -307,6 +294,7 @@ copyUrl: "URL āĻāĻĒāĻŋ āĻāϰā§āύ"
|
||||
rename: "āĻĒā§āύāĻāύāĻžāĻŽāĻāϰāĻŖ"
|
||||
avatar: "āĻĒā§āϰā§āĻĢāĻžāĻāϞ āĻāĻŦāĻŋ"
|
||||
banner: "āĻŦā§āϝāĻžāύāĻžāϰ"
|
||||
nsfw: "āϏāĻāĻŦā§āĻĻāύāĻļā§āϞ āĻŦāĻŋāώā§āĻŦāϏā§āϤā§"
|
||||
whenServerDisconnected: "āϏāĻžāϰā§āĻāĻžāϰā§āϰ āϏāĻžāĻĨā§ āϏāĻāϝā§āĻ āĻŦāĻŋāĻā§āĻāĻŋāύā§āύ āĻšāϝāĻŧā§ āĻā§āϞā§"
|
||||
disconnectedFromServer: "āϏāĻžāϰā§āĻāĻžāϰ āĻĨā§āĻā§ āϏāĻāϝā§āĻ āĻŦāĻŋāĻā§āĻāĻŋāύā§āύ āĻšāϝāĻŧā§āĻā§"
|
||||
reload: "āĻāĻŦāĻžāϰ āϞā§āĻĄ āĻāϰā§āύ"
|
||||
@@ -336,10 +324,12 @@ enableLocalTimeline: "āϏā§āĻĨāĻžāύā§ā§ āĻāĻžāĻāĻŽāϞāĻžāĻāύ āĻāĻžāϞ
|
||||
enableGlobalTimeline: "āĻā§āϞā§āĻŦāĻžāϞ āĻāĻžāĻāĻŽāϞāĻžāĻāύ āĻāĻžāϞ⧠āĻāϰā§āύ"
|
||||
disablingTimelinesInfo: "āĻāĻĒāύāĻŋ āĻāĻ āĻāĻžāĻāĻŽāϞāĻžāĻāύāĻā§āϞāĻŋ āĻŦāύā§āϧ āĻāϰāϞā§āĻ āĻĒā§āϰāĻļāĻžāϏāĻ āĻāĻŦāĻ āĻŽāĻĄāĻžāϰā§āĻāϰāϰāĻž āĻāĻ āĻāĻžāĻāĻŽāϞāĻžāĻāύāĻā§āϞāĻŋ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŦā§"
|
||||
registration: "āύāĻŋāĻŦāύā§āϧāύ"
|
||||
enableRegistration: "āύāϤā§āύ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻāĻžāϰ⧠āύāĻŋāĻŦāύā§āϧāύ āĻāĻžāϞ⧠āĻāϰā§āύ"
|
||||
invite: "āĻāĻŽāύā§āϤā§āϰāĻŖ"
|
||||
driveCapacityPerLocalAccount: "āĻĒā§āϰāϤā§āϝā§āĻ āϏā§āĻĨāĻžāύā§ā§ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āĻāύā§āϝ āĻĄā§āϰāĻžāĻāĻā§āϰ āĻāĻžā§āĻāĻž"
|
||||
driveCapacityPerRemoteAccount: "āĻĒā§āϰāϤā§āϝā§āĻ āϰāĻŋāĻŽā§āĻ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āĻāύā§āϝ āĻĄā§āϰāĻžāĻāĻā§āϰ āĻāĻžā§āĻāĻž"
|
||||
inMb: "āĻŽā§āĻāĻžāĻŦāĻžāĻāĻā§ āϞāĻŋāĻā§āύ"
|
||||
iconUrl: "āĻāĻāĻāύā§āϰ URL (āĻĢā§āϝāĻžāĻāĻŋāĻāύ, āĻāϤā§āϝāĻžāĻĻāĻŋ)"
|
||||
bannerUrl: "āĻŦā§āϝāĻžāύāĻžāϰ āĻāĻŦāĻŋāϰ URL"
|
||||
backgroundImageUrl: "āĻĒāĻāĻā§āĻŽāĻŋāϰ āĻāĻŋāϤā§āϰā§āϰ URL"
|
||||
basicInfo: "āĻāĻĒāύāĻžāϰ āĻŦā§āϝāĻā§āϤāĻŋāĻāϤ āϤāĻĨā§āϝ"
|
||||
@@ -353,8 +343,6 @@ hcaptcha: "hCaptcha"
|
||||
enableHcaptcha: "hCaptcha āĻāĻžāϞ⧠āĻāϰā§āύ"
|
||||
hcaptchaSiteKey: "āϏāĻžāĻāĻ āĻā§"
|
||||
hcaptchaSecretKey: "āϏāĻŋāĻā§āϰā§āĻ āĻā§"
|
||||
mcaptchaSiteKey: "āϏāĻžāĻāĻ āĻā§"
|
||||
mcaptchaSecretKey: "āϏāĻŋāĻā§āϰā§āĻ āĻā§"
|
||||
recaptcha: "reCAPTCHA"
|
||||
enableRecaptcha: "reCAPTCHA āĻāĻžāϞ⧠āĻāϰā§āύ"
|
||||
recaptchaSiteKey: "āϏāĻžāĻāĻ āĻā§"
|
||||
@@ -407,6 +395,7 @@ share: "āĻļā§ā§āĻžāϰ"
|
||||
notFound: "āĻĒāĻžāĻā§āĻž āϝāĻžā§āύāĻŋ"
|
||||
notFoundDescription: "āĻāĻ URL-āĻāϰ āϏāĻžāĻĨā§ āϏāĻŽā§āĻĒāϰā§āĻāĻŋāϤ āĻā§āύ⧠āĻĒā§āώā§āĻ āĻž āύā§āĻāĨ¤"
|
||||
uploadFolder: "āĻāĻĒāϞā§āĻĄā§āϰ āĻāύā§āϝ āĻĄāĻŋāĻĢāϞā§āĻ āĻĢā§āϞā§āĻĄāĻžāϰ"
|
||||
cacheClear: "āĻā§āϝāĻžāĻļ āĻĒāϰāĻŋāώā§āĻāĻžāϰ āĻāϰā§āύ"
|
||||
markAsReadAllNotifications: "āϏāĻŽāϏā§āϤ āĻŦāĻŋāĻā§āĻāĻĒā§āϤāĻŋāĻā§āϞāĻŋ āĻĒāĻ āĻŋāϤ āĻšāĻŋāϏāĻžāĻŦā§ āĻāĻŋāĻšā§āύāĻŋāϤ āĻāϰā§āύ"
|
||||
markAsReadAllUnreadNotes: "āϏāĻŽāϏā§āϤ āύā§āĻāĻā§āϞāĻŋ āĻĒāĻ āĻŋāϤ āĻšāĻŋāϏāĻžāĻŦā§ āĻāĻŋāĻšā§āύāĻŋāϤ āĻāϰā§āύ"
|
||||
markAsReadAllTalkMessages: "āϏāĻŽāϏā§āϤ āĻŽā§āϏā§āĻ āĻĒāĻ āĻŋāϤ āĻšāĻŋāϏāĻžāĻŦā§ āĻāĻŋāĻšā§āύāĻŋāϤ āĻāϰā§āύ"
|
||||
@@ -424,6 +413,8 @@ retype: "āĻĒā§āύāĻ āĻĒā§āϰāĻŦā§āĻļ"
|
||||
noteOf: "{user} āĻāϰ āύā§āĻ"
|
||||
quoteAttached: "āĻāĻĻā§āϧā§āϤ"
|
||||
quoteQuestion: "āĻāĻĻā§āϧā§āϤāĻŋ āĻšāĻŋāϏāĻžāĻŦā§ āϏāĻāϝā§āĻā§āϤ āĻāϰāĻŦā§āύ?"
|
||||
noMessagesYet: "āĻā§āύ āĻŽā§āϏā§āĻ āύā§āĻ"
|
||||
newMessageExists: "āύāϤā§āύ āĻŽā§āϏā§āĻ āĻĒā§ā§ā§āĻā§āύ"
|
||||
onlyOneFileCanBeAttached: "āĻāĻĒāύāĻŋ āĻŽā§āϏā§āĻā§āϰ āϏāĻžāĻĨā§ āϏāϰā§āĻŦā§āĻā§āĻ āĻāĻāĻāĻŋ āĻĢāĻžāĻāϞ āϝā§āĻā§āϤ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŦā§āύ"
|
||||
signinRequired: "āĻĻāϝāĻŧāĻž āĻāϰ⧠āϞāĻ āĻāύ āĻāϰā§āύ"
|
||||
invitations: "āĻāĻŽāύā§āϤā§āϰāĻŖ"
|
||||
@@ -445,6 +436,7 @@ or: "āĻ
āĻĨāĻŦāĻž"
|
||||
language: "āĻāĻžāώāĻž"
|
||||
uiLanguage: "UI āĻāϰ āĻāĻžāώāĻž"
|
||||
aboutX: "{x} āϏāĻŽā§āĻĒāϰā§āĻā§"
|
||||
disableDrawer: "āĻĄā§āϰāϝāĻŧāĻžāϰ āĻŽā§āύ⧠āĻĒā§āϰāĻĻāϰā§āĻļāύ āĻāϰāĻŦā§āύ āύāĻž"
|
||||
noHistory: "āĻā§āύ⧠āĻāϤāĻŋāĻšāĻžāϏ āύā§āĻ"
|
||||
signinHistory: "āĻĒā§āϰāĻŦā§āĻļ āĻāϰāĻžāϰ āĻāϤāĻŋāĻšāĻžāϏ"
|
||||
doing: "āĻĒā§āϰāĻā§āϰāĻŋā§āĻž āĻāϰāĻā§..."
|
||||
@@ -618,7 +610,10 @@ abuseReported: "āĻāĻĒāύāĻžāϰ āĻ
āĻāĻŋāϝā§āĻāĻāĻŋ āĻĻāĻžāĻāĻŋāϞ āĻāϰ
|
||||
reporter: "āĻ
āĻāĻŋāϝā§āĻāĻāĻžāϰā§"
|
||||
reporteeOrigin: "āĻ
āĻāĻŋāϝā§āĻāĻāĻŋāϰ āĻā§āϏ"
|
||||
reporterOrigin: "āĻ
āĻāĻŋāϝā§āĻāĻāĻžāϰā§āϰ āĻā§āϏ"
|
||||
forwardReport: "āϰāĻŋāĻŽā§āĻ āĻāύā§āϏāϤā§āϝāĻžāύā§āϏ⧠āĻ
āĻāĻŋāϝā§āĻāĻāĻŋ āĻĒāĻžāĻ āĻžāύ"
|
||||
forwardReportIsAnonymous: "āĻāĻĒāύāĻžāϰ āϤāĻĨā§āϝ āϰāĻŋāĻŽā§āĻ āĻāύā§āϏāϤā§āϝāĻžāύā§āϏ⧠āĻĒāĻžāĻ āĻžāύ⧠āĻšāĻŦā§ āύāĻž āĻāĻŦāĻ āĻāĻāĻāĻŋ āĻŦā§āύāĻžāĻŽā§ āϏāĻŋāϏā§āĻā§āĻŽ āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻ āĻšāĻŋāϏāĻžāĻŦā§ āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻšāĻŦā§āĨ¤"
|
||||
send: "āĻĒāĻžāĻ āĻžāύ"
|
||||
abuseMarkAsResolved: "āĻ
āĻāĻŋāϝā§āĻāĻāĻŋāĻā§ āϏāĻŽāĻžāϧāĻžāĻā§āϤ āĻšāĻŋāϏāĻžāĻŦā§ āĻāĻŋāĻšā§āύāĻŋāϤ āĻāϰā§āύ"
|
||||
openInNewTab: "āύāϤā§āύ āĻā§āϝāĻžāĻŦā§ āĻā§āϞā§āύ"
|
||||
openInSideView: "āϏāĻžāĻāĻĄ āĻāĻŋāĻāϤ⧠āĻā§āϞā§āύ"
|
||||
defaultNavigationBehaviour: "āĻĄāĻŋāĻĢāϞā§āĻ āύā§āĻāĻŋāĻā§āĻļāύ"
|
||||
@@ -634,7 +629,6 @@ createNew: "āύāϤā§āύ"
|
||||
optional: "āĻĒā§āϰāϝāĻŧā§āĻāύā§ā§ āύā§"
|
||||
createNewClip: "āύāϤā§āύ āĻā§āϞāĻŋāĻĒ āϤā§āϰāĻŋ āĻāϰā§āύ"
|
||||
public: "āϏāϰā§āĻŦāĻāύā§āύ"
|
||||
private: "āĻŦā§āϝāĻžāĻā§āϤāĻŋāĻāϤ"
|
||||
i18nInfo: "Misskey āϏā§āĻŦā§āĻā§āĻāĻžāϏā§āĻŦāĻāĻĻā§āϰ āĻĻā§āĻŦāĻžāϰāĻž āĻŦāĻŋāĻāĻŋāύā§āύ āĻāĻžāώāĻžāϝāĻŧ āĻ
āύā§āĻŦāĻžāĻĻ āĻāϰāĻž āĻšāĻā§āĻā§āĨ¤ āĻāĻĒāύāĻŋ {link} āĻ āĻāĻŋā§ā§ āĻ
āύā§āĻŦāĻžāĻĻā§ āϏāĻšāϝā§āĻāĻŋāϤāĻž āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤"
|
||||
manageAccessTokens: "āĻ
ā§āϝāĻžāĻā§āϏā§āϏ āĻā§āĻā§āύ āĻĒāϰāĻŋāĻāĻžāϞāύāĻž āĻāϰā§āύ"
|
||||
accountInfo: "āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻā§āϰ āϤāĻĨā§āϝ"
|
||||
@@ -672,6 +666,7 @@ experimentalFeatures: "āĻĒāϰā§āĻā§āώāĻžāĻŽā§āϞāĻ āĻŦā§āĻļāĻŋāώā§āĻ
|
||||
developer: "āĻĄā§āĻā§āϞāĻĒāĻžāϰ"
|
||||
makeExplorable: "āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻ \"āĻā§āϰ⧠āĻĻā§āĻā§āύ\" āĻĒā§āώā§āĻ āĻžā§ āĻĻā§āĻāĻžāύ"
|
||||
makeExplorableDescription: "āĻāĻĒāύāĻŋ āĻāĻāĻŋ āĻŦāύā§āϧ āĻāϰāϞā§, āĻāĻĒāύāĻžāϰ āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻ \"āĻā§āϰ⧠āĻĻā§āĻā§āύ\" āĻĒā§āώā§āĻ āĻžā§ āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻšāĻŦā§ āύāĻžāĨ¤"
|
||||
showGapBetweenNotesInTimeline: "āĻāĻžāĻāĻŽāϞāĻžāĻāύ āĻāĻŦāĻ āύā§āĻā§āϰ āĻŽāĻžāĻā§ āĻĢāĻžāĻāĻž āĻāĻžā§āĻāĻž āϰāĻžāĻā§āύ"
|
||||
duplicate: "āĻĒā§āϰāϤāĻŋāϰā§āĻĒ"
|
||||
left: "āĻŦāĻžāĻŽ"
|
||||
center: "āĻŽāĻžāĻāĻāĻžāύ"
|
||||
@@ -801,6 +796,8 @@ makeReactionsPublicDescription: "āĻāĻĒāύāĻžāϰ āĻĒā§āϰā§āĻŦāĻŦāϰā§āϤā§
|
||||
classic: "āĻā§āϞāĻžāϏāĻŋāĻ"
|
||||
muteThread: "āĻĨā§āϰā§āĻĄ āĻŽāĻŋāĻāĻ āĻāϰā§āύ"
|
||||
unmuteThread: "āĻĨā§āϰā§āĻĄ āĻāύāĻŽāĻŋāĻāĻ āĻāϰā§āύ"
|
||||
ffVisibility: "āĻ
āύā§āϏāϰāĻŖ/āĻ
āύā§āϏāϰāĻŖāĻāĻžāϰā§āĻĻā§āϰ āĻĻā§āĻļā§āϝāĻŽāĻžāύā§āϝāϤāĻž"
|
||||
ffVisibilityDescription: "āĻāĻĒāύāĻŋ āĻāĻžāĻā§ āĻ
āύā§āϏāϰāĻŖ āĻāϰā§āύ āĻāĻŦāĻ āĻā§ āĻāĻĒāύāĻžāĻā§ āĻ
āύā§āϏāϰāĻŖ āĻāϰā§, āϏā§āĻāĻž āĻāĻžāϰāĻž āĻĻā§āĻāϤ⧠āĻĒāĻžāĻŦā§ āϤāĻž āύāĻŋāϰā§āϧāĻžāϰāĻŖ āĻāϰā§āĨ¤"
|
||||
continueThread: "āĻāϰ⧠āĻĨā§āϰā§āĻĄ āĻĻā§āĻā§āύ"
|
||||
deleteAccountConfirm: "āĻāĻĒāύāĻžāϰ āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻ āĻŽā§āĻā§ āĻĢā§āϞāĻž āĻšāĻŦā§āĨ¤ āĻ āĻŋāĻ āĻāĻā§?"
|
||||
incorrectPassword: "āĻāĻĒāύāĻžāϰ āĻĻā§āĻā§āĻž āĻĒāĻžāϏāĻāϝāĻŧāĻžāϰā§āĻĄāĻāĻŋ āĻā§āϞāĨ¤"
|
||||
@@ -839,36 +836,6 @@ account: "āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻāĻā§āϞāĻŋ"
|
||||
like: "āĻĒāĻāύā§āĻĻ āĻāϰāĻž"
|
||||
show: "āĻĒā§āϰāĻĻāϰā§āĻļāύ"
|
||||
color: "āϰāĻ"
|
||||
horizontal: "āĻĒāĻžāĻļā§"
|
||||
youFollowing: "āĻ
āύā§āϏāϰāĻŖ āĻāϰāĻž āĻšāĻā§āĻā§"
|
||||
icon: "āĻĒā§āϰā§āĻĢāĻžāĻāϞ āĻāĻŦāĻŋ"
|
||||
replies: "āĻāĻŦāĻžāĻŦ"
|
||||
renotes: "āϰāĻŋāύā§āĻ"
|
||||
sourceCode: "āϏā§āϰā§āϏ āĻā§āĻĄ"
|
||||
flip: "āĻāϞā§āĻāĻžāύ"
|
||||
postForm: "āύā§āĻ āϞāĻŋāĻā§āύ"
|
||||
information: "āĻāĻĒāύāĻžāϰ āϏāĻŽā§āĻĒāϰā§āĻā§"
|
||||
inMinutes: "āĻŽāĻŋāύāĻŋāĻ"
|
||||
inDays: "āĻĻāĻŋāύ"
|
||||
widgets: "āĻāĻāĻā§āĻāĻā§āϞāĻŋ"
|
||||
_imageEditing:
|
||||
_vars:
|
||||
filename: "āĻĢāĻžāĻāϞā§āϰ āύāĻžāĻŽ"
|
||||
_imageFrameEditor:
|
||||
header: "āĻšā§āĻĄāĻžāϰ"
|
||||
font: "āĻĢāύā§āĻ"
|
||||
fontSerif: "āϏā§āϰāĻŋāĻĢ"
|
||||
fontSansSerif: "āϏā§āϝāĻžāύā§āϏ āϏā§āϰāĻŋāĻĢ"
|
||||
_chat:
|
||||
invitations: "āĻāĻŽāύā§āϤā§āϰāĻŖ"
|
||||
noHistory: "āĻā§āύ⧠āĻāϤāĻŋāĻšāĻžāϏ āύā§āĻ"
|
||||
members: "āϏāĻĻāϏā§āϝāĻŦā§āύā§āĻĻ"
|
||||
home: "āĻŽā§āϞ āĻĒāĻžāϤāĻž"
|
||||
send: "āĻĒāĻžāĻ āĻžāύ"
|
||||
_delivery:
|
||||
stop: "āϏā§āĻĨāĻāĻŋāϤ āĻāϰāĻž āĻšā§ā§āĻā§"
|
||||
_type:
|
||||
none: "āĻĒā§āϰāĻāĻžāĻļ āĻāϰāĻž āĻšāĻā§āĻā§"
|
||||
_role:
|
||||
priority: "āĻ
āĻā§āϰāĻžāϧāĻŋāĻāĻžāϰ"
|
||||
_priority:
|
||||
@@ -918,7 +885,6 @@ _plugin:
|
||||
install: "āĻĒā§āϞāĻžāĻāĻāύ āĻāύā§āϏāĻāϞ āĻāϰā§āύ"
|
||||
installWarn: "āĻ
āĻŦāĻŋāĻļā§āĻŦāϏā§āϤ āĻĒā§āϞāĻžāĻāĻāύ āĻāύāϏā§āĻāϞ āĻāϰāĻŦā§āύ āύāĻžāĨ¤"
|
||||
manage: "āĻĒā§āϞāĻžāĻāĻāύ āĻŽā§āϝāĻžāύā§āĻ āĻāϰā§āύ"
|
||||
viewSource: "āĻā§āϏ āĻĻā§āĻā§āύ"
|
||||
_registry:
|
||||
scope: "āϏā§āĻā§āĻĒ"
|
||||
key: "āĻā§"
|
||||
@@ -934,6 +900,10 @@ _aboutMisskey:
|
||||
donate: "Misskey āϤ⧠āĻĻāĻžāύ āĻāϰā§āύ"
|
||||
morePatrons: "āĻāϰāĻ āĻ
āύā§āĻā§ āĻāĻŽāĻžāĻĻā§āϰ āϏāĻžāĻšāĻžāϝā§āϝ āĻāϰāĻā§āύāĨ¤ āϤāĻžāĻĻā§āϰ āϏāĻŦāĻžāĻāĻā§ āϧāύā§āϝāĻŦāĻžāĻĻ đĨ°"
|
||||
patrons: "āϏāĻŽāϰā§āĻĨāύāĻāĻžāϰā§"
|
||||
_nsfw:
|
||||
respect: "āϏā§āĻĒāϰā§āĻļāĻāĻžāϤāϰ āĻŽāĻŋāĻĄāĻŋā§āĻž āϞā§āĻāĻžāύ"
|
||||
ignore: "āϏā§āĻĒāϰā§āĻļāĻāĻžāϤāϰ āĻŽāĻŋāĻĄāĻŋā§āĻž āϞā§āĻāĻžāĻŦā§āύ āύāĻž"
|
||||
force: "āϏāĻāϞ āĻŽāĻŋāĻĄāĻŋā§āĻž āϞā§āĻāĻžāύ"
|
||||
_instanceTicker:
|
||||
none: "āĻĻā§āĻāĻžāĻŦā§āύ āύāĻž"
|
||||
remote: "āϰāĻŋāĻŽā§āĻ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻĻā§āϰ āĻāύā§āϝ āĻĻā§āĻāĻžāύ"
|
||||
@@ -961,6 +931,11 @@ _wordMute:
|
||||
muteWords: "āύāĻŋāĻāĻļāĻŦā§āĻĻ āĻāϰāĻž āĻļāĻŦā§āĻĻāĻā§āϞāĻŋ"
|
||||
muteWordsDescription: "āϏā§āĻĒā§āϏ āĻĻāĻŋāϝāĻŧā§ āĻāϞāĻžāĻĻāĻž āĻāϰāϞ⧠AND āĻļāϰā§āϤ āϤā§āϰāĻŋ āĻšāĻŦā§ āĻāĻŦāĻ āĻāϞāĻžāĻĻāĻž āϞāĻžāĻāύ⧠āϞāĻŋāĻāϞ⧠OR āĻļāϰā§āϤ āϤā§āϰāĻŋ āĻšāĻŦā§āĨ¤"
|
||||
muteWordsDescription2: "āϰā§āĻā§āϞāĻžāϰ āĻāĻā§āϏāĻĒā§āϰā§āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰāϤ⧠āϏā§āϞā§āϝāĻžāĻļ āĻĻāĻŋāϝāĻŧā§ āĻā§āĻāϝāĻŧāĻžāϰā§āĻĄāĻā§ āĻāĻŋāϰ⧠āϰāĻžāĻā§āύāĨ¤"
|
||||
softDescription: "āĻāĻžāĻāĻŽāϞāĻžāĻāύ āĻĨā§āĻā§ āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻļāϰā§āϤāĻžāύā§āϝāĻžā§ā§ āύā§āĻ āϞā§āĻāĻŋāϝāĻŧā§ āϰāĻžāĻā§āĨ¤"
|
||||
hardDescription: "āύāĻŋāϰā§āĻĻāĻŋāώā§āĻ āĻļāϰā§āϤāĻžāύā§āϝāĻžā§ā§ āύā§āĻāĻā§āϞāĻŋāĻā§ āĻāĻžāĻāĻŽāϞāĻžāĻāύ āĻĨā§āĻā§ āĻŦāĻžāĻĻ āĻĻā§ā§āĨ¤ āĻāĻĒāύāĻŋ āĻļāϰā§āϤ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰāϞā§āĻ āϝ⧠āύā§āĻāĻā§āϞāĻŋ āϝā§āĻ āĻāϰāĻž āĻšāϝāĻŧāύāĻŋ āϏā§āĻā§āϞāĻŋ āĻŦāĻžāĻĻ āĻĻā§āĻāϝāĻŧāĻž āĻšāĻŦā§āĨ¤"
|
||||
soft: "āύāĻŽāύā§ā§"
|
||||
hard: "āĻāĻ ā§āϰ"
|
||||
mutedNotes: "āĻŽāĻŋāĻāĻ āĻāϰāĻž āύā§āĻāĻā§āϞāĻŋ"
|
||||
_instanceMute:
|
||||
instanceMuteDescription: "āĻāύāĻĢāĻŋāĻāĻžāϰ āĻāϰāĻž āĻāύā§āϏāĻā§āϝāĻžāύā§āϏā§āϰ āϏāĻŦ āύā§āĻ āĻāĻŦāĻ āϰāĻŋāύā§āĻ āĻŽāĻŋāĻāĻ āĻāϰā§āύ, āĻŽāĻŋāĻāĻ āĻāϰāĻž āĻāύā§āϏāĻā§āϝāĻžāύā§āϏā§āϰ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻĻā§āϰ āĻāϤā§āϤāϰ āϏāĻšāĨ¤"
|
||||
instanceMuteDescription2: "āĻĒā§āϰāϤāĻŋāĻāĻŋāĻā§ āĻāϞāĻžāĻĻāĻž āϞāĻžāĻāύ⧠āϞāĻŋāĻā§āύ"
|
||||
@@ -1007,6 +982,7 @@ _theme:
|
||||
header: "āĻšā§āĻĄāĻžāϰ"
|
||||
navBg: "āϏāĻžāĻāĻĄāĻŦāĻžāϰā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ"
|
||||
navFg: "āϏāĻžāĻāĻĄāĻŦāĻžāϰā§āϰ āĻĒāĻžāĻ ā§āϝ"
|
||||
navHoverFg: "āϏāĻžāĻāĻĄāĻŦāĻžāϰā§āϰ āĻĒāĻžāĻ ā§āϝ (āĻšāĻāĻžāϰ)"
|
||||
navActive: "āϏāĻžāĻāĻĄāĻŦāĻžāϰā§āϰ āĻĒāĻžāĻ ā§āϝ (āĻ
ā§āϝāĻžāĻāĻāĻŋāĻ)"
|
||||
navIndicator: "āϏāĻžāĻāĻĄāĻŦāĻžāϰā§āϰ āĻāύāĻĄāĻŋāĻā§āĻāϰ"
|
||||
link: "āϞāĻŋāĻāĻ"
|
||||
@@ -1023,18 +999,30 @@ _theme:
|
||||
infoFg: "āϤāĻĨā§āϝā§āϰ āĻĒāĻžāĻ ā§āϝ"
|
||||
infoWarnBg: "āĻā§āĻžāϰā§āύāĻŋāĻ āĻāϰ āĻĒāĻāĻā§āĻŽāĻŋ"
|
||||
infoWarnFg: "āĻā§āĻžāϰā§āύāĻŋāĻ āĻāϰ āĻĒāĻžāĻ ā§āϝ"
|
||||
cwBg: "CW āĻŦāĻžāĻāύā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ"
|
||||
cwFg: "CW āĻŦāĻžāĻāύā§āϰ āĻĒāĻžāĻ ā§āϝ"
|
||||
cwHoverBg: "CW āĻŦāĻžāĻāύā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ (āĻšāĻāĻžāϰ)"
|
||||
toastBg: "āĻŦāĻŋāĻā§āĻāĻĒā§āϤāĻŋāϰ āĻĒāĻāĻā§āĻŽāĻŋ"
|
||||
toastFg: "āĻŦāĻŋāĻā§āĻāĻĒā§āϤāĻŋāϰ āĻĒāĻžāĻ ā§āϝ"
|
||||
buttonBg: "āĻŦāĻžāĻāύā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ"
|
||||
buttonHoverBg: "āĻŦāĻžāĻāύā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ (āĻšāĻāĻžāϰ)"
|
||||
inputBorder: "āĻāύāĻĒā§āĻ āĻĢāĻŋāϞā§āĻĄā§āϰ āĻŦāϰā§āĻĄāĻžāϰ"
|
||||
listItemHoverBg: "āϞāĻŋāϏā§āĻ āĻāĻāĻā§āĻŽā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ (āĻšā§āĻāĻžāϰ)"
|
||||
driveFolderBg: "āĻĄā§āϰāĻžāĻāĻ āĻĢā§āϞā§āĻĄāĻžāϰā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ"
|
||||
wallpaperOverlay: "āĻāϝāĻŧāĻžāϞāĻĒā§āĻĒāĻžāϰ āĻāĻāĻžāϰāϞā§"
|
||||
badge: "āĻŦā§āϝāĻžāĻ"
|
||||
messageBg: "āĻā§āϝāĻžāĻā§āϰ āĻĒāĻāĻā§āĻŽāĻŋ"
|
||||
accentDarken: "āĻ
ā§āϝāĻžāĻāϏā§āύā§āĻ (āĻāĻžā§)"
|
||||
accentLighten: "āĻ
ā§āϝāĻžāĻāϏā§āύā§āĻ (āĻšāĻžāϞā§āĻāĻž)"
|
||||
fgHighlighted: "āĻšāĻžāĻāϞāĻžāĻāĻ āĻāϰāĻž āĻĒāĻžāĻ ā§āϝ"
|
||||
_sfx:
|
||||
note: "āύā§āĻāĻā§āϞāĻŋ"
|
||||
noteMy: "āύā§āĻ (āĻāĻĒāύāĻžāϰ)"
|
||||
notification: "āĻŦāĻŋāĻā§āĻāĻĒā§āϤāĻŋ"
|
||||
chat: "āĻā§āϝāĻžāĻ"
|
||||
chatBg: "āĻā§āϝāĻžāĻ (āĻŦā§āϝāĻžāĻāĻā§āϰāĻžāĻāύā§āĻĄ)"
|
||||
antenna: "āĻ
ā§āϝāĻžāύā§āĻā§āύāĻžāĻā§āϞāĻŋ"
|
||||
channel: "āĻā§āϝāĻžāύā§āϞā§āϰ āĻŦāĻŋāĻā§āĻāĻĒā§āϤāĻŋ"
|
||||
_ago:
|
||||
future: "āĻāĻŦāĻŋāώā§āϝā§"
|
||||
justNow: "āĻāĻāĻŽāĻžāϤā§āϰ"
|
||||
@@ -1051,14 +1039,37 @@ _time:
|
||||
minute: "āĻŽāĻŋāύāĻŋāĻ"
|
||||
hour: "āĻāĻŖā§āĻāĻž"
|
||||
day: "āĻĻāĻŋāύ"
|
||||
_tutorial:
|
||||
title: "Misskey āĻāĻŋāĻāĻžāĻŦā§ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ āĻāϰāĻŦā§āύ"
|
||||
step1_1: "āϏā§āĻŦāĻžāĻāϤāĻŽ!"
|
||||
step1_2: "āĻāĻ āϏā§āĻā§āϰā§āύāĻāĻŋāĻā§ \"āĻāĻžāĻāĻŽāϞāĻžāĻāύ\" āĻŦāϞāĻž āĻšāϝāĻŧ āĻāĻŦāĻ āĻāĻžāϞāĻžāύā§āĻā§āϰāĻŽāĻŋāĻ āĻā§āϰāĻŽā§ āĻāĻĒāύāĻžāϰ āĻāĻŦāĻ āĻāĻĒāύāĻŋ āϝāĻžāĻĻā§āϰ \"āĻ
āύā§āϏāϰāĻŖ āĻāϰā§āύ\" āϤāĻžāĻĻā§āϰ \"āύā§āĻāĻā§āϞāĻŋ\" āĻĻā§āĻāĻžāϝāĻŧ⧎"
|
||||
step1_3: "āĻāĻĒāύāĻŋ āĻāĻĒāύāĻžāϰ āĻāĻžāĻāĻŽāϞāĻžāĻāύ⧠āĻāĻŋāĻā§ āĻĻā§āĻāϤ⧠āĻĒāĻžāĻŦā§āύ āύāĻž āĻāĻžāϰāĻŖ āĻāĻĒāύāĻŋ āĻāĻāύāĻ āĻā§āύ⧠āύā§āĻ āĻĒā§āϏā§āĻ āĻāϰā§āύāύāĻŋ āĻāĻŦāĻ āĻāĻĒāύāĻŋ āĻāĻžāĻāĻā§ āĻ
āύā§āϏāϰāĻŖ āĻāϰāĻā§āύ āύāĻžā§ˇ"
|
||||
step2_1: "āύā§āĻ āϤā§āϰāĻŋ āĻāϰāĻžāϰ āĻāĻā§ āĻŦāĻž āĻāĻžāĻāĻā§ āĻ
āύā§āϏāϰāĻŖ āĻāϰāĻžāϰ āĻāĻā§ āĻĒā§āϰāĻĨāĻŽā§ āĻāĻĒāύāĻžāϰ āĻĒā§āϰā§āĻĢāĻžāĻāϞāĻāĻŋ āϏāĻŽā§āĻĒā§āϰā§āĻŖ āĻāϰā§āύāĨ¤"
|
||||
step2_2: "āĻāĻĒāύāĻŋ āĻā§ āϤāĻž āĻāĻžāύāĻž āĻ
āύā§āĻ āϞā§āĻā§āϰ āĻāύā§āϝ āĻāĻĒāύāĻžāϰ āύā§āĻāĻā§āϞāĻŋ āĻĻā§āĻāĻž āĻāĻŦāĻ āĻ
āύā§āϏāϰāĻŖ āĻāϰāĻžāĻā§ āϏāĻšāĻ āĻāϰ⧠āϤā§āϞā§ā§ˇ"
|
||||
step3_1: "āĻāĻĒāύāĻŋ āĻāĻŋ āϏāĻĢāϞāĻāĻžāĻŦā§ āĻāĻĒāύāĻžāϰ āĻĒā§āϰā§āĻĢāĻžāĻāϞ āϏā§āĻ āĻāĻĒ āĻāϰā§āĻā§āύ?"
|
||||
step3_2: "āĻāĻāύ, āĻāĻŋāĻā§ āύā§āĻ āĻĒā§āϏā§āĻ āĻāϰāĻžāϰ āĻā§āώā§āĻāĻž āĻāϰā§āύāĨ¤ āĻĒā§āϏā§āĻ āĻĢāϰā§āĻŽ āĻā§āϞāϤ⧠āĻĒā§āύā§āϏāĻŋāϞ āĻāĻŋāĻšā§āύāϝā§āĻā§āϤ āĻŦāĻžāĻāύ⧠āĻā§āϞāĻŋāĻ āĻāϰā§āύāĨ¤"
|
||||
step3_3: "āĻŦāĻŋāώāϝāĻŧāĻŦāϏā§āϤ⧠āϞā§āĻāĻžāϰ āĻĒāϰā§, āĻāĻĒāύāĻŋ āĻĢāϰā§āĻŽā§āϰ āĻāĻĒāϰā§āϰ āĻĄāĻžāύāĻĻāĻŋāĻā§āϰ āĻŦāĻžāĻāύ⧠āĻā§āϞāĻŋāĻ āĻāϰ⧠āĻĒā§āϏā§āĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤"
|
||||
step3_4: "āĻĒā§āϏā§āĻ āĻāϰāĻžāϰ āĻŽāϤ āĻāĻŋāĻā§ āĻŽāύ⧠āĻĒāϰāĻā§ āύāĻž? \"āĻāĻŽāĻŋ āĻŽāĻŋāϏāĻāĻŋ āϏā§āĻ āĻāĻĒ āĻāϰāĻāĻŋ\" āĻŦāϞāϞ⧠āĻā§āĻŽāύ āĻšāϝāĻŧ?"
|
||||
step4_1: "āĻĒā§āϏā§āĻ āĻāϰā§āĻā§āύ?"
|
||||
step4_2: "āϏāĻžāĻŦāĻžāĻļ! āĻāĻāύ āĻāĻĒāύāĻžāϰ āύā§āĻ āĻāĻžāĻāĻŽāϞāĻžāĻāύ⧠āĻĻā§āĻāĻž āϝāĻžāĻŦā§āĨ¤"
|
||||
step5_1: "āĻāĻāύ āĻ
āύā§āϝāĻĻā§āϰāĻā§ āĻ
āύā§āϏāϰāĻŖ āĻāϰ⧠āĻāĻĒāύāĻžāϰ āĻāĻžāĻāĻŽāϞāĻžāĻāύāĻā§ āĻĒā§āϰāĻžāĻŖāĻŦāύā§āϤ āĻāϰ⧠āϤā§āϞā§āύāĨ¤"
|
||||
step5_2: "āĻāĻĒāύāĻŋ {featured}-āĻ āĻāύāĻĒā§āϰāĻŋāϝāĻŧ āύā§āĻāĻā§āϞāĻŋ āĻĻā§āĻāϤ⧠āĻĒāĻžāϰā§āύ, āϝāĻžāϤ⧠āĻāĻĒāύāĻŋ āϝ⧠āĻŦā§āϝāĻā§āϤāĻŋāĻā§ āĻĒāĻāύā§āĻĻ āĻāϰā§āύ āϤāĻžāĻā§ āĻŦā§āĻā§ āύāĻŋāϤ⧠āĻāĻŦāĻ āĻ
āύā§āϏāϰāĻŖ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ, āĻ
āĻĨāĻŦāĻž {explore}-āĻ āĻāύāĻĒā§āϰāĻŋāϝāĻŧ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻĻā§āϰ āĻĻā§āĻāϤ⧠āĻĒāĻžāϰā§āύ⧎"
|
||||
step5_3: "āĻāĻāĻāύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻā§ āĻ
āύā§āϏāϰāĻŖ āĻāϰāϤā§, āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āĻāĻāĻāύ⧠āĻā§āϞāĻŋāĻ āĻāϰā§āύ āĻāĻŦāĻ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āĻĒā§āώā§āĻ āĻžāϤ⧠\"āĻ
āύā§āϏāϰāĻŖ āĻāϰā§āύ\" āĻŦāĻžāĻāύ⧠āĻā§āϞāĻŋāĻ āĻāϰā§āύāĨ¤"
|
||||
step5_4: "āϝāĻĻāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āϰ āύāĻžāĻŽā§āϰ āĻĒāĻžāĻļā§ āĻāĻāĻāĻŋ āϞāĻ āĻāĻāĻāύ āĻĨāĻžāĻā§ āϤāĻžāĻšāϞ⧠āĻāĻĒāύāĻžāϰ āĻ
āύā§āϏāϰāĻŖā§āϰ āĻ
āύā§āϰā§āϧ āĻā§āϰāĻšāĻŖ āĻāϰāĻžāϰ āĻāύā§āϝ āϤāĻžāϰāĻž āĻāĻŋāĻā§ āϏāĻŽāϝāĻŧ āύāĻŋāϤ⧠āĻĒāĻžāϰā§āĨ¤"
|
||||
step6_1: "āϏāĻŦāĻāĻŋāĻā§ āĻ āĻŋāĻ āĻĨāĻžāĻāϞ⧠āĻāĻĒāύāĻŋ āĻāĻžāĻāĻŽāϞāĻžāĻāύ⧠āĻ
āύā§āϝ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻāĻžāϰā§āĻĻā§āϰ āύā§āĻ āĻĻā§āĻāϤ⧠āĻĒāĻžāĻŦā§āύāĨ¤"
|
||||
step6_2: "āĻāĻĒāύāĻŋ āϏāĻšāĻā§āĻ āĻāĻĒāύāĻžāϰ āĻĒā§āϰāϤāĻŋāĻā§āϰāĻŋāϝāĻŧāĻž āĻāĻžāύāĻžāϤ⧠āĻ
āύā§āϝ āĻŦā§āϝāĻā§āϤāĻŋāϰ āύā§āĻā§ \"āϰāĻŋāĻ
ā§āϝāĻžāĻāĻļāύ\" āϝā§āĻ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύāĨ¤"
|
||||
step6_3: "āĻāĻāĻāĻŋ āϰāĻŋāĻ
ā§āϝāĻžāĻāĻļāύ āϝā§āĻ āĻāϰāϤā§, āύā§āĻā§ \"+\" āĻāĻŋāĻšā§āύ⧠āĻā§āϞāĻŋāĻ āĻāϰā§āύ āĻāĻŦāĻ āĻāĻĒāύāĻžāϰ āĻĒāĻāύā§āĻĻā§āϰ āϰāĻŋāĻ
ā§āϝāĻžāĻāĻļāύ āύāĻŋāϰā§āĻŦāĻžāĻāύ āĻāϰā§āύāĨ¤"
|
||||
step7_1: "āĻ
āĻāĻŋāύāύā§āĻĻāύ! āĻāĻĒāύāĻŋ āĻāĻāύ Misskey-āϰ āĻĒā§āϰāĻžāĻĨāĻŽāĻŋāĻ āĻāĻŋāĻāĻā§āϰāĻŋāϝāĻŧāĻžāϞāĻāĻŋ āĻļā§āώ āĻāϰā§āĻā§āύāĨ¤"
|
||||
step7_2: "āĻāĻĒāύāĻŋ āϝāĻĻāĻŋ Misskey āϏāĻŽā§āĻĒāϰā§āĻā§ āĻāϰāĻ āĻāĻžāύāϤ⧠āĻāĻžāύ, āϤāĻžāĻšāϞ⧠{help} āĻ āĻĻā§āĻā§āύāĨ¤"
|
||||
step7_3: "āĻāĻāύ Misskey āĻāĻĒāĻā§āĻ āĻāϰā§āύ đ"
|
||||
_2fa:
|
||||
alreadyRegistered: "āĻāĻĒāύāĻŋ āĻāϤāĻŋāĻŽāϧā§āϝ⧠āĻāĻāĻāĻŋ 2-āĻĢā§āϝāĻžāĻā§āĻāϰ āĻ
āĻĨā§āύāĻāĻŋāĻā§āĻļāύ āĻĄāĻŋāĻāĻžāĻāϏ āύāĻŋāĻŦāύā§āϧāύ āĻāϰā§āĻā§āύ⧎"
|
||||
step1: "āĻĒā§āϰāĻĨāĻŽā§, āĻāĻĒāύāĻžāϰ āĻĄāĻŋāĻāĻžāĻāϏ⧠{a} āĻŦāĻž {b} āĻāϰ āĻŽāϤ⧠āĻāĻāĻāĻŋ āĻ
āĻĨā§āύāĻāĻŋāĻā§āĻļāύ āĻ
ā§āϝāĻžāĻĒ āĻāύāϏā§āĻāϞ āĻāϰā§āύ⧎"
|
||||
step2: "āĻāϰāĻĒāϰā§, āĻ
ā§āϝāĻžāĻĒā§āϰ āϏāĻžāĻšāĻžāϝā§āϝ⧠āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ QR āĻā§āĻĄāĻāĻŋ āϏā§āĻā§āϝāĻžāύ āĻāϰā§āύāĨ¤"
|
||||
step2Url: "āĻĄā§āϏā§āĻāĻāĻĒ āĻ
ā§āϝāĻžāĻĒā§, āύāĻŋāĻŽā§āύāϞāĻŋāĻāĻŋāϤ URL āϞāĻŋāĻā§āύ:"
|
||||
step3: "āĻ
ā§āϝāĻžāĻĒā§ āĻĒā§āϰāĻĻāϰā§āĻļāĻŋāϤ āĻā§āĻā§āύāĻāĻŋ āϞāĻŋāĻā§āύ āĻāĻŦāĻ āĻāĻĒāύāĻžāϰ āĻāĻžāĻ āĻļā§āώāĨ¤"
|
||||
step4: "āĻāĻĒāύāĻžāĻā§ āĻāĻāύ āĻĨā§āĻā§ āϞāĻ āĻāύ āĻāϰāĻžāϰ āϏāĻŽāϝāĻŧ, āĻāĻāĻāĻžāĻŦā§ āĻā§āĻā§āύ āϞāĻŋāĻāϤ⧠āĻšāĻŦā§āĨ¤"
|
||||
securityKeyInfo: "āĻāĻĒāύāĻŋ āĻāĻāĻāĻŋ āĻšāĻžāϰā§āĻĄāĻāϝāĻŧā§āϝāĻžāϰ āϏāĻŋāĻāĻŋāĻāϰāĻŋāĻāĻŋ āĻā§ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āϞāĻ āĻāύ āĻāϰāϤ⧠āĻĒāĻžāϰā§āύ āϝāĻž FIDO2 āĻŦāĻž āĻĄāĻŋāĻāĻžāĻāϏā§āϰ āĻĢāĻŋāĻā§āĻāĻžāϰāĻĒā§āϰāĻŋāύā§āĻ āϏā§āύā§āϏāϰ āĻŦāĻž āĻĒāĻŋāύ āϏāĻŽāϰā§āĻĨāύ āĻāϰā§ā§ˇ"
|
||||
renewTOTPCancel: "āύāĻž, āϧāύā§āϝāĻŦāĻžāĻĻ"
|
||||
_permissions:
|
||||
"read:account": "āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻā§āϰ āϤāĻĨā§āϝ āĻĻā§āĻā§āύ"
|
||||
"write:account": "āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻā§āϰ āϤāĻĨā§āϝ āϏāĻŽā§āĻĒāĻžāĻĻāύ āĻāϰā§āύ"
|
||||
@@ -1092,7 +1103,6 @@ _permissions:
|
||||
"write:gallery": "āĻā§āϝāĻžāϞāĻžāϰ⧠āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰā§āύ"
|
||||
"read:gallery-likes": "āĻā§āϝāĻžāϞāĻžāϰā§āϰ āĻĒāĻāύā§āĻĻāĻā§āϞāĻŋ āĻĻā§āĻā§āύ"
|
||||
"write:gallery-likes": "āĻā§āϝāĻžāϞāĻžāϰā§āϰ āĻĒāĻāύā§āĻĻāĻā§āϞāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰā§āύ"
|
||||
"write:chat": "āĻā§āϝāĻžāĻāĻā§āϞāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰā§āύ"
|
||||
_auth:
|
||||
shareAccess: "\"{name}\" āĻā§ āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻā§āϰ āĻ
ā§āϝāĻžāĻā§āϏā§āϏ āĻĻāĻŋāĻŦā§āύ?"
|
||||
shareAccessAsk: "āĻ
ā§āϝāĻžāĻĒā§āϞāĻŋāĻā§āĻļāύāĻāĻŋāĻā§ āĻ
ā§āϝāĻžāĻāĻžāĻāύā§āĻā§āϰ āĻ
ā§āϝāĻžāĻā§āϏā§āϏ āĻĻāĻŋāĻŦā§āύ?"
|
||||
@@ -1177,9 +1187,6 @@ _postForm:
|
||||
replyPlaceholder: "āύā§āĻāĻāĻŋāϰ āĻāĻŦāĻžāĻŦ āĻĻāĻŋāύ..."
|
||||
quotePlaceholder: "āύā§āĻāĻāĻŋāĻā§ āĻāĻĻā§āϧā§āϤ āĻāϰā§āύ..."
|
||||
channelPlaceholder: "āĻā§āϝāĻžāύā§āϞ⧠āĻĒā§āϏā§āĻ āĻāϰā§āύ..."
|
||||
_howToUse:
|
||||
visibility_title: "āĻĻā§āĻļā§āϝāĻŽāĻžāύāϤāĻž"
|
||||
menu_title: "āĻŽā§āύā§"
|
||||
_placeholders:
|
||||
a: "āĻāĻĒāύāĻŋ āĻāĻāύ āĻāĻŋ āĻāϰāĻā§āύ?"
|
||||
b: "āĻāĻĒāύāĻžāϰ āĻāĻļā§ āĻĒāĻžāĻļā§ āĻāĻŋ āĻšāĻā§āĻā§?"
|
||||
@@ -1201,7 +1208,6 @@ _profile:
|
||||
changeBanner: "āĻŦā§āϝāĻžāύāĻžāϰ āĻĒāϰāĻŋāĻŦāϰā§āϤāύ āĻāϰā§āύ"
|
||||
_exportOrImport:
|
||||
allNotes: "āϏāĻāϞ āύā§āĻ"
|
||||
clips: "āĻā§āϞāĻŋāĻĒ"
|
||||
followingList: "āĻ
āύā§āϏāϰāĻŖ āĻāϰāĻž āĻšāĻā§āĻā§"
|
||||
muteList: "āĻŽāĻŋāĻāĻ"
|
||||
blockingList: "āĻŦā§āϞāĻ"
|
||||
@@ -1249,6 +1255,9 @@ _pages:
|
||||
newPage: "āύāϤā§āύ āĻĒā§āώā§āĻ āĻž āĻŦāĻžāύāĻžāύ"
|
||||
editPage: "āĻĒā§āώā§āĻ āĻžāĻāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰā§āύ"
|
||||
readPage: "āĻā§āϏ āĻĻā§āĻāĻā§āύ"
|
||||
created: "āĻĒā§āώā§āĻ āĻž āϤā§āϰāĻŋ āĻāϰāĻž āĻšā§ā§āĻā§"
|
||||
updated: "āĻĒā§āώā§āĻ āĻž āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻāϰāĻž āĻšā§ā§āĻā§"
|
||||
deleted: "āĻĒā§āώā§āĻ āĻž āĻŽā§āĻā§ āĻĢā§āϞāĻž āĻšā§ā§āĻā§"
|
||||
pageSetting: "āĻĒā§āώā§āĻ āĻžāϰ āϏā§āĻāĻŋāĻāϏ"
|
||||
nameAlreadyExists: "āĻĒā§āώā§āĻ āĻžāϰ URLāĻāĻŋ āĻāϤāĻŋāĻŽāϧā§āϝā§āĻ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ āĻāϰāĻž āĻšā§ā§āĻā§"
|
||||
invalidNameTitle: "āĻĒā§āώā§āĻ āĻžāϰ URL āĻ
āĻŦā§āϧ"
|
||||
@@ -1317,7 +1326,6 @@ _notification:
|
||||
pollEnded: "āĻĒā§āϞ āĻļā§āώ"
|
||||
receiveFollowRequest: "āĻĒā§āϰāĻžāĻĒā§āϤ āĻ
āύā§āϏāϰāĻŖā§āϰ āĻ
āύā§āϰā§āϧāϏāĻŽā§āĻš"
|
||||
followRequestAccepted: "āĻā§āĻšā§āϤ āĻ
āύā§āϏāϰāĻŖā§āϰ āĻ
āύā§āϰā§āϧāϏāĻŽā§āĻš"
|
||||
login: "āĻĒā§āϰāĻŦā§āĻļ āĻāϰā§āύ"
|
||||
app: "āϞāĻŋāĻā§āĻ āĻāϰāĻž āĻ
ā§āϝāĻžāĻĒ āĻĨā§āĻā§ āĻŦāĻŋāĻā§āĻāĻĒā§āϤāĻŋ"
|
||||
_actions:
|
||||
followBack: "āĻĢāϞ⧠āĻŦā§āϝāĻžāĻ āĻāϰā§āĻā§"
|
||||
@@ -1348,34 +1356,4 @@ _deck:
|
||||
_webhookSettings:
|
||||
name: "āύāĻžāĻŽ"
|
||||
active: "āĻāĻžāϞā§"
|
||||
_abuseReport:
|
||||
_notificationRecipient:
|
||||
_recipientType:
|
||||
mail: "āĻāĻŽā§āĻāϞ"
|
||||
_moderationLogTypes:
|
||||
suspend: "āϏā§āĻĨāĻāĻŋāϤ āĻāϰāĻž"
|
||||
resetPassword: "āĻĒāĻžāϏāĻāϝāĻŧāĻžāϰā§āĻĄ āϰāĻŋāϏā§āĻ āĻāϰā§āύ"
|
||||
_reversi:
|
||||
total: "āĻŽā§āĻ"
|
||||
_remoteLookupErrors:
|
||||
_noSuchObject:
|
||||
title: "āĻĒāĻžāĻā§āĻž āϝāĻžā§āύāĻŋ"
|
||||
_search:
|
||||
searchScopeAll: "āϏāĻŦāĻā§āϞā§"
|
||||
searchScopeLocal: "āϏā§āĻĨāĻžāύā§āϝāĻŧ"
|
||||
_watermarkEditor:
|
||||
opacity: "āĻ
āϏā§āĻŦāĻā§āĻāϤāĻž"
|
||||
scale: "āĻāĻāĻžāϰ"
|
||||
text: "āϞā§āĻāĻž"
|
||||
image: "āĻāĻŦāĻŋ"
|
||||
advanced: "āĻāύā§āύāϤ"
|
||||
_imageEffector:
|
||||
_fxProps:
|
||||
scale: "āĻāĻāĻžāϰ"
|
||||
size: "āĻāĻāĻžāϰ"
|
||||
color: "āϰāĻ"
|
||||
opacity: "āĻ
āϏā§āĻŦāĻā§āĻāϤāĻž"
|
||||
lightness: "āĻāĻā§āĻā§āĻŦāϞ āĻāϰā§āύ"
|
||||
_qr:
|
||||
showTabTitle: "āĻĒā§āϰāĻĻāϰā§āĻļāύ"
|
||||
raw: "āϞā§āĻāĻž"
|
||||
|
||||
|
||||