Compare commits

..

2 Commits

Author SHA1 Message Date
rinsuki
a5a74f4434 12.119.2 2022-12-04 00:31:01 +09:00
mei23
993110d114 Fix: forkbomb 2 2022-12-04 00:29:42 +09:00
3576 changed files with 137423 additions and 353080 deletions

View File

@@ -1,224 +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:
# 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
# Proxy remote files (default: true)
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

View File

@@ -1,11 +1,4 @@
# misskey settings
# MISSKEY_URL=https://example.tld/
# db settings # db settings
POSTGRES_PASSWORD=example-misskey-pass POSTGRES_PASSWORD=example-misskey-pass
# DATABASE_PASSWORD=${POSTGRES_PASSWORD}
POSTGRES_USER=example-misskey-user POSTGRES_USER=example-misskey-user
# DATABASE_USER=${POSTGRES_USER}
POSTGRES_DB=misskey POSTGRES_DB=misskey
# DATABASE_DB=${POSTGRES_DB}
DATABASE_URL="postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}"

View File

@@ -1,221 +0,0 @@
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Misskey configuration
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# ┌─────┐
#───┘ 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
# 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: 3000
# ┌──────────────────────────┐
#───┘ PostgreSQL configuration └────────────────────────────────
db:
host: 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
# 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 └─────────────────────────────
# 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
# ┌───────────────┐
#───┘ 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:
# 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
# Proxy remote files (default: true)
proxyRemoteFiles: true
# Sign to ActivityPub GET request (default: true)
signToActivityPubGet: true
# 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)).
#allowedPrivateNetworks: [
# '127.0.0.1/32'
#]
# Upload or download file size limits (bytes)
#maxFileSize: 262144000

View File

@@ -2,77 +2,6 @@
# Misskey configuration # 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 └───────────────────────────────────────────────────── #───┘ URL └─────────────────────────────────────────────────────
@@ -101,10 +30,6 @@ url: https://example.tld/
# The port that your Misskey server should listen on. # The port that your Misskey server should listen on.
port: 3000 port: 3000
# You can also use UNIX domain socket.
# socket: /path/to/misskey.sock
# chmodSocket: '777'
# ┌──────────────────────────┐ # ┌──────────────────────────┐
#───┘ PostgreSQL configuration └──────────────────────────────── #───┘ PostgreSQL configuration └────────────────────────────────
@@ -126,23 +51,6 @@ db:
#extra: #extra:
# ssl: true # 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 configuration └─────────────────────────────────────
@@ -153,62 +61,16 @@ redis:
#pass: example-pass #pass: example-pass
#prefix: example-prefix #prefix: example-prefix
#db: 1 #db: 1
# You can specify more ioredis options...
#username: example-username
#redisForPubsub: # ┌─────────────────────────────┐
#───┘ Elasticsearch configuration └─────────────────────────────
#elasticsearch:
# host: localhost # host: localhost
# port: 6379 # port: 9200
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 # ssl: false
# #pass: example-pass # user:
# #prefix: example-prefix # pass:
# #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
# ┌───────────────────────────┐
#───┘ MeiliSearch configuration └─────────────────────────────
# 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
# ┌───────────────┐ # ┌───────────────┐
#───┘ ID generation └─────────────────────────────────────────── #───┘ ID generation └───────────────────────────────────────────
@@ -219,7 +81,6 @@ redis:
# Available methods: # Available methods:
# aid ... Short, Millisecond accuracy # aid ... Short, Millisecond accuracy
# aidx ... Millisecond accuracy
# meid ... Similar to ObjectID, Millisecond accuracy # meid ... Similar to ObjectID, Millisecond accuracy
# ulid ... Millisecond accuracy # ulid ... Millisecond accuracy
# objectid ... This is left for backward compatibility # objectid ... This is left for backward compatibility
@@ -227,22 +88,7 @@ redis:
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE # ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
# ID SETTINGS AFTER THAT! # ID SETTINGS AFTER THAT!
id: 'aidx' id: 'aid'
# ┌────────────────┐
#───┘ 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:
# options:
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
# ┌─────────────────────┐ # ┌─────────────────────┐
#───┘ Other configuration └───────────────────────────────────── #───┘ Other configuration └─────────────────────────────────────
@@ -254,36 +100,32 @@ id: 'aidx'
#clusterLimit: 1 #clusterLimit: 1
# Job concurrency per worker # Job concurrency per worker
#deliverJobConcurrency: 128 # deliverJobConcurrency: 128
#inboxJobConcurrency: 16 # inboxJobConcurrency: 16
#relationshipJobConcurrency: 16
# What's relationshipJob?:
# Follow, unfollow, block and unblock(ings) while following-imports, etc. or account migrations.
# Job rate limiter # Job rate limiter
#deliverJobPerSec: 128 # deliverJobPerSec: 128
#inboxJobPerSec: 32 # inboxJobPerSec: 16
#relationshipJobPerSec: 64
# Job attempts # Job attempts
#deliverJobMaxAttempts: 12 # deliverJobMaxAttempts: 12
#inboxJobMaxAttempts: 8 # inboxJobMaxAttempts: 8
# Local address used for outgoing requests
#outgoingAddress: 127.0.0.1
# IP address family used for outgoing request (ipv4, ipv6 or dual) # IP address family used for outgoing request (ipv4, ipv6 or dual)
#outgoingAddressFamily: ipv4 #outgoingAddressFamily: ipv4
# Syslog option
#syslog:
# host: localhost
# port: 514
# Proxy for HTTP/HTTPS # Proxy for HTTP/HTTPS
#proxy: http://127.0.0.1:3128 #proxy: http://127.0.0.1:3128
proxyBypassHosts: #proxyBypassHosts: [
- api.deepl.com # 'example.com',
- api-free.deepl.com # '192.0.2.8'
- www.recaptcha.net #]
- hcaptcha.com
- challenges.cloudflare.com
# Proxy for SMTP/SMTPS # Proxy for SMTP/SMTPS
#proxySmtp: http://127.0.0.1:3128 # use HTTP/1.1 CONNECT #proxySmtp: http://127.0.0.1:3128 # use HTTP/1.1 CONNECT
@@ -291,33 +133,17 @@ proxyBypassHosts:
#proxySmtp: socks5://127.0.0.1:1080 # use SOCKS5 #proxySmtp: socks5://127.0.0.1:1080 # use SOCKS5
# Media Proxy # Media Proxy
# Reference Implementation: https://github.com/misskey-dev/media-proxy
# * Deliver a common cache between instances
# * Perform image compression (on a different server resource than the main process)
#mediaProxy: https://example.com/proxy #mediaProxy: https://example.com/proxy
# Proxy remote files (default: true) # Proxy remote files (default: false)
# Proxy remote files by this instance or mediaProxy to prevent remote files from running in remote domains. #proxyRemoteFiles: true
proxyRemoteFiles: true
# Movie Thumbnail Generation URL # Sign to ActivityPub GET request (default: false)
# There is no reference implementation. #signToActivityPubGet: true
# 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
# Sign to ActivityPub GET request (default: true)
signToActivityPubGet: true
# 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)).
#allowedPrivateNetworks: [ #allowedPrivateNetworks: [
# '127.0.0.1/32' # '127.0.0.1/32'
#] #]
# Upload or download file size limits (bytes) # Upload or download file size limits (bytes)
#maxFileSize: 262144000 #maxFileSize: 262144000
# PID File of master process
#pidFile: /tmp/misskey.pid

View File

@@ -1 +0,0 @@
FROM mcr.microsoft.com/devcontainers/javascript-node:0-18

View File

@@ -1,53 +0,0 @@
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- ../:/workspace:cached
- node_modules:/workspace/node_modules
command: sleep infinity
networks:
- internal_network
- external_network
redis:
restart: unless-stopped
image: redis:7-alpine
networks:
- internal_network
volumes:
- redis-data:/data
healthcheck:
test: "redis-cli ping"
interval: 5s
retries: 20
db:
restart: unless-stopped
image: postgres:15-alpine
networks:
- internal_network
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: misskey
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"
interval: 5s
retries: 20
volumes:
postgres-data:
redis-data:
node_modules:
networks:
internal_network:
internal: true
external_network:

View File

@@ -1,26 +0,0 @@
{
"name": "Misskey",
"dockerComposeFile": "compose.yml",
"service": "app",
"workspaceFolder": "/workspace",
"features": {
"ghcr.io/devcontainers/features/node:1": {
"version": "22.11.0"
},
"ghcr.io/devcontainers-contrib/features/corepack:1": {}
},
"forwardPorts": [3000],
"postCreateCommand": "/bin/bash .devcontainer/init.sh",
"customizations": {
"vscode": {
"extensions": [
"editorconfig.editorconfig",
"dbaeumer.vscode-eslint",
"Vue.volar",
"Orta.vscode-jest",
"dbaeumer.vscode-eslint",
"mrmlnc.vscode-json5"
]
}
}
}

View File

@@ -1,211 +0,0 @@
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# Misskey configuration
#━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
# ┌─────┐
#───┘ URL └─────────────────────────────────────────────────────
# Final accessible URL seen by a user.
url: http://127.0.0.1:3000/
# 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: 3000
# ┌──────────────────────────┐
#───┘ 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:
# 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
# Proxy remote files (default: true)
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

View File

@@ -1,17 +0,0 @@
#!/bin/bash
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
git submodule update --init
corepack install
corepack enable
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

View File

@@ -7,24 +7,9 @@ Dockerfile
build/ build/
built/ built/
db/ db/
.devcontainer/compose.yml docker-compose.yml
elasticsearch/
node_modules/ node_modules/
packages/*/node_modules
redis/ redis/
files/ files/
fluent-emojis/ misskey-assets/
.pnp.*
# .yarné–ĸ逪
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
.pnpm-store
.idea/
packages/*/.vscode/
packages/backend/test/compose.yml

View File

@@ -1,3 +0,0 @@
DKL-DI-0005
DKL-DI-0006
DKL-LI-0003

View File

@@ -5,11 +5,6 @@ indent_style = tab
indent_size = 2 indent_size = 2
charset = utf-8 charset = utf-8
insert_final_newline = true insert_final_newline = true
end_of_line = lf
trim_trailing_whitespace = true
[*.md] [*.yml]
trim_trailing_whitespace = false
[*.{yml,yaml}]
indent_style = space indent_style = space

1
.gitattributes vendored
View File

@@ -5,4 +5,3 @@
*.glb -diff -text *.glb -diff -text
*.blend -diff -text *.blend -diff -text
*.afdesign -diff -text *.afdesign -diff -text
* text=auto eol=lf

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
# These are supported funding model platforms
patreon: syuilo

42
.github/ISSUE_TEMPLATE/01_bug-report.md vendored Normal file
View File

@@ -0,0 +1,42 @@
---
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.
-->
## 💡 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:

View File

@@ -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: 2024.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: 2024.x.x
* Node: 20.x.x
* PostgreSQL: 15.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

View 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 -->

View File

@@ -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

View File

@@ -1,8 +1,7 @@
contact_links: contact_links:
- name: đŸ‘Ē Misskey Forum
url: https://forum.misskey.io/
about: Ask questions and share knowledge
- name: đŸ’Ŧ Misskey official Discord - name: đŸ’Ŧ Misskey official Discord
url: https://discord.gg/Wp8gVStHW3 url: https://discord.gg/Wp8gVStHW3
about: Chat freely about Misskey 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

17
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,17 @@
<!-- ℹ おčĒ­ãŋください / README
PRありがとうございぞすīŧ PRをäŊœæˆã™ã‚‹å‰ãĢã€ã‚ŗãƒŗãƒˆãƒĒビãƒĨãƒŧã‚ˇãƒ§ãƒŗã‚ŦイドをごįĸēčĒãã ã•ã„:
Thank you for your PR! Before creating a PR, please check the contribution guide:
https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md
-->
# What
<!-- こぎPRでäŊ•をしたぎかīŧŸ おう変わるぎかīŧŸ -->
<!-- What did you do with this PR? How will it change things? -->
# Why
<!-- ãĒぜそうするぎかīŧŸ ãŠã†ã„ã†æ„å›ŗãĒぎかīŧŸ äŊ•ãŒå›°ãŖãĻいるぎかīŧŸ -->
<!-- Why do you do it? What are your intentions? What is the problem? -->
# Additional info (optional)
<!-- テ゚トčĻŗį‚šãĒお -->
<!-- Test perspective, etc -->

View File

@@ -1,23 +0,0 @@
<!-- ℹ おčĒ­ãŋください / README
PRありがとうございぞすīŧ PRをäŊœæˆã™ã‚‹å‰ãĢã€ã‚ŗãƒŗãƒˆãƒĒビãƒĨãƒŧã‚ˇãƒ§ãƒŗã‚ŦイドをごįĸēčĒãã ã•ã„:
Thank you for your PR! Before creating a PR, please check the contribution guide:
https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md
-->
## What
<!-- こぎPRでäŊ•をしたぎかīŧŸ おう変わるぎかīŧŸ -->
<!-- What did you do with this PR? How will it change things? -->
## Why
<!-- ãĒぜそうするぎかīŧŸ ãŠã†ã„ã†æ„å›ŗãĒぎかīŧŸ äŊ•ãŒå›°ãŖãĻいるぎかīŧŸ -->
<!-- Why do you do it? What are your intentions? What is the problem? -->
## Additional info (optional)
<!-- テ゚トčĻŗį‚šãĒお -->
<!-- Test perspective, etc -->
## Checklist
- [ ] Read the [contribution guide](https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md)
- [ ] Test working in a local environment
- [ ] (If needed) Update CHANGELOG.md
- [ ] (If possible) Add tests

View File

@@ -1,23 +0,0 @@
<!-- ℹ おčĒ­ãŋください / README
PRありがとうございぞすīŧ PRをäŊœæˆã™ã‚‹å‰ãĢã€ã‚ŗãƒŗãƒˆãƒĒビãƒĨãƒŧã‚ˇãƒ§ãƒŗã‚ŦイドをごįĸēčĒãã ã•ã„:
Thank you for your PR! Before creating a PR, please check the contribution guide:
https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md
-->
## What
<!-- こぎPRでäŊ•をしたぎかīŧŸ おう変わるぎかīŧŸ -->
<!-- What did you do with this PR? How will it change things? -->
## Why
<!-- ãĒぜそうするぎかīŧŸ ãŠã†ã„ã†æ„å›ŗãĒぎかīŧŸ äŊ•ãŒå›°ãŖãĻいるぎかīŧŸ -->
<!-- Why do you do it? What are your intentions? What is the problem? -->
## Additional info (optional)
<!-- テ゚トčĻŗį‚šãĒお -->
<!-- Test perspective, etc -->
## Checklist
- [ ] Read the [contribution guide](https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md)
- [ ] Test working in a local environment
- [ ] (If needed) Update CHANGELOG.md
- [ ] (If possible) Add tests

View File

@@ -1,20 +0,0 @@
## Summary
This is a release PR.
For more information on the release instructions, please see:
https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md#release
## For reviewers
- CHANGELOGãĢ抜けæŧã‚Œã¯į„Ąã„か
- バãƒŧã‚¸ãƒ§ãƒŗãŽä¸Šã’æ–šã¯éŠåˆ‡ã‹
- äģ–ãĢこぎãƒĒãƒĒãƒŧ゚ãĢåĢめãĒければãĒらãĒã„å¤‰æ›´ã¯į„Ąã„ã‹
- 全äŊ“įš„ãĒ変更内厚をäŋ¯įž°ã—å•éĄŒã¯į„Ąã„ã‹
- ãƒŦビãƒĨãƒŧされãĻいãĒã„ã‚ŗãƒŸãƒƒãƒˆãŒã‚ã‚‹å ´åˆã¯ã€ãã‚ŒãŒå•éĄŒãĒいか
- 最įĩ‚įš„ãĒ動äŊœįĸēčĒã‚’čĄŒã„å•éĄŒã¯į„Ąã„ã‹
ãĒおをįĸēčĒã—ã€ãƒĒãƒĒãƒŧ゚するæē–å‚™ãŒæ•´ãŖãĻいると思われる場合は approve しãĻください。
## Checklist
- [ ] package.jsonぎバãƒŧã‚¸ãƒ§ãƒŗãŒæ­Ŗã—ãæ›´æ–°ã•ã‚ŒãĻいる
- [ ] CHANGELOGが過不čļŗį„Ąãæ›´æ–°ã•れãĻいる
- [ ] CIが全ãĻé€šãŖãĻいる

View File

@@ -5,44 +5,18 @@
version: 2 version: 2
updates: updates:
- package-ecosystem: github-actions
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 100
# Add only the root, not each workspace item
# https://github.com/dependabot/dependabot-core/issues/4993#issuecomment-1289133027
- package-ecosystem: npm - package-ecosystem: npm
directory: "/" directory: "/"
schedule: schedule:
interval: daily interval: daily
open-pull-requests-limit: 10 open-pull-requests-limit: 0
# List dependencies required to be updated together, sharing the same version numbers. - package-ecosystem: npm
# Those who simply have the common owner (e.g. @fastify) don't need to be listed. directory: "/packages/backend"
groups: schedule:
aws-sdk: interval: daily
patterns: open-pull-requests-limit: 0
- "@aws-sdk/*" - package-ecosystem: npm
bull-board: directory: "/packages/client"
patterns: schedule:
- "@bull-board/*" interval: daily
nestjs: open-pull-requests-limit: 0
patterns:
- "@nestjs/*"
slacc:
patterns:
- "slacc-*"
storybook:
patterns:
- "storybook*"
- "@storybook/*"
swc-core:
patterns:
- "@swc/core*"
typescript-eslint:
patterns:
- "@typescript-eslint/*"
tensorflow:
patterns:
- "@tensorflow/*"

40
.github/labeler.yml vendored
View File

@@ -1,34 +1,12 @@
'packages/backend': 'âš™ī¸Server':
- any: - packages/backend/**/*
- changed-files:
- any-glob-to-any-file: ['packages/backend/**/*']
'packages/backend:test': 'đŸ–Ĩī¸Client':
- any: - packages/client/**/*
- changed-files:
- any-glob-to-any-file: ['packages/backend/test/**/*', 'packages/backend/test-federation/**/*']
'packages/frontend': 'đŸ§ĒTest':
- any: - cypress/**/*
- changed-files: - packages/backend/test/**/*
- any-glob-to-any-file: ['packages/frontend/**/*']
'packages/frontend:test': 'â€ŧī¸ wrong locales':
- any: - any: ['locales/*.yml', '!locales/ja-JP.yml']
- 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/**/*']

View File

@@ -1,17 +1,15 @@
url: 'http://misskey.local' url: 'http://misskey.local'
setupPassword: example_password_please_change_this_or_you_will_get_hacked
# ロãƒŧã‚ĢãƒĢでテ゚トするときãĢポãƒŧトをčĸĢらãĒいようãĢするためデフりãƒĢトぎもぎとは変える(äģĨ下同じ) # ロãƒŧã‚ĢãƒĢでテ゚トするときãĢポãƒŧトをčĸĢらãĒいようãĢするためデフりãƒĢトぎもぎとは変える(äģĨ下同じ)
port: 61812 port: 61812
db: db:
host: 127.0.0.1 host: localhost
port: 54312 port: 54312
db: test-misskey db: test-misskey
user: postgres user: postgres
pass: '' pass: ''
redis: redis:
host: 127.0.0.1 host: localhost
port: 56312 port: 56312
id: aidx id: aid

View File

@@ -1,24 +0,0 @@
<!-- ℹ おčĒ­ãŋください / README
PRありがとうございぞすīŧ PRをäŊœæˆã™ã‚‹å‰ãĢã€ã‚ŗãƒŗãƒˆãƒĒビãƒĨãƒŧã‚ˇãƒ§ãƒŗã‚ŦイドをごįĸēčĒãã ã•ã„:
Thank you for your PR! Before creating a PR, please check the contribution guide:
https://github.com/misskey-dev/misskey/blob/develop/CONTRIBUTING.md
-->
## What
<!-- こぎPRでäŊ•をしたぎかīŧŸ おう変わるぎかīŧŸ -->
<!-- What did you do with this PR? How will it change things? -->
## Why
<!-- ãĒぜそうするぎかīŧŸ ãŠã†ã„ã†æ„å›ŗãĒぎかīŧŸ äŊ•ãŒå›°ãŖãĻいるぎかīŧŸ -->
<!-- Why do you do it? What are your intentions? What is the problem? -->
## Additional info (optional)
<!-- テ゚トčĻŗį‚šãĒお -->
<!-- Test perspective, etc -->
## 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

View File

@@ -1,43 +0,0 @@
name: API report (misskey.js)
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:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4.1.1
- run: corepack enable
- name: Setup Node.js
uses: actions/setup-node@v4.0.4
with:
node-version-file: '.node-version'
cache: 'pnpm'
- name: Install dependencies
run: pnpm i --frozen-lockfile
- name: Build
run: pnpm --filter misskey-js build
- name: Check files
run: ls packages/misskey-js/built
- name: API report
run: pnpm --filter misskey-js api-prod
- name: Show report
if: always()
run: cat packages/misskey-js/temp/misskey-js.api.md

View File

@@ -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@v4.1.1
- name: Setup Node.js
uses: actions/setup-node@v4.0.4
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

View File

@@ -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@v4.1.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@v4.0.4
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@v4
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@v4.1.1
with:
submodules: true
persist-credentials: false
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- name: Upload From Merged
uses: actions/upload-artifact@v4
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@v4
with:
name: generated-misskey-js
path: misskey-js-generated
- name: download actual-misskey-js
uses: actions/download-artifact@v4
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@v2
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@v2
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

View File

@@ -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@v4.1.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

View File

@@ -1,79 +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@v4.1.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/.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/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

View File

@@ -1,18 +0,0 @@
name: Check copyright year
on:
push:
branches:
- master
- develop
jobs:
check_copyright_year:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4.1.1
- run: |
if [ "$(grep Copyright COPYING | sed -e 's/.*2014-\([0-9]*\) .*/\1/g')" -ne "$(date +%Y)" ]; then
echo "Please change copyright year!"
exit 1
fi

View File

@@ -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@v4.1.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 }}

View File

@@ -6,83 +6,28 @@ on:
- develop - develop
workflow_dispatch: workflow_dispatch:
env:
REGISTRY_IMAGE: misskey/misskey
jobs: jobs:
# see https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners push_to_registry:
build: name: Push Docker image to Docker Hub
name: Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
if: github.repository == 'misskey-dev/misskey'
steps: steps:
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Check out the repo - name: Check out the repo
uses: actions/checkout@v4.1.1 uses: actions/checkout@v2
- name: Set up Docker Buildx - name: Docker meta
uses: docker/setup-buildx-action@v3 id: meta
uses: docker/metadata-action@v3
with:
images: misskey/misskey
- name: Log in to Docker Hub - name: Log in to Docker Hub
uses: docker/login-action@v3 uses: docker/login-action@v1
with: with:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push by digest - name: Build and Push to Docker Hub
id: build uses: docker/build-push-action@v2
uses: docker/build-push-action@v6
with: with:
context: . context: .
push: true push: true
platforms: ${{ matrix.platform }} tags: misskey/misskey:develop
provenance: false
labels: 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@v4
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@v4
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

View File

@@ -5,101 +5,28 @@ on:
types: [published] types: [published]
workflow_dispatch: 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: jobs:
# see https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners push_to_registry:
build: name: Push Docker image to Docker Hub
name: Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform:
- linux/amd64
- linux/arm64
steps: steps:
- name: Prepare
run: |
platform=${{ matrix.platform }}
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
- name: Check out the repo - name: Check out the repo
uses: actions/checkout@v4.1.1 uses: actions/checkout@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Docker meta - name: Docker meta
id: meta id: meta
uses: docker/metadata-action@v5 uses: docker/metadata-action@v3
with: with:
images: ${{ env.REGISTRY_IMAGE }} images: misskey/misskey
tags: ${{ env.TAGS }}
- name: Log in to Docker Hub - name: Log in to Docker Hub
uses: docker/login-action@v3 uses: docker/login-action@v1
with: with:
username: ${{ secrets.DOCKER_USERNAME }} username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push to Docker Hub - name: Build and Push to Docker Hub
id: build uses: docker/build-push-action@v2
uses: docker/build-push-action@v6
with: with:
context: . context: .
push: true push: true
platforms: ${{ matrix.platform }} tags: ${{ steps.meta.outputs.tags }}
provenance: false
labels: ${{ steps.meta.outputs.labels }} 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@v4
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@v4
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 }}

View File

@@ -1,32 +0,0 @@
---
name: Dockle
on:
push:
branches:
- master
- develop
pull_request:
jobs:
dockle:
runs-on: ubuntu-latest
env:
DOCKER_CONTENT_TRUST: 1
DOCKLE_VERSION: 0.4.14
steps:
- uses: actions/checkout@v4.1.1
- name: Download and install dockle v${{ env.DOCKLE_VERSION }}
run: |
curl -L -o dockle.deb "https://github.com/goodwithtech/dockle/releases/download/v${DOCKLE_VERSION}/dockle_${DOCKLE_VERSION}_Linux-64bit.deb"
sudo dpkg -i dockle.deb
- run: |
cp .config/docker_example.env .config/docker.env
cp ./compose_example.yml ./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}"

View File

@@ -1,69 +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:
node-version: [22.11.0]
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@v4.1.1
with:
ref: ${{ matrix.ref }}
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.4
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
- 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@v4
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@v4
with:
name: api-artifact-pr-number
path: pr_number

View File

@@ -11,6 +11,6 @@ jobs:
pull-requests: write pull-requests: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/labeler@v5 - uses: actions/labeler@v4
with: with:
repo-token: "${{ secrets.GITHUB_TOKEN }}" repo-token: "${{ secrets.GITHUB_TOKEN }}"

View File

@@ -5,107 +5,35 @@ on:
branches: branches:
- master - master
- develop - develop
paths:
- packages/backend/**
- packages/frontend/**
- packages/frontend-shared/**
- packages/frontend-embed/**
- packages/sw/**
- packages/misskey-js/**
- packages/misskey-bubble-game/**
- packages/misskey-reversi/**
- packages/shared/eslint.config.js
- .github/workflows/lint.yml
pull_request: pull_request:
paths:
- packages/backend/**
- packages/frontend/**
- packages/frontend-shared/**
- packages/frontend-embed/**
- packages/sw/**
- packages/misskey-js/**
- packages/misskey-bubble-game/**
- packages/misskey-reversi/**
- packages/shared/eslint.config.js
- .github/workflows/lint.yml
jobs: jobs:
pnpm_install: backend:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4.1.1 - uses: actions/checkout@v2
with: with:
fetch-depth: 0
submodules: true submodules: true
- uses: pnpm/action-setup@v4 - uses: actions/setup-node@v3
- uses: actions/setup-node@v4.0.4
with: with:
node-version-file: '.node-version' node-version: 18.x
cache: 'pnpm' cache: 'yarn'
- run: corepack enable cache-dependency-path: |
- run: pnpm i --frozen-lockfile packages/backend/yarn.lock
- run: yarn install
- run: yarn --cwd ./packages/backend lint
lint: client:
needs: [pnpm_install]
runs-on: ubuntu-latest runs-on: ubuntu-latest
continue-on-error: true
strategy:
matrix:
workspace:
- backend
- frontend
- frontend-shared
- frontend-embed
- 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: steps:
- uses: actions/checkout@v4.1.1 - uses: actions/checkout@v2
with: with:
fetch-depth: 0
submodules: true submodules: true
- uses: pnpm/action-setup@v4 - uses: actions/setup-node@v3
- uses: actions/setup-node@v4.0.4
with: with:
node-version-file: '.node-version' node-version: 18.x
cache: 'pnpm' cache: 'yarn'
- run: corepack enable cache-dependency-path: |
- run: pnpm i --frozen-lockfile packages/client/yarn.lock
- name: Restore eslint cache - run: yarn install
uses: actions/cache@v4.1.0 - run: yarn --cwd ./packages/client lint
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
typecheck:
needs: [pnpm_install]
runs-on: ubuntu-latest
continue-on-error: true
strategy:
matrix:
workspace:
- backend
- sw
- misskey-js
steps:
- uses: actions/checkout@v4.1.1
with:
fetch-depth: 0
submodules: true
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4.0.4
with:
node-version-file: '.node-version'
cache: 'pnpm'
- run: corepack enable
- run: pnpm i --frozen-lockfile
- run: pnpm --filter misskey-js run build
if: ${{ matrix.workspace == 'backend' || matrix.workspace == 'sw' }}
- run: pnpm --filter misskey-reversi run build
if: ${{ matrix.workspace == 'backend' }}
- run: pnpm --filter ${{ matrix.workspace }} run typecheck

View File

@@ -1,28 +0,0 @@
name: Lint
on:
push:
paths:
- locales/**
- .github/workflows/locale.yml
pull_request:
paths:
- locales/**
- .github/workflows/locale.yml
jobs:
locale_verify:
runs-on: ubuntu-latest
continue-on-error: true
steps:
- uses: actions/checkout@v4.1.1
with:
fetch-depth: 0
submodules: true
- uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4.0.4
with:
node-version-file: '.node-version'
cache: 'pnpm'
- run: corepack enable
- run: pnpm i --frozen-lockfile
- run: cd locales && node verify.js

View File

@@ -17,13 +17,13 @@ jobs:
# See app.yml for an example app manifest # See app.yml for an example app manifest
- name: Generate token - name: Generate token
id: generate_token id: generate_token
uses: tibdex/github-app-token@v2 uses: tibdex/github-app-token@v1
with: with:
app_id: ${{ secrets.DEPLOYBOT_APP_ID }} app_id: ${{ secrets.DEPLOYBOT_APP_ID }}
private_key: ${{ secrets.DEPLOYBOT_PRIVATE_KEY }} private_key: ${{ secrets.DEPLOYBOT_PRIVATE_KEY }}
- name: Slash Command Dispatch - name: Slash Command Dispatch
uses: peter-evans/slash-command-dispatch@v4 uses: peter-evans/slash-command-dispatch@v1
env: env:
TOKEN: ${{ steps.generate_token.outputs.token }} TOKEN: ${{ steps.generate_token.outputs.token }}
with: with:

View File

@@ -1,42 +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
strategy:
matrix:
node-version: [22.11.0]
steps:
- uses: actions/checkout@v4.1.1
with:
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.4
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
registry-url: 'https://registry.npmjs.org'
- name: Publish package
run: |
corepack enable
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 }}

View File

@@ -1,5 +1,7 @@
# Run secret-dependent integration tests only after /deploy approval # Run secret-dependent integration tests only after /deploy approval
on: on:
pull_request:
types: [opened, reopened, synchronize]
repository_dispatch: repository_dispatch:
types: [deploy-command] types: [deploy-command]
@@ -10,10 +12,11 @@ jobs:
deploy-preview-environment: deploy-preview-environment:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: if:
github.event_name == 'repository_dispatch' &&
github.event.client_payload.slash_command.sha != '' && github.event.client_payload.slash_command.sha != '' &&
contains(github.event.client_payload.pull_request.head.sha, github.event.client_payload.slash_command.sha) contains(github.event.client_payload.pull_request.head.sha, github.event.client_payload.slash_command.sha)
steps: steps:
- uses: actions/github-script@v7.0.1 - uses: actions/github-script@v5
id: check-id id: check-id
env: env:
number: ${{ github.event.client_payload.pull_request.number }} number: ${{ github.event.client_payload.pull_request.number }}
@@ -37,7 +40,7 @@ jobs:
return check[0].id; return check[0].id;
- uses: actions/github-script@v7.0.1 - uses: actions/github-script@v5
env: env:
check_id: ${{ steps.check-id.outputs.result }} check_id: ${{ steps.check-id.outputs.result }}
details_url: ${{ github.server_url }}/${{ github.repository }}/runs/${{ github.run_id }} details_url: ${{ github.server_url }}/${{ github.repository }}/runs/${{ github.run_id }}
@@ -53,7 +56,7 @@ jobs:
# Check out merge commit # Check out merge commit
- name: Fork based /deploy checkout - name: Fork based /deploy checkout
uses: actions/checkout@v4.1.1 uses: actions/checkout@v2
with: with:
ref: 'refs/pull/${{ github.event.client_payload.pull_request.number }}/merge' ref: 'refs/pull/${{ github.event.client_payload.pull_request.number }}/merge'
@@ -72,7 +75,7 @@ jobs:
timeout: 15m timeout: 15m
# Update check run called "integration-fork" # Update check run called "integration-fork"
- uses: actions/github-script@v7.0.1 - uses: actions/github-script@v5
id: update-check-run id: update-check-run
if: ${{ always() }} if: ${{ always() }}
env: env:

View File

@@ -10,45 +10,12 @@ jobs:
destroy-preview-environment: destroy-preview-environment:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/github-script@v7.0.1
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 - name: Context
if: steps.check-conclusion.outputs.result == 'success'
uses: okteto/context@latest uses: okteto/context@latest
with: with:
token: ${{ secrets.OKTETO_TOKEN }} token: ${{ secrets.OKTETO_TOKEN }}
- name: Destroy preview environment - name: Destroy preview environment
if: steps.check-conclusion.outputs.result == 'success'
uses: okteto/destroy-preview@latest uses: okteto/destroy-preview@latest
with: with:
name: pr-${{ github.event.number }}-syuilo name: pr-${{ github.event.number }}-syuilo

View File

@@ -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@v4
# 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 }}

View File

@@ -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@v4
# 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 }}

View File

@@ -1,47 +0,0 @@
name: "Release Manager: release RC when ready for review"
on:
pull_request:
types: [ready_for_review]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
permissions:
contents: write
issues: write
pull-requests: write
jobs:
check:
runs-on: ubuntu-latest
outputs:
head: ${{ steps.get_pr.outputs.head }}
base: ${{ steps.get_pr.outputs.base }}
steps:
- uses: actions/checkout@v4
# PRæƒ…å ąã‚’å–åž—
- name: Get PR
run: |
pr_json=$(gh pr view "$PR_NUMBER" --json isDraft,headRefName,baseRefName)
echo "head=$(echo $pr_json | jq -r '.headRefName')" >> $GITHUB_OUTPUT
echo "base=$(echo $pr_json | jq -r '.baseRefName')" >> $GITHUB_OUTPUT
id: get_pr
env:
PR_NUMBER: ${{ github.event.pull_request.number }}
release:
uses: misskey-dev/release-manager-actions/.github/workflows/create-prerelease.yml@v2
needs: check
if: needs.check.outputs.head == github.event.repository.default_branch && needs.check.outputs.base == vars.STABLE_BRANCH
with:
pr_number: ${{ github.event.pull_request.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
reset_number_on_channel_change: true
secrets:
RELEASE_APP_ID: ${{ secrets.RELEASE_APP_ID }}
RELEASE_APP_PRIVATE_KEY: ${{ secrets.RELEASE_APP_PRIVATE_KEY }}

View File

@@ -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@v7.0.1
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@v4
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@v2
with:
pr_number: ${{ steps.load-pr-num.outputs.pr-number }}
comment_tag: show_diff
filePath: ./output.md
- name: Tell error to PR
uses: thollander/actions-comment-pull-request@v2
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 }})をįĸēčĒã—ãĻください。

View File

@@ -1,118 +0,0 @@
name: Storybook
on:
push:
branches:
- master
- develop
- dev/storybook8 # for testing
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@v4.1.1
if: github.event_name != 'pull_request_target'
with:
fetch-depth: 0
submodules: true
- uses: actions/checkout@v4.1.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'
id: rev
run: |
echo "base=$(git rev-list --parents -n1 HEAD | cut -d" " -f2)" >> $GITHUB_OUTPUT
git checkout $(git rev-list --parents -n1 HEAD | cut -d" " -f3)
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Use Node.js 20.x
uses: actions/setup-node@v4.0.4
with:
node-version-file: '.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
- name: Build misskey-js
run: pnpm --filter misskey-js 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: |
DIFF="${{ steps.rev.outputs.base }} 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
BRANCH="${{ github.event.pull_request.head.user.login }}:$HEAD_REF"
if [ "$BRANCH" = "misskey-dev:$HEAD_REF" ]; then
BRANCH="$HEAD_REF"
fi
pnpm --filter frontend chromatic --exit-once-uploaded -d storybook-static --branch-name "$BRANCH" $(echo "$CHROMATIC_PARAMETER")
env:
HEAD_REF: ${{ github.event.pull_request.head.ref }}
CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
- name: Notify that Chromatic detects changes
uses: actions/github-script@v7.0.1
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@v4
with:
name: storybook
path: packages/frontend/storybook-static

View File

@@ -1,114 +0,0 @@
name: Test (backend)
on:
push:
branches:
- master
- develop
paths:
- packages/backend/**
# for permissions
- packages/misskey-js/**
- .github/workflows/test-backend.yml
pull_request:
paths:
- packages/backend/**
# for permissions
- packages/misskey-js/**
- .github/workflows/test-backend.yml
jobs:
unit:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.11.0]
services:
postgres:
image: postgres:15
ports:
- 54312:5432
env:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:7
ports:
- 56312:6379
steps:
- uses: actions/checkout@v4.1.1
with:
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install FFmpeg
uses: FedericoCarboni/setup-ffmpeg@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.4
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
- name: Copy Configure
run: cp .github/misskey/test.yml .config
- name: Build
run: pnpm build
- name: Test
run: pnpm --filter backend test-and-coverage
- name: Upload to Codecov
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/coverage/coverage-final.json
e2e:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.11.0]
services:
postgres:
image: postgres:15
ports:
- 54312:5432
env:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:7
ports:
- 56312:6379
steps:
- uses: actions/checkout@v4.1.1
with:
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.4
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
- 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

View File

@@ -1,59 +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
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.11.0]
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Install FFmpeg
uses: FedericoCarboni/setup-ffmpeg@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.3
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Build Misskey
run: |
corepack enable && corepack prepare
pnpm i --frozen-lockfile
pnpm build
- name: Setup
run: |
cd packages/backend/test-federation
bash ./setup.sh
sudo chmod 644 ./certificates/*.test.key
- name: Start servers
# https://github.com/docker/compose/issues/1294#issuecomment-374847206
run: |
cd packages/backend/test-federation
docker compose up -d --scale tester=0
- name: Test
run: |
cd packages/backend/test-federation
docker compose run --no-deps tester
- name: Stop servers
run: |
cd packages/backend/test-federation
docker compose down

View File

@@ -1,128 +0,0 @@
name: Test (frontend)
on:
push:
branches:
- master
- develop
paths:
- packages/frontend/**
# for permissions
- packages/misskey-js/**
# for e2e
- packages/backend/**
- .github/workflows/test-frontend.yml
pull_request:
paths:
- packages/frontend/**
# for permissions
- packages/misskey-js/**
# for e2e
- packages/backend/**
- .github/workflows/test-frontend.yml
jobs:
vitest:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.11.0]
steps:
- uses: actions/checkout@v4.1.1
with:
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.4
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
- name: Copy Configure
run: cp .github/misskey/test.yml .config
- name: Build
run: pnpm build
- name: Test
run: pnpm --filter frontend test-and-coverage
- name: Upload Coverage
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/frontend/coverage/coverage-final.json
e2e:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [22.11.0]
browser: [chrome]
services:
postgres:
image: postgres:15
ports:
- 54312:5432
env:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:7
ports:
- 56312:6379
steps:
- uses: actions/checkout@v4.1.1
with:
submodules: true
# https://github.com/cypress-io/cypress-docker-images/issues/150
#- name: Install mplayer for FireFox
# run: sudo apt install mplayer -y
# if: ${{ matrix.browser == 'firefox' }}
#- uses: browser-actions/setup-firefox@latest
# if: ${{ matrix.browser == 'firefox' }}
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.4
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
- name: Build
run: pnpm build
# https://github.com/cypress-io/cypress/issues/4351#issuecomment-559489091
- name: ALSA Env
run: echo -e 'pcm.!default {\n type hw\n card 0\n}\n\nctl.!default {\n type hw\n card 0\n}' > ~/.asoundrc
# XXX: This tries reinstalling Cypress if the binary is not cached
# Remove this when the cache issue is fixed
- name: Cypress install
run: pnpm exec cypress install
- name: Cypress run
uses: cypress-io/github-action@v6
timeout-minutes: 15
with:
install: false
start: pnpm start:test
wait-on: 'http://localhost:61812'
headed: true
browser: ${{ matrix.browser }}
- uses: actions/upload-artifact@v4
if: failure()
with:
name: ${{ matrix.browser }}-cypress-screenshots
path: cypress/screenshots
- uses: actions/upload-artifact@v4
if: always()
with:
name: ${{ matrix.browser }}-cypress-videos
path: cypress/videos

View File

@@ -1,57 +0,0 @@
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
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:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.11.0]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- name: Checkout
uses: actions/checkout@v4.1.1
- run: corepack enable
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.4
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Install dependencies
run: pnpm i --frozen-lockfile
- name: Check pnpm-lock.yaml
run: git diff --exit-code pnpm-lock.yaml
- name: Build
run: pnpm --filter misskey-js build
- name: Test
run: pnpm --filter misskey-js test
env:
CI: true
- name: Upload Coverage
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/misskey-js/coverage/coverage-final.json

View File

@@ -1,39 +0,0 @@
name: Test (production install and build)
on:
push:
branches:
- master
- develop
pull_request:
env:
NODE_ENV: production
jobs:
production:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [22.11.0]
steps:
- uses: actions/checkout@v4.1.1
with:
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.4
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
- name: Copy Configure
run: cp .github/misskey/test.yml .config/default.yml
- name: Build
run: pnpm build

122
.github/workflows/test.yml vendored Normal file
View File

@@ -0,0 +1,122 @@
name: Test
on:
push:
branches:
- master
- develop
pull_request:
jobs:
mocha:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
services:
postgres:
image: postgres:13
ports:
- 54312:5432
env:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:6
ports:
- 56312:6379
steps:
- uses: actions/checkout@v2
with:
submodules: true
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
cache-dependency-path: |
packages/backend/yarn.lock
packages/client/yarn.lock
- name: Install dependencies
run: yarn install
- name: Check yarn.lock
run: git diff --exit-code yarn.lock
- name: Copy Configure
run: cp .github/misskey/test.yml .config
- name: Build
run: yarn build
- name: Test
run: yarn mocha
e2e:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node-version: [18.x]
browser: [chrome]
services:
postgres:
image: postgres:13
ports:
- 54312:5432
env:
POSTGRES_DB: test-misskey
POSTGRES_HOST_AUTH_METHOD: trust
redis:
image: redis:6
ports:
- 56312:6379
steps:
- uses: actions/checkout@v2
with:
submodules: true
# https://github.com/cypress-io/cypress-docker-images/issues/150
#- name: Install mplayer for FireFox
# run: sudo apt install mplayer -y
# if: ${{ matrix.browser == 'firefox' }}
#- uses: browser-actions/setup-firefox@latest
# if: ${{ matrix.browser == 'firefox' }}
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'yarn'
cache-dependency-path: |
packages/backend/yarn.lock
packages/client/yarn.lock
- name: Install dependencies
run: yarn install
- name: Check yarn.lock
run: git diff --exit-code yarn.lock
- name: Copy Configure
run: cp .github/misskey/test.yml .config
- name: Build
run: yarn build
# https://github.com/cypress-io/cypress/issues/4351#issuecomment-559489091
- name: ALSA Env
run: echo -e 'pcm.!default {\n type hw\n card 0\n}\n\nctl.!default {\n type hw\n card 0\n}' > ~/.asoundrc
- name: Cypress run
uses: cypress-io/github-action@v4
with:
install: false
start: npm run start:test
wait-on: 'http://localhost:61812'
headless: false
browser: ${{ matrix.browser }}
- uses: actions/upload-artifact@v2
if: failure()
with:
name: ${{ matrix.browser }}-cypress-screenshots
path: cypress/screenshots
- uses: actions/upload-artifact@v2
if: always()
with:
name: ${{ matrix.browser }}-cypress-videos
path: cypress/videos

View File

@@ -1,45 +0,0 @@
name: Test (backend)
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
strategy:
matrix:
node-version: [22.11.0]
steps:
- uses: actions/checkout@v4.1.1
with:
submodules: true
- name: Install pnpm
uses: pnpm/action-setup@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4.0.4
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'
- name: Install Redocly CLI
run: npm i -g @redocly/cli
- run: corepack enable
- 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

37
.gitignore vendored
View File

@@ -9,20 +9,6 @@
node_modules node_modules
report.*.json report.*.json
# Yarn
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
packages/frontend/.yarn/cache
packages/backend/.yarn/cache
packages/sw/.yarn/cache
# pnpm
.pnpm-store
# Cypress # Cypress
cypress/screenshots cypress/screenshots
cypress/videos cypress/videos
@@ -33,23 +19,15 @@ coverage
# config # config
/.config/* /.config/*
!/.config/example.yml !/.config/example.yml
!/.config/docker_example.yml
!/.config/docker_example.env !/.config/docker_example.env
!/.config/cypress-devcontainer.yml
docker-compose.yml
./compose.yml
.devcontainer/compose.yml
!/.devcontainer/compose.yml
# misskey # misskey
/build /build
built built
built-test
js-built
/data /data
/.cache-loader /.cache-loader
/db /db
/meili_data /elasticsearch
npm-debug.log npm-debug.log
*.pem *.pem
run.bat run.bat
@@ -60,16 +38,6 @@ api-docs.json
.DS_Store .DS_Store
/files /files
ormconfig.json 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 # blender backups
*.blend1 *.blend1
@@ -77,6 +45,3 @@ vite.config.local-dev.ts.timestamp-*
*.blend3 *.blend3
*.blend4 *.blend4
*.blend5 *.blend5
# VSCode addon
.favorites.json

6
.gitmodules vendored
View File

@@ -1,3 +1,3 @@
[submodule "fluent-emojis"] [submodule "misskey-assets"]
path = fluent-emojis path = misskey-assets
url = https://github.com/misskey-dev/emojis.git url = https://github.com/misskey-dev/assets.git

View File

@@ -1 +1 @@
22.11.0 v16.15.0

3
.npmrc
View File

@@ -1 +1,2 @@
engine-strict = true save-exact = true
package-lock = false

View File

@@ -1,9 +1,9 @@
{ {
"recommendations": [ "recommendations": [
"editorconfig.editorconfig", "editorconfig.editorconfig",
"eg2.vscode-npm-script",
"dbaeumer.vscode-eslint", "dbaeumer.vscode-eslint",
"Vue.volar", "Vue.volar",
"Orta.vscode-jest", "Vue.vscode-typescript-vue-plugin"
"mrmlnc.vscode-json5"
] ]
} }

15
.vscode/settings.json vendored
View File

@@ -1,15 +0,0 @@
{
"search.exclude": {
"**/node_modules": true
},
"typescript.tsdk": "node_modules/typescript/lib",
"files.associations": {
"*.test.ts": "typescript"
},
"jest.jestCommandLine": "pnpm run jest",
"jest.runMode": "on-demand",
"editor.codeActionsOnSave": {
"source.fixAll": "explicit"
},
"editor.formatOnSave": false
}

1
.yarnrc Normal file
View File

@@ -0,0 +1 @@
network-timeout 600000

File diff suppressed because it is too large Load Diff

View File

@@ -2,131 +2,45 @@
## Our Pledge ## Our Pledge
We as members, contributors, and leaders pledge to make participation in our 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.
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.
## Our Standards ## Our Standards
Examples of behavior that contributes to a positive environment for our Examples of behavior that contributes to creating a positive environment include:
community include:
* Demonstrating empathy and kindness toward other people * Using welcoming and inclusive language
* Being respectful of differing opinions, viewpoints, and experiences * Being respectful of differing viewpoints and experiences
* Giving and gracefully accepting constructive feedback * Gracefully accepting constructive criticism
* Accepting responsibility and apologizing to those affected by our mistakes, * Focusing on what is best for the community
and learning from the experience * Showing empathy towards other community members
* Focusing on what is best not just for us as individuals, but for the overall
community
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 * The use of sexualized language or imagery and unwelcome sexual attention or advances
any kind * Trolling, insulting/derogatory comments, and personal or political attacks
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment * Public or private harassment
* Publishing others' private information, such as a physical or email address, * Publishing others' private information, such as a physical or electronic address, without explicit permission
without their explicit permission * Other conduct which could reasonably be considered inappropriate in a professional setting
* 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 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.
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject 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.
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.
## Scope ## Scope
This Code of Conduct applies within all community spaces, and also applies when 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.
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.
## Enforcement ## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be 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.
reported to the community leaders responsible for enforcement at
<syuilotan@yahoo.co.jp>.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the 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.
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.
## Attribution ## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by [homepage]: http://contributor-covenant.org
[Mozilla's code of conduct enforcement ladder][Mozilla CoC]. [version]: http://contributor-covenant.org/version/1/4/
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

View File

@@ -1,7 +1,7 @@
# Contribution guide # 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. 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.** > 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.\ > 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. > 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. - To avoid duplication, please search for similar issues before creating a new issue.
- Do not use Issues to ask questions or troubleshooting. - Do not use Issues to ask questions or troubleshooting.
- Issues should only be used to feature requests, suggestions, and bug tracking. - 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/) 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. > 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 ## Before implementation
We welcome your proposal.
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. 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. 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. 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). 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.
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.
## Well-known branches ## Well-known branches
- **`master`** branch is tracking the latest release and used for production purposes. - **`master`** branch is tracking the latest release and used for production purposes.
@@ -59,34 +44,14 @@ Thank you for your PR! Before creating a PR, please check the following:
- Check if there are any documents that need to be created or updated due to this change. - 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. - 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. - 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 `npm run test` and `npm run lint`. [See more info](#testing)
- If this PR includes UI changes, please attach a screenshot in the text. - If this PR includes UI changes, please attach a screenshot in the text.
Thanks for your cooperation 🤗 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 ## Reviewers guide
Be willing to comment on the good points and not just the things you want fixed đŸ’¯ 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 ### Review perspective
- Scope - Scope
- Are the goals of the PR clear? - Are the goals of the PR clear?
@@ -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? - Are there any omissions or gaps?
- Does it check for anomalies? - 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 ## Deploy
The `/deploy` command by issue comment can be used to deploy the contents of a PR to the preview environment. The `/deploy` command by issue comment can be used to deploy the contents of a PR to the preview environment.
``` ```
@@ -128,140 +77,58 @@ An actual domain will be assigned so you can test the federation.
## Release ## Release
### Release Instructions ### 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. 2. Create a release PR.
- Into `master` from `develop` branch. - Into `master` from `develop` branch.
- The title must be in the format `Release: x.y.z`. - The title must be in the format `Release: x.y.z`.
- `x.y.z` is the new version you are trying to release. - `x.y.z` is the new version you are trying to release.
3. Deploy and perform a simple QA check. Also verify that the tests passed. 3. Deploy and perform a simple QA check. Also verify that the tests passed.
4. Merge it. (Do not squash commit) 4. Merge it.
5. Create a [release of GitHub](https://github.com/misskey-dev/misskey/releases) 5. Create a [release of GitHub](https://github.com/misskey-dev/misskey/releases)
- The target branch must be `master` - The target branch must be `master`
- The tag name must be the version - The tag name must be the version
> [!NOTE]
> Why this instruction is necessary:
> - To perform final QA checks
> - To distribute responsibility
> - To check direct commits to develop
> - To celebrate the release together 🎉
## Localization (l10n) ## Localization (l10n)
Misskey uses [Crowdin](https://crowdin.com/project/misskey) for localization management. Misskey uses [Crowdin](https://crowdin.com/project/misskey) for localization management.
You can improve our translations with your Crowdin account. 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. 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. 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. If your language is not listed in Crowdin, please open an issue.
For newly added languages, once the translation progress per language exceeds 70%, it will be officially introduced into Misskey and made available to users.
![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg) ![Crowdin](https://d322cqt584bo4o.cloudfront.net/misskey/localized.svg)
## Development ## Development
### Setup During development, it is useful to use the `npm run dev` command.
Before developing, you have to set up environment. Misskey requires Redis, PostgreSQL, and FFmpeg. This command monitors the server-side and client-side source files and automatically builds them if they are modified.
In addition, it will also automatically start the Misskey server process.
You would want to install Meilisearch to experiment related features. Technically, meilisearch is not strict requirement, but some features and tests require it.
There are a few ways to proceed.
#### 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.
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.
**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.
``` bash
git submodule update --init
pnpm install --frozen-lockfile
cp .devcontainer/devcontainer.yml .config/default.yml
pnpm build
pnpm migrate
```
After finishing the migration, you can proceed.
### Start developing
During development, it is useful to use the
```
pnpm dev
```
command.
- 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.
- The front end can be viewed by accessing `http://localhost:5173`.
- The backend listens on the port configured with `port` in .config/default.yml.
If you have not changed it from the default, it will be "http://localhost:3000".
If "port" in .config/default.yml is set to something other than 3000, you need to change the proxy settings in packages/frontend/vite.config.local-dev.ts.
### `MK_DEV_PREFER=backend pnpm dev`
pnpm dev has another mode with `MK_DEV_PREFER=backend`.
```
MK_DEV_PREFER=backend pnpm dev
```
- This mode is closer to the production environment than the default mode.
- Vite runs behind the backend (the backend will proxy Vite at /vite).
- You can see Misskey by accessing `http://localhost:3000` (Replace `3000` with the port configured with `port` in .config/default.yml).
- To change the port of Vite, specify with `VITE_PORT` environment variable.
- HMR may not work in some environments such as Windows.
## Testing ## Testing
You can run non-backend tests by executing following commands: - Test codes are located in [`/test`](/test).
```sh
pnpm --filter frontend test ### Run test
pnpm --filter misskey-js test Create a config file.
```
cp test/test.yml .config/
```
Prepare DB/Redis for testing.
```
docker-compose -f test/docker-compose.yml up
```
Alternatively, prepare an empty (data can be erased) DB and edit `.config/test.yml`.
Run all test.
```
npm run test
``` ```
Backend tests require manual preparation of servers. See the next section for more on this. #### Run specify test
```
### Backend npx cross-env TS_NODE_FILES=true TS_NODE_TRANSPILE_ONLY=true TS_NODE_PROJECT="./test/tsconfig.json" npx mocha test/foo.ts --require ts-node/register
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: ### e2e tests
```sh TODO
docker compose -f packages/backend/test/compose.yml up
```
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
```
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
```
#### Running Multiple-server E2E Tests
See [`/packages/backend/test-federation/README.md`](/packages/backend/test-federation/README.md).
## 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.
## Continuous integration ## Continuous integration
Misskey uses GitHub Actions for executing automated tests. Misskey uses GitHub Actions for executing automated tests.
@@ -280,7 +147,7 @@ niraxは、MisskeyでäŊŋį”¨ã—ãĻいるã‚ĒãƒĒジナãƒĢãŽãƒ•ãƒ­ãƒŗãƒˆã‚¨ãƒŗãƒ‰
### ãƒĢãƒŧãƒˆåŽšįžŠ ### ãƒĢãƒŧãƒˆåŽšįžŠ
ãƒĢãƒŧãƒˆåŽšįžŠã¯ã€äģĨ下ぎåŊĸåŧãŽã‚Ēブジェクトぎ配列です。 ãƒĢãƒŧãƒˆåŽšįžŠã¯ã€äģĨ下ぎåŊĸåŧãŽã‚Ēブジェクトぎ配列です。
```ts ``` ts
{ {
name?: string; name?: string;
path: string; path: string;
@@ -293,7 +160,7 @@ niraxは、MisskeyでäŊŋį”¨ã—ãĻいるã‚ĒãƒĒジナãƒĢãŽãƒ•ãƒ­ãƒŗãƒˆã‚¨ãƒŗãƒ‰
} }
``` ```
> [!WARNING] > **Warning**
> įžįŠļ、ãƒĢãƒŧãƒˆã¯åŽšįžŠã•ã‚ŒãŸé †ãĢčŠ•äžĄã•ã‚Œãžã™ã€‚ > įžįŠļ、ãƒĢãƒŧãƒˆã¯åŽšįžŠã•ã‚ŒãŸé †ãĢčŠ•äžĄã•ã‚Œãžã™ã€‚
> たとえば、`/foo/:id`ãƒĢãƒŧãƒˆåŽšįžŠãŽæŦĄãĢ`/foo/bar`ãƒĢãƒŧãƒˆåŽšįžŠãŒã•ã‚ŒãĻã„ãŸå ´åˆã€åžŒč€…ãŒãƒžãƒƒãƒã™ã‚‹ã“ã¨ã¯ã‚ã‚Šãžã›ã‚“ã€‚ > たとえば、`/foo/:id`ãƒĢãƒŧãƒˆåŽšįžŠãŽæŦĄãĢ`/foo/bar`ãƒĢãƒŧãƒˆåŽšįžŠãŒã•ã‚ŒãĻã„ãŸå ´åˆã€åžŒč€…ãŒãƒžãƒƒãƒã™ã‚‹ã“ã¨ã¯ã‚ã‚Šãžã›ã‚“ã€‚
@@ -301,199 +168,10 @@ niraxは、MisskeyでäŊŋį”¨ã—ãĻいるã‚ĒãƒĒジナãƒĢãŽãƒ•ãƒ­ãƒŗãƒˆã‚¨ãƒŗãƒ‰
vue-routerとぎ最大ぎ違いは、niraxã¯č¤‡æ•°ãŽãƒĢãƒŧã‚ŋãƒŧãŒå­˜åœ¨ã™ã‚‹ã“ã¨ã‚’č¨ąå¯ã—ãĻã„ã‚‹į‚šã§ã™ã€‚ 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 ## Notes
### How to resolve conflictions occurred at yarn.lock?
### MisskeyãŽãƒ‰ãƒĄã‚¤ãƒŗå›ē有ぎæĻ‚åŋĩは`Mi`をprefixする Just execute `yarn` to fix it.
䞋えばGoogleがč‡Ēį¤žã‚ĩãƒŧビ゚をMap、Earth、DriveではãĒくGoogle Map、Google Earth、Google DriveぎようãĢå‘Ŋ名するぎと同じ
ã‚ŗãƒŧド上でMisskeyãŽãƒ‰ãƒĄã‚¤ãƒŗå›ē有ぎæĻ‚åŋĩãĢは`Mi`をprefixすることで、äģ–ãŽãƒ‰ãƒĄã‚¤ãƒŗãŽåŒæ§˜ãŽæĻ‚åŋĩとåŒēåˆĨできるãģã‹ã€åå‰ãŽčĄįĒã‚’é˜˛ãã€‚
ãŸã ã—ã€æ–‡č„ˆä¸ŠMisskeyãŽã‚‚ãŽã‚’æŒ‡ã™ã“ã¨ãŒæ˜Žã‚‰ã‹ã§ã‚ã‚Šã€åå‰ãŽčĄįĒãŽæã‚ŒãŒãĒã„å ´åˆã¯ã€ä¸€æ™‚įš„ãĒロãƒŧã‚ĢãƒĢ変数ãĢé™ãŖãĻ`Mi`ã‚’įœį•ĨしãĻもよい。
### How to resolve conflictions occurred at pnpm-lock.yaml?
Just execute `pnpm` to fix it.
### INSERTするときãĢはsaveではãĒくinsertをäŊŋį”¨ã™ã‚‹ ### INSERTするときãĢはsaveではãĒくinsertをäŊŋį”¨ã™ã‚‹
#6441 #6441
@@ -572,41 +250,19 @@ SQLã§ã¯é…åˆ—ãŽã‚¤ãƒŗãƒ‡ãƒƒã‚¯ã‚šã¯**1始ぞり**。
### null IN ### null IN
nullがåĢぞれる可čƒŊ性ぎあるã‚ĢナムãĢINするときは、そぎぞぞだとおかしくãĒるぎでORãĒおでnullãŽãƒãƒŗãƒ‰ãƒĒãƒŗã‚°ã‚’ã—ã‚ˆã†ã€‚ nullがåĢぞれる可čƒŊ性ぎあるã‚ĢナムãĢINするときは、そぎぞぞだとおかしくãĒるぎでORãĒおでnullãŽãƒãƒŗãƒ‰ãƒĒãƒŗã‚°ã‚’ã—ã‚ˆã†ã€‚
### enumぎ削除は気をつける ### `undefined`ãĢã”į”¨åŋƒ
enumぎ列挙ぎ内厚ぎ削除は、そぎ値をもつãƒŦã‚ŗãƒŧドを全ãĻ削除しãĒいといけãĒい MongoDBぎ時とは違い、findOneでãƒŦã‚ŗãƒŧドを取垗する時ãĢå¯žčąĄãƒŦã‚ŗãƒŧドが存在しãĒい場合 **`undefined`** がčŋ”ãŖãĻãã‚‹ãŽã§æŗ¨æ„ã€‚
MongoDBは`null`でčŋ”しãĻきãĻたぎで、そぎ感čĻšã§`if (x === null)`とか書くとバグる。äģŖã‚ã‚ŠãĢ`if (x == null)`と書いãĻください
å‰Šé™¤ãŒé‡ãŸã‹ãŖãŸã‚Šä¸å¯čƒŊã ãŖãŸã‚Šã™ã‚‹å ´åˆã¯ã€å‰Šé™¤ã—ãĒいでおく
### MigrationäŊœæˆæ–šæŗ• ### MigrationäŊœæˆæ–šæŗ•
packages/backendで: packages/backendで:
```sh ```sh
pnpm dlx typeorm migration:generate -d ormconfig.js -o <migration name> npx typeorm migration:generate -d ormconfig.js -o <migration name>
``` ```
- į”ŸæˆåžŒã€ãƒ•ã‚Ąã‚¤ãƒĢをmigration下ãĢį§ģしãĻください - į”ŸæˆåžŒã€ãƒ•ã‚Ąã‚¤ãƒĢを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ãĢついãĻã€į‰‡æ–šã‚’åŋ…é ˆã¨ã—ã¤ã¤ä¸Ąæ–šãŽæŒ‡åŽšã‚‚ã‚ã‚Šã†ã‚‹å ´åˆ:
```ts
export const paramDef = {
type: 'object',
properties: {
hoge: { type: 'string', minLength: 1 },
fuga: { type: 'string', minLength: 1 },
},
anyOf: [
{ required: ['hoge'] },
{ required: ['fuga'] },
],
} as const;
```
### ã‚ŗãƒã‚¯ã‚ˇãƒ§ãƒŗãĢは`markRaw`せよ ### ã‚ŗãƒã‚¯ã‚ˇãƒ§ãƒŗãĢは`markRaw`せよ
**VueãŽã‚ŗãƒŗãƒãƒŧãƒãƒŗãƒˆãŽdataã‚Ēãƒ—ã‚ˇãƒ§ãƒŗã¨ã—ãĻ**misskey.jsãŽã‚ŗãƒã‚¯ã‚ˇãƒ§ãƒŗã‚’č¨­åŽšã™ã‚‹ã¨ãã€åŋ…ず`markRaw`でナップしãĻãã ã•ã„ã€‚ã‚¤ãƒŗã‚šã‚ŋãƒŗã‚šãŒä¸åŋ…čρãĢãƒĒã‚ĸã‚¯ãƒ†ã‚Ŗãƒ–åŒ–ã•ã‚Œã‚‹ã“ã¨ã§ã€misskey.js内ぎå‡Ļį†ã§ä¸å…ˇåˆãŒį™ēį”Ÿã™ã‚‹ã¨ã¨ã‚‚ãĢ、パフりãƒŧãƒžãƒŗã‚šä¸ŠãŽå•éĄŒãĢã‚‚įš‹ãŒã‚‹ã€‚ãĒお、Composition APIをäŊŋう場合はこぎ限りではãĒい(ãƒĒã‚ĸã‚¯ãƒ†ã‚Ŗãƒ–åŒ–ã¯ãƒžãƒ‹ãƒĨã‚ĸãƒĢãĒため)。 **VueãŽã‚ŗãƒŗãƒãƒŧãƒãƒŗãƒˆãŽdataã‚Ēãƒ—ã‚ˇãƒ§ãƒŗã¨ã—ãĻ**misskey.jsãŽã‚ŗãƒã‚¯ã‚ˇãƒ§ãƒŗã‚’č¨­åŽšã™ã‚‹ã¨ãã€åŋ…ず`markRaw`でナップしãĻãã ã•ã„ã€‚ã‚¤ãƒŗã‚šã‚ŋãƒŗã‚šãŒä¸åŋ…čρãĢãƒĒã‚ĸã‚¯ãƒ†ã‚Ŗãƒ–åŒ–ã•ã‚Œã‚‹ã“ã¨ã§ã€misskey.js内ぎå‡Ļį†ã§ä¸å…ˇåˆãŒį™ēį”Ÿã™ã‚‹ã¨ã¨ã‚‚ãĢ、パフりãƒŧãƒžãƒŗã‚šä¸ŠãŽå•éĄŒãĢã‚‚įš‹ãŒã‚‹ã€‚ãĒお、Composition APIをäŊŋう場合はこぎ限りではãĒい(ãƒĒã‚ĸã‚¯ãƒ†ã‚Ŗãƒ–åŒ–ã¯ãƒžãƒ‹ãƒĨã‚ĸãƒĢãĒため)。
@@ -620,27 +276,3 @@ marginã¯ããŽã‚ŗãƒŗãƒãƒŧãƒãƒŗãƒˆã‚’äŊŋã†å´ãŒč¨­åŽšã™ã‚‹
## そぎäģ– ## そぎäģ–
### HTMLぎクナ゚名で follow という単čĒžã¯äŊŋわãĒい ### 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);
```

View File

@@ -1,5 +1,5 @@
Unless otherwise stated this repository is Unless otherwise stated this repository is
Copyright Š 2014-2024 syuilo and contributors Copyright Š 2014-2022 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. And is distributed under The GNU Affero General Public License Version 3, you should have received a copy of the license file as LICENSE.

View File

@@ -1,108 +1,32 @@
# syntax = docker/dockerfile:1.4 FROM node:16.15.1-bullseye AS builder
ARG NODE_VERSION=22.11.0-bullseye
# build assets & compile TypeScript
FROM --platform=$BUILDPLATFORM node:${NODE_VERSION} AS native-builder
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
--mount=type=cache,target=/var/lib/apt,sharing=locked \
rm -f /etc/apt/apt.conf.d/docker-clean \
; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache \
&& 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 ["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/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 ARG NODE_ENV=production
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \ WORKDIR /misskey
pnpm i --frozen-lockfile --aggregate-output
COPY --link . ./ COPY . ./
RUN apt-get update
RUN apt-get install -y build-essential
RUN git submodule update --init RUN git submodule update --init
RUN pnpm build RUN yarn install
RUN rm -rf .git/ RUN yarn build
RUN rm -rf .git
# build native dependencies for target platform FROM node:16.15.1-bullseye-slim AS runner
FROM --platform=$TARGETPLATFORM node:${NODE_VERSION} AS target-builder
RUN apt-get update \
&& apt-get install -yqq --no-install-recommends \
build-essential
RUN corepack enable
WORKDIR /misskey WORKDIR /misskey
COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"] RUN apt-get update
COPY --link ["scripts", "./scripts"] RUN apt-get install -y ffmpeg tini
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 COPY --from=builder /misskey/node_modules ./node_modules
COPY --from=builder /misskey/built ./built
COPY --from=builder /misskey/packages/backend/node_modules ./packages/backend/node_modules
COPY --from=builder /misskey/packages/backend/built ./packages/backend/built
COPY --from=builder /misskey/packages/client/node_modules ./packages/client/node_modules
COPY . ./
RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
pnpm i --frozen-lockfile --aggregate-output
FROM --platform=$TARGETPLATFORM node:${NODE_VERSION}-slim AS runner
ARG UID="991"
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 \
&& 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 {} \; \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists
USER misskey
WORKDIR /misskey
# add package.json to add pnpm
COPY --chown=misskey:misskey ./package.json ./package.json
RUN corepack install
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/fluent-emojis /misskey/fluent-emojis
COPY --chown=misskey:misskey . ./
ENV LD_PRELOAD=/usr/local/lib/libjemalloc.so
ENV NODE_ENV=production ENV NODE_ENV=production
HEALTHCHECK --interval=5s --retries=20 CMD ["/bin/bash", "/misskey/healthcheck.sh"]
ENTRYPOINT ["/usr/bin/tini", "--"] ENTRYPOINT ["/usr/bin/tini", "--"]
CMD ["pnpm", "run", "migrateandstart"] CMD ["npm", "run", "migrateandstart"]

View File

@@ -1,18 +1,16 @@
<div align="center"> <div align="center">
<a href="https://misskey-hub.net"> <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> </a>
**🌎 **Misskey** is an open source, federated social media platform that's free forever! 🚀** **🌎 **[Misskey](https://misskey-hub.net/)** is an open source, decentralized social media platform that's free forever! 🚀**
[Learn more](https://misskey-hub.net/)
--- ---
<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> <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> <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"> <a href="./CONTRIBUTING.md">
@@ -24,26 +22,36 @@
<a href="https://www.patreon.com/syuilo"> <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> <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>
---
</div> </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> ## Sponsors
<div align="center">
Thanks to [Crowdin](https://crowdin.com/) for providing the localization platform that helps us translate Misskey into many languages. <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>
<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.

View File

@@ -5,25 +5,25 @@ Also, the later tasks are more indefinite and are subject to change as developme
## (1) Improve maintainability \<current phase\> ## (1) Improve maintainability \<current phase\>
This is the phase we are at now. We need to make a high-maintenance environment that can withstand future development. 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 (backend)
- Make the number of type errors zero (frontend) - Probably need to switch some libraries to others that make it difficult to reduce type errors
- e.g. koa to fastify https://github.com/misskey-dev/misskey/issues/7537
- Improve CI - Improve CI
- ~~Fix tests~~ → Done âœ”ī¸ - Fix tests
- mocha, jest, etc. do not support the combination of `TypeScript + ESM + Path alias`, and the tests currently do not work.
- Fix random test failures - https://github.com/misskey-dev/misskey/issues/7985 and https://github.com/misskey-dev/misskey/issues/7986 - Fix random test failures - https://github.com/misskey-dev/misskey/issues/7985 and https://github.com/misskey-dev/misskey/issues/7986
- Add more tests - Add more tests
- ~~May need to implement a mechanism that allows for DI~~ → Done âœ”ī¸ - May need to implement a mechanism that allows for DI
- https://github.com/misskey-dev/misskey/pull/9085 - https://github.com/misskey-dev/misskey/pull/9085
- ~~Measure coverage~~ → Done âœ”ī¸ - Measure coverage
- https://github.com/misskey-dev/misskey/pull/9081 - https://github.com/misskey-dev/misskey/pull/9081
- Improve documentation - Improve documentation
- Refactoring
- Extract the logic of each endpoint definition into a service and just call it
## (2) Improve functionality ## (2) Improve functionality
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. 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 - 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? - GraphQL support?
## (3) Improve scalability ## (3) Improve scalability

View File

@@ -1,15 +1,9 @@
# Reporting Security Issues # 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 This will allow us to assess the risk, and make a fix available before we add a
bug report to the GitHub repository. bug report to the GitHub repository.
Thanks for helping make Misskey safe for everyone. Thanks for helping make Misskey safe for everyone.
## 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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -1,4 +1,3 @@
apiVersion: v2 apiVersion: v2
name: misskey name: misskey
version: 0.0.0 version: 0.0.0
description: This chart is created for the purpose of previewing Pull Requests. Do not use this for production use.

View File

@@ -72,75 +72,25 @@ db:
#extra: #extra:
# ssl: true # 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 configuration └─────────────────────────────────────
redis: redis:
host: localhost host: localhost
port: 6379 port: 6379
#family: 0 # 0=Both, 4=IPv4, 6=IPv6
#pass: example-pass #pass: example-pass
#prefix: example-prefix #prefix: example-prefix
#db: 1 #db: 1
#redisForPubsub: # ┌─────────────────────────────┐
#───┘ Elasticsearch configuration └─────────────────────────────
#elasticsearch:
# host: localhost # host: localhost
# port: 6379 # port: 9200
# #family: 0 # 0=Both, 4=IPv4, 6=IPv6 # ssl: false
# #pass: example-pass # user:
# #prefix: example-prefix # pass:
# #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: ''
# ┌───────────────┐ # ┌───────────────┐
#───┘ ID generation └─────────────────────────────────────────── #───┘ ID generation └───────────────────────────────────────────
@@ -151,7 +101,6 @@ redis:
# Available methods: # Available methods:
# aid ... Short, Millisecond accuracy # aid ... Short, Millisecond accuracy
# aidx ... Millisecond accuracy
# meid ... Similar to ObjectID, Millisecond accuracy # meid ... Similar to ObjectID, Millisecond accuracy
# ulid ... Millisecond accuracy # ulid ... Millisecond accuracy
# objectid ... This is left for backward compatibility # objectid ... This is left for backward compatibility
@@ -159,23 +108,7 @@ redis:
# ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE # ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
# ID SETTINGS AFTER THAT! # ID SETTINGS AFTER THAT!
id: "aidx" id: "aid"
# ┌────────────────┐
#───┘ 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:
# options:
# dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0'
# ┌─────────────────────┐ # ┌─────────────────────┐
#───┘ Other configuration └───────────────────────────────────── #───┘ Other configuration └─────────────────────────────────────
@@ -191,7 +124,7 @@ id: "aidx"
# Job rate limiter # Job rate limiter
# deliverJobPerSec: 128 # deliverJobPerSec: 128
# inboxJobPerSec: 32 # inboxJobPerSec: 16
# Job attempts # Job attempts
# deliverJobMaxAttempts: 12 # deliverJobMaxAttempts: 12
@@ -200,6 +133,11 @@ id: "aidx"
# IP address family used for outgoing request (ipv4, ipv6 or dual) # IP address family used for outgoing request (ipv4, ipv6 or dual)
#outgoingAddressFamily: ipv4 #outgoingAddressFamily: ipv4
# Syslog option
#syslog:
# host: localhost
# port: 514
# Proxy for HTTP/HTTPS # Proxy for HTTP/HTTPS
#proxy: http://127.0.0.1:3128 #proxy: http://127.0.0.1:3128
@@ -216,8 +154,8 @@ id: "aidx"
# Media Proxy # Media Proxy
#mediaProxy: https://example.com/proxy #mediaProxy: https://example.com/proxy
# Sign to ActivityPub GET request (default: true) # Sign to ActivityPub GET request (default: false)
signToActivityPubGet: true #signToActivityPubGet: true
#allowedPrivateNetworks: [ #allowedPrivateNetworks: [
# '127.0.0.1/32' # '127.0.0.1/32'

View File

@@ -27,7 +27,7 @@ spec:
ports: ports:
- containerPort: 3000 - containerPort: 3000
- name: postgres - name: postgres
image: postgres:15-alpine image: postgres:14-alpine
env: env:
- name: POSTGRES_USER - name: POSTGRES_USER
value: "example-misskey-user" value: "example-misskey-user"
@@ -38,7 +38,7 @@ spec:
ports: ports:
- containerPort: 5432 - containerPort: 5432
- name: redis - name: redis
image: redis:7-alpine image: redis:alpine
ports: ports:
- containerPort: 6379 - containerPort: 6379
volumes: volumes:

View File

@@ -1,4 +0,0 @@
coverage:
status:
project: false
patch: false

View File

@@ -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:15-alpine
ports:
- "5432:5432"
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
# 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

View File

@@ -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: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
# 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:

149
cypress/e2e/basic.cy.js Normal file
View File

@@ -0,0 +1,149 @@
describe('Before setup instance', () => {
beforeEach(() => {
cy.resetState();
});
afterEach(() => {
// テ゚トįĩ‚äē†į›´å‰ãĢペãƒŧã‚¸éˇį§ģするようãĒãƒ†ã‚šãƒˆã‚ąãƒŧ゚(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆäŊœæˆ)だと、たãļんCypressぎバグでブナã‚Ļã‚ļぎ内厚がæŦĄãŽãƒ†ã‚šãƒˆã‚ąãƒŧ゚ãĢåŧ•きįļ™ãŒã‚ŒãĻしぞう(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆãŒäŊœæˆã—įĩ‚ã‚ãŖãŸæŽĩ階からテ゚トが始ぞる)。
// waitをå…Ĩã‚Œã‚‹ã“ã¨ã§ãã‚Œã‚’é˜˛æ­ĸできる
cy.wait(1000);
});
it('successfully loads', () => {
cy.visit('/');
});
it('setup instance', () => {
cy.visit('/');
cy.intercept('POST', '/api/admin/accounts/create').as('signup');
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();
// ãĒぜか動かãĒい
//cy.wait('@signup').should('have.property', 'response.statusCode');
cy.wait('@signup');
});
});
describe('After setup instance', () => {
beforeEach(() => {
cy.resetState();
// ã‚¤ãƒŗã‚šã‚ŋãƒŗã‚šåˆæœŸã‚ģットã‚ĸップ
cy.registerUser('admin', 'pass', true);
});
afterEach(() => {
// テ゚トįĩ‚äē†į›´å‰ãĢペãƒŧã‚¸éˇį§ģするようãĒãƒ†ã‚šãƒˆã‚ąãƒŧ゚(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆäŊœæˆ)だと、たãļんCypressぎバグでブナã‚Ļã‚ļぎ内厚がæŦĄãŽãƒ†ã‚šãƒˆã‚ąãƒŧ゚ãĢåŧ•きįļ™ãŒã‚ŒãĻしぞう(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆãŒäŊœæˆã—įĩ‚ã‚ãŖãŸæŽĩ階からテ゚トが始ぞる)。
// waitをå…Ĩã‚Œã‚‹ã“ã¨ã§ãã‚Œã‚’é˜˛æ­ĸできる
cy.wait(1000);
});
it('successfully loads', () => {
cy.visit('/');
});
it('signup', () => {
cy.visit('/');
cy.intercept('POST', '/api/signup').as('signup');
cy.get('[data-cy-signup]').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');
cy.get('[data-cy-signup-submit]').click();
cy.wait('@signup');
});
});
describe('After user signup', () => {
beforeEach(() => {
cy.resetState();
// ã‚¤ãƒŗã‚šã‚ŋãƒŗã‚šåˆæœŸã‚ģットã‚ĸップ
cy.registerUser('admin', 'pass', true);
// ãƒĻãƒŧã‚ļãƒŧäŊœæˆ
cy.registerUser('alice', 'alice1234');
});
afterEach(() => {
// テ゚トįĩ‚äē†į›´å‰ãĢペãƒŧã‚¸éˇį§ģするようãĒãƒ†ã‚šãƒˆã‚ąãƒŧ゚(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆäŊœæˆ)だと、たãļんCypressぎバグでブナã‚Ļã‚ļぎ内厚がæŦĄãŽãƒ†ã‚šãƒˆã‚ąãƒŧ゚ãĢåŧ•きįļ™ãŒã‚ŒãĻしぞう(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆãŒäŊœæˆã—įĩ‚ã‚ãŖãŸæŽĩ階からテ゚トが始ぞる)。
// waitをå…Ĩã‚Œã‚‹ã“ã¨ã§ãã‚Œã‚’é˜˛æ­ĸできる
cy.wait(1000);
});
it('successfully loads', () => {
cy.visit('/');
});
it('signin', () => {
cy.visit('/');
cy.intercept('POST', '/api/signin').as('signin');
cy.get('[data-cy-signin]').click();
cy.get('[data-cy-signin-username] input').type('alice');
// Enterキãƒŧでã‚ĩã‚¤ãƒŗã‚¤ãƒŗã§ãã‚‹ã‹ãŽįĸēčĒã‚‚å…ŧねる
cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
cy.wait('@signin');
});
it('suspend', function() {
cy.request('POST', '/api/admin/suspend-user', {
i: this.admin.token,
userId: this.alice.id,
});
cy.visit('/');
cy.get('[data-cy-signin]').click();
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);
});
});
describe('After user singed in', () => {
beforeEach(() => {
cy.resetState();
// ã‚¤ãƒŗã‚šã‚ŋãƒŗã‚šåˆæœŸã‚ģットã‚ĸップ
cy.registerUser('admin', 'pass', true);
// ãƒĻãƒŧã‚ļãƒŧäŊœæˆ
cy.registerUser('alice', 'alice1234');
cy.login('alice', 'alice1234');
});
afterEach(() => {
// テ゚トįĩ‚äē†į›´å‰ãĢペãƒŧã‚¸éˇį§ģするようãĒãƒ†ã‚šãƒˆã‚ąãƒŧ゚(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆäŊœæˆ)だと、たãļんCypressぎバグでブナã‚Ļã‚ļぎ内厚がæŦĄãŽãƒ†ã‚šãƒˆã‚ąãƒŧ゚ãĢåŧ•きįļ™ãŒã‚ŒãĻしぞう(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆãŒäŊœæˆã—įĩ‚ã‚ãŖãŸæŽĩ階からテ゚トが始ぞる)。
// waitをå…Ĩã‚Œã‚‹ã“ã¨ã§ãã‚Œã‚’é˜˛æ­ĸできる
cy.wait(1000);
});
it('successfully loads', () => {
cy.get('[data-cy-open-post-form]').should('be.visible');
});
it('note', () => {
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!');
});
});
// TODO: 投į¨ŋフりãƒŧムぎå…Ŧé–‹į¯„å›˛æŒ‡åŽšãŽãƒ†ã‚šãƒˆ
// TODO: 投į¨ŋフりãƒŧãƒ ãŽãƒ•ã‚Ąã‚¤ãƒĢæˇģäģ˜ãŽãƒ†ã‚šãƒˆ
// TODO: 投į¨ŋフりãƒŧãƒ ãŽãƒãƒƒã‚ˇãƒĨã‚ŋグäŋæŒãƒ•ã‚ŖãƒŧãƒĢドぎテ゚ト

View File

@@ -1,255 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
describe('Before setup instance', () => {
beforeEach(() => {
cy.resetState();
});
afterEach(() => {
// テ゚トįĩ‚äē†į›´å‰ãĢペãƒŧã‚¸éˇį§ģするようãĒãƒ†ã‚šãƒˆã‚ąãƒŧ゚(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆäŊœæˆ)だと、たãļんCypressぎバグでブナã‚Ļã‚ļぎ内厚がæŦĄãŽãƒ†ã‚šãƒˆã‚ąãƒŧ゚ãĢåŧ•きįļ™ãŒã‚ŒãĻしぞう(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆãŒäŊœæˆã—įĩ‚ã‚ãŖãŸæŽĩ階からテ゚トが始ぞる)。
// waitをå…Ĩã‚Œã‚‹ã“ã¨ã§ãã‚Œã‚’é˜˛æ­ĸできる
cy.wait(1000);
});
it('successfully loads', () => {
cy.visitHome();
});
it('setup instance', () => {
cy.visitHome();
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();
// ãĒぜか動かãĒい
//cy.wait('@signup').should('have.property', 'response.statusCode');
cy.wait('@signup');
});
});
describe('After setup instance', () => {
beforeEach(() => {
cy.resetState();
// ã‚¤ãƒŗã‚šã‚ŋãƒŗã‚šåˆæœŸã‚ģットã‚ĸップ
cy.registerUser('admin', 'pass', true);
});
afterEach(() => {
// テ゚トįĩ‚äē†į›´å‰ãĢペãƒŧã‚¸éˇį§ģするようãĒãƒ†ã‚šãƒˆã‚ąãƒŧ゚(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆäŊœæˆ)だと、たãļんCypressぎバグでブナã‚Ļã‚ļぎ内厚がæŦĄãŽãƒ†ã‚šãƒˆã‚ąãƒŧ゚ãĢåŧ•きįļ™ãŒã‚ŒãĻしぞう(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆãŒäŊœæˆã—įĩ‚ã‚ãŖãŸæŽĩ階からテ゚トが始ぞる)。
// waitをå…Ĩã‚Œã‚‹ã“ã¨ã§ãã‚Œã‚’é˜˛æ­ĸできる
cy.wait(1000);
});
it('successfully loads', () => {
cy.visitHome();
});
it('signup', () => {
cy.visitHome();
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('not.be.disabled');
cy.get('[data-cy-signup-submit]').click();
cy.wait('@signup');
});
it('signup with duplicated username', () => {
cy.registerUser('alice', 'alice1234');
cy.visitHome();
// ãƒĻãƒŧã‚ļãƒŧåãŒé‡č¤‡ã—ãĻいる場合ぎ挙動įĸēčĒ
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');
cy.get('[data-cy-signup-submit]').should('be.disabled');
});
});
describe('After user signup', () => {
beforeEach(() => {
cy.resetState();
// ã‚¤ãƒŗã‚šã‚ŋãƒŗã‚šåˆæœŸã‚ģットã‚ĸップ
cy.registerUser('admin', 'pass', true);
// ãƒĻãƒŧã‚ļãƒŧäŊœæˆ
cy.registerUser('alice', 'alice1234');
});
afterEach(() => {
// テ゚トįĩ‚äē†į›´å‰ãĢペãƒŧã‚¸éˇį§ģするようãĒãƒ†ã‚šãƒˆã‚ąãƒŧ゚(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆäŊœæˆ)だと、たãļんCypressぎバグでブナã‚Ļã‚ļぎ内厚がæŦĄãŽãƒ†ã‚šãƒˆã‚ąãƒŧ゚ãĢåŧ•きįļ™ãŒã‚ŒãĻしぞう(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆãŒäŊœæˆã—įĩ‚ã‚ãŖãŸæŽĩ階からテ゚トが始ぞる)。
// waitをå…Ĩã‚Œã‚‹ã“ã¨ã§ãã‚Œã‚’é˜˛æ­ĸできる
cy.wait(1000);
});
it('successfully loads', () => {
cy.visitHome();
});
it('signin', () => {
cy.visitHome();
cy.intercept('POST', '/api/signin-flow').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-password] input').type('alice1234{enter}');
cy.wait('@signin');
});
it('suspend', function() {
cy.request('POST', '/api/admin/suspend-user', {
i: this.admin.token,
userId: this.alice.id,
});
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}');
// TODO: cypressãĢブナã‚Ļã‚ļãŽč¨€čĒžæŒ‡åŽšã§ãã‚‹æŠŸčƒŊãŒåŽŸčŖ…ã•ã‚ŒæŦĄįŦŦ英čĒžãŽãŋテ゚トするようãĢする
cy.contains(/ã‚ĸã‚Ģã‚ĻãƒŗãƒˆãŒå‡įĩã•れãĻいぞす|This account has been suspended due to/gi);
});
});
describe('After user signed in', () => {
beforeEach(() => {
cy.resetState();
// ã‚¤ãƒŗã‚šã‚ŋãƒŗã‚šåˆæœŸã‚ģットã‚ĸップ
cy.registerUser('admin', 'pass', true);
// ãƒĻãƒŧã‚ļãƒŧäŊœæˆ
cy.registerUser('alice', 'alice1234');
cy.login('alice', 'alice1234');
});
afterEach(() => {
// テ゚トįĩ‚äē†į›´å‰ãĢペãƒŧã‚¸éˇį§ģするようãĒãƒ†ã‚šãƒˆã‚ąãƒŧ゚(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆäŊœæˆ)だと、たãļんCypressぎバグでブナã‚Ļã‚ļぎ内厚がæŦĄãŽãƒ†ã‚šãƒˆã‚ąãƒŧ゚ãĢåŧ•きįļ™ãŒã‚ŒãĻしぞう(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆãŒäŊœæˆã—įĩ‚ã‚ãŖãŸæŽĩ階からテ゚トが始ぞる)。
// waitをå…Ĩã‚Œã‚‹ã“ã¨ã§ãã‚Œã‚’é˜˛æ­ĸできる
cy.wait(1000);
});
it('successfully loads', () => {
// 襨į¤ēãĢ時間がかかるぎでデフりãƒĢãƒˆį§’æ•°ã ã¨ã‚ŋイムã‚ĸã‚Ļトする
cy.get('[data-cy-user-setup-continue]', { timeout: 30000 }).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!');
});
it('open note form with hotkey', () => {
// Wait until the page loads
cy.get('[data-cy-open-post-form]').should('be.visible');
// Use trigger() to give different `code` to test if hotkeys also work on non-QWERTY keyboards.
cy.document().trigger("keydown", { eventConstructor: 'KeyboardEvent', key: "n", code: "KeyL" });
// See if the form is opened
cy.get('[data-cy-post-form-text]').should('be.visible');
// Close it
cy.focused().trigger("keydown", { eventConstructor: 'KeyboardEvent', key: "Escape", code: "Escape" });
// See if the form is closed
cy.get('[data-cy-post-form-text]').should('not.be.visible');
});
});
// TODO: 投į¨ŋフりãƒŧムぎå…Ŧé–‹į¯„å›˛æŒ‡åŽšãŽãƒ†ã‚šãƒˆ
// TODO: 投į¨ŋフりãƒŧãƒ ãŽãƒ•ã‚Ąã‚¤ãƒĢæˇģäģ˜ãŽãƒ†ã‚šãƒˆ
// TODO: 投į¨ŋフりãƒŧãƒ ãŽãƒãƒƒã‚ˇãƒĨã‚ŋグäŋæŒãƒ•ã‚ŖãƒŧãƒĢドぎテ゚ト

View File

@@ -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')
});
});
});

65
cypress/e2e/widgets.cy.js Normal file
View File

@@ -0,0 +1,65 @@
describe('After user signed in', () => {
beforeEach(() => {
cy.resetState();
cy.viewport('macbook-16');
// ã‚¤ãƒŗã‚šã‚ŋãƒŗã‚šåˆæœŸã‚ģットã‚ĸップ
cy.registerUser('admin', 'pass', true);
// ãƒĻãƒŧã‚ļãƒŧäŊœæˆ
cy.registerUser('alice', 'alice1234');
cy.login('alice', 'alice1234');
});
afterEach(() => {
// テ゚トįĩ‚äē†į›´å‰ãĢペãƒŧã‚¸éˇį§ģするようãĒãƒ†ã‚šãƒˆã‚ąãƒŧ゚(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆäŊœæˆ)だと、たãļんCypressぎバグでブナã‚Ļã‚ļぎ内厚がæŦĄãŽãƒ†ã‚šãƒˆã‚ąãƒŧ゚ãĢåŧ•きįļ™ãŒã‚ŒãĻしぞう(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆãŒäŊœæˆã—įĩ‚ã‚ãŖãŸæŽĩ階からテ゚トが始ぞる)。
// waitをå…Ĩã‚Œã‚‹ã“ã¨ã§ãã‚Œã‚’é˜˛æ­ĸできる
cy.wait(1000);
});
it('widget edit toggle is visible', () => {
cy.get('.mk-widget-edit').should('be.visible');
});
it('widget select should be visible in edit mode', () => {
cy.get('.mk-widget-edit').click();
cy.get('.mk-widget-select').should('be.visible');
});
it('first widget should be removed', () => {
cy.get('.mk-widget-edit').click();
cy.get('.customize-container:first-child .remove._button').click();
cy.get('.customize-container').should('have.length', 2);
});
function buildWidgetTest(widgetName) {
it(`${widgetName} widget should get added`, () => {
cy.get('.mk-widget-edit').click();
cy.get('.mk-widget-select select').select(widgetName, { force: true });
cy.get('.bg._modalBg.transparent').click({ multiple: true, force: true });
cy.get('.mk-widget-add').click({ force: true });
cy.get(`.mkw-${widgetName}`).should('exist');
});
}
buildWidgetTest('memo');
buildWidgetTest('notifications');
buildWidgetTest('timeline');
buildWidgetTest('calendar');
buildWidgetTest('rss');
buildWidgetTest('trends');
buildWidgetTest('clock');
buildWidgetTest('activity');
buildWidgetTest('photos');
buildWidgetTest('digitalClock');
buildWidgetTest('federation');
buildWidgetTest('postForm');
buildWidgetTest('slideshow');
buildWidgetTest('serverMetric');
buildWidgetTest('onlineUsers');
buildWidgetTest('jobQueue');
buildWidgetTest('button');
buildWidgetTest('aiscript');
buildWidgetTest('aichan');
});

View File

@@ -1,76 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
/* flaky
describe('After user signed in', () => {
beforeEach(() => {
cy.resetState();
cy.viewport('macbook-16');
// ã‚¤ãƒŗã‚šã‚ŋãƒŗã‚šåˆæœŸã‚ģットã‚ĸップ
cy.registerUser('admin', 'pass', true);
// ãƒĻãƒŧã‚ļãƒŧäŊœæˆ
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(() => {
// テ゚トįĩ‚äē†į›´å‰ãĢペãƒŧã‚¸éˇį§ģするようãĒãƒ†ã‚šãƒˆã‚ąãƒŧ゚(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆäŊœæˆ)だと、たãļんCypressぎバグでブナã‚Ļã‚ļぎ内厚がæŦĄãŽãƒ†ã‚šãƒˆã‚ąãƒŧ゚ãĢåŧ•きįļ™ãŒã‚ŒãĻしぞう(䞋えばã‚ĸã‚Ģã‚ĻãƒŗãƒˆãŒäŊœæˆã—įĩ‚ã‚ãŖãŸæŽĩ階からテ゚トが始ぞる)。
// waitをå…Ĩã‚Œã‚‹ã“ã¨ã§ãã‚Œã‚’é˜˛æ­ĸできる
cy.wait(1000);
});
it('widget edit toggle is visible', () => {
cy.get('[data-cy-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');
});
it('first widget should be removed', () => {
cy.get('[data-cy-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('[data-cy-bg]._modalBg[data-cy-transparent]').click({ multiple: true, force: true });
cy.get('[data-cy-widget-add]').click({ force: true });
cy.get(`[data-cy-mkw-${widgetName}]`).should('exist');
});
}
buildWidgetTest('memo');
buildWidgetTest('notifications');
buildWidgetTest('timeline');
buildWidgetTest('calendar');
buildWidgetTest('rss');
buildWidgetTest('trends');
buildWidgetTest('clock');
buildWidgetTest('activity');
buildWidgetTest('photos');
buildWidgetTest('digitalClock');
buildWidgetTest('federation');
buildWidgetTest('postForm');
buildWidgetTest('slideshow');
buildWidgetTest('serverMetric');
buildWidgetTest('onlineUsers');
buildWidgetTest('jobQueue');
buildWidgetTest('button');
buildWidgetTest('aiscript');
buildWidgetTest('aichan');
});
*/

View File

@@ -0,0 +1,55 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
Cypress.Commands.add('resetState', () => {
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);
});
Cypress.Commands.add('registerUser', (username, password, isAdmin = false) => {
const route = isAdmin ? '/api/admin/accounts/create' : '/api/signup';
cy.request('POST', route, {
username: username,
password: password,
}).its('body').as(username);
});
Cypress.Commands.add('login', (username, password) => {
cy.visit('/');
cy.intercept('POST', '/api/signin').as('signin');
cy.get('[data-cy-signin]').click();
cy.get('[data-cy-signin-username] input').type(username);
cy.get('[data-cy-signin-password] input').type(`${password}{enter}`);
cy.wait('@signin').as('signedIn');
});

View File

@@ -1,67 +0,0 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
Cypress.Commands.add('visitHome', () => {
cy.visit('/');
cy.get('button', { timeout: 30000 }).should('be.visible');
})
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 => {
win.indexedDB.deleteDatabase('keyval-store');
});
*/
cy.request('POST', '/api/reset-db', {}).as('reset');
cy.get('@reset').its('status').should('equal', 204);
cy.reload(true);
});
Cypress.Commands.add('registerUser', (username, password, isAdmin = false) => {
const route = isAdmin ? '/api/admin/accounts/create' : '/api/signup';
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.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-password] input').type(`${password}{enter}`);
cy.wait('@signin').as('signedIn');
});

32
cypress/support/e2e.js Normal file
View File

@@ -0,0 +1,32 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')
Cypress.on('uncaught:exception', (err, runnable) => {
if ([
// Chrome
'ResizeObserver loop limit exceeded',
// Firefox
'ResizeObserver loop completed with undelivered notifications',
].some(msg => err.message.includes(msg))) {
return false;
}
});

View File

@@ -1,34 +0,0 @@
// ***********************************************************
// This example support/index.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')
Cypress.on('uncaught:exception', (err, runnable) => {
if ([
'The source image cannot be decoded',
// Chrome
'ResizeObserver loop limit exceeded',
// Firefox
'ResizeObserver loop completed with undelivered notifications',
].some(msg => err.message.includes(msg))) {
return false;
}
});

View File

@@ -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 {}

View File

@@ -1,8 +0,0 @@
{
"compilerOptions": {
"lib": ["dom", "es5"],
"target": "es5",
"types": ["cypress", "node"]
},
"include": ["./**/*.ts"]
}

52
docker-compose.yml Normal file
View File

@@ -0,0 +1,52 @@
version: "3"
services:
web:
build: .
restart: always
links:
- db
- redis
# - es
ports:
- "3000:3000"
networks:
- internal_network
- external_network
volumes:
- ./files:/misskey/files
- ./.config:/misskey/.config:ro
redis:
restart: always
image: redis:4.0-alpine
networks:
- internal_network
volumes:
- ./redis:/data
db:
restart: always
image: postgres:12.2-alpine
networks:
- internal_network
env_file:
- .config/docker.env
volumes:
- ./db:/var/lib/postgresql/data
# 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
View 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!

Submodule fluent-emojis deleted from cae981eb4c

65
gulpfile.js Normal file
View 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:client:fonts', () =>
gulp.src('./packages/client/node_modules/three/examples/fonts/**/*').pipe(gulp.dest('./built/_client_dist_/fonts/'))
);
gulp.task('copy:client:fontawesome', () =>
gulp.src('./packages/client/node_modules/@fortawesome/fontawesome-free/**/*').pipe(gulp.dest('./built/_client_dist_/fontawesome/'))
);
gulp.task('copy:client:locales', cb => {
fs.mkdirSync('./built/_client_dist_/locales', { recursive: true });
const v = { '_version_': meta.version };
for (const [lang, locale] of Object.entries(locales)) {
fs.writeFileSync(`./built/_client_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:client:locales', 'copy:backend:views', 'build:backend:script', 'build:backend:style', 'copy:client:fonts', 'copy:client:fontawesome'
));
gulp.task('default', gulp.task('build'));
gulp.task('watch', () => {
gulp.watch([
'./packages/*/src/**/*',
], { ignoreInitial: false }, gulp.task('build'));
});

View File

@@ -1,7 +0,0 @@
#!/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"

View File

@@ -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/addon-actions';
import { 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>;

View File

@@ -1,41 +0,0 @@
<!--
SPDX-FileCopyrightText: syuilo and misskey-project
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div :class="[$style.root]">
<div :inert="disabled" :class="[{ [$style.disabled]: disabled }]">
<slot></slot>
</div>
<div v-if="disabled" :class="[$style.cover]"></div>
</div>
</template>
<script lang="ts" setup>
defineProps<{
disabled?: boolean;
}>();
</script>
<style lang="scss" module>
.root {
position: relative;
}
.disabled {
opacity: 0.7;
}
.cover {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
cursor: not-allowed;
--color: color(from var(--MI_THEME-error) srgb r g b / 0.25);
background-size: auto auto;
background-image: repeating-linear-gradient(135deg, transparent, transparent 10px, var(--color) 4px, var(--color) 14px);
}
</style>

View File

@@ -1 +0,0 @@
äŊŋわれãĒくãĒãŖãŸã‘ãŠæļˆã™ãŽã¯å‹ŋäŊ“ãĒい(将æĨäŊŋえるかもしれãĒい)ã‚ŗãƒŧドをå…ĨれãĻおくとこ

File diff suppressed because it is too large Load Diff

View File

@@ -2,7 +2,6 @@
_lang_: "āĻŦāĻžāĻ‚āϞāĻž" _lang_: "āĻŦāĻžāĻ‚āϞāĻž"
headlineMisskey: "āύ⧋āϟ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϏāĻ‚āϝ⧁āĻ•ā§āϤ āύ⧇āϟāĻ“ā§ŸāĻžāĻ°ā§āĻ•" headlineMisskey: "āύ⧋āϟ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϏāĻ‚āϝ⧁āĻ•ā§āϤ āύ⧇āϟāĻ“ā§ŸāĻžāĻ°ā§āĻ•"
introMisskey: "āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ! āĻŽāĻŋāϏāĻ•āĻŋ āĻāĻ•āϟāĻŋ āĻ“āĻĒ⧇āύ āϏ⧋āĻ°ā§āϏ, āĻĄāĻŋāϏ⧇āĻ¨ā§āĻŸā§āϰāĻžāϞāĻžāχāϜāĻĄ āĻŽāĻžāχāĻ•ā§āϰ⧋āĻŦā§āϞāĻ—āĻŋāĻ‚ āĻĒāϰāĻŋāώ⧇āĻŦāĻžāĨ¤ \n\"āύ⧋āϟ\" āϤ⧈āϰāĻŋāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āϝāĻž āϘāϟāϛ⧇ āϤāĻž āϏāĻŦāĻžāϰ āϏāĻžāĻĨ⧇ āĻļā§‡ā§ŸāĻžāϰ āĻ•āϰ⧁āύ 📡\n\"āϰāĻŋāĻ…ā§āϝāĻžāĻ•āĻļāύ\" āϗ⧁āϞāĻŋāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āϝ⧇āϕ⧋āύ⧋ āύ⧋āϟ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āφāĻĒāύāĻžāϰ āĻ…āύ⧁āĻ­ā§‚āϤāĻŋ āĻŦā§āϝāĻžāĻ•ā§āϤ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ 👍\nāĻāĻ•āϟāĻŋ āύāϤ⧁āύ āĻĻ⧁āύāĻŋ⧟āĻž āϘ⧁āϰ⧇ āĻĻ⧇āϖ⧁āύ 🚀\n" introMisskey: "āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ! āĻŽāĻŋāϏāĻ•āĻŋ āĻāĻ•āϟāĻŋ āĻ“āĻĒ⧇āύ āϏ⧋āĻ°ā§āϏ, āĻĄāĻŋāϏ⧇āĻ¨ā§āĻŸā§āϰāĻžāϞāĻžāχāϜāĻĄ āĻŽāĻžāχāĻ•ā§āϰ⧋āĻŦā§āϞāĻ—āĻŋāĻ‚ āĻĒāϰāĻŋāώ⧇āĻŦāĻžāĨ¤ \n\"āύ⧋āϟ\" āϤ⧈āϰāĻŋāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āϝāĻž āϘāϟāϛ⧇ āϤāĻž āϏāĻŦāĻžāϰ āϏāĻžāĻĨ⧇ āĻļā§‡ā§ŸāĻžāϰ āĻ•āϰ⧁āύ 📡\n\"āϰāĻŋāĻ…ā§āϝāĻžāĻ•āĻļāύ\" āϗ⧁āϞāĻŋāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āϝ⧇āϕ⧋āύ⧋ āύ⧋āϟ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇ āφāĻĒāύāĻžāϰ āĻ…āύ⧁āĻ­ā§‚āϤāĻŋ āĻŦā§āϝāĻžāĻ•ā§āϤ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ 👍\nāĻāĻ•āϟāĻŋ āύāϤ⧁āύ āĻĻ⧁āύāĻŋ⧟āĻž āϘ⧁āϰ⧇ āĻĻ⧇āϖ⧁āύ 🚀\n"
poweredByMisskeyDescription: "{name} āĻšāϞ āĻ“āĻĒ⧇āύ āϏ⧋āĻ°ā§āϏ āĻĒā§āĻ˛ā§āϝāĻžāϟāĻĢāĻ°ā§āĻŽ <b>Misskey</b>-āĻāϰ āϏāĻžāĻ°ā§āĻ­āĻžāϰāϗ⧁āϞāĻŋāϰ āĻāĻ•āϟāĻŋ⧎"
monthAndDay: "{day}/{month}" monthAndDay: "{day}/{month}"
search: "āϖ⧁āρāϜ⧁āύ" search: "āϖ⧁āρāϜ⧁āύ"
notifications: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ" notifications: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ"
@@ -13,14 +12,12 @@ fetchingAsApObject: "āĻĢ⧇āĻĄāĻŋāĻ­āĻžāĻ°ā§āϏ āĻĨ⧇āϕ⧇ āĻ–āĻŦāϰ āφāύ
ok: "āĻ āĻŋāĻ•" ok: "āĻ āĻŋāĻ•"
gotIt: "āĻŦ⧁āĻā§‡āĻ›āĻŋ" gotIt: "āĻŦ⧁āĻā§‡āĻ›āĻŋ"
cancel: "āĻŦāĻžāϤāĻŋāϞ" cancel: "āĻŦāĻžāϤāĻŋāϞ"
noThankYou: "āύāĻž, āϧāĻ¨ā§āϝāĻŦāĻžāĻĻ"
enterUsername: "āχāωāϜāĻžāϰāύ⧇āĻŽ āϞāĻŋāϖ⧁āύ" enterUsername: "āχāωāϜāĻžāϰāύ⧇āĻŽ āϞāĻŋāϖ⧁āύ"
renotedBy: "{user} āϰāĻŋāύ⧋āϟ āĻ•āϰ⧇āϛ⧇āύ" renotedBy: "{user} āϰāĻŋāύ⧋āϟ āĻ•āϰ⧇āϛ⧇āύ"
noNotes: "āϕ⧋āύ āύ⧋āϟ āύ⧇āχ" noNotes: "āϕ⧋āύ āύ⧋āϟ āύ⧇āχ"
noNotifications: "āϕ⧋āύ⧋ āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ āύ⧇āχ" noNotifications: "āϕ⧋āύ⧋ āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ āύ⧇āχ"
instance: "āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ" instance: "āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ"
settings: "āϏ⧇āϟāĻŋāĻ‚āϏ" settings: "āϏ⧇āϟāĻŋāĻ‚āϏ"
notificationSettings: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋāϰ āϏ⧇āϟāĻŋāĻ‚āϏ"
basicSettings: "āϏāĻžāϧāĻžāϰāĻŖ āϏ⧇āϟāĻŋāĻ‚āϏ" basicSettings: "āϏāĻžāϧāĻžāϰāĻŖ āϏ⧇āϟāĻŋāĻ‚āϏ"
otherSettings: "āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āϏ⧇āϟāĻŋāĻ‚āϏ" otherSettings: "āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ āϏ⧇āϟāĻŋāĻ‚āϏ"
openInWindow: "āύāϤ⧁āύ āωāχāĻ¨ā§āĻĄā§‹āϤ⧇ āϖ⧁āϞāĻž" openInWindow: "āύāϤ⧁āύ āωāχāĻ¨ā§āĻĄā§‹āϤ⧇ āϖ⧁āϞāĻž"
@@ -45,20 +42,12 @@ pin: "āĻĒāĻŋāύ āĻ•āϰāĻž"
unpin: "āĻĒāĻŋāύ āϏāϰāĻžāύ" unpin: "āĻĒāĻŋāύ āϏāϰāĻžāύ"
copyContent: "āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁ āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ" copyContent: "āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁ āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ"
copyLink: "āϞāĻŋāĻ™ā§āĻ• āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ" copyLink: "āϞāĻŋāĻ™ā§āĻ• āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ"
copyLinkRenote: "āϰāĻŋāύ⧋āϟ āϞāĻŋāĻ™ā§āĻ• āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ"
delete: "āĻŽā§āϛ⧁āύ" delete: "āĻŽā§āϛ⧁āύ"
deleteAndEdit: "āĻŽā§āϛ⧁āύ āĻāĻŦāĻ‚ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻ•āϰ⧁āύ" deleteAndEdit: "āĻŽā§āϛ⧁āύ āĻāĻŦāĻ‚ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻ•āϰ⧁āύ"
deleteAndEditConfirm: "āφāĻĒāύāĻŋ āĻ•āĻŋ āĻāχ āύ⧋āϟāϟāĻŋ āĻŽā§āϛ⧇ āĻāϟāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻ•āϰāĻžāϰ āĻŦāĻŋāώāϝāĻŧ⧇ āύāĻŋāĻļā§āϚāĻŋāϤ? āφāĻĒāύāĻŋ āĻāϟāĻŋāϰ āϏāĻŽāĻ¸ā§āϤ āϰāĻŋāĻ…ā§āϝāĻžāĻ•āĻļāύ, āϰāĻŋāύ⧋āϟ āĻāĻŦāĻ‚ āϜāĻŦāĻžāĻŦ āĻšāĻžāϰāĻžāĻŦ⧇āύāĨ¤" deleteAndEditConfirm: "āφāĻĒāύāĻŋ āĻ•āĻŋ āĻāχ āύ⧋āϟāϟāĻŋ āĻŽā§āϛ⧇ āĻāϟāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻ•āϰāĻžāϰ āĻŦāĻŋāώāϝāĻŧ⧇ āύāĻŋāĻļā§āϚāĻŋāϤ? āφāĻĒāύāĻŋ āĻāϟāĻŋāϰ āϏāĻŽāĻ¸ā§āϤ āϰāĻŋāĻ…ā§āϝāĻžāĻ•āĻļāύ, āϰāĻŋāύ⧋āϟ āĻāĻŦāĻ‚ āϜāĻŦāĻžāĻŦ āĻšāĻžāϰāĻžāĻŦ⧇āύāĨ¤"
addToList: "āϞāĻŋāĻ¸ā§āϟ āĻ āϝ⧋āĻ— āĻ•āϰ⧁āύ" addToList: "āϞāĻŋāĻ¸ā§āϟ āĻ āϝ⧋āĻ— āĻ•āϰ⧁āύ"
addToAntenna: "āĻ…ā§āϝāĻžāĻ¨ā§āĻŸā§‡āύāĻž āĻ āϝ⧋āĻ— āĻ•āϰ⧁āύ"
sendMessage: "āĻāĻ•āϟāĻŋ āĻŦāĻžāĻ°ā§āϤāĻž āĻĒāĻžāĻ āĻžāύ" sendMessage: "āĻāĻ•āϟāĻŋ āĻŦāĻžāĻ°ā§āϤāĻž āĻĒāĻžāĻ āĻžāύ"
copyRSS: "RSS āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ"
copyUsername: "āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āύāĻžāĻŽ āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ" copyUsername: "āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āύāĻžāĻŽ āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ"
copyUserId: "āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ ID āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ"
copyNoteId: "āύ⧋āĻŸā§‡āϰ ID āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ"
copyFileId: "āĻĢāĻžāχāϞ ID āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ"
copyFolderId: "āĻĢā§‹āĻ˛ā§āĻĄāĻžāϰ ID āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ"
copyProfileUrl: "āĻĒā§āϰ⧋āĻĢāĻžāχāϞ URL āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ"
searchUser: "āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀ āϖ⧁āρāϜ⧁āύ..." searchUser: "āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀ āϖ⧁āρāϜ⧁āύ..."
reply: "āϜāĻŦāĻžāĻŦ" reply: "āϜāĻŦāĻžāĻŦ"
loadMore: "āφāϰāĻ“ āĻĻ⧇āϖ⧁āύ" loadMore: "āφāϰāĻ“ āĻĻ⧇āϖ⧁āύ"
@@ -111,8 +100,6 @@ renoted: "āϰāĻŋāύ⧋āϟ āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇"
cantRenote: "āĻāχ āύ⧋āϟāϟāĻŋ āϰāĻŋāύ⧋āϟ āĻ•āϰāĻž āϝāĻžāĻŦ⧇ āύāĻžāĨ¤" cantRenote: "āĻāχ āύ⧋āϟāϟāĻŋ āϰāĻŋāύ⧋āϟ āĻ•āϰāĻž āϝāĻžāĻŦ⧇ āύāĻžāĨ¤"
cantReRenote: "āϰāĻŋāύ⧋āϟāϕ⧇ āϰāĻŋāύ⧋āϟ āĻ•āϰāĻž āϝāĻžāĻŦ⧇ āύāĻžāĨ¤" cantReRenote: "āϰāĻŋāύ⧋āϟāϕ⧇ āϰāĻŋāύ⧋āϟ āĻ•āϰāĻž āϝāĻžāĻŦ⧇ āύāĻžāĨ¤"
quote: "āωāĻĻā§āϧ⧃āϤāĻŋ" quote: "āωāĻĻā§āϧ⧃āϤāĻŋ"
inChannelRenote: "āĻšā§āϝāĻžāύ⧇āϞ⧇ āϰāĻŋāύ⧋āϟ"
inChannelQuote: "āĻšā§āϝāĻžāύ⧇āϞ⧇ āωāĻĻā§āϧ⧃āϤāĻŋ"
pinnedNote: "āĻĒāĻŋāύ āĻ•āϰāĻž āύ⧋āϟ" pinnedNote: "āĻĒāĻŋāύ āĻ•āϰāĻž āύ⧋āϟ"
pinned: "āĻĒāĻŋāύ āĻ•āϰāĻž" pinned: "āĻĒāĻŋāύ āĻ•āϰāĻž"
you: "āφāĻĒāύāĻŋ" you: "āφāĻĒāύāĻŋ"
@@ -120,11 +107,7 @@ clickToShow: "āĻĻ⧇āĻ–āĻžāϰ āϜāĻ¨ā§āϝ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ"
sensitive: "āϏāĻ‚āĻŦ⧇āĻĻāύāĻļā§€āϞ āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁" sensitive: "āϏāĻ‚āĻŦ⧇āĻĻāύāĻļā§€āϞ āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁"
add: "āϝ⧁āĻ•ā§āϤ āĻ•āϰ⧁āύ" add: "āϝ⧁āĻ•ā§āϤ āĻ•āϰ⧁āύ"
reaction: "āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž" reaction: "āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž"
reactions: "āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž" reactionSetting: "āϰāĻŋāĻ…ā§āϝāĻžāĻ•āĻļāύ āĻĒāĻŋāĻ•āĻžāϰ⧇ āϝ⧇āϏāĻ•āϞ āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋ⧟āĻž āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāĻŦ⧇"
emojiPicker: "āχāĻŽā§‹āϜāĻŋ āĻĒāĻŋāĻ•āĻžāϰ"
pinnedEmojisForReactionSettingDescription: "āϰāĻŋāĻ…ā§āϝāĻžāĻ•āĻļāύ āĻĻā§‡ā§ŸāĻžāϰ āϏāĻŽāϝāĻŧ āφāĻĒāύāĻŋ āχāĻŽā§‹āϜāĻŋāϟāĻŋāϕ⧇ āĻĒāĻŋāύ āĻ•āϰāĻž āĻāĻŦāĻ‚ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšāĻ“āϝāĻŧāĻžāϰ āϜāĻ¨ā§āϝ āϏ⧇āϟ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤"
pinnedEmojisSettingDescription: "āχāĻŽā§‹āϜāĻŋ āχāύāĻĒ⧁āϟ āĻĻā§‡ā§ŸāĻžāϰ āϏāĻŽāϝāĻŧ āφāĻĒāύāĻŋ āχāĻŽā§‹āϜāĻŋāϟāĻŋāϕ⧇ āĻĒāĻŋāύ āĻ•āϰāĻž āĻāĻŦāĻ‚ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšāĻ“āϝāĻŧāĻžāϰ āϜāĻ¨ā§āϝ āϏ⧇āϟ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤"
emojiPickerDisplay: "āĻĒāĻŋāĻ•āĻžāϰ āĻĄāĻŋāϏāĻĒā§āϞ⧇"
reactionSettingDescription2: "āĻĒ⧁āύāϰāĻžāϝāĻŧ āϏāĻžāϜāĻžāϤ⧇ āĻŸā§‡āύ⧇ āφāύ⧁āύ, āĻŽā§āĻ›āϤ⧇ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ, āϝ⧋āĻ— āĻ•āϰāϤ⧇ + āϟāĻŋāĻĒ⧁āύāĨ¤" reactionSettingDescription2: "āĻĒ⧁āύāϰāĻžāϝāĻŧ āϏāĻžāϜāĻžāϤ⧇ āĻŸā§‡āύ⧇ āφāύ⧁āύ, āĻŽā§āĻ›āϤ⧇ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰ⧁āύ, āϝ⧋āĻ— āĻ•āϰāϤ⧇ + āϟāĻŋāĻĒ⧁āύāĨ¤"
rememberNoteVisibility: "āύ⧋āĻŸā§‡āϰ āĻĻ⧃āĻļā§āϝāĻŽāĻžāĻ¨ā§āϝāϤāĻžāϰ āϏ⧇āϟāĻŋāĻ‚āϏ āĻŽāύ⧇ āϰāĻžāϖ⧁āύ" rememberNoteVisibility: "āύ⧋āĻŸā§‡āϰ āĻĻ⧃āĻļā§āϝāĻŽāĻžāĻ¨ā§āϝāϤāĻžāϰ āϏ⧇āϟāĻŋāĻ‚āϏ āĻŽāύ⧇ āϰāĻžāϖ⧁āύ"
attachCancel: "āĻ…ā§āϝāĻžāϟāĻžāϚāĻŽā§‡āĻ¨ā§āϟ āϏāϰāĻžāύ " attachCancel: "āĻ…ā§āϝāĻžāϟāĻžāϚāĻŽā§‡āĻ¨ā§āϟ āϏāϰāĻžāύ "
@@ -181,6 +164,7 @@ annotation: "āĻŽāĻ¨ā§āϤāĻŦā§āϝ"
federation: "āĻĢ⧇āĻĄāĻŋāĻ­āĻžāĻ°ā§āϏ" federation: "āĻĢ⧇āĻĄāĻŋāĻ­āĻžāĻ°ā§āϏ"
instances: "āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ" instances: "āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ"
registeredAt: "āϝ⧋āĻ— āĻĻāĻŋā§Ÿā§‡āϛ⧇āύ" registeredAt: "āϝ⧋āĻ— āĻĻāĻŋā§Ÿā§‡āϛ⧇āύ"
latestRequestSentAt: "āĻļ⧇āώ āϰāĻŋāĻ•ā§ā§Ÿā§‡āĻ¸ā§āϟ āĻĒāĻžāĻ āĻžāύ⧋ āĻšā§Ÿā§‡āϛ⧇"
latestRequestReceivedAt: "āĻļ⧇āώ āϰāĻŋāĻ•ā§ā§Ÿā§‡āĻ¸ā§āϟ āĻ—ā§ƒāĻšā§€āϤ āĻšā§Ÿā§‡āϛ⧇" latestRequestReceivedAt: "āĻļ⧇āώ āϰāĻŋāĻ•ā§ā§Ÿā§‡āĻ¸ā§āϟ āĻ—ā§ƒāĻšā§€āϤ āĻšā§Ÿā§‡āϛ⧇"
latestStatus: "āϏāĻ°ā§āĻŦāĻļ⧇āώ āĻ…āĻŦāĻ¸ā§āĻĨāĻž" latestStatus: "āϏāĻ°ā§āĻŦāĻļ⧇āώ āĻ…āĻŦāĻ¸ā§āĻĨāĻž"
storageUsage: "āĻ¸ā§āĻŸā§‹āϰ⧇āĻœā§‡āϰ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ" storageUsage: "āĻ¸ā§āĻŸā§‹āϰ⧇āĻœā§‡āϰ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ"
@@ -268,12 +252,12 @@ noMoreHistory: "āφāϰ āϕ⧋āύ āχāϤāĻŋāĻšāĻžāϏ āύ⧇āχ"
startMessaging: "āĻšā§āϝāĻžāϟ āĻļ⧁āϰ⧁ āĻ•āϰ⧁āύ" startMessaging: "āĻšā§āϝāĻžāϟ āĻļ⧁āϰ⧁ āĻ•āϰ⧁āύ"
nUsersRead: "{n} āϜāύ āĻĒā§œā§‡āϛ⧇āύ" nUsersRead: "{n} āϜāύ āĻĒā§œā§‡āϛ⧇āύ"
agreeTo: "{0} āĻāϰ āĻĒā§āϰāϤāĻŋ āφāĻŽāĻŋ āϏāĻŽā§āĻŽāϤ" agreeTo: "{0} āĻāϰ āĻĒā§āϰāϤāĻŋ āφāĻŽāĻŋ āϏāĻŽā§āĻŽāϤ"
tos: "āĻĒāϰāĻŋāώ⧇āĻŦāĻžāϰ āĻļāĻ°ā§āϤāĻžāĻĻāĻŋ"
start: "āĻļ⧁āϰ⧁ āĻ•āϰ⧁āύ" start: "āĻļ⧁āϰ⧁ āĻ•āϰ⧁āύ"
home: "āĻŽā§‚āϞ āĻĒāĻžāϤāĻž" home: "āĻŽā§‚āϞ āĻĒāĻžāϤāĻž"
remoteUserCaution: "āĻāχ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀ āϰāĻŋāĻŽā§‹āϟ āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ⧇āϰ, āύāĻŋāĻŽā§āύāĻ•ā§āϤ āϤāĻĨā§āϝ āĻ…āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻšāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤" remoteUserCaution: "āĻāχ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀ āϰāĻŋāĻŽā§‹āϟ āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ⧇āϰ, āύāĻŋāĻŽā§āύāĻ•ā§āϤ āϤāĻĨā§āϝ āĻ…āϏāĻŽā§āĻĒā§‚āĻ°ā§āĻŖ āĻšāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤"
activity: "āĻ•āĻžāĻ°ā§āϝāĻ•āϞāĻžāĻĒ" activity: "āĻ•āĻžāĻ°ā§āϝāĻ•āϞāĻžāĻĒ"
images: "āĻ›āĻŦāĻŋ" images: "āĻ›āĻŦāĻŋ"
image: "āĻ›āĻŦāĻŋ"
birthday: "āϜāĻ¨ā§āĻŽāĻĻāĻŋāύ" birthday: "āϜāĻ¨ā§āĻŽāĻĻāĻŋāύ"
yearsOld: "{age} āĻŦāĻ›āϰ" yearsOld: "{age} āĻŦāĻ›āϰ"
registeredDate: "āϝ⧋āĻ—āĻĻāĻžāύ⧇āϰ āϤāĻžāϰāĻŋāĻ–" registeredDate: "āϝ⧋āĻ—āĻĻāĻžāύ⧇āϰ āϤāĻžāϰāĻŋāĻ–"
@@ -310,6 +294,7 @@ copyUrl: "URL āĻ•āĻĒāĻŋ āĻ•āϰ⧁āύ"
rename: "āĻĒ⧁āύāσāύāĻžāĻŽāĻ•āϰāĻŖ" rename: "āĻĒ⧁āύāσāύāĻžāĻŽāĻ•āϰāĻŖ"
avatar: "āĻĒā§āϰ⧋āĻĢāĻžāχāϞ āĻ›āĻŦāĻŋ" avatar: "āĻĒā§āϰ⧋āĻĢāĻžāχāϞ āĻ›āĻŦāĻŋ"
banner: "āĻŦā§āϝāĻžāύāĻžāϰ" banner: "āĻŦā§āϝāĻžāύāĻžāϰ"
nsfw: "āϏāĻ‚āĻŦ⧇āĻĻāύāĻļā§€āϞ āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁"
whenServerDisconnected: "āϏāĻžāĻ°ā§āĻ­āĻžāϰ⧇āϰ āϏāĻžāĻĨ⧇ āϏāĻ‚āϝ⧋āĻ— āĻŦāĻŋāĻšā§āĻ›āĻŋāĻ¨ā§āύ āĻšāϝāĻŧ⧇ āϗ⧇āϞ⧇" whenServerDisconnected: "āϏāĻžāĻ°ā§āĻ­āĻžāϰ⧇āϰ āϏāĻžāĻĨ⧇ āϏāĻ‚āϝ⧋āĻ— āĻŦāĻŋāĻšā§āĻ›āĻŋāĻ¨ā§āύ āĻšāϝāĻŧ⧇ āϗ⧇āϞ⧇"
disconnectedFromServer: "āϏāĻžāĻ°ā§āĻ­āĻžāϰ āĻĨ⧇āϕ⧇ āϏāĻ‚āϝ⧋āĻ— āĻŦāĻŋāĻšā§āĻ›āĻŋāĻ¨ā§āύ āĻšāϝāĻŧ⧇āϛ⧇" disconnectedFromServer: "āϏāĻžāĻ°ā§āĻ­āĻžāϰ āĻĨ⧇āϕ⧇ āϏāĻ‚āϝ⧋āĻ— āĻŦāĻŋāĻšā§āĻ›āĻŋāĻ¨ā§āύ āĻšāϝāĻŧ⧇āϛ⧇"
reload: "āφāĻŦāĻžāϰ āϞ⧋āĻĄ āĻ•āϰ⧁āύ" reload: "āφāĻŦāĻžāϰ āϞ⧋āĻĄ āĻ•āϰ⧁āύ"
@@ -339,10 +324,12 @@ enableLocalTimeline: "āĻ¸ā§āĻĨāĻžāĻ¨ā§€ā§Ÿ āϟāĻžāχāĻŽāϞāĻžāχāύ āϚāĻžāϞ
enableGlobalTimeline: "āĻ—ā§āϞ⧋āĻŦāĻžāϞ āϟāĻžāχāĻŽāϞāĻžāχāύ āϚāĻžāϞ⧁ āĻ•āϰ⧁āύ" enableGlobalTimeline: "āĻ—ā§āϞ⧋āĻŦāĻžāϞ āϟāĻžāχāĻŽāϞāĻžāχāύ āϚāĻžāϞ⧁ āĻ•āϰ⧁āύ"
disablingTimelinesInfo: "āφāĻĒāύāĻŋ āĻāχ āϟāĻžāχāĻŽāϞāĻžāχāύāϗ⧁āϞāĻŋ āĻŦāĻ¨ā§āϧ āĻ•āϰāϞ⧇āĻ“ āĻĒā§āϰāĻļāĻžāϏāĻ• āĻāĻŦāĻ‚ āĻŽāĻĄāĻžāϰ⧇āϟāϰāϰāĻž āĻāχ āϟāĻžāχāĻŽāϞāĻžāχāύāϗ⧁āϞāĻŋ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŦ⧇" disablingTimelinesInfo: "āφāĻĒāύāĻŋ āĻāχ āϟāĻžāχāĻŽāϞāĻžāχāύāϗ⧁āϞāĻŋ āĻŦāĻ¨ā§āϧ āĻ•āϰāϞ⧇āĻ“ āĻĒā§āϰāĻļāĻžāϏāĻ• āĻāĻŦāĻ‚ āĻŽāĻĄāĻžāϰ⧇āϟāϰāϰāĻž āĻāχ āϟāĻžāχāĻŽāϞāĻžāχāύāϗ⧁āϞāĻŋ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰāĻŦ⧇"
registration: "āύāĻŋāĻŦāĻ¨ā§āϧāύ" registration: "āύāĻŋāĻŦāĻ¨ā§āϧāύ"
enableRegistration: "āύāϤ⧁āύ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀ āύāĻŋāĻŦāĻ¨ā§āϧāύ āϚāĻžāϞ⧁ āĻ•āϰ⧁āύ"
invite: "āφāĻŽāĻ¨ā§āĻ¤ā§āϰāĻŖ" invite: "āφāĻŽāĻ¨ā§āĻ¤ā§āϰāĻŖ"
driveCapacityPerLocalAccount: "āĻĒā§āϰāĻ¤ā§āϝ⧇āĻ• āĻ¸ā§āĻĨāĻžāĻ¨ā§€ā§Ÿ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āϜāĻ¨ā§āϝ āĻĄā§āϰāĻžāχāϭ⧇āϰ āϜāĻžā§ŸāĻ—āĻž" driveCapacityPerLocalAccount: "āĻĒā§āϰāĻ¤ā§āϝ⧇āĻ• āĻ¸ā§āĻĨāĻžāĻ¨ā§€ā§Ÿ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āϜāĻ¨ā§āϝ āĻĄā§āϰāĻžāχāϭ⧇āϰ āϜāĻžā§ŸāĻ—āĻž"
driveCapacityPerRemoteAccount: "āĻĒā§āϰāĻ¤ā§āϝ⧇āĻ• āϰāĻŋāĻŽā§‹āϟ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āϜāĻ¨ā§āϝ āĻĄā§āϰāĻžāχāϭ⧇āϰ āϜāĻžā§ŸāĻ—āĻž" driveCapacityPerRemoteAccount: "āĻĒā§āϰāĻ¤ā§āϝ⧇āĻ• āϰāĻŋāĻŽā§‹āϟ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āϜāĻ¨ā§āϝ āĻĄā§āϰāĻžāχāϭ⧇āϰ āϜāĻžā§ŸāĻ—āĻž"
inMb: "āĻŽā§‡āĻ—āĻžāĻŦāĻžāχāĻŸā§‡ āϞāĻŋāϖ⧁āύ" inMb: "āĻŽā§‡āĻ—āĻžāĻŦāĻžāχāĻŸā§‡ āϞāĻŋāϖ⧁āύ"
iconUrl: "āφāχāĻ•āύ⧇āϰ URL (āĻĢā§āϝāĻžāĻ­āĻŋāĻ•āύ, āχāĻ¤ā§āϝāĻžāĻĻāĻŋ)"
bannerUrl: "āĻŦā§āϝāĻžāύāĻžāϰ āĻ›āĻŦāĻŋāϰ URL" bannerUrl: "āĻŦā§āϝāĻžāύāĻžāϰ āĻ›āĻŦāĻŋāϰ URL"
backgroundImageUrl: "āĻĒāϟāĻ­ā§‚āĻŽāĻŋāϰ āϚāĻŋāĻ¤ā§āϰ⧇āϰ URL" backgroundImageUrl: "āĻĒāϟāĻ­ā§‚āĻŽāĻŋāϰ āϚāĻŋāĻ¤ā§āϰ⧇āϰ URL"
basicInfo: "āφāĻĒāύāĻžāϰ āĻŦā§āϝāĻ•ā§āϤāĻŋāĻ—āϤ āϤāĻĨā§āϝ" basicInfo: "āφāĻĒāύāĻžāϰ āĻŦā§āϝāĻ•ā§āϤāĻŋāĻ—āϤ āϤāĻĨā§āϝ"
@@ -356,14 +343,10 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "hCaptcha āϚāĻžāϞ⧁ āĻ•āϰ⧁āύ" enableHcaptcha: "hCaptcha āϚāĻžāϞ⧁ āĻ•āϰ⧁āύ"
hcaptchaSiteKey: "āϏāĻžāχāϟ āϕ⧀" hcaptchaSiteKey: "āϏāĻžāχāϟ āϕ⧀"
hcaptchaSecretKey: "āϏāĻŋāĻ•ā§āϰ⧇āϟ āϕ⧀" hcaptchaSecretKey: "āϏāĻŋāĻ•ā§āϰ⧇āϟ āϕ⧀"
mcaptchaSiteKey: "āϏāĻžāχāϟ āϕ⧀"
mcaptchaSecretKey: "āϏāĻŋāĻ•ā§āϰ⧇āϟ āϕ⧀"
recaptcha: "reCAPTCHA" recaptcha: "reCAPTCHA"
enableRecaptcha: "reCAPTCHA āϚāĻžāϞ⧁ āĻ•āϰ⧁āύ" enableRecaptcha: "reCAPTCHA āϚāĻžāϞ⧁ āĻ•āϰ⧁āύ"
recaptchaSiteKey: "āϏāĻžāχāϟ āϕ⧀" recaptchaSiteKey: "āϏāĻžāχāϟ āϕ⧀"
recaptchaSecretKey: "āϏāĻŋāĻ•ā§āϰ⧇āϟ āϕ⧀" recaptchaSecretKey: "āϏāĻŋāĻ•ā§āϰ⧇āϟ āϕ⧀"
turnstileSiteKey: "āϏāĻžāχāϟ āϕ⧀"
turnstileSecretKey: "āϏāĻŋāĻ•ā§āϰ⧇āϟ āϕ⧀"
avoidMultiCaptchaConfirm: "āĻāĻ•āĻžāϧāĻŋāĻ• Captcha āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϞ⧇ āϤāĻžāϰāĻž āĻĒāϰāĻ¸ā§āĻĒāϰ⧇āϰ āĻ•āĻžāĻœā§‡ āĻŦāĻžāϧāĻž āĻĻāĻŋāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āφāĻĒāύāĻŋ āĻ•āĻŋ āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ Captcha āύāĻŋāĻˇā§āĻ•ā§āϰāĻŋāϝāĻŧ āĻ•āϰāϤ⧇ āϚāĻžāύ? āφāĻĒāύāĻŋ 'āĻŦāĻžāϤāĻŋāϞ' āĻ•ā§āϞāĻŋāĻ• āĻ•āϰāĻžāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻāĻ•āĻžāϧāĻŋāĻ• Captcha āϚāĻžāϞ⧁ āϰāĻžāĻ–āϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤" avoidMultiCaptchaConfirm: "āĻāĻ•āĻžāϧāĻŋāĻ• Captcha āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϞ⧇ āϤāĻžāϰāĻž āĻĒāϰāĻ¸ā§āĻĒāϰ⧇āϰ āĻ•āĻžāĻœā§‡ āĻŦāĻžāϧāĻž āĻĻāĻŋāϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āφāĻĒāύāĻŋ āĻ•āĻŋ āĻ…āĻ¨ā§āϝāĻžāĻ¨ā§āϝ Captcha āύāĻŋāĻˇā§āĻ•ā§āϰāĻŋāϝāĻŧ āĻ•āϰāϤ⧇ āϚāĻžāύ? āφāĻĒāύāĻŋ 'āĻŦāĻžāϤāĻŋāϞ' āĻ•ā§āϞāĻŋāĻ• āĻ•āϰāĻžāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āĻāĻ•āĻžāϧāĻŋāĻ• Captcha āϚāĻžāϞ⧁ āϰāĻžāĻ–āϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤"
antennas: "āĻ…ā§āϝāĻžāĻ¨ā§āĻŸā§‡āύāĻž" antennas: "āĻ…ā§āϝāĻžāĻ¨ā§āĻŸā§‡āύāĻž"
manageAntennas: "āĻ…ā§āϝāĻžāĻ¨ā§āĻŸā§‡āύāĻž āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻžāĻĒāύāĻž" manageAntennas: "āĻ…ā§āϝāĻžāĻ¨ā§āĻŸā§‡āύāĻž āĻŦā§āϝāĻŦāĻ¸ā§āĻĨāĻžāĻĒāύāĻž"
@@ -397,9 +380,12 @@ about: "āφāĻĒāύāĻžāϰ āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇"
aboutMisskey: "Misskey āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇" aboutMisskey: "Misskey āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇"
administrator: "āĻĒā§āϰāĻļāĻžāϏāĻ•" administrator: "āĻĒā§āϰāĻļāĻžāϏāĻ•"
token: "āĻŸā§‹āϕ⧇āύ" token: "āĻŸā§‹āϕ⧇āύ"
twoStepAuthentication: "⧍-āϧāĻžāĻĒ āĻĒā§āϰāĻŽāĻžāĻŖā§€āĻ•āϰāĻŖ"
moderator: "āĻŽāĻĄāĻžāϰ⧇āϟāϰ" moderator: "āĻŽāĻĄāĻžāϰ⧇āϟāϰ"
nUsersMentioned: "{n} āϜāύāϕ⧇ āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇" nUsersMentioned: "{n} āϜāύāϕ⧇ āωāĻ˛ā§āϞ⧇āĻ– āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇"
securityKey: "āϏāĻŋāĻ•āĻŋāωāϰāĻŋāϟāĻŋ āϕ⧀" securityKey: "āϏāĻŋāĻ•āĻŋāωāϰāĻŋāϟāĻŋ āϕ⧀"
securityKeyName: "āϕ⧀'āϰ āύāĻžāĻŽ"
registerSecurityKey: "āϏāĻŋāĻ•āĻŋāωāϰāĻŋāϟāĻŋ āϕ⧀ āύāĻŋāĻŦāĻ¨ā§āϧāύ āĻ•āϰ⧁āύ"
lastUsed: "āĻļ⧇āώ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇" lastUsed: "āĻļ⧇āώ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇"
unregister: "āύāĻŋāĻŦāĻ¨ā§āϧāύāĻŽā§āĻ•ā§āϤ āĻšāύ" unregister: "āύāĻŋāĻŦāĻ¨ā§āϧāύāĻŽā§āĻ•ā§āϤ āĻšāύ"
passwordLessLogin: "āĻĒāĻžāϏāĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ-āĻŦāĻŋāĻšā§€āύ āϞāĻ—āχāύ āϏ⧇āϟ āφāĻĒ āĻ•āϰ⧁āύ" passwordLessLogin: "āĻĒāĻžāϏāĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ-āĻŦāĻŋāĻšā§€āύ āϞāĻ—āχāύ āϏ⧇āϟ āφāĻĒ āĻ•āϰ⧁āύ"
@@ -410,21 +396,31 @@ share: "āĻļā§‡ā§ŸāĻžāϰ"
notFound: "āĻĒāĻžāĻ“ā§ŸāĻž āϝāĻžā§ŸāύāĻŋ" notFound: "āĻĒāĻžāĻ“ā§ŸāĻž āϝāĻžā§ŸāύāĻŋ"
notFoundDescription: "āĻāχ URL-āĻāϰ āϏāĻžāĻĨ⧇ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āϕ⧋āύ⧋ āĻĒ⧃āĻˇā§āĻ āĻž āύ⧇āχāĨ¤" notFoundDescription: "āĻāχ URL-āĻāϰ āϏāĻžāĻĨ⧇ āϏāĻŽā§āĻĒāĻ°ā§āĻ•āĻŋāϤ āϕ⧋āύ⧋ āĻĒ⧃āĻˇā§āĻ āĻž āύ⧇āχāĨ¤"
uploadFolder: "āφāĻĒāϞ⧋āĻĄā§‡āϰ āϜāĻ¨ā§āϝ āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻĢā§‹āĻ˛ā§āĻĄāĻžāϰ" uploadFolder: "āφāĻĒāϞ⧋āĻĄā§‡āϰ āϜāĻ¨ā§āϝ āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻĢā§‹āĻ˛ā§āĻĄāĻžāϰ"
cacheClear: "āĻ•ā§āϝāĻžāĻļ āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰ āĻ•āϰ⧁āύ"
markAsReadAllNotifications: "āϏāĻŽāĻ¸ā§āϤ āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋāϗ⧁āϞāĻŋ āĻĒāĻ āĻŋāϤ āĻšāĻŋāϏāĻžāĻŦ⧇ āϚāĻŋāĻšā§āύāĻŋāϤ āĻ•āϰ⧁āύ" markAsReadAllNotifications: "āϏāĻŽāĻ¸ā§āϤ āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋāϗ⧁āϞāĻŋ āĻĒāĻ āĻŋāϤ āĻšāĻŋāϏāĻžāĻŦ⧇ āϚāĻŋāĻšā§āύāĻŋāϤ āĻ•āϰ⧁āύ"
markAsReadAllUnreadNotes: "āϏāĻŽāĻ¸ā§āϤ āύ⧋āϟāϗ⧁āϞāĻŋ āĻĒāĻ āĻŋāϤ āĻšāĻŋāϏāĻžāĻŦ⧇ āϚāĻŋāĻšā§āύāĻŋāϤ āĻ•āϰ⧁āύ" markAsReadAllUnreadNotes: "āϏāĻŽāĻ¸ā§āϤ āύ⧋āϟāϗ⧁āϞāĻŋ āĻĒāĻ āĻŋāϤ āĻšāĻŋāϏāĻžāĻŦ⧇ āϚāĻŋāĻšā§āύāĻŋāϤ āĻ•āϰ⧁āύ"
markAsReadAllTalkMessages: "āϏāĻŽāĻ¸ā§āϤ āĻŽā§‡āϏ⧇āϜ āĻĒāĻ āĻŋāϤ āĻšāĻŋāϏāĻžāĻŦ⧇ āϚāĻŋāĻšā§āύāĻŋāϤ āĻ•āϰ⧁āύ" markAsReadAllTalkMessages: "āϏāĻŽāĻ¸ā§āϤ āĻŽā§‡āϏ⧇āϜ āĻĒāĻ āĻŋāϤ āĻšāĻŋāϏāĻžāĻŦ⧇ āϚāĻŋāĻšā§āύāĻŋāϤ āĻ•āϰ⧁āύ"
help: "āϏāĻšāĻžāϝāĻŧāϤāĻž" help: "āϏāĻšāĻžāϝāĻŧāϤāĻž"
inputMessageHere: "āĻāĻ–āĻžāύ⧇ āĻŽā§‡āϏ⧇āϜ āϞāĻŋāϖ⧁āύ" inputMessageHere: "āĻāĻ–āĻžāύ⧇ āĻŽā§‡āϏ⧇āϜ āϞāĻŋāϖ⧁āύ"
close: "āĻŦāĻ¨ā§āϧ" close: "āĻŦāĻ¨ā§āϧ"
group: "āĻ—ā§āϰ⧁āĻĒ"
groups: "āĻ—ā§āϰ⧁āĻĒāϏāĻŽā§‚āĻš"
createGroup: "āĻ—ā§āϰ⧁āĻĒ āϤ⧈āϰ⧀ āĻ•āϰ⧁āύ"
ownedGroups: "āφāĻĒāύāĻžāϰ āĻ—ā§āϰ⧁āĻĒāϗ⧁āϞāĻŋ"
joinedGroups: "āϝ⧇āϏāĻŦ āĻ—ā§āϰ⧁āĻĒ⧇ āφāĻĒāύāĻŋ āφāϛ⧇āύ"
invites: "āφāĻŽāĻ¨ā§āĻ¤ā§āϰāĻŖ" invites: "āφāĻŽāĻ¨ā§āĻ¤ā§āϰāĻŖ"
groupName: "āĻ—ā§āϰ⧁āĻĒ⧇āϰ āύāĻžāĻŽ"
members: "āϏāĻĻāĻ¸ā§āϝāĻŦ⧃āĻ¨ā§āĻĻ" members: "āϏāĻĻāĻ¸ā§āϝāĻŦ⧃āĻ¨ā§āĻĻ"
transfer: "āĻšāĻ¸ā§āϤāĻžāĻ¨ā§āϤāϰ" transfer: "āĻšāĻ¸ā§āϤāĻžāĻ¨ā§āϤāϰ"
messagingWithUser: "āĻĒā§āϰāĻžāχāϭ⧇āϟ āĻšā§āϝāĻžāϟ"
messagingWithGroup: "āĻ—ā§āϰ⧁āĻĒ āĻšā§āϝāĻžāϟ"
title: "āĻļāĻŋāϰ⧋āύāĻžāĻŽ" title: "āĻļāĻŋāϰ⧋āύāĻžāĻŽ"
text: "āĻĒāĻžāĻ ā§āϝ" text: "āĻĒāĻžāĻ ā§āϝ"
enable: "āϏāĻ•ā§āϰāĻŋ⧟" enable: "āϏāĻ•ā§āϰāĻŋ⧟"
next: "āĻĒāϰāĻŦāĻ°ā§āϤ⧀" next: "āĻĒāϰāĻŦāĻ°ā§āϤ⧀"
retype: "āĻĒ⧁āύāσ āĻĒā§āϰāĻŦ⧇āĻļ" retype: "āĻĒ⧁āύāσ āĻĒā§āϰāĻŦ⧇āĻļ"
noteOf: "{user} āĻāϰ āύ⧋āϟ" noteOf: "{user} āĻāϰ āύ⧋āϟ"
inviteToGroup: "āĻ—ā§āϰ⧁āĻĒ⧇ āφāĻŽāĻ¨ā§āĻ¤ā§āϰāĻŖ āϜāĻžāύāĻžāύ"
quoteAttached: "āωāĻĻā§āϧ⧃āϤ" quoteAttached: "āωāĻĻā§āϧ⧃āϤ"
quoteQuestion: "āωāĻĻā§āϧ⧃āϤāĻŋ āĻšāĻŋāϏāĻžāĻŦ⧇ āϏāĻ‚āϝ⧁āĻ•ā§āϤ āĻ•āϰāĻŦ⧇āύ?" quoteQuestion: "āωāĻĻā§āϧ⧃āϤāĻŋ āĻšāĻŋāϏāĻžāĻŦ⧇ āϏāĻ‚āϝ⧁āĻ•ā§āϤ āĻ•āϰāĻŦ⧇āύ?"
noMessagesYet: "āϕ⧋āύ āĻŽā§‡āϏ⧇āϜ āύ⧇āχ" noMessagesYet: "āϕ⧋āύ āĻŽā§‡āϏ⧇āϜ āύ⧇āχ"
@@ -446,12 +442,19 @@ passwordMatched: "āĻŽāĻŋāϞ⧇āϛ⧇"
passwordNotMatched: "āĻŽāĻŋāϞ⧇āύāĻŋ" passwordNotMatched: "āĻŽāĻŋāϞ⧇āύāĻŋ"
signinWith: "{x} āĻāϰ āϏāĻžāĻšāĻžāĻ¯ā§āϝ⧇ āϏāĻžāχāύ āχāύ āĻ•āϰ⧁āύ" signinWith: "{x} āĻāϰ āϏāĻžāĻšāĻžāĻ¯ā§āϝ⧇ āϏāĻžāχāύ āχāύ āĻ•āϰ⧁āύ"
signinFailed: "āϞāĻ— āχāύ āĻ•āϰāĻž āϝāĻžāϝāĻŧāύāĻŋāĨ¤ āφāĻĒāύāĻžāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āύāĻžāĻŽ āĻāĻŦāĻ‚ āĻĒāĻžāϏāĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āĻšā§‡āĻ• āĻ•āϰ⧁āύ." signinFailed: "āϞāĻ— āχāύ āĻ•āϰāĻž āϝāĻžāϝāĻŧāύāĻŋāĨ¤ āφāĻĒāύāĻžāϰ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āύāĻžāĻŽ āĻāĻŦāĻ‚ āĻĒāĻžāϏāĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āĻšā§‡āĻ• āĻ•āϰ⧁āύ."
tapSecurityKey: "āϏāĻŋāĻ•āĻŋāωāϰāĻŋāϟāĻŋ āϕ⧀ āĻ¸ā§āĻĒāĻ°ā§āĻļ āĻ•āϰ⧁āύ"
or: "āĻ…āĻĨāĻŦāĻž" or: "āĻ…āĻĨāĻŦāĻž"
language: "āĻ­āĻžāώāĻž" language: "āĻ­āĻžāώāĻž"
uiLanguage: "UI āĻāϰ āĻ­āĻžāώāĻž" uiLanguage: "UI āĻāϰ āĻ­āĻžāώāĻž"
groupInvited: "āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ āĻ—ā§āϰ⧁āĻĒ⧇ āφāĻŽāĻ¨ā§āĻ¤ā§āϰāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇āύ"
aboutX: "{x} āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇" aboutX: "{x} āϏāĻŽā§āĻĒāĻ°ā§āϕ⧇"
useOsNativeEmojis: "āĻ…āĻĒāĻžāϰ⧇āϟāĻŋāĻ‚ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽā§‡āϰ āύ⧇āϟāĻŋāĻ­ āχāĻŽā§‹āϜāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ"
disableDrawer: "āĻĄā§āϰāϝāĻŧāĻžāϰ āĻŽā§‡āύ⧁ āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ āĻ•āϰāĻŦ⧇āύ āύāĻž"
youHaveNoGroups: "āφāĻĒāύāĻžāϰ āϕ⧋āύ āĻ—ā§āϰ⧁āĻĒ āύ⧇āχ "
joinOrCreateGroup: "āĻāĻ•āϟāĻŋ āĻŦāĻŋāĻĻā§āϝāĻŽāĻžāύ āĻ—ā§āϰ⧁āĻĒ⧇āϰ āφāĻŽāĻ¨ā§āĻ¤ā§āϰāĻŖ āĻĒāĻžāύ āĻŦāĻž āĻāĻ•āϟāĻŋ āύāϤ⧁āύ āĻ—ā§āϰ⧁āĻĒ āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ⧎"
noHistory: "āϕ⧋āύ⧋ āχāϤāĻŋāĻšāĻžāϏ āύ⧇āχ" noHistory: "āϕ⧋āύ⧋ āχāϤāĻŋāĻšāĻžāϏ āύ⧇āχ"
signinHistory: "āĻĒā§āϰāĻŦ⧇āĻļ āĻ•āϰāĻžāϰ āχāϤāĻŋāĻšāĻžāϏ" signinHistory: "āĻĒā§āϰāĻŦ⧇āĻļ āĻ•āϰāĻžāϰ āχāϤāĻŋāĻšāĻžāϏ"
disableAnimatedMfm: "āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻŸā§‡āĻĄ MFM āĻ…āĻ•ā§āώāĻŽ āĻ•āϰ⧁āύ"
doing: "āĻĒā§āϰāĻ•ā§āϰāĻŋ⧟āĻž āĻ•āϰāϛ⧇..." doing: "āĻĒā§āϰāĻ•ā§āϰāĻŋ⧟āĻž āĻ•āϰāϛ⧇..."
category: "āĻŦāĻŋāĻ­āĻžāĻ—" category: "āĻŦāĻŋāĻ­āĻžāĻ—"
tags: "āĻŸâ€ā§āϝāĻžāĻ—āϏāĻŽā§‚āĻš" tags: "āĻŸâ€ā§āϝāĻžāĻ—āϏāĻŽā§‚āĻš"
@@ -498,7 +501,6 @@ deleteAll: "āϏāĻŦ āĻŽā§āϛ⧁āύ"
showFixedPostForm: "āϟāĻžāχāĻŽāϞāĻžāχāύ⧇āϰ āĻļā§€āĻ°ā§āώ⧇ āĻĒā§‹āĻ¸ā§āϟ āĻ•āϰāĻžāϰ āĻĢāĻ°ā§āĻŽāϟāĻŋ āĻĻ⧇āĻ–āĻžāύ" showFixedPostForm: "āϟāĻžāχāĻŽāϞāĻžāχāύ⧇āϰ āĻļā§€āĻ°ā§āώ⧇ āĻĒā§‹āĻ¸ā§āϟ āĻ•āϰāĻžāϰ āĻĢāĻ°ā§āĻŽāϟāĻŋ āĻĻ⧇āĻ–āĻžāύ"
newNoteRecived: "āύāϤ⧁āύ āύ⧋āϟ āφāϛ⧇" newNoteRecived: "āύāϤ⧁āύ āύ⧋āϟ āφāϛ⧇"
sounds: "āĻļāĻŦā§āĻĻ" sounds: "āĻļāĻŦā§āĻĻ"
sound: "āĻļāĻŦā§āĻĻ"
listen: "āĻļ⧁āύ⧁āύ" listen: "āĻļ⧁āύ⧁āύ"
none: "āĻ•āĻŋāϛ⧁āχ āύāĻž" none: "āĻ•āĻŋāϛ⧁āχ āύāĻž"
showInPage: "āĻĒ⧇āĻœā§‡ āĻĻ⧇āĻ–āĻžāύ" showInPage: "āĻĒ⧇āĻœā§‡ āĻĻ⧇āĻ–āĻžāύ"
@@ -575,6 +577,7 @@ tokenRequested: "āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āĻŸā§‡ āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ
pluginTokenRequestedDescription: "āĻāχ āĻĒā§āϞāĻžāĻ—āχāύāϟāĻŋ āĻāĻ–āĻžāύ⧇ āĻĻ⧇āĻ“ā§ŸāĻž āĻ…āύ⧁āĻŽā§āϤāĻŋāϏāĻŽā§‚āĻš āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇" pluginTokenRequestedDescription: "āĻāχ āĻĒā§āϞāĻžāĻ—āχāύāϟāĻŋ āĻāĻ–āĻžāύ⧇ āĻĻ⧇āĻ“ā§ŸāĻž āĻ…āύ⧁āĻŽā§āϤāĻŋāϏāĻŽā§‚āĻš āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰ āĻ•āϰāĻŦ⧇"
notificationType: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋāϰ āϧāϰāύ" notificationType: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋāϰ āϧāϰāύ"
edit: "āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž" edit: "āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž"
useStarForReactionFallback: "āϰāĻŋāĻ…ā§āϝāĻžāĻ•āĻļāύ⧇āϰ āχāĻŽā§‹āϜāĻŋ āύāĻž āϜāĻžāύāϞ⧇ ★ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧁āύ"
emailServer: "āχāĻŽā§‡āχāϞ āϏāĻžāĻ°ā§āĻ­āĻžāϰ" emailServer: "āχāĻŽā§‡āχāϞ āϏāĻžāĻ°ā§āĻ­āĻžāϰ"
enableEmail: "āχāĻŽā§‡āχāϞ āĻŦāĻŋāϤāϰāĻŖ āϚāĻžāϞ⧁ āĻ•āϰ⧁āύ" enableEmail: "āχāĻŽā§‡āχāϞ āĻŦāĻŋāϤāϰāĻŖ āϚāĻžāϞ⧁ āĻ•āϰ⧁āύ"
emailConfigInfo: "āφāĻĒāύāĻžāϰ āχāĻŽā§‡āϞ āĻ āĻŋāĻ•āĻžāύāĻž āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰāϤ⧇ āĻāĻŦāĻ‚ āφāĻĒāύāĻžāϰ āĻĒāĻžāϏāĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āĻĒ⧁āύāϰāĻžāϝāĻŧ āϏ⧇āϟ āĻ•āϰāϤ⧇ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāϝāĻŧ" emailConfigInfo: "āφāĻĒāύāĻžāϰ āχāĻŽā§‡āϞ āĻ āĻŋāĻ•āĻžāύāĻž āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰāϤ⧇ āĻāĻŦāĻ‚ āφāĻĒāύāĻžāϰ āĻĒāĻžāϏāĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āĻĒ⧁āύāϰāĻžāϝāĻŧ āϏ⧇āϟ āĻ•āϰāϤ⧇ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšāϝāĻŧ"
@@ -623,7 +626,10 @@ abuseReported: "āφāĻĒāύāĻžāϰ āĻ…āĻ­āĻŋāϝ⧋āĻ—āϟāĻŋ āĻĻāĻžāĻ–āĻŋāϞ āĻ•āϰ
reporter: "āĻ…āĻ­āĻŋāϝ⧋āĻ—āĻ•āĻžāϰ⧀" reporter: "āĻ…āĻ­āĻŋāϝ⧋āĻ—āĻ•āĻžāϰ⧀"
reporteeOrigin: "āĻ…āĻ­āĻŋāϝ⧋āĻ—āϟāĻŋāϰ āĻ‰ā§ŽāϏ" reporteeOrigin: "āĻ…āĻ­āĻŋāϝ⧋āĻ—āϟāĻŋāϰ āĻ‰ā§ŽāϏ"
reporterOrigin: "āĻ…āĻ­āĻŋāϝ⧋āĻ—āĻ•āĻžāϰ⧀āϰ āĻ‰ā§ŽāϏ" reporterOrigin: "āĻ…āĻ­āĻŋāϝ⧋āĻ—āĻ•āĻžāϰ⧀āϰ āĻ‰ā§ŽāϏ"
forwardReport: "āϰāĻŋāĻŽā§‹āϟ āχāĻ¨ā§āϏāĻ¤ā§āϝāĻžāĻ¨ā§āϏ⧇ āĻ…āĻ­āĻŋāϝ⧋āĻ—āϟāĻŋ āĻĒāĻžāĻ āĻžāύ"
forwardReportIsAnonymous: "āφāĻĒāύāĻžāϰ āϤāĻĨā§āϝ āϰāĻŋāĻŽā§‹āϟ āχāĻ¨ā§āϏāĻ¤ā§āϝāĻžāĻ¨ā§āϏ⧇ āĻĒāĻžāĻ āĻžāύ⧋ āĻšāĻŦ⧇ āύāĻž āĻāĻŦāĻ‚ āĻāĻ•āϟāĻŋ āĻŦ⧇āύāĻžāĻŽā§€ āϏāĻŋāĻ¸ā§āĻŸā§‡āĻŽ āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āϟ āĻšāĻŋāϏāĻžāĻŦ⧇ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻšāĻŦ⧇āĨ¤"
send: "āĻĒāĻžāĻ āĻžāύ" send: "āĻĒāĻžāĻ āĻžāύ"
abuseMarkAsResolved: "āĻ…āĻ­āĻŋāϝ⧋āĻ—āϟāĻŋāϕ⧇ āϏāĻŽāĻžāϧāĻžāĻ•ā§ƒāϤ āĻšāĻŋāϏāĻžāĻŦ⧇ āϚāĻŋāĻšā§āύāĻŋāϤ āĻ•āϰ⧁āύ"
openInNewTab: "āύāϤ⧁āύ āĻŸā§āϝāĻžāĻŦ⧇ āϖ⧁āϞ⧁āύ" openInNewTab: "āύāϤ⧁āύ āĻŸā§āϝāĻžāĻŦ⧇ āϖ⧁āϞ⧁āύ"
openInSideView: "āϏāĻžāχāĻĄ āĻ­āĻŋāωāϤ⧇ āϖ⧁āϞ⧁āύ" openInSideView: "āϏāĻžāχāĻĄ āĻ­āĻŋāωāϤ⧇ āϖ⧁āϞ⧁āύ"
defaultNavigationBehaviour: "āĻĄāĻŋāĻĢāĻ˛ā§āϟ āύ⧇āĻ­āĻŋāϗ⧇āĻļāύ" defaultNavigationBehaviour: "āĻĄāĻŋāĻĢāĻ˛ā§āϟ āύ⧇āĻ­āĻŋāϗ⧇āĻļāύ"
@@ -639,7 +645,6 @@ createNew: "āύāϤ⧁āύ"
optional: "āĻĒā§āϰāϝāĻŧā§‹āϜāĻ¨ā§€ā§Ÿ āύ⧟" optional: "āĻĒā§āϰāϝāĻŧā§‹āϜāĻ¨ā§€ā§Ÿ āύ⧟"
createNewClip: "āύāϤ⧁āύ āĻ•ā§āϞāĻŋāĻĒ āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ" createNewClip: "āύāϤ⧁āύ āĻ•ā§āϞāĻŋāĻĒ āϤ⧈āϰāĻŋ āĻ•āϰ⧁āύ"
public: "āϏāĻ°ā§āĻŦāϜāύ⧀āύ" public: "āϏāĻ°ā§āĻŦāϜāύ⧀āύ"
private: "āĻŦā§āϝāĻžāĻ•ā§āϤāĻŋāĻ—āϤ"
i18nInfo: "Misskey āĻ¸ā§āĻŦ⧇āĻšā§āĻ›āĻžāϏ⧇āĻŦāĻ•āĻĻ⧇āϰ āĻĻā§āĻŦāĻžāϰāĻž āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āĻ­āĻžāώāĻžāϝāĻŧ āĻ…āύ⧁āĻŦāĻžāĻĻ āĻ•āϰāĻž āĻšāĻšā§āϛ⧇āĨ¤ āφāĻĒāύāĻŋ {link} āĻ āĻ—āĻŋā§Ÿā§‡ āĻ…āύ⧁āĻŦāĻžāĻĻ⧇ āϏāĻšāϝ⧋āĻ—āĻŋāϤāĻž āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤" i18nInfo: "Misskey āĻ¸ā§āĻŦ⧇āĻšā§āĻ›āĻžāϏ⧇āĻŦāĻ•āĻĻ⧇āϰ āĻĻā§āĻŦāĻžāϰāĻž āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āĻ­āĻžāώāĻžāϝāĻŧ āĻ…āύ⧁āĻŦāĻžāĻĻ āĻ•āϰāĻž āĻšāĻšā§āϛ⧇āĨ¤ āφāĻĒāύāĻŋ {link} āĻ āĻ—āĻŋā§Ÿā§‡ āĻ…āύ⧁āĻŦāĻžāĻĻ⧇ āϏāĻšāϝ⧋āĻ—āĻŋāϤāĻž āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤"
manageAccessTokens: "āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āĻŸā§‹āϕ⧇āύ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž āĻ•āϰ⧁āύ" manageAccessTokens: "āĻ…ā§āϝāĻžāĻ•ā§āϏ⧇āϏ āĻŸā§‹āϕ⧇āύ āĻĒāϰāĻŋāϚāĻžāϞāύāĻž āĻ•āϰ⧁āύ"
accountInfo: "āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āĻŸā§‡āϰ āϤāĻĨā§āϝ" accountInfo: "āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āĻŸā§‡āϰ āϤāĻĨā§āϝ"
@@ -807,11 +812,15 @@ makeReactionsPublicDescription: "āφāĻĒāύāĻžāϰ āĻĒā§‚āĻ°ā§āĻŦāĻŦāĻ°ā§āϤ⧀
classic: "āĻ•ā§āϞāĻžāϏāĻŋāĻ•" classic: "āĻ•ā§āϞāĻžāϏāĻŋāĻ•"
muteThread: "āĻĨā§āϰ⧇āĻĄ āĻŽāĻŋāωāϟ āĻ•āϰ⧁āύ" muteThread: "āĻĨā§āϰ⧇āĻĄ āĻŽāĻŋāωāϟ āĻ•āϰ⧁āύ"
unmuteThread: "āĻĨā§āϰ⧇āĻĄ āφāύāĻŽāĻŋāωāϟ āĻ•āϰ⧁āύ" unmuteThread: "āĻĨā§āϰ⧇āĻĄ āφāύāĻŽāĻŋāωāϟ āĻ•āϰ⧁āύ"
ffVisibility: "āĻ…āύ⧁āϏāϰāĻŖ/āĻ…āύ⧁āϏāϰāĻŖāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āĻĻ⧃āĻļā§āϝāĻŽāĻžāĻ¨ā§āϝāϤāĻž"
ffVisibilityDescription: "āφāĻĒāύāĻŋ āĻ•āĻžāϕ⧇ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰ⧇āύ āĻāĻŦāĻ‚ āϕ⧇ āφāĻĒāύāĻžāϕ⧇ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰ⧇, āϏ⧇āϟāĻž āĻ•āĻžāϰāĻž āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻŦ⧇ āϤāĻž āύāĻŋāĻ°ā§āϧāĻžāϰāĻŖ āĻ•āϰ⧇āĨ¤"
continueThread: "āφāϰ⧋ āĻĨā§āϰ⧇āĻĄ āĻĻ⧇āϖ⧁āύ" continueThread: "āφāϰ⧋ āĻĨā§āϰ⧇āĻĄ āĻĻ⧇āϖ⧁āύ"
deleteAccountConfirm: "āφāĻĒāύāĻžāϰ āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āϟ āĻŽā§āϛ⧇ āĻĢ⧇āϞāĻž āĻšāĻŦ⧇āĨ¤ āĻ āĻŋāĻ• āφāϛ⧇?" deleteAccountConfirm: "āφāĻĒāύāĻžāϰ āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āϟ āĻŽā§āϛ⧇ āĻĢ⧇āϞāĻž āĻšāĻŦ⧇āĨ¤ āĻ āĻŋāĻ• āφāϛ⧇?"
incorrectPassword: "āφāĻĒāύāĻžāϰ āĻĻ⧇āĻ“ā§ŸāĻž āĻĒāĻžāϏāĻ“āϝāĻŧāĻžāĻ°ā§āĻĄāϟāĻŋ āϭ⧁āϞāĨ¤" incorrectPassword: "āφāĻĒāύāĻžāϰ āĻĻ⧇āĻ“ā§ŸāĻž āĻĒāĻžāϏāĻ“āϝāĻŧāĻžāĻ°ā§āĻĄāϟāĻŋ āϭ⧁āϞāĨ¤"
voteConfirm: "\"{choice}\" āĻ āĻ­ā§‹āϟ āĻĻāĻŋāϤ⧇ āϚāĻžāύīŧŸ" voteConfirm: "\"{choice}\" āĻ āĻ­ā§‹āϟ āĻĻāĻŋāϤ⧇ āϚāĻžāύīŧŸ"
hide: "āϞ⧁āĻ•āĻžāύ" hide: "āϞ⧁āĻ•āĻžāύ"
leaveGroup: "āĻ—ā§āϰ⧁āĻĒ āĻ›ā§‡ā§œā§‡ āϚāϞ⧇ āϝāĻžāύ"
leaveGroupConfirm: "\"{name}\" āĻ—ā§āϰ⧁āĻĒ āĻ›ā§‡ā§œā§‡ āϚāϞ⧇ āϝ⧇āϤ⧇ āϚāĻžāύ?"
useDrawerReactionPickerForMobile: "āĻŽā§‹āĻŦāĻžāχāϞ⧇ āϰāĻŋāĻ…ā§āϝāĻžāĻ•āĻļāύ āĻĒāĻŋāĻ•āĻžāϰāϕ⧇ āĻĄā§āϰāϝāĻŧāĻžāϰ⧇ āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ āĻ•āϰ⧁āύ" useDrawerReactionPickerForMobile: "āĻŽā§‹āĻŦāĻžāχāϞ⧇ āϰāĻŋāĻ…ā§āϝāĻžāĻ•āĻļāύ āĻĒāĻŋāĻ•āĻžāϰāϕ⧇ āĻĄā§āϰāϝāĻŧāĻžāϰ⧇ āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ āĻ•āϰ⧁āύ"
welcomeBackWithName: "āφāĻŦāĻžāϰ āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ, {name}" welcomeBackWithName: "āφāĻŦāĻžāϰ āĻ¸ā§āĻŦāĻžāĻ—āϤāĻŽ, {name}"
clickToFinishEmailVerification: " [{ok}] āĻ•ā§āϞāĻŋāĻ• āĻ•āϰāĻžāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āφāĻĒāύāĻžāϰ āχāĻŽā§‡āϞ āĻ āĻŋāĻ•āĻžāύāĻž āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύāĨ¤" clickToFinishEmailVerification: " [{ok}] āĻ•ā§āϞāĻŋāĻ• āĻ•āϰāĻžāϰ āĻŽāĻžāĻ§ā§āϝāĻŽā§‡ āφāĻĒāύāĻžāϰ āχāĻŽā§‡āϞ āĻ āĻŋāĻ•āĻžāύāĻž āύāĻŋāĻļā§āϚāĻŋāϤ āĻ•āϰ⧁āύāĨ¤"
@@ -827,7 +836,6 @@ instanceDefaultLightTheme: "āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ⧇āϰ āĻĄāĻŋāĻĢāϞ
instanceDefaultDarkTheme: "āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ⧇āϰ āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻĄāĻžāĻ°ā§āĻ• āĻĨāĻŋāĻŽ" instanceDefaultDarkTheme: "āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ⧇āϰ āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻĄāĻžāĻ°ā§āĻ• āĻĨāĻŋāĻŽ"
instanceDefaultThemeDescription: "āĻ…āĻŦāĻœā§‡āĻ•ā§āϟ āĻĢāϰāĻŽā§āϝāĻžāĻŸā§‡ āĻĨāĻŋāĻŽ āϕ⧋āĻĄ āϞāĻŋāϖ⧁āύ" instanceDefaultThemeDescription: "āĻ…āĻŦāĻœā§‡āĻ•ā§āϟ āĻĢāϰāĻŽā§āϝāĻžāĻŸā§‡ āĻĨāĻŋāĻŽ āϕ⧋āĻĄ āϞāĻŋāϖ⧁āύ"
mutePeriod: "āĻŽāĻŋāωāĻŸā§‡āϰ āϏāĻŽā§ŸāĻ•āĻžāϞ" mutePeriod: "āĻŽāĻŋāωāĻŸā§‡āϰ āϏāĻŽā§ŸāĻ•āĻžāϞ"
period: "āĻĒā§‹āϞ⧇āϰ āϏāĻŽāϝāĻŧāϏ⧀āĻŽāĻž"
indefinitely: "āĻ…āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ" indefinitely: "āĻ…āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ"
tenMinutes: "ā§§ā§Ļ āĻŽāĻŋāύāĻŋāϟ" tenMinutes: "ā§§ā§Ļ āĻŽāĻŋāύāĻŋāϟ"
oneHour: "ā§§ āϘāĻŖā§āϟāĻž" oneHour: "ā§§ āϘāĻŖā§āϟāĻž"
@@ -842,26 +850,6 @@ colored: "āϰāĻ™ā§āĻ—āĻŋāύ"
label: "āϞ⧇āĻŦ⧇āϞ" label: "āϞ⧇āĻŦ⧇āϞ"
localOnly: "āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āϞ⧋āĻ•āĻžāϞ" localOnly: "āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āϞ⧋āĻ•āĻžāϞ"
account: "āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āϟāϗ⧁āϞāĻŋ" account: "āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āϟāϗ⧁āϞāĻŋ"
like: "āĻĒāĻ›āĻ¨ā§āĻĻ āĻ•āϰāĻž"
show: "āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ"
color: "āϰāĻ‚"
horizontal: "āĻĒāĻžāĻļ⧇"
youFollowing: "āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāĻž āĻšāĻšā§āϛ⧇"
icon: "āĻĒā§āϰ⧋āĻĢāĻžāχāϞ āĻ›āĻŦāĻŋ"
replies: "āϜāĻŦāĻžāĻŦ"
renotes: "āϰāĻŋāύ⧋āϟ"
sourceCode: "āϏ⧋āĻ°ā§āϏ āϕ⧋āĻĄ"
flip: "āωāĻ˛ā§āϟāĻžāύ"
_delivery:
stop: "āĻ¸ā§āĻĨāĻ—āĻŋāϤ āĻ•āϰāĻž āĻšā§Ÿā§‡āϛ⧇"
_type:
none: "āĻĒā§āϰāĻ•āĻžāĻļ āĻ•āϰāĻž āĻšāĻšā§āϛ⧇"
_role:
priority: "āĻ…āĻ—ā§āϰāĻžāϧāĻŋāĻ•āĻžāϰ"
_priority:
low: "āύāĻŋāĻŽā§āύ"
middle: "āĻŽāĻžāĻāĻžāϰāĻŋ"
high: "āωāĻšā§āϚ"
_emailUnavailable: _emailUnavailable:
used: "āĻāχ āχāĻŽā§‡āχāϞ āĻ āĻŋāĻ•āĻžāύāĻžāϟāĻŋ āχāϤ⧋āĻŽāĻ§ā§āϝ⧇ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšā§Ÿā§‡āϛ⧇" used: "āĻāχ āχāĻŽā§‡āχāϞ āĻ āĻŋāĻ•āĻžāύāĻžāϟāĻŋ āχāϤ⧋āĻŽāĻ§ā§āϝ⧇ āĻŦā§āϝāĻŦāĻšā§ƒāϤ āĻšā§Ÿā§‡āϛ⧇"
format: "āĻāχ āχāĻŽā§‡āϞ āĻ āĻŋāĻ•āĻžāύāĻžāϟāĻŋ āϏāĻ āĻŋāĻ•āĻ­āĻžāĻŦ⧇ āϞāĻŋāĻ–āĻž āĻšā§ŸāύāĻŋ" format: "āĻāχ āχāĻŽā§‡āϞ āĻ āĻŋāĻ•āĻžāύāĻžāϟāĻŋ āϏāĻ āĻŋāĻ•āĻ­āĻžāĻŦ⧇ āϞāĻŋāĻ–āĻž āĻšā§ŸāύāĻŋ"
@@ -886,7 +874,6 @@ _accountDelete:
_ad: _ad:
back: "āĻĒāĻŋāĻ›āύ⧇" back: "āĻĒāĻŋāĻ›āύ⧇"
reduceFrequencyOfThisAd: "āĻāχ āĻŦāĻŋāĻœā§āĻžāĻžāĻĒāύāϟāĻŋ āĻ•āĻŽ āĻĻ⧇āĻ–āĻžāύ" reduceFrequencyOfThisAd: "āĻāχ āĻŦāĻŋāĻœā§āĻžāĻžāĻĒāύāϟāĻŋ āĻ•āĻŽ āĻĻ⧇āĻ–āĻžāύ"
hide: "āĻĻ⧇āĻ–āĻžāĻŦ⧇āύ āύāĻž"
_forgotPassword: _forgotPassword:
enterEmail: "āφāĻĒāύāĻŋ āφāĻĒāύāĻžāϰ āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āĻŸā§‡āϰ āϜāĻ¨ā§āϝ āύāĻŋāĻŦāĻ¨ā§āϧāĻŋāϤ āχāĻŽā§‡āϞ āĻ āĻŋāĻ•āĻžāύāĻž āϞāĻŋāϖ⧁āύ. āϏ⧇āχ āĻ āĻŋāĻ•āĻžāύāĻžāϝāĻŧ āĻāĻ•āϟāĻŋ āĻĒāĻžāϏāĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āϰāĻŋāϏ⧇āϟ āϞāĻŋāĻ™ā§āĻ• āĻĒāĻžāĻ āĻžāύ⧋ āĻšāĻŦ⧇āĨ¤" enterEmail: "āφāĻĒāύāĻŋ āφāĻĒāύāĻžāϰ āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āĻŸā§‡āϰ āϜāĻ¨ā§āϝ āύāĻŋāĻŦāĻ¨ā§āϧāĻŋāϤ āχāĻŽā§‡āϞ āĻ āĻŋāĻ•āĻžāύāĻž āϞāĻŋāϖ⧁āύ. āϏ⧇āχ āĻ āĻŋāĻ•āĻžāύāĻžāϝāĻŧ āĻāĻ•āϟāĻŋ āĻĒāĻžāϏāĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āϰāĻŋāϏ⧇āϟ āϞāĻŋāĻ™ā§āĻ• āĻĒāĻžāĻ āĻžāύ⧋ āĻšāĻŦ⧇āĨ¤"
ifNoEmail: "āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āύāĻŋāĻŦāĻ¨ā§āϧāύ⧇āϰ āϏāĻŽā§Ÿ āχ-āĻŽā§‡āχāϞ āĻ āĻŋāĻ•āĻžāύāĻž āύāĻž āĻĻāĻŋā§Ÿā§‡ āĻĨāĻžāϕ⧇āύ, āϤāĻžāĻšāϞ⧇ āĻ…āύ⧁āĻ—ā§āϰāĻš āĻ•āϰ⧇ āĻĒā§āϰāĻļāĻžāϏāϕ⧇āϰ āϏāĻžāĻĨ⧇ āϝ⧋āĻ—āĻžāϝ⧋āĻ— āĻ•āϰ⧁āύāĨ¤" ifNoEmail: "āφāĻĒāύāĻŋ āϝāĻĻāĻŋ āύāĻŋāĻŦāĻ¨ā§āϧāύ⧇āϰ āϏāĻŽā§Ÿ āχ-āĻŽā§‡āχāϞ āĻ āĻŋāĻ•āĻžāύāĻž āύāĻž āĻĻāĻŋā§Ÿā§‡ āĻĨāĻžāϕ⧇āύ, āϤāĻžāĻšāϞ⧇ āĻ…āύ⧁āĻ—ā§āϰāĻš āĻ•āϰ⧇ āĻĒā§āϰāĻļāĻžāϏāϕ⧇āϰ āϏāĻžāĻĨ⧇ āϝ⧋āĻ—āĻžāϝ⧋āĻ— āĻ•āϰ⧁āύāĨ¤"
@@ -905,7 +892,6 @@ _plugin:
install: "āĻĒā§āϞāĻžāĻ—āχāύ āχāĻ¨ā§āϏāϟāϞ āĻ•āϰ⧁āύ" install: "āĻĒā§āϞāĻžāĻ—āχāύ āχāĻ¨ā§āϏāϟāϞ āĻ•āϰ⧁āύ"
installWarn: "āĻ…āĻŦāĻŋāĻļā§āĻŦāĻ¸ā§āϤ āĻĒā§āϞāĻžāĻ—āχāύ āχāύāĻ¸ā§āϟāϞ āĻ•āϰāĻŦ⧇āύ āύāĻžāĨ¤" installWarn: "āĻ…āĻŦāĻŋāĻļā§āĻŦāĻ¸ā§āϤ āĻĒā§āϞāĻžāĻ—āχāύ āχāύāĻ¸ā§āϟāϞ āĻ•āϰāĻŦ⧇āύ āύāĻžāĨ¤"
manage: "āĻĒā§āϞāĻžāĻ—āχāύ āĻŽā§āϝāĻžāύ⧇āϜ āĻ•āϰ⧁āύ" manage: "āĻĒā§āϞāĻžāĻ—āχāύ āĻŽā§āϝāĻžāύ⧇āϜ āĻ•āϰ⧁āύ"
viewSource: "āĻ‰ā§ŽāϏ āĻĻ⧇āϖ⧁āύ"
_registry: _registry:
scope: "āĻ¸ā§āϕ⧋āĻĒ" scope: "āĻ¸ā§āϕ⧋āĻĒ"
key: "āϕ⧀" key: "āϕ⧀"
@@ -921,6 +907,74 @@ _aboutMisskey:
donate: "Misskey āϤ⧇ āĻĻāĻžāύ āĻ•āϰ⧁āύ" donate: "Misskey āϤ⧇ āĻĻāĻžāύ āĻ•āϰ⧁āύ"
morePatrons: "āφāϰāĻ“ āĻ…āύ⧇āϕ⧇ āφāĻŽāĻžāĻĻ⧇āϰ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰāϛ⧇āύāĨ¤ āϤāĻžāĻĻ⧇āϰ āϏāĻŦāĻžāχāϕ⧇ āϧāĻ¨ā§āϝāĻŦāĻžāĻĻ đŸĨ°" morePatrons: "āφāϰāĻ“ āĻ…āύ⧇āϕ⧇ āφāĻŽāĻžāĻĻ⧇āϰ āϏāĻžāĻšāĻžāĻ¯ā§āϝ āĻ•āϰāϛ⧇āύāĨ¤ āϤāĻžāĻĻ⧇āϰ āϏāĻŦāĻžāχāϕ⧇ āϧāĻ¨ā§āϝāĻŦāĻžāĻĻ đŸĨ°"
patrons: "āϏāĻŽāĻ°ā§āĻĨāύāĻ•āĻžāϰ⧀" patrons: "āϏāĻŽāĻ°ā§āĻĨāύāĻ•āĻžāϰ⧀"
_nsfw:
respect: "āĻ¸ā§āĻĒāĻ°ā§āĻļāĻ•āĻžāϤāϰ āĻŽāĻŋāĻĄāĻŋ⧟āĻž āϞ⧁āĻ•āĻžāύ"
ignore: "āĻ¸ā§āĻĒāĻ°ā§āĻļāĻ•āĻžāϤāϰ āĻŽāĻŋāĻĄāĻŋ⧟āĻž āϞ⧁āĻ•āĻžāĻŦ⧇āύ āύāĻž"
force: "āϏāĻ•āϞ āĻŽāĻŋāĻĄāĻŋ⧟āĻž āϞ⧁āĻ•āĻžāύ"
_mfm:
cheatSheet: "MFM āϚāĻŋāϟāĻļāĻŋāϟ"
intro: "MFM āĻāĻ•āϟāĻŋ āĻŽāĻžāĻ°ā§āĻ•āφāĻĒ āĻ­āĻžāώāĻž āϝāĻž Misskey-āĻāϰ āĻŽāĻ§ā§āϝ⧇ āĻŦāĻŋāĻ­āĻŋāĻ¨ā§āύ āϜāĻžāϝāĻŧāĻ—āĻžāϝāĻŧ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝ⧇āϤ⧇ āĻĒāĻžāϰ⧇āĨ¤ āĻāĻ–āĻžāύ⧇ āφāĻĒāύāĻŋ MFM-āĻāϰ āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏāϗ⧁āϞāĻŋāϰ āĻāĻ•āϟāĻŋ āϤāĻžāϞāĻŋāĻ•āĻž āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāϰāĻŦ⧇āύāĨ¤"
dummy: "āĻŽāĻŋāϏāĻ•āĻŋ āĻĢ⧇āĻĄāĻŋāĻ­āĻžāĻ°ā§āϏ⧇āϰ āĻŦāĻŋāĻļā§āĻŦāϕ⧇ āĻĒā§āϰāϏāĻžāϰāĻŋāϤ āĻ•āϰ⧇"
mention: "āωāĻ˛ā§āϞ⧇āĻ–"
mentionDescription: "@ āϚāĻŋāĻšā§āύ + āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āύāĻžāĻŽ āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϕ⧇ āύāĻŋāĻ°ā§āĻĻ⧇āĻļ āĻ•āϰāϤ⧇ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāĻž āϝāĻžā§ŸāĨ¤"
hashtag: "āĻšā§āϝāĻžāĻļāĻŸā§āϝāĻžāĻ—"
hashtagDescription: "āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ # āϚāĻŋāĻšā§āύ + āĻŸā§āϝāĻžāĻ— āϏāĻš āĻāĻ•āϟāĻŋ āĻšā§āϝāĻžāĻļāĻŸā§āϝāĻžāĻ— āύāĻŋāĻ°ā§āĻĻ⧇āĻļ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤"
url: "URL"
urlDescription: "URL āĻĻ⧇āĻ–āĻžāύ⧋ āϏāĻŽā§āĻ­āĻŦāĨ¤"
link: "āϞāĻŋāĻ‚āĻ•"
linkDescription: "āφāĻĒāύāĻŋ āĻĒāĻžāĻ ā§āϝ⧇āϰ āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ…āĻ‚āĻļāϕ⧇ URL āĻšāĻŋāϏāĻžāĻŦ⧇ āĻĻ⧇āĻ–āĻžāϤ⧇ āĻĒāĻžāϰ⧇āύ⧎"
bold: "āĻ—āĻžā§"
boldDescription: "āĻ…āĻ•ā§āώāϰāϗ⧁āϞāĻŋāϕ⧇ āĻŽā§‹āϟāĻžāĻ•āϰ⧇ āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ āĻ•āϰāĻž āĻšāĻŦ⧇āĨ¤"
small: "āϛ⧋āϟ"
smallDescription: "āϞ⧇āĻ–āĻž āϛ⧋āϟ āĻāĻŦāĻ‚ āĻĒāĻžāϤāϞāĻž āĻ•āϰ⧇ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāĻŦ⧇āĨ¤"
center: "āϏ⧇āĻ¨ā§āϟāĻžāϰ"
centerDescription: "āϞ⧇āĻ–āĻž āĻŽāĻžāĻ āĻŦāϰāĻžāĻŦāϰ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāĻŦ⧇"
inlineCode: "āϕ⧋āĻĄ (āχāύāϞāĻžāχāύ)"
inlineCodeDescription: " āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽā§‡āϰ āϕ⧋āĻĄā§‡āϰ āϜāĻ¨ā§āϝ āχāύāϞāĻžāχāύ āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ āĻšāĻžāχāϞāĻžāχāϟāĻŋāĻ‚ āĻ•āϰāĻž āĻšāĻŦ⧇"
blockCode: "āϕ⧋āĻĄ (āĻŦā§āϞāĻ•)"
blockCodeDescription: "āĻŽāĻžāĻ˛ā§āϟāĻŋ-āϞāĻžāχāύ āĻĒā§āϰ⧋āĻ—ā§āϰāĻžāĻŽā§‡āϰ āϕ⧋āĻĄā§‡āϰ āϜāĻ¨ā§āϝ āϏāĻŋāύāĻŸā§āϝāĻžāĻ•ā§āϏ āĻšāĻžāχāϞāĻžāχāϟ āĻ•āϰ⧇āĨ¤"
inlineMath: "āĻ—āĻžāĻŖāĻŋāϤāĻŋāĻ• āϏ⧂āĻ¤ā§āϰ (āχāύāϞāĻžāχāύ)"
inlineMathDescription: "āĻ—āĻžāĻŖāĻŋāϤāĻŋāĻ• āϏ⧂āĻ¤ā§āϰ āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ āĻ•āϰ⧁āύ (KaTeX) āχāύāϞāĻžāχāύāĨ¤"
blockMath: "āĻ—āĻžāĻŖāĻŋāϤāĻŋāĻ• āϏ⧂āĻ¤ā§āϰ (āĻŦā§āϞāĻ•)"
blockMathDescription: "āĻāĻ•āϟāĻŋ āĻŦā§āϞāϕ⧇ āĻāĻ•āĻžāϧāĻŋāĻ• āϞāĻžāχāύ⧇āϰ āĻ—āĻžāĻŖāĻŋāϤāĻŋāĻ• āϏ⧂āĻ¤ā§āϰ āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ āĻ•āϰ⧁āύ (KaTeX)āĨ¤"
quote: "āωāĻĻā§āϧ⧃āϤāĻŋ"
quoteDescription: "āĻŦāĻŋāώāϝāĻŧāĻŦāĻ¸ā§āϤ⧁āϕ⧇ āĻāĻ•āϟāĻŋ āωāĻĻā§āϧ⧃āϤāĻŋ āĻšāĻŋāϏāĻžāĻŦ⧇ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāĻŦ⧇āĨ¤"
emoji: "āĻ¸ā§āĻŦāύāĻŋāĻ°ā§āϧāĻžāϰāĻŋāϤ āχāĻŽā§‹āϜāĻŋāϗ⧁āϞāĻŋ"
emojiDescription: "āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ āĻ•āĻžāĻ¸ā§āϟāĻŽ āχāĻŽā§‹āϜāĻŋāϰ āύāĻžāĻŽ āϕ⧋āϞāύ⧇ āφāĻŦāĻĻā§āϧ āĻ•āϰ⧇ āĻ•āĻžāĻ¸ā§āϟāĻŽ āχāĻŽā§‹āϜāĻŋāϟāĻŋ āĻĻ⧇āĻ–āĻžāϤ⧇ āĻĒāĻžāϰ⧇āύ⧎"
search: "āϖ⧁āρāϜ⧁āύ"
searchDescription: "āĻĒā§‚āĻ°ā§āĻŦ-āϟāĻžāχāĻĒ āĻ•āϰāĻž āĻĒāĻžāĻ ā§āϝ āϏāĻš āĻāĻ•āϟāĻŋ āĻ…āύ⧁āϏāĻ¨ā§āϧāĻžāύ āĻŦāĻžāĻ•ā§āϏ āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ āĻ•āϰ⧇āĨ¤"
flip: "āωāĻ˛ā§āϟāĻžāύ"
flipDescription: "āĻŦāĻŋāώāϝāĻŧāĻŦāĻ¸ā§āϤ⧁ āωāĻĒāϰ⧇/āύ⧀āĻšā§‡ āĻŦāĻž āĻŦāĻžāĻŽ/āĻĄāĻžāύ⧇ āωāĻ˛ā§āϟāĻžāύāĨ¤"
jelly: "āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ (āĻœā§‡āϞāĻŋ)"
jellyDescription: "āĻœā§‡āϞāĻŋāϰ āĻŽāϤ āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ āĻĻ⧇āĻ–āĻžā§ŸāĨ¤"
tada: "āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ (āϟāĻžāĻĄāĻž)"
tadaDescription: "\"āϟāĻžāĻĄāĻž!\" āĻāϰ āĻŽāϤ āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ āĻĻ⧇āĻ–āĻžā§ŸāĨ¤"
jump: "āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ (āϞāĻžāĻĢ)"
jumpDescription: "āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁āϤ⧇ āϞāĻžāĻĢ āĻŽāĻžāϰāĻžāϰ āĻŽāϤ āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ āĻĻ⧇āĻ–āĻžā§ŸāĨ¤"
bounce: "āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ (āϤāĻŋ⧜āĻŋāĻ‚ āĻŦāĻŋ⧜āĻŋāĻ‚)"
bounceDescription: "āϤāĻŋ⧜āĻŋāĻ‚ āĻŦāĻŋ⧜āĻŋāĻ‚ āĻ•āϰāĻžāϰ āĻŽāϤ āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ āĻĻ⧇āĻ–āĻžā§ŸāĨ¤"
shake: "āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ (āĻāĻžāρāĻ•āĻŋ)"
shakeDescription: "āĻāĻžāρāĻ•āĻŋāϰ āĻŽāϤ āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ āĻĻ⧇āĻ–āĻžā§ŸāĨ¤"
twitch: "āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ (āĻŽā§‹āϚāĻĄāĻŧāĻžāύ⧋)"
twitchDescription: "āĻŽā§‹āϚāĻĄāĻŧāĻžāύ⧋āϰ āĻŽāϤ āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ āĻĻ⧇āĻ–āĻžā§ŸāĨ¤"
spin: "āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ (āϘ⧁āϰāĻž)"
spinDescription: "āϘ⧁āϰāĻžāϰ āĻŽāϤ āĻ…ā§āϝāĻžāύāĻŋāĻŽā§‡āĻļāύ āĻĻ⧇āĻ–āĻžā§ŸāĨ¤"
x2: "āĻŦ⧜"
x2Description: "āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁ āĻŦ⧜ āĻ•āϰ⧇ āĻĻ⧇āĻ–āĻžā§ŸāĨ¤"
x3: "āĻ…āύ⧇āĻ• āĻŦ⧜"
x3Description: "āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁ āφāϰāĻ“ āĻŦ⧜ āĻ•āϰ⧇ āĻĻ⧇āĻ–āĻžā§ŸāĨ¤"
x4: "āĻ…āĻ¸ā§āĻŦāĻžāĻ­āĻžāĻŦāĻŋāĻ• āĻŦ⧜"
x4Description: "āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁āϕ⧇ āφāϗ⧇āϰ āĻĨ⧇āϕ⧇āĻ“ āφāϰāĻ“ āĻŦ⧜ āĻ•āϰ⧇ āĻĻ⧇āĻ–āĻžā§ŸāĨ¤"
blur: "āĻŦā§āϞāĻžāϰ"
blurDescription: "āĻŦāĻŋāώāϝāĻŧāĻŦāĻ¸ā§āϤ⧁āϕ⧇ āĻŦā§āϞāĻžāϰ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύāĨ¤ āφāĻĒāύāĻŋ āĻāϰ āωāĻĒāϰ āĻŽāĻžāωāϏ āĻ•āĻžāĻ°ā§āϏāĻžāϰ āϰāĻžāĻ–āϞ⧇, āĻāϟāĻŋ āĻĒāϰāĻŋāĻˇā§āĻ•āĻžāϰāĻ­āĻžāĻŦ⧇ āĻĻ⧇āĻ–āϤ⧇ āĻĒāĻžāĻŦ⧇āύāĨ¤"
font: "āĻĢāĻ¨ā§āϟ"
fontDescription: "āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁āϕ⧇ āϕ⧋āύ āĻĢāĻ¨ā§āĻŸā§‡ āĻĻ⧇āĻ–āĻžāύ⧋ āĻšāĻŦ⧇ āϤāĻž āύāĻŋāĻ°ā§āϧāĻžāϰāĻŖ āĻ•āϰ⧇āĨ¤"
rainbow: "āϰ⧇āχāύāĻŦā§‹"
rainbowDescription: "āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁āϕ⧇ āϰāĻ‚āϧāύ⧁āϰ āϰāĻ‚ āϗ⧁āϞāĻŋāϤ⧇ āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ āĻ•āϰ⧇āĨ¤"
sparkle: "āϚāĻŋāĻ• āϚāĻŋāĻ•"
sparkleDescription: "āĻŦāĻŋāώāϝāĻŧāĻŦāĻ¸ā§āϤ⧁āϕ⧇ āĻāĻ•āϟāĻŋ āϚāĻŋāĻ•āϚāĻŋāϕ⧇ āĻ•āĻŖāĻž āĻĒā§āϰāĻ­āĻžāĻŦ āĻĻ⧇āϝāĻŧāĨ¤"
rotate: "āϘ⧁āϰāĻžāύ"
rotateDescription: "āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁āϕ⧇ āĻāĻ•āϟāĻŋ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϕ⧋āύ⧇ āϘ⧁āϰāĻžā§ŸāĨ¤"
_instanceTicker: _instanceTicker:
none: "āĻĻ⧇āĻ–āĻžāĻŦ⧇āύ āύāĻž" none: "āĻĻ⧇āĻ–āĻžāĻŦ⧇āύ āύāĻž"
remote: "āϰāĻŋāĻŽā§‹āϟ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āϜāĻ¨ā§āϝ āĻĻ⧇āĻ–āĻžāύ" remote: "āϰāĻŋāĻŽā§‹āϟ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āϜāĻ¨ā§āϝ āĻĻ⧇āĻ–āĻžāύ"
@@ -948,6 +1002,11 @@ _wordMute:
muteWords: "āύāĻŋāσāĻļāĻŦā§āĻĻ āĻ•āϰāĻž āĻļāĻŦā§āĻĻāϗ⧁āϞāĻŋ" muteWords: "āύāĻŋāσāĻļāĻŦā§āĻĻ āĻ•āϰāĻž āĻļāĻŦā§āĻĻāϗ⧁āϞāĻŋ"
muteWordsDescription: "āĻ¸ā§āĻĒ⧇āϏ āĻĻāĻŋāϝāĻŧ⧇ āφāϞāĻžāĻĻāĻž āĻ•āϰāϞ⧇ AND āĻļāĻ°ā§āϤ āϤ⧈āϰāĻŋ āĻšāĻŦ⧇ āĻāĻŦāĻ‚ āφāϞāĻžāĻĻāĻž āϞāĻžāχāύ⧇ āϞāĻŋāĻ–āϞ⧇ OR āĻļāĻ°ā§āϤ āϤ⧈āϰāĻŋ āĻšāĻŦ⧇āĨ¤" muteWordsDescription: "āĻ¸ā§āĻĒ⧇āϏ āĻĻāĻŋāϝāĻŧ⧇ āφāϞāĻžāĻĻāĻž āĻ•āϰāϞ⧇ AND āĻļāĻ°ā§āϤ āϤ⧈āϰāĻŋ āĻšāĻŦ⧇ āĻāĻŦāĻ‚ āφāϞāĻžāĻĻāĻž āϞāĻžāχāύ⧇ āϞāĻŋāĻ–āϞ⧇ OR āĻļāĻ°ā§āϤ āϤ⧈āϰāĻŋ āĻšāĻŦ⧇āĨ¤"
muteWordsDescription2: "āϰ⧇āϗ⧁āϞāĻžāϰ āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻ¸ā§āĻ˛ā§āϝāĻžāĻļ āĻĻāĻŋāϝāĻŧ⧇ āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄāϕ⧇ āϘāĻŋāϰ⧇ āϰāĻžāϖ⧁āύāĨ¤" muteWordsDescription2: "āϰ⧇āϗ⧁āϞāĻžāϰ āĻāĻ•ā§āϏāĻĒā§āϰ⧇āĻļāύ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰāϤ⧇ āĻ¸ā§āĻ˛ā§āϝāĻžāĻļ āĻĻāĻŋāϝāĻŧ⧇ āϕ⧀āĻ“āϝāĻŧāĻžāĻ°ā§āĻĄāϕ⧇ āϘāĻŋāϰ⧇ āϰāĻžāϖ⧁āύāĨ¤"
softDescription: "āϟāĻžāχāĻŽāϞāĻžāχāύ āĻĨ⧇āϕ⧇ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻļāĻ°ā§āϤāĻžāύ⧁āϝāĻžā§Ÿā§€ āύ⧋āϟ āϞ⧁āĻ•āĻŋāϝāĻŧ⧇ āϰāĻžāϖ⧇āĨ¤"
hardDescription: "āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻļāĻ°ā§āϤāĻžāύ⧁āϝāĻžā§Ÿā§€ āύ⧋āϟāϗ⧁āϞāĻŋāϕ⧇ āϟāĻžāχāĻŽāϞāĻžāχāύ āĻĨ⧇āϕ⧇ āĻŦāĻžāĻĻ āĻĻā§‡ā§ŸāĨ¤ āφāĻĒāύāĻŋ āĻļāĻ°ā§āϤ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰāϞ⧇āĻ“ āϝ⧇ āύ⧋āϟāϗ⧁āϞāĻŋ āϝ⧋āĻ— āĻ•āϰāĻž āĻšāϝāĻŧāύāĻŋ āϏ⧇āϗ⧁āϞāĻŋ āĻŦāĻžāĻĻ āĻĻ⧇āĻ“āϝāĻŧāĻž āĻšāĻŦ⧇āĨ¤"
soft: "āύāĻŽāĻ¨ā§€ā§Ÿ"
hard: "āĻ•āĻ ā§‹āϰ"
mutedNotes: "āĻŽāĻŋāωāϟ āĻ•āϰāĻž āύ⧋āϟāϗ⧁āϞāĻŋ"
_instanceMute: _instanceMute:
instanceMuteDescription: "āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ āĻ•āϰāĻž āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ⧇āϰ āϏāĻŦ āύ⧋āϟ āĻāĻŦāĻ‚ āϰāĻŋāύ⧋āϟ āĻŽāĻŋāωāϟ āĻ•āϰ⧁āύ, āĻŽāĻŋāωāϟ āĻ•āϰāĻž āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ⧇āϰ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āωāĻ¤ā§āϤāϰ āϏāĻšāĨ¤" instanceMuteDescription: "āĻ•āύāĻĢāĻŋāĻ—āĻžāϰ āĻ•āϰāĻž āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ⧇āϰ āϏāĻŦ āύ⧋āϟ āĻāĻŦāĻ‚ āϰāĻŋāύ⧋āϟ āĻŽāĻŋāωāϟ āĻ•āϰ⧁āύ, āĻŽāĻŋāωāϟ āĻ•āϰāĻž āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ⧇āϰ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āωāĻ¤ā§āϤāϰ āϏāĻšāĨ¤"
instanceMuteDescription2: "āĻĒā§āϰāϤāĻŋāϟāĻŋāϕ⧇ āφāϞāĻžāĻĻāĻž āϞāĻžāχāύ⧇ āϞāĻŋāϖ⧁āύ" instanceMuteDescription2: "āĻĒā§āϰāϤāĻŋāϟāĻŋāϕ⧇ āφāϞāĻžāĻĻāĻž āϞāĻžāχāύ⧇ āϞāĻŋāϖ⧁āύ"
@@ -1011,11 +1070,15 @@ _theme:
infoFg: "āϤāĻĨā§āϝ⧇āϰ āĻĒāĻžāĻ ā§āϝ" infoFg: "āϤāĻĨā§āϝ⧇āϰ āĻĒāĻžāĻ ā§āϝ"
infoWarnBg: "āĻ“ā§ŸāĻžāĻ°ā§āύāĻŋāĻ‚ āĻāϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ" infoWarnBg: "āĻ“ā§ŸāĻžāĻ°ā§āύāĻŋāĻ‚ āĻāϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ"
infoWarnFg: "āĻ“ā§ŸāĻžāĻ°ā§āύāĻŋāĻ‚ āĻāϰ āĻĒāĻžāĻ ā§āϝ" infoWarnFg: "āĻ“ā§ŸāĻžāĻ°ā§āύāĻŋāĻ‚ āĻāϰ āĻĒāĻžāĻ ā§āϝ"
cwBg: "CW āĻŦāĻžāϟāύ⧇āϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ"
cwFg: "CW āĻŦāĻžāϟāύ⧇āϰ āĻĒāĻžāĻ ā§āϝ"
cwHoverBg: "CW āĻŦāĻžāϟāύ⧇āϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ (āĻšāĻ­āĻžāϰ)"
toastBg: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋāϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ" toastBg: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋāϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ"
toastFg: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋāϰ āĻĒāĻžāĻ ā§āϝ" toastFg: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋāϰ āĻĒāĻžāĻ ā§āϝ"
buttonBg: "āĻŦāĻžāϟāύ⧇āϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ" buttonBg: "āĻŦāĻžāϟāύ⧇āϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ"
buttonHoverBg: "āĻŦāĻžāϟāύ⧇āϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ (āĻšāĻ­āĻžāϰ)" buttonHoverBg: "āĻŦāĻžāϟāύ⧇āϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ (āĻšāĻ­āĻžāϰ)"
inputBorder: "āχāύāĻĒ⧁āϟ āĻĢāĻŋāĻ˛ā§āĻĄā§‡āϰ āĻŦāĻ°ā§āĻĄāĻžāϰ" inputBorder: "āχāύāĻĒ⧁āϟ āĻĢāĻŋāĻ˛ā§āĻĄā§‡āϰ āĻŦāĻ°ā§āĻĄāĻžāϰ"
listItemHoverBg: "āϞāĻŋāĻ¸ā§āϟ āφāχāĻŸā§‡āĻŽā§‡āϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ (āĻšā§‹āĻ­āĻžāϰ)"
driveFolderBg: "āĻĄā§āϰāĻžāχāĻ­ āĻĢā§‹āĻ˛ā§āĻĄāĻžāϰ⧇āϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ" driveFolderBg: "āĻĄā§āϰāĻžāχāĻ­ āĻĢā§‹āĻ˛ā§āĻĄāĻžāϰ⧇āϰ āĻĒāϟāĻ­ā§‚āĻŽāĻŋ"
wallpaperOverlay: "āĻ“āϝāĻŧāĻžāϞāĻĒ⧇āĻĒāĻžāϰ āĻ“āĻ­āĻžāϰāϞ⧇" wallpaperOverlay: "āĻ“āϝāĻŧāĻžāϞāĻĒ⧇āĻĒāĻžāϰ āĻ“āĻ­āĻžāϰāϞ⧇"
badge: "āĻŦā§āϝāĻžāϜ" badge: "āĻŦā§āϝāĻžāϜ"
@@ -1027,6 +1090,10 @@ _sfx:
note: "āύ⧋āϟāϗ⧁āϞāĻŋ" note: "āύ⧋āϟāϗ⧁āϞāĻŋ"
noteMy: "āύ⧋āϟ (āφāĻĒāύāĻžāϰ)" noteMy: "āύ⧋āϟ (āφāĻĒāύāĻžāϰ)"
notification: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ" notification: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ"
chat: "āĻšā§āϝāĻžāϟ"
chatBg: "āĻšā§āϝāĻžāϟ (āĻŦā§āϝāĻžāĻ•āĻ—ā§āϰāĻžāωāĻ¨ā§āĻĄ)"
antenna: "āĻ…ā§āϝāĻžāĻ¨ā§āĻŸā§‡āύāĻžāϗ⧁āϞāĻŋ"
channel: "āĻšā§āϝāĻžāύ⧇āϞ⧇āϰ āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ"
_ago: _ago:
future: "āĻ­āĻŦāĻŋāĻˇā§āĻ¯ā§Ž" future: "āĻ­āĻŦāĻŋāĻˇā§āĻ¯ā§Ž"
justNow: "āĻāχāĻŽāĻžāĻ¤ā§āϰ" justNow: "āĻāχāĻŽāĻžāĻ¤ā§āϰ"
@@ -1037,20 +1104,44 @@ _ago:
weeksAgo: "{n} āϏāĻĒā§āϤāĻžāĻš āφāϗ⧇" weeksAgo: "{n} āϏāĻĒā§āϤāĻžāĻš āφāϗ⧇"
monthsAgo: "{n} āĻŽāĻžāϏ āφāϗ⧇" monthsAgo: "{n} āĻŽāĻžāϏ āφāϗ⧇"
yearsAgo: "{n} āĻŦāĻ›āϰ āφāϗ⧇" yearsAgo: "{n} āĻŦāĻ›āϰ āφāϗ⧇"
invalid: "āĻāĻ–āĻžāύ⧇ āĻ•āĻŋāϛ⧁āχ āύāĻžāχ"
_time: _time:
second: "āϏ⧇āϕ⧇āĻ¨ā§āĻĄ" second: "āϏ⧇āϕ⧇āĻ¨ā§āĻĄ"
minute: "āĻŽāĻŋāύāĻŋāϟ" minute: "āĻŽāĻŋāύāĻŋāϟ"
hour: "āϘāĻŖā§āϟāĻž" hour: "āϘāĻŖā§āϟāĻž"
day: "āĻĻāĻŋāύ" 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: _2fa:
alreadyRegistered: "āφāĻĒāύāĻŋ āχāϤāĻŋāĻŽāĻ§ā§āϝ⧇ āĻāĻ•āϟāĻŋ 2-āĻĢā§āϝāĻžāĻ•ā§āϟāϰ āĻ…āĻĨ⧇āύāϟāĻŋāϕ⧇āĻļāύ āĻĄāĻŋāĻ­āĻžāχāϏ āύāĻŋāĻŦāĻ¨ā§āϧāύ āĻ•āϰ⧇āϛ⧇āύ⧎" alreadyRegistered: "āφāĻĒāύāĻŋ āχāϤāĻŋāĻŽāĻ§ā§āϝ⧇ āĻāĻ•āϟāĻŋ 2-āĻĢā§āϝāĻžāĻ•ā§āϟāϰ āĻ…āĻĨ⧇āύāϟāĻŋāϕ⧇āĻļāύ āĻĄāĻŋāĻ­āĻžāχāϏ āύāĻŋāĻŦāĻ¨ā§āϧāύ āĻ•āϰ⧇āϛ⧇āύ⧎"
registerDevice: "āύāϤ⧁āύ āĻĄāĻŋāĻ­āĻžāχāϏ āύāĻŋāĻŦāĻ¨ā§āϧāύ āĻ•āϰ⧁āύ"
registerKey: "āϏāĻŋāĻ•āĻŋāωāϰāĻŋāϟāĻŋ āϕ⧀ āύāĻŋāĻŦāĻ¨ā§āϧāύ āĻ•āϰ⧁āύ"
step1: "āĻĒā§āϰāĻĨāĻŽā§‡, āφāĻĒāύāĻžāϰ āĻĄāĻŋāĻ­āĻžāχāϏ⧇ {a} āĻŦāĻž {b} āĻāϰ āĻŽāϤ⧋ āĻāĻ•āϟāĻŋ āĻ…āĻĨ⧇āύāϟāĻŋāϕ⧇āĻļāύ āĻ…ā§āϝāĻžāĻĒ āχāύāĻ¸ā§āϟāϞ āĻ•āϰ⧁āύ⧎" step1: "āĻĒā§āϰāĻĨāĻŽā§‡, āφāĻĒāύāĻžāϰ āĻĄāĻŋāĻ­āĻžāχāϏ⧇ {a} āĻŦāĻž {b} āĻāϰ āĻŽāϤ⧋ āĻāĻ•āϟāĻŋ āĻ…āĻĨ⧇āύāϟāĻŋāϕ⧇āĻļāύ āĻ…ā§āϝāĻžāĻĒ āχāύāĻ¸ā§āϟāϞ āĻ•āϰ⧁āύ⧎"
step2: "āĻāϰāĻĒāϰ⧇, āĻ…ā§āϝāĻžāĻĒ⧇āϰ āϏāĻžāĻšāĻžāĻ¯ā§āϝ⧇ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ QR āϕ⧋āĻĄāϟāĻŋ āĻ¸ā§āĻ•ā§āϝāĻžāύ āĻ•āϰ⧁āύāĨ¤" step2: "āĻāϰāĻĒāϰ⧇, āĻ…ā§āϝāĻžāĻĒ⧇āϰ āϏāĻžāĻšāĻžāĻ¯ā§āϝ⧇ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ QR āϕ⧋āĻĄāϟāĻŋ āĻ¸ā§āĻ•ā§āϝāĻžāύ āĻ•āϰ⧁āύāĨ¤"
step2Url: "āĻĄā§‡āĻ¸ā§āĻ•āϟāĻĒ āĻ…ā§āϝāĻžāĻĒ⧇, āύāĻŋāĻŽā§āύāϞāĻŋāĻ–āĻŋāϤ URL āϞāĻŋāϖ⧁āύ:"
step3: "āĻ…ā§āϝāĻžāĻĒ⧇ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻŸā§‹āϕ⧇āύāϟāĻŋ āϞāĻŋāϖ⧁āύ āĻāĻŦāĻ‚ āφāĻĒāύāĻžāϰ āĻ•āĻžāϜ āĻļ⧇āώāĨ¤" step3: "āĻ…ā§āϝāĻžāĻĒ⧇ āĻĒā§āϰāĻĻāĻ°ā§āĻļāĻŋāϤ āĻŸā§‹āϕ⧇āύāϟāĻŋ āϞāĻŋāϖ⧁āύ āĻāĻŦāĻ‚ āφāĻĒāύāĻžāϰ āĻ•āĻžāϜ āĻļ⧇āώāĨ¤"
step4: "āφāĻĒāύāĻžāϕ⧇ āĻāĻ–āύ āĻĨ⧇āϕ⧇ āϞāĻ— āχāύ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ, āĻāχāĻ­āĻžāĻŦ⧇ āĻŸā§‹āϕ⧇āύ āϞāĻŋāĻ–āϤ⧇ āĻšāĻŦ⧇āĨ¤" step4: "āφāĻĒāύāĻžāϕ⧇ āĻāĻ–āύ āĻĨ⧇āϕ⧇ āϞāĻ— āχāύ āĻ•āϰāĻžāϰ āϏāĻŽāϝāĻŧ, āĻāχāĻ­āĻžāĻŦ⧇ āĻŸā§‹āϕ⧇āύ āϞāĻŋāĻ–āϤ⧇ āĻšāĻŦ⧇āĨ¤"
securityKeyInfo: "āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ āĻšāĻžāĻ°ā§āĻĄāĻ“āϝāĻŧā§āϝāĻžāϰ āϏāĻŋāĻ•āĻŋāωāϰāĻŋāϟāĻŋ āϕ⧀ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϞāĻ— āχāύ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ āϝāĻž FIDO2 āĻŦāĻž āĻĄāĻŋāĻ­āĻžāχāϏ⧇āϰ āĻĢāĻŋāĻ™ā§āĻ—āĻžāϰāĻĒā§āϰāĻŋāĻ¨ā§āϟ āϏ⧇āĻ¨ā§āϏāϰ āĻŦāĻž āĻĒāĻŋāύ āϏāĻŽāĻ°ā§āĻĨāύ āĻ•āϰ⧇⧎" securityKeyInfo: "āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ āĻšāĻžāĻ°ā§āĻĄāĻ“āϝāĻŧā§āϝāĻžāϰ āϏāĻŋāĻ•āĻŋāωāϰāĻŋāϟāĻŋ āϕ⧀ āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻ•āϰ⧇ āϞāĻ— āχāύ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ āϝāĻž FIDO2 āĻŦāĻž āĻĄāĻŋāĻ­āĻžāχāϏ⧇āϰ āĻĢāĻŋāĻ™ā§āĻ—āĻžāϰāĻĒā§āϰāĻŋāĻ¨ā§āϟ āϏ⧇āĻ¨ā§āϏāϰ āĻŦāĻž āĻĒāĻŋāύ āϏāĻŽāĻ°ā§āĻĨāύ āĻ•āϰ⧇⧎"
renewTOTPCancel: "āύāĻž, āϧāĻ¨ā§āϝāĻŦāĻžāĻĻ"
_permissions: _permissions:
"read:account": "āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āĻŸā§‡āϰ āϤāĻĨā§āϝ āĻĻ⧇āϖ⧁āύ" "read:account": "āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āĻŸā§‡āϰ āϤāĻĨā§āϝ āĻĻ⧇āϖ⧁āύ"
"write:account": "āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āĻŸā§‡āϰ āϤāĻĨā§āϝ āϏāĻŽā§āĻĒāĻžāĻĻāύ āĻ•āϰ⧁āύ" "write:account": "āĻ…ā§āϝāĻžāĻ•āĻžāωāĻ¨ā§āĻŸā§‡āϰ āϤāĻĨā§āϝ āϏāĻŽā§āĻĒāĻžāĻĻāύ āĻ•āϰ⧁āύ"
@@ -1096,6 +1187,7 @@ _antennaSources:
homeTimeline: "āφāĻĒāύāĻŋ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāϛ⧇āύ, āĻāĻŽāύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āύ⧋āϟ" homeTimeline: "āφāĻĒāύāĻŋ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāϛ⧇āύ, āĻāĻŽāύ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āύ⧋āϟ"
users: "āĻāĻ• āĻŦāĻž āĻāĻ•āĻžāϧāĻŋāĻ• āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āύ⧋āϟ" users: "āĻāĻ• āĻŦāĻž āĻāĻ•āĻžāϧāĻŋāĻ• āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āύ⧋āϟ"
userList: "āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϤāĻžāϞāĻŋāĻ•āĻžāϝāĻŧ āύāĻžāĻŽ āĻĨāĻžāĻ•āĻž āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āύ⧋āϟ" userList: "āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āϤāĻžāϞāĻŋāĻ•āĻžāϝāĻŧ āύāĻžāĻŽ āĻĨāĻžāĻ•āĻž āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āύ⧋āϟ"
userGroup: "āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻ—ā§āϰ⧁āĻĒ⧇ āĻĨāĻžāĻ•āĻž āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āύ⧋āϟ"
_weekday: _weekday:
sunday: "āϰāĻŦāĻŋāĻŦāĻžāϰ" sunday: "āϰāĻŦāĻŋāĻŦāĻžāϰ"
monday: "āϏ⧋āĻŽāĻŦāĻžāϰ" monday: "āϏ⧋āĻŽāĻŦāĻžāϰ"
@@ -1105,8 +1197,6 @@ _weekday:
friday: "āĻļ⧁āĻ•ā§āϰāĻŦāĻžāϰ" friday: "āĻļ⧁āĻ•ā§āϰāĻŦāĻžāϰ"
saturday: "āĻļāύāĻŋāĻŦāĻžāϰ" saturday: "āĻļāύāĻŋāĻŦāĻžāϰ"
_widgets: _widgets:
profile: "āĻĒā§āϰ⧋āĻĢāĻžāχāϞ"
instanceInfo: "āχāĻ¨ā§āϏāĻŸā§āϝāĻžāĻ¨ā§āϏ⧇āϰ āϤāĻĨā§āϝ"
memo: "āĻ¸ā§āϟāĻŋāĻ•āĻŋ āύ⧋āϟ" memo: "āĻ¸ā§āϟāĻŋāĻ•āĻŋ āύ⧋āϟ"
notifications: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ" notifications: "āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ"
timeline: "āϟāĻžāχāĻŽāϞāĻžāχāύ" timeline: "āϟāĻžāχāĻŽāϞāĻžāχāύ"
@@ -1126,8 +1216,6 @@ _widgets:
serverMetric: "āϏāĻžāĻ°ā§āĻ­āĻžāϰ āĻŽā§‡āĻŸā§āϰāĻŋāĻ•ā§āϏ" serverMetric: "āϏāĻžāĻ°ā§āĻ­āĻžāϰ āĻŽā§‡āĻŸā§āϰāĻŋāĻ•ā§āϏ"
aiscript: "AiScript āĻ•āύāϏ⧋āϞ" aiscript: "AiScript āĻ•āύāϏ⧋āϞ"
aichan: "āφāχ āϚāĻžāύ" aichan: "āφāχ āϚāĻžāύ"
_userList:
chooseList: "āϞāĻŋāĻ¸ā§āϟ āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ āĻ•āϰ⧁āύ"
_cw: _cw:
hide: "āϞ⧁āĻ•āĻžāύ" hide: "āϞ⧁āĻ•āĻžāύ"
show: "āφāϰāĻ“ āĻĻ⧇āϖ⧁āύ" show: "āφāϰāĻ“ āĻĻ⧇āϖ⧁āύ"
@@ -1164,6 +1252,8 @@ _visibility:
followersDescription: "āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āφāĻĒāύāĻžāϰ āĻ…āύ⧁āϏāϰāĻŖāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āύāĻŋāĻ•āϟ āĻĒā§‹āĻ¸ā§āϟ āĻ•āϰ⧁āύ" followersDescription: "āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āφāĻĒāύāĻžāϰ āĻ…āύ⧁āϏāϰāĻŖāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āύāĻŋāĻ•āϟ āĻĒā§‹āĻ¸ā§āϟ āĻ•āϰ⧁āύ"
specified: "āĻĄāĻžāχāϰ⧇āĻ•ā§āϟ āύ⧋āϟ" specified: "āĻĄāĻžāχāϰ⧇āĻ•ā§āϟ āύ⧋āϟ"
specifiedDescription: "āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āύāĻŋāĻ•āϟ āĻĒāĻžāĻ āĻžāύ" specifiedDescription: "āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āύāĻŋāĻ°ā§āĻĻāĻŋāĻˇā§āϟ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āύāĻŋāĻ•āϟ āĻĒāĻžāĻ āĻžāύ"
localOnly: "āĻļ⧁āϧ⧁āĻŽāĻžāĻ¤ā§āϰ āϞ⧋āĻ•āĻžāϞ"
localOnlyDescription: "āϰāĻŋāĻŽā§‹āϟ āĻŦā§āϝāĻžāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āĻĻ⧇āϰ āύāĻŋāĻ•āϟ āĻĻ⧃āĻļā§āϝāĻŽāĻžāύ āύ⧟"
_postForm: _postForm:
replyPlaceholder: "āύ⧋āϟāϟāĻŋāϰ āϜāĻŦāĻžāĻŦ āĻĻāĻŋāύ..." replyPlaceholder: "āύ⧋āϟāϟāĻŋāϰ āϜāĻŦāĻžāĻŦ āĻĻāĻŋāύ..."
quotePlaceholder: "āύ⧋āϟāϟāĻŋāϕ⧇ āωāĻĻā§āϧ⧃āϤ āĻ•āϰ⧁āύ..." quotePlaceholder: "āύ⧋āϟāϟāĻŋāϕ⧇ āωāĻĻā§āϧ⧃āϤ āĻ•āϰ⧁āύ..."
@@ -1189,7 +1279,6 @@ _profile:
changeBanner: "āĻŦā§āϝāĻžāύāĻžāϰ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰ⧁āύ" changeBanner: "āĻŦā§āϝāĻžāύāĻžāϰ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤāύ āĻ•āϰ⧁āύ"
_exportOrImport: _exportOrImport:
allNotes: "āϏāĻ•āϞ āύ⧋āϟ" allNotes: "āϏāĻ•āϞ āύ⧋āϟ"
clips: "āĻ•ā§āϞāĻŋāĻĒ"
followingList: "āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāĻž āĻšāĻšā§āϛ⧇" followingList: "āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāĻž āĻšāĻšā§āϛ⧇"
muteList: "āĻŽāĻŋāωāϟ" muteList: "āĻŽāĻŋāωāϟ"
blockingList: "āĻŦā§āϞāĻ•" blockingList: "āĻŦā§āϞāĻ•"
@@ -1227,12 +1316,6 @@ _timelines:
local: "āĻ¸ā§āĻĨāĻžāύ⧀āϝāĻŧ" local: "āĻ¸ā§āĻĨāĻžāύ⧀āϝāĻŧ"
social: "āϏāĻžāĻŽāĻžāϜāĻŋāĻ•" social: "āϏāĻžāĻŽāĻžāϜāĻŋāĻ•"
global: "āĻ—ā§āϞ⧋āĻŦāĻžāϞ" global: "āĻ—ā§āϞ⧋āĻŦāĻžāϞ"
_play:
viewSource: "āĻ‰ā§ŽāϏ āĻĻ⧇āϖ⧁āύ"
featured: "āϜāύāĻĒā§āϰāĻŋāϝāĻŧ"
title: "āĻļāĻŋāϰ⧋āύāĻžāĻŽ"
script: "āĻ¸ā§āĻ•ā§āϰāĻŋāĻĒā§āϟ"
summary: "āĻŦāĻ°ā§āĻŖāύāĻž"
_pages: _pages:
newPage: "āύāϤ⧁āύ āĻĒ⧃āĻˇā§āĻ āĻž āĻŦāĻžāύāĻžāύ" newPage: "āύāϤ⧁āύ āĻĒ⧃āĻˇā§āĻ āĻž āĻŦāĻžāύāĻžāύ"
editPage: "āĻĒ⧃āĻˇā§āĻ āĻžāϟāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻ•āϰ⧁āύ" editPage: "āĻĒ⧃āĻˇā§āĻ āĻžāϟāĻŋ āϏāĻŽā§āĻĒāĻžāĻĻāύāĻž āĻ•āϰ⧁āύ"
@@ -1268,6 +1351,8 @@ _pages:
eyeCatchingImageRemove: "āĻĨāĻžāĻŽā§āĻŦāύ⧇āχāϞ āϏāϰāĻžāύ" eyeCatchingImageRemove: "āĻĨāĻžāĻŽā§āĻŦāύ⧇āχāϞ āϏāϰāĻžāύ"
chooseBlock: "āĻŦā§āϞāĻ• āϝ⧋āĻ— āĻ•āϰ⧁āύ" chooseBlock: "āĻŦā§āϞāĻ• āϝ⧋āĻ— āĻ•āϰ⧁āύ"
selectType: "āϧāϰāύ āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ āĻ•āϰ⧁āύ" selectType: "āϧāϰāύ āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ āĻ•āϰ⧁āύ"
enterVariableName: "āϚāϞāϕ⧇āϰ āύāĻžāĻŽ āϞāĻŋāϖ⧁āύ"
variableNameIsAlreadyUsed: "āϚāϞāϕ⧇āϰ āύāĻžāĻŽāϟāĻŋ āχāϤāĻŋāĻĒā§‚āĻ°ā§āĻŦ⧇ āĻŦā§āϝāĻžāĻŦāĻšā§ƒāϤ āĻšā§Ÿā§‡āϛ⧇"
contentBlocks: "āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁" contentBlocks: "āĻŦāĻŋāώ⧟āĻŦāĻ¸ā§āϤ⧁"
inputBlocks: "āχāύāĻĒ⧁āϟ" inputBlocks: "āχāύāĻĒ⧁āϟ"
specialBlocks: "āĻŦāĻŋāĻļ⧇āώ" specialBlocks: "āĻŦāĻŋāĻļ⧇āώ"
@@ -1277,11 +1362,249 @@ _pages:
section: "āĻŦāĻŋāĻ­āĻžāĻ—" section: "āĻŦāĻŋāĻ­āĻžāĻ—"
image: "āĻ›āĻŦāĻŋ" image: "āĻ›āĻŦāĻŋ"
button: "āĻŦāĻžāϟāύ" button: "āĻŦāĻžāϟāύ"
if: "āϝāĻĻāĻŋ"
_if:
variable: "āϚāϞāĻ•āϗ⧁āϞāĻŋ"
post: "āύ⧋āϟ āϞāĻŋāϖ⧁āύ"
_post:
text: "āĻŦāĻŋāώāϝāĻŧāĻŦāĻ¸ā§āϤ⧁"
attachCanvasImage: "āĻ•ā§āϝāĻžāύāĻ­āĻžāϏ āĻ›āĻŦāĻŋāϏāĻš āĻĒā§‹āĻ¸ā§āϟ āĻ•āϰ⧁āύ"
canvasId: "āĻ•ā§āϝāĻžāύāĻ­āĻžāϏ ID"
textInput: "āĻŸā§‡āĻ•ā§āϏāϟ āχāύāĻĒ⧁āϟ"
_textInput:
name: "āϚāϞāϕ⧇āϰ āύāĻžāĻŽ"
text: "āĻļāĻŋāϰ⧋āύāĻžāĻŽ"
default: "āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻŽāĻžāύ"
textareaInput: "āĻāĻ•āĻžāϧāĻŋāĻ• āϞāĻžāχāύ⧇āϰ āĻŸā§‡āĻ•ā§āϏāϟ āχāύāĻĒ⧁āϟ"
_textareaInput:
name: "āϚāϞāϕ⧇āϰ āύāĻžāĻŽ"
text: "āĻļāĻŋāϰ⧋āύāĻžāĻŽ"
default: "āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻŽāĻžāύ"
numberInput: "āϏāĻ‚āĻ–ā§āϝāĻž āχāύāĻĒ⧁āϟ"
_numberInput:
name: "āϚāϞāϕ⧇āϰ āύāĻžāĻŽ"
text: "āĻļāĻŋāϰ⧋āύāĻžāĻŽ"
default: "āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻŽāĻžāύ"
canvas: "āĻ•ā§āϝāĻžāύāĻ­āĻžāϏ"
_canvas:
id: "āĻ•ā§āϝāĻžāύāĻ­āĻžāϏ ID"
width: "āĻĒā§āϰāĻ¸ā§āĻĨ"
height: "āωāĻšā§āϚāϤāĻž"
note: "āĻāĻŽā§āĻŦ⧇āĻĄ āύ⧋āϟ" note: "āĻāĻŽā§āĻŦ⧇āĻĄ āύ⧋āϟ"
_note: _note:
id: "āύ⧋āϟ ID" id: "āύ⧋āϟ ID"
idDescription: "āφāĻĒāύāĻŋ āĻāϰ āĻŦāĻĻāϞ⧇ āύ⧋āĻŸā§‡āϰ URL āĻĒ⧇āĻ¸ā§āϟ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ." idDescription: "āφāĻĒāύāĻŋ āĻāϰ āĻŦāĻĻāϞ⧇ āύ⧋āĻŸā§‡āϰ URL āĻĒ⧇āĻ¸ā§āϟ āĻ•āϰāϤ⧇ āĻĒāĻžāϰ⧇āύ."
detailed: "āĻŦāĻŋāĻ¸ā§āϤāĻžāϰāĻŋāϤ āĻĻ⧇āϖ⧁āύ" detailed: "āĻŦāĻŋāĻ¸ā§āϤāĻžāϰāĻŋāϤ āĻĻ⧇āϖ⧁āύ"
switch: "āϏ⧁āχāϚ"
_switch:
name: "āϚāϞāϕ⧇āϰ āύāĻžāĻŽ"
text: "āĻļāĻŋāϰ⧋āύāĻžāĻŽ"
default: "āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻŽāĻžāύ"
counter: "āĻ•āĻžāωāĻ¨ā§āϟāĻžāϰ"
_counter:
name: "āϚāϞāϕ⧇āϰ āύāĻžāĻŽ"
text: "āĻļāĻŋāϰ⧋āύāĻžāĻŽ"
inc: "āĻāĻ­āĻžāĻŦ⧇ āĻŽāĻžāύ āĻŦāĻžāĻĄāĻŧāĻžāύ"
_button:
text: "āĻļāĻŋāϰ⧋āύāĻžāĻŽ"
colored: "āϰāĻ™ā§āĻ—āĻŋāύ"
action: "āĻŦāĻžāϟāύ⧇ āĻ•ā§āϞāĻŋāĻ• āĻ•āϰāϞ⧇ āϝāĻž āĻšāĻŦ⧇"
_action:
dialog: "āĻĄāĻžā§ŸāĻžāϞāĻ— āĻĻ⧇āĻ–āĻžāύ "
_dialog:
content: "āĻŦāĻŋāώāϝāĻŧāĻŦāĻ¸ā§āϤ⧁"
resetRandom: "āĻ°â€ā§āϝāĻžāύāĻĄāĻŽ āϏāĻŋāĻĄ āϰāĻŋāϏ⧇āϟ āĻ•āϰ⧁āύ"
pushEvent: "āχāϭ⧇āĻ¨ā§āϟ āĻĒāĻžāĻ āĻžāύ"
_pushEvent:
event: "āχāϭ⧇āĻ¨ā§āĻŸā§‡āϰ āύāĻžāĻŽ"
message: "āϚāĻžāϞ⧁ āĻšāϞ⧇ āĻĒā§āϰāĻĻāĻ°ā§āĻļāύ⧇āϰ āϜāĻ¨ā§āϝ āĻŦāĻžāĻ°ā§āϤāĻž"
variable: "āĻĒāĻžāĻ āĻžāύ⧋ āϚāϞāĻ•"
no-variable: "āĻ•āĻŋāϛ⧁āχ āύāĻž"
callAiScript: "AiScript āϚāĻžāϞāĻžāύ"
_callAiScript:
functionName: "āĻĢāĻžāĻ‚āĻļāύ⧇āϰ āύāĻžāĻŽ"
radioButton: "āĻŦāĻšā§āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ⧀"
_radioButton:
name: "āϚāϞāϕ⧇āϰ āύāĻžāĻŽ"
title: "āĻļāĻŋāϰ⧋āύāĻžāĻŽ"
values: "āĻŦāĻŋāĻ•āĻ˛ā§āĻĒāϗ⧁āϞāĻŋāϕ⧇ āφāϞāĻžāĻĻāĻž āϞāĻžāχāύ⧇ āϞāĻŋāϖ⧁āύ"
default: "āĻĄāĻŋāĻĢāĻ˛ā§āϟ āĻŽāĻžāύ"
script:
categories:
flow: "āύāĻŋāϝāĻŧāĻ¨ā§āĻ¤ā§āϰāĻŖ"
logical: "āϞāϜāĻŋāĻ•ā§āϝāĻžāϞ āĻ…āĻĒāĻžāϰ⧇āĻļāύ"
operation: "āĻšāĻŋāϏāĻžāĻŦ-āύāĻŋāĻ•āĻžāĻļ"
comparison: "āϤ⧁āϞāύāĻž"
random: "āĻ°â€ā§āϝāĻžāĻ¨ā§āĻĄāĻŽ"
value: "āĻŽāĻžāύ"
fn: "āĻĢāĻžāĻ‚āĻļāύ"
text: "āĻŸā§‡āĻ•ā§āϏāϟ āĻŽā§āϝāĻžāύāĻŋāĻĒ⧁āϞ⧇āĻļāύ"
convert: "āϰ⧁āĻĒāĻžāĻ¨ā§āϤāϰ"
list: "āϞāĻŋāĻ¸ā§āϟ"
blocks:
text: "āϞ⧇āĻ–āĻž"
multiLineText: "āϞ⧇āĻ–āĻž (āĻāĻ•āĻžāϧāĻŋāĻ• āϞāĻžāχāύ)"
textList: "āϞ⧇āĻ–āĻžāϰ āϞāĻŋāĻ¸ā§āϟ"
_textList:
info: "āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻāĻ¨ā§āĻŸā§āϰāĻŋāϕ⧇ āφāϞāĻžāĻĻāĻž āϞāĻžāχāύ⧇ āϞāĻŋāϖ⧁āύ"
strLen: "āϞ⧇āĻ–āĻžāϰ āĻĻ⧈āĻ°ā§āĻ˜ā§āϝ"
_strLen:
arg1: "āϞ⧇āĻ–āĻž"
strPick: "āĻ…āĻ•ā§āώāϰ āĻŦ⧇āϰ āĻ•āϰ⧇ āφāύ⧁āύ"
_strPick:
arg1: "āϞ⧇āĻ–āĻž"
arg2: "āĻ…āĻ•ā§āώāϰ⧇āϰ āĻ…āĻŦāĻ¸ā§āĻĨāĻžāύ"
strReplace: "āϞ⧇āĻ–āĻž āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ"
_strReplace:
arg1: "āϞ⧇āĻ–āĻž"
arg2: "āϝ⧇ āϞ⧇āĻ–āĻž āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰāĻž āĻšāĻŦ⧇"
arg3: "āϝāĻž āĻĻā§āĻŦāĻžāϰāĻž āĻĒā§āϰāϤāĻŋāĻ¸ā§āĻĨāĻžāĻĒāύ āĻ•āϰāĻž āĻšāĻŦ⧇"
strReverse: "āϞ⧇āĻ–āĻž āωāĻ˛ā§āϟāĻžāύ"
_strReverse:
arg1: "āϞ⧇āĻ–āĻž"
join: "āϞ⧇āĻ–āĻž āϝ⧁āĻ•ā§āϤ āĻ•āϰ⧁āύ"
_join:
arg1: "āϞāĻŋāĻ¸ā§āϟ"
arg2: "āĻŦāĻŋāĻ­āĻžāϜāĻ•"
add: "āϝ⧋āĻ—"
_add:
arg1: "A"
arg2: "B"
subtract: "āĻŦāĻŋāϝāĻŧā§‹āĻ—"
_subtract:
arg1: "A"
arg2: "B"
multiply: "āϗ⧁āύ"
_multiply:
arg1: "A"
arg2: "B"
divide: "āĻ­āĻžāĻ—"
_divide:
arg1: "A"
arg2: "B"
mod: "āĻ­āĻžāĻ—āĻļ⧇āώ"
_mod:
arg1: "A"
arg2: "B"
round: "āĻĻāĻļāĻŽāĻŋāĻ• āϰāĻžāωāĻ¨ā§āĻĄ āĻ•āϰ⧁āύ"
_round:
arg1: "āϏāĻ‚āĻ–ā§āϝāĻž"
eq: "A āĻ“ B āϏāĻŽāĻžāύ"
_eq:
arg1: "A"
arg2: "B"
notEq: "A āĻ“ B āϏāĻŽāĻžāύ āύāĻž"
_notEq:
arg1: "A"
arg2: "B"
and: "A āĻāĻŦāĻ‚ B"
_and:
arg1: "A"
arg2: "B"
or: "A āĻ…āĻĨāĻŦāĻž B"
_or:
arg1: "A"
arg2: "B"
lt: "< A , B āĻšāϤ⧇ āĻ•āĻŽ"
_lt:
arg1: "A"
arg2: "B"
gt: "> A , B āĻšāϤ⧇ āĻŦ⧇āĻļā§€"
_gt:
arg1: "A"
arg2: "B"
ltEq: "<= A , B āĻšāϤ⧇ āĻ•āĻŽ āĻŦāĻž āϏāĻŽāĻžāύ"
_ltEq:
arg1: "A"
arg2: "B"
gtEq: ">= A , B āĻšāϤ⧇ āĻŦ⧇āĻļā§€ āĻŦāĻž āϏāĻŽāĻžāύ"
_gtEq:
arg1: "A"
arg2: "B"
if: "āϝāĻĻāĻŋ"
_if:
arg1: "āϝāĻĻāĻŋ"
arg2: "āϤāĻžāĻšāϞ⧇"
arg3: "āϤāĻžāĻ›āĻžā§œāĻž"
not: "āύāĻž"
_not:
arg1: "āύāĻž"
random: "āĻ°â€ā§āϝāĻžāĻ¨ā§āĻĄāĻŽ"
_random:
arg1: "āϏāĻŽā§āĻ­āĻžāĻŦā§āϝāϤāĻž"
rannum: "āĻ°â€ā§āϝāĻžāύāĻĄāĻŽ āϏāĻ‚āĻ–ā§āϝāĻž"
_rannum:
arg1: "āĻ¨ā§āϝ⧂āύāϤāĻŽ āĻŽāĻžāύ"
arg2: "āϏāĻ°ā§āĻŦā§‹āĻšā§āϚ āĻŽāĻžāύ"
randomPick: "āϤāĻžāϞāĻŋāĻ•āĻž āĻĨ⧇āϕ⧇ āĻĻ⧈āĻŦāϚ⧟āύ āĻ•āϰ⧁āύ"
_randomPick:
arg1: "āϞāĻŋāĻ¸ā§āϟ"
dailyRandom: "āĻ°â€ā§āϝāĻžāĻ¨ā§āĻĄāĻŽ āϏāĻ‚āĻ–ā§āϝāĻž (āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āϜāĻ¨ā§āϝ āĻĒā§āϰāϤāĻŋāĻĻāĻŋāύ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤ⧀āϤ āĻšā§Ÿ)"
_dailyRandom:
arg1: "āϏāĻŽā§āĻ­āĻžāĻŦā§āϝāϤāĻž"
dailyRannum: "āĻ°â€ā§āϝāĻžāĻ¨ā§āĻĄāĻŽ āϏāĻ‚āĻ–ā§āϝāĻž (āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āϜāĻ¨ā§āϝ āĻĒā§āϰāϤāĻŋāĻĻāĻŋāύ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤ⧀āϤ āĻšā§Ÿ)"
_dailyRannum:
arg1: "āĻ¨ā§āϝ⧂āύāϤāĻŽ āĻŽāĻžāύ"
arg2: "āϏāĻ°ā§āĻŦā§‹āĻšā§āϚ āĻŽāĻžāύ"
dailyRandomPick: "āϤāĻžāϞāĻŋāĻ•āĻž āĻĨ⧇āϕ⧇ āĻāϞ⧋āĻŽā§‡āϞ⧋āĻ­āĻžāĻŦ⧇ āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ āĻ•āϰ⧁āύ (āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āϜāĻ¨ā§āϝ āĻĒā§āϰāϤāĻŋāĻĻāĻŋāύ āĻĒāϰāĻŋāĻŦāĻ°ā§āϤ⧀āϤ āĻšā§Ÿ)"
_dailyRandomPick:
arg1: "āϞāĻŋāĻ¸ā§āϟ"
seedRandom: "āĻ°â€ā§āϝāĻžāύāĻĄāĻŽ (āϏ⧀āĻĄ āĻĻā§āĻŦāĻžāϰāĻž)"
_seedRandom:
arg1: "āϏ⧀āĻĄ"
arg2: "āϏāĻŽā§āĻ­āĻžāĻŦā§āϝāϤāĻž"
seedRannum: "āĻ°â€ā§āϝāĻžāύāĻĄāĻŽ āϏāĻ‚āĻ–ā§āϝāĻž (āϏ⧀āĻĄ āĻĻā§āĻŦāĻžāϰāĻž)"
_seedRannum:
arg1: "āϏ⧀āĻĄ"
arg2: "āĻ¨ā§āϝ⧂āύāϤāĻŽ āĻŽāĻžāύ"
arg3: "āϏāĻ°ā§āĻŦā§‹āĻšā§āϚ āĻŽāĻžāύ"
seedRandomPick: "āϤāĻžāϞāĻŋāĻ•āĻž āĻĨ⧇āϕ⧇ āĻĻ⧈āĻŦāϚ⧟āύ āĻ•āϰ⧁āύ (āϏ⧀āĻĄ āĻĻā§āĻŦāĻžāϰāĻž)"
_seedRandomPick:
arg1: "āϏ⧀āĻĄ"
arg2: "āϞāĻŋāĻ¸ā§āϟ"
DRPWPM: "āϏāĻŽā§āĻ­āĻžāĻŦā§āϝāϤāĻž āϏāĻš āĻāĻ•āϟāĻŋ āϤāĻžāϞāĻŋāĻ•āĻž āĻĨ⧇āϕ⧇ āĻāϞ⧋āĻŽā§‡āϞ⧋āĻ­āĻžāĻŦ⧇ āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ āĻ•āϰ⧁āύ (āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻŦā§āϝāĻŦāĻšāĻžāϰāĻ•āĻžāϰ⧀āϰ āϜāĻ¨ā§āϝ āĻĒā§āϰāϤāĻŋāĻĻāĻŋāύ)"
_DRPWPM:
arg1: "āϞ⧇āĻ–āĻžāϰ āϞāĻŋāĻ¸ā§āϟ"
pick: "āϤāĻžāϞāĻŋāĻ•āĻž āĻĨ⧇āϕ⧇ āύāĻŋāĻ°ā§āĻŦāĻžāϚāύ āĻ•āϰ⧁āύ"
_pick:
arg1: "āϞāĻŋāĻ¸ā§āϟ"
arg2: "āĻ…āĻŦāĻ¸ā§āĻĨāĻžāύ"
listLen: "āϞāĻŋāĻ¸ā§āĻŸā§‡āϰ āĻĻ⧈āĻ°ā§āĻ˜ā§āϝ āĻĒāĻžāύ"
_listLen:
arg1: "āϞāĻŋāĻ¸ā§āϟ"
number: "āϏāĻ‚āĻ–ā§āϝāĻž"
stringToNumber: "āĻĒāĻžāĻ ā§āϝ āĻĨ⧇āϕ⧇ āϏāĻ‚āĻ–ā§āϝāĻž"
_stringToNumber:
arg1: "āϞ⧇āĻ–āĻž"
numberToString: "āϏāĻ‚āĻ–ā§āϝāĻž āĻĨ⧇āϕ⧇ āĻĒāĻžāĻ ā§āϝ"
_numberToString:
arg1: "āϏāĻ‚āĻ–ā§āϝāĻž"
splitStrByLine: "āĻĒāĻžāĻ ā§āϝāϕ⧇ āϞāĻžāχāύ⧇ āĻŦāĻŋāĻ­āĻ•ā§āϤ āĻ•āϰ⧁āύ"
_splitStrByLine:
arg1: "āϞ⧇āĻ–āĻž"
ref: "āϚāϞāĻ•"
aiScriptVar: "AiScript āϚāϞāĻ•"
fn: "āĻĢāĻžāĻ‚āĻļāύ"
_fn:
slots: "āĻ¸ā§āϞāϟāϗ⧁āϞāĻŋ"
slots-info: "āĻĒā§āϰāϤāĻŋāϟāĻŋ āĻ¸ā§āϞāϟāϕ⧇ āφāϞāĻžāĻĻāĻž āϞāĻžāχāύ⧇ āϞāĻŋāϖ⧁āύ"
arg1: "āφāωāϟāĻĒ⧁āϟ"
for: "for-āϞ⧁āĻĒ"
_for:
arg1: "āĻ•āϤāĻŦāĻžāϰ āϚāϞāĻŦ⧇"
arg2: "āĻ…ā§āϝāĻžāĻ•āĻļāύ"
typeError: "āĻ¸ā§āϞāϟ {slot}, {expect} āϧāϰāύ⧇āϰ āĻŽāĻžāύ āĻ—ā§āϰāĻšāĻŖ āĻ•āϰ⧇, āĻ•āĻŋāĻ¨ā§āϤ⧁ {actual} āϧāϰāύ⧇āϰ āĻŽāĻžāύ āĻĻ⧇āĻ“ā§ŸāĻž āĻšā§Ÿā§‡āϛ⧇!"
thereIsEmptySlot: "āĻ¸ā§āϞāϟ {slot} āĻ–āĻžāϞāĻŋīŧ"
types:
string: "āϞ⧇āĻ–āĻž"
number: "āϏāĻ‚āĻ–ā§āϝāĻž"
boolean: "āĻĢā§āĻ˛ā§āϝāĻžāĻ—"
array: "āϞāĻŋāĻ¸ā§āϟ"
stringArray: "āϞ⧇āĻ–āĻžāϰ āϞāĻŋāĻ¸ā§āϟ"
emptySlot: "āĻ–āĻžāϞāĻŋ āĻ¸ā§āϞāϟ"
enviromentVariables: "āĻāύāĻ­āĻžāχāϰāύāĻŽā§‡āĻ¨ā§āϟ āĻ­ā§āϝāĻžāϰāĻŋā§Ÿā§‡āĻŦāϞ"
pageVariables: "āĻĒ⧇āĻœā§‡āϰ āϚāϞāĻ•"
argVariables: "āχāύāĻĒ⧁āĻŸā§‡āϰ āϜāĻžā§ŸāĻ—āĻž"
_relayStatus: _relayStatus:
requesting: "āĻ…āĻĒ⧇āĻ•ā§āώāĻŽāĻžāύ" requesting: "āĻ…āĻĒ⧇āĻ•ā§āώāĻŽāĻžāύ"
accepted: "āĻ…āύ⧁āĻŽā§‹āĻĻāĻŋāϤ" accepted: "āĻ…āύ⧁āĻŽā§‹āĻĻāĻŋāϤ"
@@ -1292,9 +1615,13 @@ _notification:
youGotReply: "{name} āφāĻĒāύāĻžāϕ⧇ āϜāĻŦāĻžāĻŦ āĻĻāĻŋā§Ÿā§‡āϛ⧇" youGotReply: "{name} āφāĻĒāύāĻžāϕ⧇ āϜāĻŦāĻžāĻŦ āĻĻāĻŋā§Ÿā§‡āϛ⧇"
youGotQuote: "{name} āφāĻĒāύāĻžāϕ⧇ āωāĻĻā§āϧ⧃āϤ āĻ•āϰ⧇āϛ⧇" youGotQuote: "{name} āφāĻĒāύāĻžāϕ⧇ āωāĻĻā§āϧ⧃āϤ āĻ•āϰ⧇āϛ⧇"
youRenoted: "{name} āĻāϰ Renote" youRenoted: "{name} āĻāϰ Renote"
youGotPoll: "{name} āφāĻĒāύāĻžāϰ āĻĒā§‹āϞ⧇ āĻ­ā§‹āϟ āĻĻāĻŋā§Ÿā§‡āϛ⧇"
youGotMessagingMessageFromUser: "{name} āφāĻĒāύāĻžāϕ⧇ āĻŽā§‡āϏ⧇āϜ āĻ•āϰ⧇āϛ⧇"
youGotMessagingMessageFromGroup: "{name} āĻ—ā§āϰ⧁āĻĒ⧇ āĻāĻ•āϟāĻŋ āύāϤ⧁āύ āĻŽā§‡āϏ⧇āϜ āφāϛ⧇"
youWereFollowed: "āφāĻĒāύāĻžāϕ⧇ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāϛ⧇" youWereFollowed: "āφāĻĒāύāĻžāϕ⧇ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāϛ⧇"
youReceivedFollowRequest: "āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻ…āύ⧁āϰ⧋āϧ āĻĒāĻžāĻ“ā§ŸāĻž āϗ⧇āϛ⧇" youReceivedFollowRequest: "āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāĻžāϰ āϜāĻ¨ā§āϝ āĻ…āύ⧁āϰ⧋āϧ āĻĒāĻžāĻ“ā§ŸāĻž āϗ⧇āϛ⧇"
yourFollowRequestAccepted: "āφāĻĒāύāĻžāϰ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāĻžāϰ āĻ…āύ⧁āϰ⧋āϧ āĻ—ā§ƒāĻšā§€āϤ āĻšā§Ÿā§‡āϛ⧇" yourFollowRequestAccepted: "āφāĻĒāύāĻžāϰ āĻ…āύ⧁āϏāϰāĻŖ āĻ•āϰāĻžāϰ āĻ…āύ⧁āϰ⧋āϧ āĻ—ā§ƒāĻšā§€āϤ āĻšā§Ÿā§‡āϛ⧇"
youWereInvitedToGroup: "āφāĻĒāύāĻŋ āĻāĻ•āϟāĻŋ āĻ—ā§āϰ⧁āĻĒ⧇ āφāĻŽāĻ¨ā§āĻ¤ā§āϰāĻŋāϤ āĻšā§Ÿā§‡āϛ⧇āύ"
pollEnded: "āĻĒā§‹āϞ⧇āϰ āĻĢāϞāĻžāĻĢāϞ āĻĻ⧇āĻ–āĻž āϝāĻžāĻŦ⧇" pollEnded: "āĻĒā§‹āϞ⧇āϰ āĻĢāϞāĻžāĻĢāϞ āĻĻ⧇āĻ–āĻž āϝāĻžāĻŦ⧇"
emptyPushNotificationMessage: "āφāĻĒāĻĄā§‡āϟ āĻ•āϰāĻž āĻĒ⧁āĻļ āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ" emptyPushNotificationMessage: "āφāĻĒāĻĄā§‡āϟ āĻ•āϰāĻž āĻĒ⧁āĻļ āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ"
_types: _types:
@@ -1305,10 +1632,11 @@ _notification:
renote: "āϰāĻŋāύ⧋āϟ" renote: "āϰāĻŋāύ⧋āϟ"
quote: "āωāĻĻā§āϧ⧃āϤāĻŋ" quote: "āωāĻĻā§āϧ⧃āϤāĻŋ"
reaction: "āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž" reaction: "āĻĒā§āϰāϤāĻŋāĻ•ā§āϰāĻŋāϝāĻŧāĻž"
pollVote: "āĻĒā§‹āϞ⧇ āĻ­ā§‹āϟ āφāϛ⧇"
pollEnded: "āĻĒā§‹āϞ āĻļ⧇āώ" pollEnded: "āĻĒā§‹āϞ āĻļ⧇āώ"
receiveFollowRequest: "āĻĒā§āϰāĻžāĻĒā§āϤ āĻ…āύ⧁āϏāϰāϪ⧇āϰ āĻ…āύ⧁āϰ⧋āϧāϏāĻŽā§‚āĻš" receiveFollowRequest: "āĻĒā§āϰāĻžāĻĒā§āϤ āĻ…āύ⧁āϏāϰāϪ⧇āϰ āĻ…āύ⧁āϰ⧋āϧāϏāĻŽā§‚āĻš"
followRequestAccepted: "āĻ—ā§ƒāĻšā§€āϤ āĻ…āύ⧁āϏāϰāϪ⧇āϰ āĻ…āύ⧁āϰ⧋āϧāϏāĻŽā§‚āĻš" followRequestAccepted: "āĻ—ā§ƒāĻšā§€āϤ āĻ…āύ⧁āϏāϰāϪ⧇āϰ āĻ…āύ⧁āϰ⧋āϧāϏāĻŽā§‚āĻš"
login: "āĻĒā§āϰāĻŦ⧇āĻļ āĻ•āϰ⧁āύ" groupInvited: "āĻ—ā§āϰ⧁āĻĒ⧇āϰ āφāĻŽāĻ¨ā§āĻ¤ā§āϰāύāϏāĻŽā§‚āĻš"
app: "āϞāĻŋāĻ™ā§āĻ• āĻ•āϰāĻž āĻ…ā§āϝāĻžāĻĒ āĻĨ⧇āϕ⧇ āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ" app: "āϞāĻŋāĻ™ā§āĻ• āĻ•āϰāĻž āĻ…ā§āϝāĻžāĻĒ āĻĨ⧇āϕ⧇ āĻŦāĻŋāĻœā§āĻžāĻĒā§āϤāĻŋ"
_actions: _actions:
followBack: "āĻĢāϞ⧋ āĻŦā§āϝāĻžāĻ• āĻ•āϰ⧇āϛ⧇" followBack: "āĻĢāϞ⧋ āĻŦā§āϝāĻžāĻ• āĻ•āϰ⧇āϛ⧇"
@@ -1333,18 +1661,5 @@ _deck:
tl: "āϟāĻžāχāĻŽāϞāĻžāχāύ" tl: "āϟāĻžāχāĻŽāϞāĻžāχāύ"
antenna: "āĻ…ā§āϝāĻžāĻ¨ā§āĻŸā§‡āύāĻž" antenna: "āĻ…ā§āϝāĻžāĻ¨ā§āĻŸā§‡āύāĻž"
list: "āϞāĻŋāĻ¸ā§āϟ" list: "āϞāĻŋāĻ¸ā§āϟ"
channel: "āĻšā§āϝāĻžāύ⧇āϞāϗ⧁āϞāĻŋ"
mentions: "āωāĻ˛ā§āϞ⧇āĻ–āϏāĻŽā§‚āĻš" mentions: "āωāĻ˛ā§āϞ⧇āĻ–āϏāĻŽā§‚āĻš"
direct: "āĻĄāĻžāχāϰ⧇āĻ•ā§āϟ āύ⧋āϟāϗ⧁āϞāĻŋ" direct: "āĻĄāĻžāχāϰ⧇āĻ•ā§āϟ āύ⧋āϟāϗ⧁āϞāĻŋ"
_webhookSettings:
name: "āύāĻžāĻŽ"
active: "āϚāĻžāϞ⧁"
_abuseReport:
_notificationRecipient:
_recipientType:
mail: "āχāĻŽā§‡āχāϞ"
_moderationLogTypes:
suspend: "āĻ¸ā§āĻĨāĻ—āĻŋāϤ āĻ•āϰāĻž"
resetPassword: "āĻĒāĻžāϏāĻ“āϝāĻŧāĻžāĻ°ā§āĻĄ āϰāĻŋāϏ⧇āϟ āĻ•āϰ⧁āύ"
_reversi:
total: "āĻŽā§‹āϟ"

Some files were not shown because too many files have changed in this diff Show More