## ✨ Features
- **ActivityPub support**\
@@ -51,12 +49,16 @@ With Misskey's built in drive, you get cloud storage right in your social media,
## Documentation
-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.
+Misskey Documentation can be found at [Misskey Hub](https://misskey-hub.net/docs/), some of the links and graphics above also lead to specific portions of it.
-## Sponsors
+## Sponsors of Misskey
-
-
+List of sponsors of Misskey can be found at [Misskey Hub](https://misskey-hub.net/).
+
+## Sponsors of Misskey.io
+
+
+
## Thanks
diff --git a/ROADMAP.md b/ROADMAP.md
index 3077c41e7..509ecb9fe 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -6,6 +6,7 @@ Also, the later tasks are more indefinite and are subject to change as developme
This is the phase we are at now. We need to make a high-maintenance environment that can withstand future development.
- ~~Make the number of type errors zero (backend)~~ → Done ✔️
+- Make the number of type errors zero (frontend)
- Improve CI
- ~~Fix tests~~ → Done ✔️
- Fix random test failures - https://github.com/misskey-dev/misskey/issues/7985 and https://github.com/misskey-dev/misskey/issues/7986
diff --git a/SECURITY.md b/SECURITY.md
index 2c026a5f3..fc5dec5de 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -1,7 +1,6 @@
# Reporting Security Issues
-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).
+If you discover a security issue in Misskey, please report it by **[this form](https://github.com/misskey-dev/misskey/security/advisories/new)**.
This will allow us to assess the risk, and make a fix available before we add a
bug report to the GitHub repository.
diff --git a/chart/files/default.yml b/chart/files/default.yml
index 87b2f677e..4cc291e80 100644
--- a/chart/files/default.yml
+++ b/chart/files/default.yml
@@ -77,17 +77,17 @@ dbReplications: false
# You can configure any number of replicas here
#dbSlaves:
# -
-# host:
-# port:
-# db:
-# user:
-# pass:
+# host:
+# port:
+# db:
+# user:
+# pass:
# -
-# host:
-# port:
-# db:
-# user:
-# pass:
+# host:
+# port:
+# db:
+# user:
+# pass:
# ┌─────────────────────┐
#───┘ Redis configuration └─────────────────────────────────────
@@ -167,7 +167,7 @@ id: "aidx"
# Job rate limiter
# deliverJobPerSec: 128
-# inboxJobPerSec: 16
+# inboxJobPerSec: 32
# Job attempts
# deliverJobMaxAttempts: 12
diff --git a/cypress/e2e/basic.cy.js b/cypress/e2e/basic.cy.js
index 5ab07c748..d2525e0a7 100644
--- a/cypress/e2e/basic.cy.js
+++ b/cypress/e2e/basic.cy.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
describe('Before setup instance', () => {
beforeEach(() => {
cy.resetState();
@@ -161,11 +166,13 @@ describe('After user signed in', () => {
});
it('successfully loads', () => {
- cy.get('[data-cy-user-setup-continue]').should('be.visible');
+ // 表示に時間がかかるのでデフォルト秒数だとタイムアウトする
+ cy.get('[data-cy-user-setup-continue]', { timeout: 30000 }).should('be.visible');
});
it('account setup wizard', () => {
- cy.get('[data-cy-user-setup-continue]').click();
+ // 表示に時間がかかるのでデフォルト秒数だとタイムアウトする
+ 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('ほげ');
@@ -202,7 +209,8 @@ describe('After user setup', () => {
cy.login('alice', 'alice1234');
// アカウント初期設定ウィザード
- cy.get('[data-cy-user-setup] [data-cy-modal-window-close]').click();
+ // 表示に時間がかかるのでデフォルト秒数だとタイムアウトする
+ cy.get('[data-cy-user-setup] [data-cy-modal-window-close]', { timeout: 30000 }).click();
cy.get('[data-cy-modal-dialog-ok]').click();
});
diff --git a/cypress/e2e/router.cy.js b/cypress/e2e/router.cy.js
new file mode 100644
index 000000000..8d8fb3af3
--- /dev/null
+++ b/cypress/e2e/router.cy.js
@@ -0,0 +1,35 @@
+/*
+ * 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')
+ });
+ });
+});
diff --git a/cypress/e2e/widgets.cy.js b/cypress/e2e/widgets.cy.js
index df6ec8357..847801a69 100644
--- a/cypress/e2e/widgets.cy.js
+++ b/cypress/e2e/widgets.cy.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
/* flaky
describe('After user signed in', () => {
beforeEach(() => {
diff --git a/docker-compose.local-db.yml b/docker-compose.local-db.yml
new file mode 100644
index 000000000..f758e03b6
--- /dev/null
+++ b/docker-compose.local-db.yml
@@ -0,0 +1,42 @@
+version: "3"
+
+# このconfigは、 dockerでMisskey本体を起動せず、 redisとpostgresql などだけを起動します
+
+services:
+ keydb:
+ restart: always
+ image: eqalpha/keydb:latest
+ ports:
+ - "6379:6379"
+ volumes:
+ - ./keydb:/data
+ healthcheck:
+ test: "keydb-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
+
diff --git a/docker-compose.yml.example b/docker-compose_example.yml
similarity index 66%
rename from docker-compose.yml.example
rename to docker-compose_example.yml
index 830c1a294..aad722730 100644
--- a/docker-compose.yml.example
+++ b/docker-compose_example.yml
@@ -7,6 +7,7 @@ services:
links:
- db
- keydb
+# - mcaptcha
# - meilisearch
depends_on:
db:
@@ -48,6 +49,36 @@ services:
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
diff --git a/healthcheck.sh b/healthcheck.sh
index 0a3639483..d6d416c7a 100644
--- a/healthcheck.sh
+++ b/healthcheck.sh
@@ -1,6 +1,6 @@
#!/bin/bash
-# SPDX-FileCopyrightText: syuilo and other misskey contributors
+# 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}')
diff --git a/locales/ar-SA.yml b/locales/ar-SA.yml
index d62990b7b..17c8f24fa 100644
--- a/locales/ar-SA.yml
+++ b/locales/ar-SA.yml
@@ -120,7 +120,6 @@ sensitive: "محتوى حساس"
add: "إضافة"
reaction: "التفاعلات"
reactions: "التفاعلات"
-reactionSetting: "التفاعلات المراد عرضها في منتقي التفاعلات."
reactionSettingDescription2: "اسحب لترتيب ، انقر للحذف ، استخدم \"+\" للإضافة."
rememberNoteVisibility: "تذكر إعدادت مدى رؤية الملاحظات"
attachCancel: "أزل المرفق"
@@ -361,6 +360,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "فعّل hCaptcha"
hcaptchaSiteKey: "مفتاح الموقع"
hcaptchaSecretKey: "المفتاح السري"
+mcaptchaSiteKey: "مفتاح الموقع"
+mcaptchaSecretKey: "المفتاح السري"
recaptcha: "reCAPTCHA"
enableRecaptcha: "تمكين reCAPTCHA"
recaptchaSiteKey: "مفتاح الموقع"
@@ -418,7 +419,6 @@ share: "شارِك"
notFound: "غير موجود"
notFoundDescription: "تعذر العثور على صفحة يقود إليها هذا الرابط."
uploadFolder: "المجلد الافتراضي للرفع"
-cacheClear: "مسح ذاكرة التخزين المؤقت"
markAsReadAllNotifications: "وضع جميع الإشعارات كأنها مقروءة"
markAsReadAllUnreadNotes: "علّم جميع الملاحظات كمقروءة"
markAsReadAllTalkMessages: "علّم جميع الرسائل كمقروءة"
@@ -818,8 +818,6 @@ makeReactionsPublicDescription: "هذا سيجعل قائمة تفاعلاتك
classic: "تقليدي"
muteThread: "اكتم النقاش"
unmuteThread: "ارفع الكتم عن النقاش"
-ffVisibility: "مرئية المتابِعين/المتابَعين"
-ffVisibilityDescription: "يسمح لك بتحديد من يمكنهم رؤية متابِعيك ومتابَعيك."
continueThread: "اعرض بقية النقاش"
deleteAccountConfirm: "سيحذف حسابك نهائيًا، أتريد المتابعة؟"
incorrectPassword: "كلمة السر خاطئة."
@@ -948,9 +946,12 @@ rolesAssignedToMe: "الأدوار المسندة إلي"
resetPasswordConfirm: "هل تريد إعادة تعيين كلمة السر؟"
license: "الرخصة"
unfavoriteConfirm: "أتريد إزالتها من المفضلة؟"
+reactionsDisplaySize: "حجم التفاعلات"
+limitWidthOfReaction: "تصغير حجم التفاعلات"
noteIdOrUrl: "معرف الملاحظة أو رابطها"
video: "فيديو"
videos: "فيديوهات"
+dataSaver: "موفر البيانات"
accountMigration: "ترحيل الحساب"
accountMoved: "نقل هذا المستخدم حسابه:"
accountMovedShort: "رُحل هذا الحساب."
@@ -958,6 +959,7 @@ operationForbidden: "عملية ممنوعة"
forceShowAds: "أظهر الإعلانات التجارية دائما"
reactionsList: "التفاعلات"
renotesList: "إعادات النشر"
+notificationDisplay: "إشعارات"
leftTop: "أعلى اليسار"
rightTop: "أعلى اليمين"
leftBottom: "أسفل اليسار"
@@ -980,6 +982,7 @@ thisChannelArchived: "أُرشفت هذه القناة."
displayOfNote: "عرض الملاحظة"
initialAccountSetting: "إعداد الملف الشخصي"
youFollowing: "متابَع"
+preventAiLearning: "منع استخدام البيانات في تعليم الآلة"
options: "خيارات"
specifyUser: "مستخدم محدد"
failedToPreviewUrl: "تتعذر المعاينة"
@@ -993,13 +996,25 @@ later: "لاحقاً"
goToMisskey: "لميسكي"
additionalEmojiDictionary: "قواميس إيموجي إضافية"
installed: "مُثبت"
+enableServerMachineStats: "نشر إحصائيات عتاد الخادم"
+turnOffToImprovePerformance: "تفعيله قد يزيد الأداء."
+createInviteCode: "ولِّد دعوة"
+inviteCodeCreated: "ولِّدت دعوة"
+inviteLimitExceeded: "وصلتَ لحد عدد الدعوات المسموح لك توليدها."
+createLimitRemaining: "حد عدد الدعوات: {limit} دعوة"
expirationDate: "تاريخ انتهاء الصلاحية"
+noExpirationDate: "لا نهاية لصلاحيتها"
+inviteCodeUsedAt: "اُستخدم رمز الدعوة في"
+registeredUserUsingInviteCode: "اِستخدم رمز الدعوة"
unused: "غير مستعمَل"
expired: "منتهية صلاحيته"
icon: "الصورة الرمزية"
replies: "رد"
renotes: "أعد النشر"
+sourceCode: "الشفرة المصدرية"
flip: "اقلب"
+lastNDays: "آخر {n} أيام"
+surrender: "ألغِ"
_initialAccountSetting:
accountCreated: "نجح إنشاء حسابك!"
letsStartAccountSetup: "إذا كنت جديدًا لنعدّ حسابك الشخصي."
@@ -1404,6 +1419,7 @@ _profile:
_exportOrImport:
allNotes: "كل الملاحظات"
favoritedNotes: " الملاحظات المفضلة"
+ clips: "مِشبك"
followingList: "المتابَعون"
muteList: "المستخدمون المكتومون"
blockingList: "المستخدمون المحجوبون"
@@ -1550,3 +1566,7 @@ _webhookSettings:
_moderationLogTypes:
suspend: "علِق"
resetPassword: "أعد تعيين كلمتك السرية"
+ createInvitation: "ولِّد دعوة"
+_reversi:
+ total: "المجموع"
+
diff --git a/locales/bn-BD.yml b/locales/bn-BD.yml
index 31f2b948e..2a23cda06 100644
--- a/locales/bn-BD.yml
+++ b/locales/bn-BD.yml
@@ -2,6 +2,7 @@
_lang_: "বাংলা"
headlineMisskey: "নোট ব্যাবহার করে সংযুক্ত নেটওয়ার্ক"
introMisskey: "স্বাগতম! মিসকি একটি ওপেন সোর্স, ডিসেন্ট্রালাইজড মাইক্রোব্লগিং পরিষেবা। \n\"নোট\" তৈরির মাধ্যমে যা ঘটছে তা সবার সাথে শেয়ার করুন 📡\n\"রিঅ্যাকশন\" গুলির মাধ্যমে যেকোনো নোট সম্পর্কে আপনার অনুভূতি ব্যাক্ত করতে পারেন 👍\nএকটি নতুন দুনিয়া ঘুরে দেখুন 🚀\n"
+poweredByMisskeyDescription: "{name} হল ওপেন সোর্স প্ল্যাটফর্ম
Misskey-এর সার্ভারগুলির একটি৷"
monthAndDay: "{day}/{month}"
search: "খুঁজুন"
notifications: "বিজ্ঞপ্তি"
@@ -12,12 +13,14 @@ fetchingAsApObject: "ফেডিভার্স থেকে খবর আন
ok: "ঠিক"
gotIt: "বুঝেছি"
cancel: "বাতিল"
+noThankYou: "না, ধন্যবাদ"
enterUsername: "ইউজারনেম লিখুন"
renotedBy: "{user} রিনোট করেছেন"
noNotes: "কোন নোট নেই"
noNotifications: "কোনো বিজ্ঞপ্তি নেই"
instance: "ইন্সট্যান্স"
settings: "সেটিংস"
+notificationSettings: "বিজ্ঞপ্তির সেটিংস"
basicSettings: "সাধারণ সেটিংস"
otherSettings: "অন্যান্য সেটিংস"
openInWindow: "নতুন উইন্ডোতে খুলা"
@@ -42,12 +45,20 @@ pin: "পিন করা"
unpin: "পিন সরান"
copyContent: "বিষয়বস্তু কপি করুন"
copyLink: "লিঙ্ক কপি করুন"
+copyLinkRenote: "রিনোট লিঙ্ক কপি করুন"
delete: "মুছুন"
deleteAndEdit: "মুছুন এবং সম্পাদনা করুন"
deleteAndEditConfirm: "আপনি কি এই নোটটি মুছে এটি সম্পাদনা করার বিষয়ে নিশ্চিত? আপনি এটির সমস্ত রিঅ্যাকশন, রিনোট এবং জবাব হারাবেন।"
addToList: "লিস্ট এ যোগ করুন"
+addToAntenna: "অ্যান্টেনা এ যোগ করুন"
sendMessage: "একটি বার্তা পাঠান"
+copyRSS: "RSS কপি করুন"
copyUsername: "ব্যবহারকারীর নাম কপি করুন"
+copyUserId: "ব্যবহারকারীর ID কপি করুন"
+copyNoteId: "নোটের ID কপি করুন"
+copyFileId: "ফাইল ID কপি করুন"
+copyFolderId: "ফোল্ডার ID কপি করুন"
+copyProfileUrl: "প্রোফাইল URL কপি করুন"
searchUser: "ব্যবহারকারী খুঁজুন..."
reply: "জবাব"
loadMore: "আরও দেখুন"
@@ -100,6 +111,8 @@ renoted: "রিনোট করা হয়েছে"
cantRenote: "এই নোটটি রিনোট করা যাবে না।"
cantReRenote: "রিনোটকে রিনোট করা যাবে না।"
quote: "উদ্ধৃতি"
+inChannelRenote: "চ্যানেলে রিনোট"
+inChannelQuote: "চ্যানেলে উদ্ধৃতি"
pinnedNote: "পিন করা নোট"
pinned: "পিন করা"
you: "আপনি"
@@ -108,7 +121,10 @@ sensitive: "সংবেদনশীল বিষয়বস্তু"
add: "যুক্ত করুন"
reaction: "প্রতিক্রিয়া"
reactions: "প্রতিক্রিয়া"
-reactionSetting: "রিঅ্যাকশন পিকারে যেসকল প্রতিক্রিয়া দেখানো হবে"
+emojiPicker: "ইমোজি পিকার"
+pinnedEmojisForReactionSettingDescription: "রিঅ্যাকশন দেয়ার সময় আপনি ইমোজিটিকে পিন করা এবং প্রদর্শিত হওয়ার জন্য সেট করতে পারেন।"
+pinnedEmojisSettingDescription: "ইমোজি ইনপুট দেয়ার সময় আপনি ইমোজিটিকে পিন করা এবং প্রদর্শিত হওয়ার জন্য সেট করতে পারেন।"
+emojiPickerDisplay: "পিকার ডিসপ্লে"
reactionSettingDescription2: "পুনরায় সাজাতে টেনে আনুন, মুছতে ক্লিক করুন, যোগ করতে + টিপুন।"
rememberNoteVisibility: "নোটের দৃশ্যমান্যতার সেটিংস মনে রাখুন"
attachCancel: "অ্যাটাচমেন্ট সরান "
@@ -341,6 +357,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "hCaptcha চালু করুন"
hcaptchaSiteKey: "সাইট কী"
hcaptchaSecretKey: "সিক্রেট কী"
+mcaptchaSiteKey: "সাইট কী"
+mcaptchaSecretKey: "সিক্রেট কী"
recaptcha: "reCAPTCHA"
enableRecaptcha: "reCAPTCHA চালু করুন"
recaptchaSiteKey: "সাইট কী"
@@ -393,7 +411,6 @@ share: "শেয়ার"
notFound: "পাওয়া যায়নি"
notFoundDescription: "এই URL-এর সাথে সম্পর্কিত কোনো পৃষ্ঠা নেই।"
uploadFolder: "আপলোডের জন্য ডিফল্ট ফোল্ডার"
-cacheClear: "ক্যাশ পরিষ্কার করুন"
markAsReadAllNotifications: "সমস্ত বিজ্ঞপ্তিগুলি পঠিত হিসাবে চিহ্নিত করুন"
markAsReadAllUnreadNotes: "সমস্ত নোটগুলি পঠিত হিসাবে চিহ্নিত করুন"
markAsReadAllTalkMessages: "সমস্ত মেসেজ পঠিত হিসাবে চিহ্নিত করুন"
@@ -795,8 +812,6 @@ makeReactionsPublicDescription: "আপনার পূর্ববর্তী
classic: "ক্লাসিক"
muteThread: "থ্রেড মিউট করুন"
unmuteThread: "থ্রেড আনমিউট করুন"
-ffVisibility: "অনুসরণ/অনুসরণকারীদের দৃশ্যমান্যতা"
-ffVisibilityDescription: "আপনি কাকে অনুসরণ করেন এবং কে আপনাকে অনুসরণ করে, সেটা কারা দেখতে পাবে তা নির্ধারণ করে।"
continueThread: "আরো থ্রেড দেখুন"
deleteAccountConfirm: "আপনার অ্যাকাউন্ট মুছে ফেলা হবে। ঠিক আছে?"
incorrectPassword: "আপনার দেওয়া পাসওয়ার্ডটি ভুল।"
@@ -840,6 +855,7 @@ youFollowing: "অনুসরণ করা হচ্ছে"
icon: "প্রোফাইল ছবি"
replies: "জবাব"
renotes: "রিনোট"
+sourceCode: "সোর্স কোড"
flip: "উল্টান"
_role:
priority: "অগ্রাধিকার"
@@ -1038,6 +1054,7 @@ _2fa:
step3: "অ্যাপে প্রদর্শিত টোকেনটি লিখুন এবং আপনার কাজ শেষ।"
step4: "আপনাকে এখন থেকে লগ ইন করার সময়, এইভাবে টোকেন লিখতে হবে।"
securityKeyInfo: "আপনি একটি হার্ডওয়্যার সিকিউরিটি কী ব্যবহার করে লগ ইন করতে পারেন যা FIDO2 বা ডিভাইসের ফিঙ্গারপ্রিন্ট সেন্সর বা পিন সমর্থন করে৷"
+ renewTOTPCancel: "না, ধন্যবাদ"
_permissions:
"read:account": "অ্যাকাউন্টের তথ্য দেখুন"
"write:account": "অ্যাকাউন্টের তথ্য সম্পাদন করুন"
@@ -1176,6 +1193,7 @@ _profile:
changeBanner: "ব্যানার পরিবর্তন করুন"
_exportOrImport:
allNotes: "সকল নোট"
+ clips: "ক্লিপ"
followingList: "অনুসরণ করা হচ্ছে"
muteList: "মিউট"
blockingList: "ব্লক"
@@ -1327,3 +1345,6 @@ _webhookSettings:
_moderationLogTypes:
suspend: "স্থগিত করা"
resetPassword: "পাসওয়ার্ড রিসেট করুন"
+_reversi:
+ total: "মোট"
+
diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml
index 62ef511bc..2ea6bd930 100644
--- a/locales/ca-ES.yml
+++ b/locales/ca-ES.yml
@@ -121,10 +121,16 @@ sensitive: "NSFW"
add: "Afegir"
reaction: "Reaccions"
reactions: "Reaccions"
-reactionSetting: "Reaccions a mostrar al selector de reaccions"
+emojiPicker: "Selecció d'emojis"
+pinnedEmojisForReactionSettingDescription: "Selecciona l'emoji amb el qual reaccionar"
+pinnedEmojisSettingDescription: "Selecciona l'emoji amb el qual reaccionar"
+emojiPickerDisplay: "Visualitza el selector d'emojis"
+overwriteFromPinnedEmojisForReaction: "Reemplaça els emojis de la reacció"
+overwriteFromPinnedEmojis: "Sobreescriu des dels emojis fixats"
reactionSettingDescription2: "Arrossega per reordenar, fes clic per suprimir, prem \"+\" per afegir."
rememberNoteVisibility: "Recorda la configuració de visibilitat de les notes"
attachCancel: "Eliminar el fitxer adjunt"
+deleteFile: "Esborrar l'arxiu "
markAsSensitive: "Marcar com a NSFW"
unmarkAsSensitive: "Deixar de marcar com a sensible"
enterFileName: "Defineix nom del fitxer"
@@ -157,6 +163,9 @@ addEmoji: "Afegeix un emoji"
settingGuide: "Configuració recomanada"
cacheRemoteFiles: "Emmagatzemar fitxers remots"
cacheRemoteFilesDescription: "Quan aquesta opció està desactivada, els fitxers remots es carreguen directament des del servidor remot. Si desactiveu això, es reduirà l'ús d'emmagatzematge, però augmentarà el trànsit, ja que no es generaran miniatures."
+youCanCleanRemoteFilesCache: "Pots netejar la memòria cau fent clic al botó de la paperera🗑️ a l'administrador d'arxius."
+cacheRemoteSensitiveFiles: "Posar a la memòria cau arxius remots sensibles"
+cacheRemoteSensitiveFilesDescription: "Quan aquesta opció és desactiva, els arxius remots sensibles es carregant directament del servidor d'origen sense que es guardin a la memòria cau."
flagAsBot: "Marca aquest compte com a bot"
flagAsBotDescription: "Marca aquest compte com a bot"
flagAsCat: "Marca aquest compte com a gat"
@@ -165,6 +174,7 @@ flagShowTimelineReplies: "Mostra les respostes a la línia de temps"
flagShowTimelineRepliesDescription: "Mostra les respostes a la línia de temps"
autoAcceptFollowed: "Aprova automàticament les sol·licituds de seguiment dels usuaris que segueixes"
addAccount: "Afegeix un compte"
+reloadAccountsList: "Recarregar la llista de contactes"
loginFailed: "S'ha produït un error al accedir."
showOnRemote: "Navega més en el perfil original"
general: "General"
@@ -191,6 +201,7 @@ perHour: "Per hora"
perDay: "Per dia"
stopActivityDelivery: "Deixa d'enviar activitats"
blockThisInstance: "Deixa d'enviar activitats"
+silenceThisInstance: "Silencia aquesta instància "
operations: "Accions"
software: "Programari"
version: "Versió"
@@ -209,6 +220,9 @@ clearQueueConfirmText: "Les notes no lliurades que quedin a la cua no es federar
clearCachedFiles: "Esborra la memòria cau"
clearCachedFilesConfirm: "Segur que voleu eliminar tots els fitxers de la memòria cau?"
blockedInstances: "Instàncies bloquejades"
+blockedInstancesDescription: "Llista els enllaços d'amfitrió de les instàncies que vols bloquejar separades per un salt de pàgina. Les instàncies llistades no podran comunicar-se amb aquesta instància."
+silencedInstances: "Instàncies silenciades"
+silencedInstancesDescription: "Llista els enllaços d'amfitrió de les instàncies que vols silenciar. Tots els comptes de les instàncies llistades s'establiran com silenciades i només podran fer sol·licitacions de seguiment, i no podran mencionar als comptes locals si no els segueixen. Això no afectarà les instàncies bloquejades."
muteAndBlock: "Silencia i bloca"
mutedUsers: "Usuaris silenciats"
blockedUsers: "Usuaris bloquejats"
@@ -223,9 +237,12 @@ preview: "Vista prèvia"
default: "Per defecte"
defaultValueIs: "Per defecte: {value}"
noCustomEmojis: "Cap emoji personalitzat"
+noJobs: "No hi ha feines"
federating: "Federant"
blocked: "Bloquejat"
suspended: "Suspés"
+all: "tot"
+subscribing: "Subscrit a"
publishing: "S'està publicant"
notResponding: "Sense resposta"
instanceFollowing: "Seguits del servidor"
@@ -250,11 +267,31 @@ removed: "Eliminat"
removeAreYouSure: "Segur que voleu retirar «{x}»?"
deleteAreYouSure: "Segur que voleu retirar «{x}»?"
resetAreYouSure: "Segur que voleu restablir-ho?"
+areYouSure: "Està segur?"
saved: "S'ha desat"
messaging: "Xat"
upload: "Puja"
+keepOriginalUploading: "Guarda la imatge original"
+keepOriginalUploadingDescription: "Guarda la imatge pujada com hi és. Si està apagat, una versió per a la visualització a la xarxa serà generada quan sigui pujada."
+fromDrive: "Des de la unitat"
+fromUrl: "Des d'un enllaç"
+uploadFromUrl: "Carrega des d'un enllaç"
+uploadFromUrlDescription: "Enllaç del fitxer que vols carregar"
+uploadFromUrlRequested: "Càrrega sol·licitada"
+uploadFromUrlMayTakeTime: "La càrrega des de l'enllaç pot prendre un temps"
+explore: "Explora"
+messageRead: "Vist"
+noMoreHistory: "No hi resta més per veure"
+startMessaging: "Començar a xatejar"
+nUsersRead: "Vist per {n}"
+agreeTo: "Accepto que {0}"
+agree: "Hi estic d'acord"
+agreeBelow: "Hi estic d'acord amb el següent"
+basicNotesBeforeCreateAccount: "Notes importants"
+termsOfService: "Condicions d'ús"
start: "Comença"
home: "Inici"
+remoteUserCaution: "Ja que aquest usuari resideix a una instància remota, la informació mostrada es podria trobar incompleta."
activity: "Activitat"
images: "Imatges"
image: "Imatges"
@@ -270,20 +307,42 @@ dark: "Fosc"
lightThemes: "Temes clars"
darkThemes: "Temes foscos"
syncDeviceDarkMode: "Sincronitza el mode fosc amb la configuració del dispositiu"
+drive: "Unitat"
+fileName: "Nom del Fitxer"
+selectFile: "Selecciona fitxers"
+selectFiles: "Selecciona fitxers"
+selectFolder: "Selecció de carpeta"
+selectFolders: "Selecció de carpeta"
renameFile: "Canvia el nom del fitxer"
folderName: "Nom de la carpeta"
createFolder: "Crea una carpeta"
renameFolder: "Canvia el nom de la carpeta"
deleteFolder: "Elimina la carpeta"
+folder: "Carpeta "
addFile: "Afegeix un fitxer"
+emptyDrive: "La teva unitat és buida"
emptyFolder: "La carpeta està buida"
unableToDelete: "No es pot eliminar"
+inputNewFileName: "Introduïu el nom de fitxer nou"
+inputNewDescription: "Inserta una nova llegenda"
+inputNewFolderName: "Introduïu el nom de la carpeta nova"
+circularReferenceFolder: "La carpeta destinatària és una subcarpeta de la carpeta a la qual la desitges moure"
+hasChildFilesOrFolders: "No és possible esborrar aquesta carpeta ja que no és buida"
copyUrl: "Copia l'URL"
rename: "Canvia el nom"
+avatar: "Icona"
+banner: "Bàner"
+displayOfSensitiveMedia: "Visualització de contingut sensible"
+whenServerDisconnected: "Quan es perdi la connexió al servidor"
+disconnectedFromServer: "Desconnectat pel servidor"
reload: "Actualitza"
doNothing: "Ignora"
-accept: "Accepta"
-normal: "Nomal"
+reloadConfirm: "Vols recarregar?"
+watch: "Veure"
+unwatch: "Deixar de veure"
+accept: "Acceptar"
+reject: "Denegar"
+normal: "Normal"
instanceName: "Nom del servidor"
instanceDescription: "Descripció del servidor"
maintainerName: "Nom de l'administrador"
@@ -301,25 +360,56 @@ connectService: "Connecta"
disconnectService: "Desconnecta"
enableLocalTimeline: "Activa la línia de temps local"
enableGlobalTimeline: "Activa la línia de temps global"
+disablingTimelinesInfo: "Fins i tot si aquestes línies de temps són desactivades, els administradors i els moderadors poden continuar visualitzant per conveniència."
registration: "Registre"
+enableRegistration: "Permet els registres d'usuaris"
invite: "Convida"
+driveCapacityPerLocalAccount: "Capacitat del disc per usuaris locals"
+driveCapacityPerRemoteAccount: "Capacitat del disc per usuaris remots"
+inMb: "En megabytes"
+bannerUrl: "Adreça URL del bàner"
+backgroundImageUrl: "Adreça URL de la imatge de fons"
basicInfo: "Informació bàsica"
pinnedUsers: "Usuaris fixats"
+pinnedUsersDescription: "Llista d'usuaris, separats per salts de línia, que seran fixats a la pestanya \"Explorar\"."
+pinnedPages: "Pàgines fixades"
+pinnedPagesDescription: "Escriu els camins de les pàgines que vols fixar a la pàgina d'inici d'aquesta instància. Separades per salts de línia."
+pinnedClipId: "ID del retall fixat"
pinnedNotes: "Nota fixada"
+hcaptcha: "hCaptcha"
+enableHcaptcha: "Activar hCaptcha"
+hcaptchaSiteKey: "Clau del lloc"
+hcaptchaSecretKey: "Clau secreta"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "Activar mCaptcha"
+mcaptchaSiteKey: "Clau del lloc"
+mcaptchaSecretKey: "Clau secreta"
+mcaptchaInstanceUrl: "Adreça URL del servidor mCaptcha"
+recaptcha: "reCAPTCHA"
+enableRecaptcha: "Activar reCAPTCHA"
+recaptchaSiteKey: "Clau del lloc"
+recaptchaSecretKey: "Clau secreta"
turnstile: "Turnstile"
enableTurnstile: "Activar Turnstile"
turnstileSiteKey: "Clau del lloc"
turnstileSecretKey: "Clau secreta"
+avoidMultiCaptchaConfirm: "Fer servir diferents sistemes de Captcha a la vegada pot causar problemes entre ells. Vols desactivar els altres sistemes de Captcha activats? Si els vols mantenir actius fes clic a cancel·lar."
antennas: "Antena"
manageAntennas: "Gestiona les antenes"
+name: "Nom"
antennaSource: "Font de l'antena"
antennaKeywords: "Paraules clau a seguir"
antennaExcludeKeywords: "Paraules clau a excloure"
antennaKeywordsDescription: "Separar amb espais per la condició AND o amb salts de línia per la condició OR."
notifyAntenna: "Notifica'm les publicacions noves"
withFileAntenna: "Només les publicacions amb fitxers"
+enableServiceworker: "Activar les notificacions al navegador"
antennaUsersDescription: "Llistar un nom d'usuari per línia"
+caseSensitive: "Sensible a majúscules i minúscules "
+withReplies: "Inclou respostes"
+connectedTo: "Aquests comptes hi són connectats"
notesAndReplies: "Amb respostes"
+withFiles: "Incloure arxius"
silence: "Silencia"
silenceConfirm: "Segur que vols silenciar aquest usuari?"
unsilence: "Deixa de silenciar"
@@ -335,79 +425,1594 @@ userList: "Llistes"
about: "Informació"
aboutMisskey: "Quant a Misskey"
administrator: "Administrador/a"
+token: "Codi de verificació"
+2fa: "Autenticació de doble factor"
+setupOf2fa: "Configurar l'autenticació de doble factor"
+totp: "Aplicació d'autenticació"
+totpDescription: "Escriu una contrasenya d'un sol us fent servir l'aplicació d'autenticació"
moderator: "Moderador/a"
moderation: "Moderació"
+moderationNote: "Nota de moderació "
+addModerationNote: "Afegir una nota de moderació "
+moderationLogs: "Registre de moderació "
nUsersMentioned: "{n} usuaris mencionats"
+securityKeyAndPasskey: "Clau de seguretat / Clau de pas"
securityKey: "Clau de seguretat"
+lastUsed: "Fet servir per última vegada"
+lastUsedAt: "Fet servir per última vegada: {t}"
unregister: "Cancel·la el registre"
passwordLessLogin: "Inici de sessió sense contrasenya"
+passwordLessLoginDescription: "Permet l'inici de sessió sense contrasenya fent servir només una Clau de seguretat/Clau de pas"
resetPassword: "Restableix la contrasenya"
newPasswordIs: "La contrasenya nova és «{password}»"
reduceUiAnimation: "Redueix les animacions de la interfície"
share: "Comparteix"
notFound: "No s'ha trobat"
+notFoundDescription: "No es troba cap pàgina que correspongui a aquesta adreça"
+uploadFolder: "Carpeta per defecte per pujades"
+markAsReadAllNotifications: "Marca totes les notificacions com a llegides"
markAsReadAllUnreadNotes: "Marca-ho tot com a llegit"
+markAsReadAllTalkMessages: "Marcar tots els missatges com llegits"
help: "Ajuda"
+inputMessageHere: "Escriu aquí el teu missatge "
+close: "Tancar"
invites: "Convida"
+members: "Membres"
+transfer: "Transferir"
+title: "Títol"
+text: "Text"
+enable: "Habilita"
next: "Següent"
+retype: "Torneu a introduir-la"
noteOf: "Publicació de: {user}"
+quoteAttached: "Frase adjunta"
+quoteQuestion: "Vols annexar-la com a cita?"
+noMessagesYet: "Encara no hi ha missatges"
+newMessageExists: "Has rebut un nou missatge"
+onlyOneFileCanBeAttached: "Només pots adjuntar un fitxer a un missatge"
+signinRequired: "Si us plau, Registra't o inicia la sessió abans de continuar"
invitations: "Convida"
+invitationCode: "Codi d'invitació"
+checking: "Comprovació en curs..."
+available: "Disponible"
+unavailable: "No és disponible"
+usernameInvalidFormat: "Pots fer servir lletres (majúscules i minúscules), números i barres baixes (\"_\")"
+tooShort: "Massa curt"
+tooLong: "Massa llarg"
+weakPassword: "Contrasenya insegura"
+normalPassword: "Bona contrasenya"
+strongPassword: "Contrasenya segura"
+passwordMatched: "Correcte!"
+passwordNotMatched: "No coincideix"
+signinWith: "Inicia sessió amb amb {x}"
+signinFailed: "Autenticació sense èxit. Intenta-ho un altre cop utilitzant la contrasenya i el nom correctes."
+or: "O"
+language: "Idioma"
+uiLanguage: "Idioma de l'interfície"
+aboutX: "Respecte a {x}"
+emojiStyle: "Estil d'emoji"
+native: "Nadiu"
+disableDrawer: "No mostrar els menús en calaixos"
+showNoteActionsOnlyHover: "Només mostra accions de la nota en passar amb el cursor"
+noHistory: "No hi ha un registre previ"
+signinHistory: "Historial d'autenticacions"
+enableAdvancedMfm: "Habilitar l'MFM avançat"
+enableAnimatedMfm: "Habilitar l'MFM amb moviment"
+doing: "Processant..."
+category: "Categoria"
tags: "Etiquetes"
docSource: "Font del document"
createAccount: "Crea un compte"
existingAccount: "Compte existent"
regenerate: "Regenera"
fontSize: "Mida del text"
+mediaListWithOneImageAppearance: "Altura de la llista de fitxers amb una única imatge"
+limitTo: "Limita a {x}"
noFollowRequests: "No tens sol·licituds de seguiment"
+openImageInNewTab: "Obre imatges a una nova pestanya"
dashboard: "Panell de control"
local: "Local"
remote: "Remot"
total: "Total"
+weekOverWeekChanges: "Canvis l'última setmana"
+dayOverDayChanges: "Canvis ahir"
appearance: "Aparença"
clientSettings: "Configuració del client"
accountSettings: "Configuració del compte"
+promotion: "Promocionat"
+promote: "Promoure"
+numberOfDays: "Nombre de dies"
hideThisNote: "Amaga la publicació"
showFeaturedNotesInTimeline: "Mostra publicacions destacades en la línia de temps"
+objectStorage: "Emmagatzematge d'objectes\n"
+useObjectStorage: "Utilitzar l'emmagatzematge d'objectes"
+objectStorageBaseUrl: "Base d'enllaç"
+objectStorageBaseUrlDesc: "Prefix d'enllaç utilitzat per a fer referencia als fitxers. Especifica l'enllaç del teu CDN o Proxy si n'estàs utilitzant qualsevol, en cas contrari, especifica l'enllaç al que es pot accedir públicament segons la guia de servei que vosté utilitza.\nPer l'ús d'S3 utilitza 'https://
.s3.amazonaws.com' I per a GCS o serveis equivalents utilitza 'https://storage.googleapis.com/'."
+objectStorageBucket: "Dipòsit "
+objectStorageBucketDesc: "Escriu el nom del dipòsit que fas servir al teu proveïdor d'emmagatzematge "
+objectStoragePrefix: "Prefix"
+objectStoragePrefixDesc: "Els fitxers es deixaren a directoris amb aquest prefix"
+objectStorageEndpoint: "Endpoint"
+objectStorageEndpointDesc: "Deixa'l buit si fas servir AWS S3, si no és així específica un punt d'entrada com '' o ':', depenent del servei que facis servir."
+objectStorageRegion: "Regió "
+objectStorageRegionDesc: "Especifica una regió com 'xx-east-1'. Si el teu servei no diferència regions has de posar 'us-east-1'. Deixa'l buit si fas servir variables d'entorn o un arxiu de configuració d'AWS."
+objectStorageUseSSL: "Fes servir SSL"
+objectStorageUseSSLDesc: "Desactiva'l si no tens pensat fer servir HTTPS per les connexions de l'API"
+objectStorageUseProxy: "Connectar-se mitjançant un Proxy"
+objectStorageUseProxyDesc: "Desactiva'l si no faràs servir un Proxy per les connexions de l'API"
+objectStorageSetPublicRead: "Configurar les pujades com públiques "
+s3ForcePathStyleDesc: "Si s3ForcePathStyle es troba activat el nom del dipòsit s'ha d'incloure a l'adreça URL en comtes del nom del host. Potser que necessitis activar-ho quan facis servir, per exemple, Minio a un servidor propi."
+serverLogs: "Registres del servidor"
+deleteAll: "Esborrar tot"
+showFixedPostForm: "Mostrar el formulari per escriure a l'inici de la línia de temps"
+showFixedPostFormInChannel: "Mostrar el formulari d'escriptura al principi de la línia de temps (Canals)"
+withRepliesByDefaultForNewlyFollowed: "Inclou les respostes d'usuaris nous seguits a la línia de temps per defecte."
newNoteRecived: "Hi ha publicacions noves"
+sounds: "Sons"
+sound: "So"
+listen: "Escoltar"
+none: "Res"
+showInPage: "Mostrar a la pàgina "
+popout: "Finestra emergent"
+volume: "Volum"
+masterVolume: "Volum principal"
+notUseSound: "Sense so"
+useSoundOnlyWhenActive: "Reproduir sons només quan Misskey estigui actiu"
+details: "Detalls"
+chooseEmoji: "Tria un emoji"
+unableToProcess: "L'operació no pot ser completada "
+recentUsed: "Utilitzat recentment"
+install: "Instal·lació "
+uninstall: "Desinstal·lar "
+installedApps: "Aplicacions autoritzades "
+nothing: "No hi ha res per veure aquí "
installedDate: "Data d'instal·lació"
+lastUsedDate: "Utilitzat per última vegada"
state: "Estat"
sort: "Ordena"
ascendingOrder: "Ascendent"
descendingOrder: "Descendent"
+scratchpad: "Bloc de proves"
+scratchpadDescription: "El bloc de proves proporciona un entorn experimental per AiScript. Pot escriure i verificar els resultats que interactuen amb Misskey."
+output: "Sortida"
+script: "Script"
+disablePagesScript: "Desactivar AiScript a les pàgines "
+updateRemoteUser: "Actualitzar la informació de l'usuari remot"
+unsetUserAvatar: "Desactivar l'avatar "
+unsetUserAvatarConfirm: "Segur que vols desactivar l'avatar?"
+unsetUserBanner: "Desactivar el bàner "
+unsetUserBannerConfirm: "Segur que vols desactivar el bàner?"
+deleteAllFiles: "Esborrar tots els arxius"
+deleteAllFilesConfirm: "Segur que vols esborrar tots els arxius?"
+removeAllFollowing: "Deixar de seguir tots els usuaris seguits"
+removeAllFollowingDescription: "El fet d'executar això, et farà deixar de seguir a tots els usuaris de {host}. Si us plau, executa això si l'amfitrió, per exemple, ja no existeix."
+userSuspended: "Aquest usuari ha sigut suspès"
+userSilenced: "Aquest usuari està sent silenciat"
+yourAccountSuspendedTitle: "Aquest compte és suspès"
+yourAccountSuspendedDescription: "Aquest compte ha sigut suspès a causa de la violació de les condicions d'ús o similars. Contacta l'administrador si en vol saber més. Si us plau, no en faci un altre compte."
+tokenRevoked: "Codi de seguretat no vàlid"
+tokenRevokedDescription: "La petició més recent ha estat denegada perquè contenia un codi de seguretat no vàlid. Actualitza la pàgina i torna-ho a provar."
+accountDeleted: "Compte eliminat amb èxit"
+accountDeletedDescription: "Aquest compte ha sigut eliminat"
+menu: "Menú"
+divider: "Divisor"
+addItem: "Afegir element"
+rearrange: "Torna a ordenar"
+relays: "Relés"
+addRelay: "Afegeix relés"
+inboxUrl: "Enllaç de la safata d'entrada"
+addedRelays: "Relés afegits"
+serviceworkerInfo: "És obligatòria l'activació per a obtenir notificacions push"
deletedNote: "Publicacions eliminades"
invisibleNote: "Publicacions amagades"
+enableInfiniteScroll: "Carrega més automàticament\n"
+visibility: "Visibilitat"
+poll: "Enquesta"
+useCw: "Amaga el contingut"
+enablePlayer: "Obre el reproductor de vídeo"
+disablePlayer: "Tanca el reproductor de vídeo"
+expandTweet: "Expandir post"
+themeEditor: "Editor de temes"
+description: "Descripció"
+describeFile: "Afegir subtitulació"
+enterFileDescription: "Afegeix un títol"
+author: "Autor"
+leaveConfirm: "Hi ha canvis sense guardar. Els vols descartar?"
+manage: "Administració"
+plugins: "Extensions"
+preferencesBackups: "Configuracions de les Còpies de seguretat"
+deck: "Escriptori"
+undeck: "Tanca l'escriptori"
+useBlurEffectForModal: "Utilitzar l'efecte de difuminació a modals"
+useFullReactionPicker: "Utilitza el cercador de reaccions d'escala sencera"
+width: "Amplada"
+height: "Alçària"
+large: "Gran"
+medium: "Mitjà"
+small: "Petit"
+generateAccessToken: "Genera codi d'accés"
+permission: "Permisos"
+adminPermission: "Permisos d'administrador "
+enableAll: "Habilita tot"
+disableAll: "Deshabilita tot"
+tokenRequested: "Donar accés al compte"
+pluginTokenRequestedDescription: "Aquest connector podrà fer servir tots els permisos configurats aquí."
+notificationType: "Tipus de notificació "
+edit: "Editar"
+emailServer: "Servidor de correu electrònic "
+enableEmail: "Activar l'enviament de correus electrònics "
+emailConfigInfo: "Es fa servir per confirmar el teu correu quan et registres o oblides la contrasenya "
+email: "Correu electrònic"
+emailAddress: "Adreça de correu electrònic"
+smtpConfig: "Configuració del servidor SMTP"
smtpHost: "Amfitrió"
+smtpPort: "Port"
smtpUser: "Nom d'usuari"
smtpPass: "Contrasenya"
+emptyToDisableSmtpAuth: "No omplis el nom d'usuari i la contrasenya si vols deshabilitar l'autenticació SMTP"
+smtpSecure: "Fes servir SSL/TLS per connexions SMTP"
+smtpSecureInfo: "Desactiva això quan facis servir connexions STARTTLS"
+testEmail: "Prova l'enviament de correu "
+wordMute: "Silenciar paraules "
+hardWordMute: "Silenciar paraules fortes"
+regexpError: "Error de l'expressió regular "
+regexpErrorDescription: "S'ha produït un error a l'expressió regular a la línia {line} de les paraules silenciades {tab}:"
+instanceMute: "Silenciar servidor"
+userSaysSomething: "{name} n'ha dit alguna cosa"
+makeActive: "Activar"
+display: "Veure"
+copy: "Copiar"
+metrics: "Mètriques"
+overview: "Visió General"
+logs: "Registres"
+delayed: "Endarrerits "
+database: "Bases de dades"
+channel: "Canals"
+create: "Crear"
+notificationSetting: "Paràmetres de notificacions"
+notificationSettingDesc: "Selecciona els tipus de notificacions que es mostraran"
+useGlobalSetting: "Fer servir la configuració global"
+useGlobalSettingDesc: "Si s'activa, es farà servir la configuració de notificacions del teu comte. Si no s'activa es poden fer configuracions individuals."
+other: "Altre"
+regenerateLoginToken: "Regenerar clau de seguretat d'inici de sessió"
+regenerateLoginTokenDescription: "Regenera la clau de seguretat que es fa servir internament durant l'inici de sessió. Normalment aquesta acció no és necessària. Si es regenera es tancarà la sessió a tots els dispositius amb una sessió activa."
+theKeywordWhenSearchingForCustomEmoji: "Cercar un emoji personalitzat "
+setMultipleBySeparatingWithSpace: "Separa múltiples entrades amb un espai"
+fileIdOrUrl: "ID de l'arxiu o URL"
+behavior: "Comportament"
+sample: "Mostrar"
+abuseReports: "Denúncies "
+reportAbuse: "Denuncia un abús "
+reportAbuseRenote: "Denuncia una renota"
+reportAbuseOf: "Denuncia a {name}"
+fillAbuseReportDescription: "Omple els detalls sobre aquesta denúncia. Si la denúncia és sobre una nota en concret inclou l'adreça URL."
+abuseReported: "La teva denúncia s'ha enviat. Moltes gràcies."
+reporter: "Denunciant "
+reporteeOrigin: "Origen de la denúncia "
+reporterOrigin: "Origen del denunciant"
+forwardReport: "Transferir la denúncia a una instància remota"
+forwardReportIsAnonymous: "En comptes del teu compte, es farà servir un compte anònim com a denunciat a la instància remota."
+send: "Enviar"
+abuseMarkAsResolved: "Marcar la denúncia com a resolta"
+openInNewTab: "Obre a una pestanya nova"
+openInSideView: "Obre a una vista lateral"
+defaultNavigationBehaviour: "Navegació per defecte"
+editTheseSettingsMayBreakAccount: "Editar aquestes opcions pot deixar inoperatiu el teu compte"
+instanceTicker: "Informació de notes de la instància "
+waitingFor: "Esperant {x}"
+random: "Aleatori "
+system: "Sistema"
+switchUi: "Canviar interfície d'usuari "
+desktop: "Escriptori"
+clip: "Retalls"
+createNew: "Crear"
+optional: "Opcional"
+createNewClip: "Crear un nou Retall"
+unclip: "Treure Retall"
+confirmToUnclipAlreadyClippedNote: "Aquesta nota ja és inclosa al Retall \"{name}\". Vols treure-la d'aquest retall?"
+public: "Públic "
+private: "Privat"
+i18nInfo: "Misskey està sent traduït a diferents idiomes per voluntaris. Pots ajudar aquí {link}."
+manageAccessTokens: "Administrar claus de seguretat d'accés "
+accountInfo: "Informació del compte"
+notesCount: "Comptador de notes"
+repliesCount: "Nombre de respostes"
renotesCount: "Impulsos fets"
+repliedCount: "Nombre de respostes rebudes"
renotedCount: "Impulsos rebuts"
+followingCount: "Nombre de comptes seguits"
+followersCount: "Nombre de seguidors"
+sentReactionsCount: "Nombre de reaccions enviades"
+receivedReactionsCount: "Nombre de reaccions rebudes"
+pollVotesCount: "Nombre de vots enviats a enquestes"
+pollVotedCount: "Nombre de vots rebuts a les enquestes"
+yes: "Sí "
+no: "No"
+driveFilesCount: "Nombre de fitxers al Disc"
+driveUsage: "Utilització de l'espai del Disc"
+noCrawle: "Rebutjar la indexació dels buscadors"
+noCrawleDescription: "No permetis que els buscadors indexin el teu perfil, notes, pàgines, etc."
+lockedAccountInfo: "Tret que establiu la visibilitat de la nota a \"Només seguidors\", les vostres notes seran visibles per qualsevol persona, fins i tot si heu d'aprovar els seguidors manualment"
+alwaysMarkSensitive: "Marcar com a sensible per defecte"
+loadRawImages: "Carregar les imatges originals en comptes de miniatures "
+disableShowingAnimatedImages: "No reproduir imatges animades"
+highlightSensitiveMedia: "Ressalta els medis marcats com a sensibles"
+verificationEmailSent: "S'ha enviat un correu electrònic de verificació. Fes clic a l'enllaç per completar la verificació."
+notSet: "Sense definir"
+emailVerified: "El correu electrònic s'ha verificat"
+noteFavoritesCount: "Nombre de notes favorites "
+pageLikesCount: "Nombre de Pàgines que t'agraden "
+pageLikedCount: "Nombre d'agraïments rebuts a les Pàgines "
+contact: "Contacte"
+useSystemFont: "Fes servir la font per defecte del sistema"
+clips: "Retalls"
+experimentalFeatures: "Característiques experimentals"
+experimental: "Experimental"
+thisIsExperimentalFeature: "Aquesta és una característica experimental. La seva funcionalitat pot canviar, i pot ser que no funcioni degudament."
+developer: "Programador"
+makeExplorable: "Fes que el compte sigui visible a la secció \"Explorar\""
+makeExplorableDescription: "Si desactives aquesta opció, el teu compte no sortirà a la secció \"Explorar\""
+showGapBetweenNotesInTimeline: "Mostra una separació entre els articles a la línia de temps"
+duplicate: "Duplicat"
+left: "Esquerra"
+center: "Centre"
+wide: "Gran"
+narrow: "Estret"
+reloadToApplySetting: "Aquest ajust només s'aplicarà després de recarregar la pàgina. Vols fer-ho ara?"
+needReloadToApply: "Es requereix recarregar per reflectir aquesta opció "
+showTitlebar: "Mostra la barra del títol "
clearCache: "Esborra la memòria cau"
+onlineUsersCount: "{n} Usuaris es troben en línia "
+nUsers: "{n} Usuaris"
+nNotes: "{n} Notes"
+sendErrorReports: "Enviar informes d'error "
+sendErrorReportsDescription: "Quan s'activa, es compartirà amb Misskey informació detallada de l'error quan es trobi un problema això farà pujar la qualitat de Misskey.\nAixò inclourà informació com la versió del SO que fas servir, el navegador web que fas servir, la teva activitat a Misskey, etc."
+myTheme: "El meu tema"
+backgroundColor: "Color de fons"
+accentColor: "Color principal"
+textColor: "Color del text"
+saveAs: "Desar com..."
+advanced: "Avançat"
+advancedSettings: "Configuració avançada"
+value: "Valor"
+createdAt: "Creat el"
+updatedAt: "Actualitzat el"
+saveConfirm: "Desar canvis?"
+deleteConfirm: "Segur que vols esborrar?"
+invalidValue: "Valor invàlid."
+registry: "Registre "
+closeAccount: "Tancar el compte"
+currentVersion: "Versió actual"
+latestVersion: "Versió nova"
+youAreRunningUpToDateClient: "Ja estàs fent servir la versió més recent del client."
+newVersionOfClientAvailable: "Tens disponible una versió del client més recent."
+usageAmount: "Ús "
+capacity: "Capacitat"
+inUse: "Fet servir"
+editCode: "Editar el codi"
+apply: "Aplicar"
+receiveAnnouncementFromInstance: "Rep notificacions d'aquesta instància "
+emailNotification: "Notificacions per correu electrònic "
+publish: "Publicar"
+inChannelSearch: "Cerca al canal"
+useReactionPickerForContextMenu: "Fes clic al botó dret del ratolí per obrir el menú de reaccions"
+typingUsers: "{users} està/estàn Escrivint "
+jumpToSpecifiedDate: "Ves a una data concreta"
showingPastTimeline: "Estàs veient una línia de temps antiga"
+clear: "Tornar"
+markAllAsRead: "Marcar tot com llegit"
+goBack: "Tornar"
+unlikeConfirm: "Vols esborrar el teu m'agrada?"
+fullView: "Vista completa."
+quitFullView: "Sortir de la vista completa"
+addDescription: "Afegeix una descripció "
+userPagePinTip: "Podeu seleccionar \"Fixar al perfil\" del menú de notes individuals per mostrar les notes aquí."
+notSpecifiedMentionWarning: "Aquesta nota esmenta usuaris que no es troben com a destinataris"
info: "Informació"
+userInfo: "Informació de l'usuari"
+unknown: "Desconegut"
+onlineStatus: "Connectat"
+hideOnlineStatus: "Ocultar l'estat de connexió"
+hideOnlineStatusDescription: "Ocultant el teu estat de connexió redueix les funcionalitats d'algunes funcions com la cerca."
+online: "Connectat"
+active: "Actiu"
+offline: "Desconnectat"
+notRecommended: "No recomanat"
+botProtection: "Protecció contra bots"
+instanceBlocking: "Instàncies blocades/silenciades"
+selectAccount: "Seleccionar un compte"
+switchAccount: "Canviar de compte"
+enabled: "Activat"
+disabled: "Desactivat"
+quickAction: "Accions ràpides"
user: "Usuaris"
+administration: "Administració"
+accounts: "Comptes"
+switch: "Canvia"
+noMaintainerInformationWarning: "La informació de l'administrador no s'ha configurat"
+noBotProtectionWarning: "La protecció contra bots no s'ha configurat."
+configure: "Configurar"
+postToGallery: "Crear una nova publicació a la galeria"
+postToHashtag: "Pública a aquesta etiqueta"
+gallery: "Galeria"
+recentPosts: "Articles recents"
+popularPosts: "Articles populars"
+shareWithNote: "Comparteix amb una nota"
+ads: "Anuncis"
+expiration: ""
+startingperiod: "Inici"
+memo: "Recordatori"
+priority: "Prioritat"
+high: "Alta"
+middle: "Mitjà"
+low: "Baixa"
+emailNotConfiguredWarning: "Adreça de correu electrònic"
+ratio: "Proporció"
+previewNoteText: "Mostrar vista prèvia"
+customCss: "CSS personalitzat"
+customCssWarn: "Aquesta configuració només hauries de configurar-la si saps que fas. Si poses valors inadequats pots fer que el client deixi de funcionar correctament."
global: "Global"
+squareAvatars: "Mostrar avatars quadrats"
+sent: "Enviar"
+received: "Rebut"
+searchResult: "Resultats de la cerca"
+hashtags: "Etiquetes"
+troubleshooting: "Solucionar problemes"
+useBlurEffect: "Fes servir efectes de desenfocament a la interfície"
+learnMore: "Saber més "
+misskeyUpdated: "Misskey s'ha actualitzat "
+whatIsNew: "Mostra canvis"
+translate: "Traduir "
+translatedFrom: "Traduït del {x}"
+accountDeletionInProgress: "S'està produint l'eliminació del compte"
+usernameInfo: "Un nom que identifiqui el teu compte d'altres en aquest servidor. Pots fer servir lletres (a~z, A~Z), números (0~9) i guions baixos (_). Els noms d'usuari no es poden canviar després."
+aiChanMode: "Mode IA"
+devMode: "Mode desenvolupador"
+keepCw: "Mantenir els avisos de contingut"
+pubSub: "Comptes Pub/Sub"
+lastCommunication: "Última comunicació "
+resolved: "Resolt"
+unresolved: "Sense resoldre"
+breakFollow: "Deixar de seguir"
+breakFollowConfirm: "Vols deixar de seguir?"
+itsOn: "Activat"
+itsOff: "Desactivat"
+on: "Activar"
+off: "Desactivar"
+emailRequiredForSignup: "Demanar correu electrònic per registrar-se "
+unread: "Sense llegir"
+filter: "Filtrar"
+controlPanel: "Panel de control"
+manageAccounts: "Gestionar comptes"
+makeReactionsPublic: "Reaccions públiques "
+makeReactionsPublicDescription: "Això fa que totes les teves reaccions siguin visibles públicament "
+classic: "Clàssic "
+muteThread: "Silenciar el fil"
+unmuteThread: "Deixar de silenciar el fil"
+followingVisibility: "Visibilitat dels seguiments"
+followersVisibility: "Visibilitat dels seguidors"
+continueThread: "Veure la continuació del fil"
+deleteAccountConfirm: "Això eliminarà el teu compte irreversiblement. Procedir?"
+incorrectPassword: "Contrasenya incorrecta."
+voteConfirm: "Confirma el teu vot \"{choice}\""
+hide: "Amagar"
+useDrawerReactionPickerForMobile: "Mostrar el selector de reaccions com un calaix al mòbil "
+welcomeBackWithName: "Benvingut de nou, {name}"
+clickToFinishEmailVerification: "Si us plau, fes clic a [{ok}] per completar la verificació per correu electrònic "
+overridedDeviceKind: "Tipus de dispositiu"
+smartphone: "Telèfon intel·ligent"
+tablet: "Tauleta"
+auto: "Automàtic "
+themeColor: "Color del tema"
+size: "Mida"
+numberOfColumn: "Nombre de columnes"
searchByGoogle: "Cercar"
+instanceDefaultLightTheme: "Tema clar per defecte de tota la instància "
+instanceDefaultDarkTheme: "Tema fosc per defecte de tota la instància "
+instanceDefaultThemeDescription: "Introdueix el codi del tema en format d'objecte"
+mutePeriod: "Duració del silenci"
+period: "Límit de temps"
+indefinitely: "Permanent"
+tenMinutes: "10 minuts"
+oneHour: "1 hora"
+oneDay: "Un dia"
+oneWeek: "Una setmana"
+oneMonth: "Un mes"
+reflectMayTakeTime: "Això pot trigar una estona a tenir efecte"
+failedToFetchAccountInformation: "No es pot obtenir la informació del compte"
+rateLimitExceeded: "S'ha arribat al màxim de peticions"
+cropImage: "Retalla la imatge"
+cropImageAsk: "Vols retallar la imatge?"
+cropYes: "Retallar"
+cropNo: "Fer servir tal qual"
file: "Fitxers"
+recentNHours: "Últimes {n} hores"
+recentNDays: "Últims {n} dies"
+noEmailServerWarning: "Correu electrònic del servidor sense configurar"
+thereIsUnresolvedAbuseReportWarning: "Hi ha informes sense solucionar."
+recommended: "Recomanat"
+check: "Verificar"
+driveCapOverrideLabel: "Canvia la capacitat del Disc per aquest usuari"
+driveCapOverrideCaption: "Restableix la mida original posant un valor de 0 o menys."
+requireAdminForView: "Has de ser administrador per poder veure això."
+isSystemAccount: "Un compte creat i operat automàticament pel sistema."
+typeToConfirm: "Si us plau, escriu {x} per confirmar"
+deleteAccount: "Esborrar el compte"
+document: "Documentació"
+numberOfPageCache: "Nombre de pàgines a la memòria cau"
+numberOfPageCacheDescription: "Incrementant aquest nombre farà que millori l'experiència de l'usuari, però es farà servir més memòria al dispositiu de l'usuari."
+logoutConfirm: "Vols sortir?"
+lastActiveDate: "Fet servir per última vegada"
+statusbar: "Barra d'estat"
+pleaseSelect: "Selecciona una opció"
+reverse: "Invertir"
+colored: "Colorit"
+refreshInterval: "Interval d'actualització "
+label: "Etiqueta"
+type: "Tipus"
+speed: "Velocitat"
+slow: "Lent"
+fast: "Ràpid "
+sensitiveMediaDetection: "Detecció de contingut sensible"
+localOnly: "Només local"
+remoteOnly: "Només remot"
+failedToUpload: "Ha fallat la pujada"
+cannotUploadBecauseInappropriate: "Aquest fitxer no es pot pujar perquè s'ha trobat que algunes parts són inapropiades."
+cannotUploadBecauseNoFreeSpace: "Ha fallat la pujada del fitxer perquè no hi ha capacitat al Disc."
+cannotUploadBecauseExceedsFileSizeLimit: "Aquest fitxer no es pot pujar perquè supera la mida permesa."
+beta: "Proves"
+enableAutoSensitive: "Marcar com a sensible automàticament "
+enableAutoSensitiveDescription: "Permet la detecció i el marcat automàtic dels mitjans sensibles fent servir aprenentatge automàtic quan sigui possible. Si aquesta opció es troba desactivada potser que estigui activada per a tota la instància. "
+activeEmailValidationDescription: "Activa la validació estricta de comptes de correu electrònic, inclou la validació d'adreces d'un sol ús i si es possible comunicar-se amb aquestes. Quan es troba desactivada només es vàlida el format del correu electrònic."
+navbar: "Barra de navegació "
+shuffle: "Aleatori"
+account: "Compte"
+move: "Mou"
+pushNotification: "Enviament de notificacions"
+subscribePushNotification: "Activar l'enviament de notificacions"
+unsubscribePushNotification: "Desactivar l'enviament de notificacions"
+pushNotificationAlreadySubscribed: "L'enviament de notificacions ja és activat"
+pushNotificationNotSupported: "El teu navegador o la teva instància no suporta l'enviament de notificacions "
+sendPushNotificationReadMessage: "Esborrar les notificacions enviades quan s'hagin llegit"
+sendPushNotificationReadMessageCaption: "Això pot fer que el teu dispositiu consumeixi més bateria"
+windowMaximize: "Maximitzar "
+windowMinimize: "Minimitzar"
+windowRestore: "Restaurar"
+caption: "Llegenda"
+loggedInAsBot: "Identificat com a bot"
+tools: "Eines"
+cannotLoad: "No es pot carregar"
+numberOfProfileView: "Visualitzacions del perfil"
+like: "M'agrada "
+unlike: "Treure m'agrada "
+numberOfLikes: "M'agraden "
+show: "Veure"
+neverShow: "No mostrar més "
+remindMeLater: "Recorda-m'ho més tard"
+didYouLikeMisskey: "T'està agradant Misskey?"
+pleaseDonate: "A {host} fem servir el software lliure Misskey. Considera fer un donatiu a Misskey perquè pugui continuar el seu desenvolupament!"
+roles: "Rols"
+role: "Rols"
+noRole: "No s'han trobat rols"
+normalUser: "Usuari normal"
+undefined: "Sense definir"
+assign: "Assignar "
+unassign: "Treure"
+color: "Color"
+manageCustomEmojis: "Gestiona els emojis personalitzats"
+manageAvatarDecorations: "Gestiona les decoracions dels avatars "
+youCannotCreateAnymore: "Has arribat al màxim de creacions"
+cannotPerformTemporary: "Temporalment no disponible"
+cannotPerformTemporaryDescription: "Aquesta acció no es pot dur a terme temporalment per arribar al seu límit d'execució. Pots esperar una mica i tornar-ho a intentar."
+invalidParamError: "Paràmetres incorrectes "
+invalidParamErrorDescription: "Els paràmetres demanats no són correctes. Normalment això es deu a un error, però també pot ser a alguna entrada excedint els límits o similar."
+permissionDeniedError: "Operació no permesa "
+permissionDeniedErrorDescription: "Aquest compte no té suficients permisos per dur a terme aquesta acció "
+preset: "Predefinit"
+selectFromPresets: "Escull des dels predefinits"
+achievements: "Assoliments"
+gotInvalidResponseError: "Resposta del servidor invàlida "
+gotInvalidResponseErrorDescription: "No es pot contactar amb el servidor o potser es troba fora de línia per manteniment. Provar-ho de nou més tard."
+thisPostMayBeAnnoying: "Aquesta nota pot ser molesta per algú."
+thisPostMayBeAnnoyingHome: "Publicar a la línia de temps d'Inici"
+thisPostMayBeAnnoyingCancel: "Cancel·lar "
+thisPostMayBeAnnoyingIgnore: "Publicar de totes maneres"
+collapseRenotes: "Col·lapsar les renotes que ja has vist"
+internalServerError: "Error intern del servidor"
+internalServerErrorDescription: "El servidor ha fallat de manera inexplicable."
+copyErrorInfo: "Copiar la informació de l'error "
+joinThisServer: "Registra't en aquesta instància "
+exploreOtherServers: "Cerca una altra instància "
+letsLookAtTimeline: "Dona una ullada a la línia de temps"
+disableFederationConfirm: "Vols treure la federació?"
+disableFederationConfirmWarn: "Fins i tot traient la federació, les publicacions continuaren sent públiques, a no ser que es digui el contrari. Normalment no has de tocar això."
+disableFederationOk: "Desactivar"
+invitationRequiredToRegister: "Aquesta instància només permet el registre per invitació. Per registrar-te has d'introduir el codi d'invitació."
+emailNotSupported: "Aquesta instància no suporta l'enviament de correus electrònics "
+postToTheChannel: "Publicar a un Canal"
+cannotBeChangedLater: "Això ja no es podrà canviar."
+reactionAcceptance: "Acceptació de reaccions "
+likeOnly: "Només m'agraden "
+likeOnlyForRemote: "Tot (només m'agraden d'instàncies remotes)"
+nonSensitiveOnly: "Només sense contingut sensible"
+nonSensitiveOnlyForLocalLikeOnlyForRemote: "Només contingut no sensible (Només m'agraden d'instàncies remotes)"
+rolesAssignedToMe: "Rols assignats "
+resetPasswordConfirm: "Vols canviar la teva contrasenya?"
+sensitiveWords: "Paraules sensibles"
+sensitiveWordsDescription: "La visibilitat de totes les notes que continguin qualsevol de les paraules configurades seran, automàticament, afegides a \"Inici\". Pots llistar diferents paraules separant les per línies noves."
+sensitiveWordsDescription2: "Fent servir espais crearà expressions AND si l'expressió s'envolta amb barres inclinades es converteix en una expressió regular."
+prohibitedWords: "Paraules prohibides"
+prohibitedWordsDescription: "Quan intenteu publicar una Nota que conté una paraula prohibida, feu que es converteixi en un error. Es poden dividir i establir múltiples línies."
+prohibitedWordsDescription2: "Fent servir espais crearà expressions AND si l'expressió s'envolta amb barres inclinades es converteix en una expressió regular."
+hiddenTags: "Etiquetes ocultes"
+hiddenTagsDescription: "La visibilitat de totes les notes que continguin qualsevol de les paraules configurades seran, automàticament, afegides a \"Inici\". Pots llistar diferents paraules separant les per línies noves."
+notesSearchNotAvailable: "La cerca de notes no es troba disponible."
+license: "Llicència"
+unfavoriteConfirm: "Esborrar dels favorits?"
+myClips: "Els meus retalls"
+drivecleaner: "Netejador de Disc"
+retryAllQueuesNow: "Prova de nou d'executar totes les cues"
+retryAllQueuesConfirmTitle: "Tornar a intentar-ho tot?"
+retryAllQueuesConfirmText: "Això farà que la càrrega del servidor augmenti temporalment."
+enableChartsForRemoteUser: "Generar gràfiques d'usuaris remots"
+enableChartsForFederatedInstances: "Generar gràfiques d'instàncies remotes"
+showClipButtonInNoteFooter: "Afegir \"Retall\" al menú d'acció de la nota"
+reactionsDisplaySize: "Mida de les reaccions"
+limitWidthOfReaction: "Limitar l'amplada màxima de la reacció i mostrar-les en una mida reduïda "
+noteIdOrUrl: "ID o URL de la nota"
+video: "Vídeo"
+videos: "Vídeos "
+audio: "So"
+audioFiles: "So"
+dataSaver: "Economitzador de dades"
+accountMigration: "Migració del compte"
+accountMoved: "Aquest usuari té un compte nou:"
+accountMovedShort: "Aquest compte ha sigut migrat"
+operationForbidden: "Operació no permesa "
+forceShowAds: "Mostra els anuncis sempre "
+addMemo: "Afegir recordatori"
+editMemo: "Editar recordatori"
+reactionsList: "Reaccions"
+renotesList: "Impulsos"
+notificationDisplay: "Notificacions"
+leftTop: "Dalt a l'esquerra "
+rightTop: "Dalt a la dreta "
+leftBottom: "A baix a l'esquerra"
+rightBottom: "A baix a la dreta"
+stackAxis: "Apilar en direcció "
+vertical: "Vertical"
+horizontal: "Horitzontal "
+position: "Posició "
+serverRules: "Regles del servidor"
+pleaseConfirmBelowBeforeSignup: "Per obrir un compte en aquest servidor, has de llegir i acceptar el següent."
+pleaseAgreeAllToContinue: "Has d'acceptar tots els camps de dalt per poder continuar."
+continue: "Continuar"
+preservedUsernames: "Noms d'usuaris reservats"
+preservedUsernamesDescription: "Llistat de noms d'usuaris que no es poden fer servir separats per salts de linia. Aquests noms d'usuaris no estaran disponibles quan es creï un compte d'usuari normal, però els administradors els poden fer servir per crear comptes manualment. Per altre banda els comptes ja creats amb aquests noms d'usuari no es veure'n afectats."
+createNoteFromTheFile: "Compon una nota des d'aquest fitxer"
+archive: "Arxiu"
+channelArchiveConfirmTitle: "Vols arxivar {name}?"
+channelArchiveConfirmDescription: "Un Canal arxivat no apareixerà a la llista de canals o als resultats de cerca. Tampoc es poden afegir noves entrades."
+thisChannelArchived: "Aquest Canal ha sigut arxivat."
+displayOfNote: "Mostrar notes"
+initialAccountSetting: "Configuració del perfil"
+youFollowing: "Seguit"
+preventAiLearning: "Descartar l'ús d'aprenentatge automàtic (IA Generativa)"
+preventAiLearningDescription: "Demanar els indexadors no fer servir els texts, imatges, etc. en cap conjunt de dades per alimentar l'aprenentatge automàtic (IA Predictiva/ Generativa). Això s'aconsegueix afegint la etiqueta \"noai\" com a resposta HTML al contingut corresponent. Prevenir aquest ús totalment pot ser que no sigui aconseguit, ja que molts indexadors poden obviar aquesta etiqueta."
+options: "Opcions"
+specifyUser: "Especificar usuari"
+failedToPreviewUrl: "Vista prèvia no disponible"
+update: "Actualitzar"
+rolesThatCanBeUsedThisEmojiAsReaction: "Rols que poden fer servir aquest emoji com a reacció "
+rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "Si cap rol es especificat tothom ho pot fer servir"
+rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "Aquests rols han de ser públics "
+cancelReactionConfirm: "Vols esborrar la teva reacció?"
+changeReactionConfirm: "Vols canviar la teva reacció?"
+later: "Més tard"
+goToMisskey: "Ves a Misskey"
+additionalEmojiDictionary: "Diccionari d'emojis adicionals"
+installed: "Instal·lats "
+branding: "Marca"
+enableServerMachineStats: "Publicar estadístiques del maquinari del servidor"
+enableIdenticonGeneration: "Activar la generació d'icones d'identificació "
+turnOffToImprovePerformance: "Desactivant aquesta opció es pot millorar el rendiment."
+createInviteCode: "Crear codi d'invitació "
+createWithOptions: "Crear invitació amb opcions"
+createCount: "Comptador d'invitacions "
+inviteCodeCreated: "Invitació creada"
+inviteLimitExceeded: "Has sobrepassat el límit d'invitacions que pots crear."
+createLimitRemaining: "Et queden {limit} invitacions restants"
+inviteLimitResetCycle: "Cada {time} {limit} invitacions."
+expirationDate: "Data de venciment"
+noExpirationDate: "Sense data de venciment"
+inviteCodeUsedAt: "Codi d'invitació fet servir el"
+registeredUserUsingInviteCode: "Codi d'invitació fet servir per l'usuari "
+waitingForMailAuth: "Esperant la verificació per correu electrònic "
+inviteCodeCreator: "Invitació creada per"
+usedAt: "Utilitzada el"
+unused: "Sense utilitzar"
+used: "Utilitzada"
+expired: "Caducat"
+doYouAgree: "Estàs d'acord?"
+beSureToReadThisAsItIsImportant: "Llegeix això perquè és molt important."
+iHaveReadXCarefullyAndAgree: "He llegit {x} i estic d'acord."
+dialog: "Diàleg "
+icon: "Icona"
+forYou: "Per a tu"
+currentAnnouncements: "Informes actuals"
+pastAnnouncements: "Informes passats"
+youHaveUnreadAnnouncements: "Tens informes per llegir."
+useSecurityKey: "Segueix les instruccions del teu navegador O dispositiu per fer servir el teu passkey."
replies: "Respondre"
renotes: "Impulsa"
+loadReplies: "Mostrar les respostes"
+loadConversation: "Mostrar la conversació "
+pinnedList: "Llista fixada"
+keepScreenOn: "Mantenir la pantalla encesa"
+verifiedLink: "La propietat de l'enllaç ha sigut verificada"
+notifyNotes: "Notificar quan hi hagi notes noves"
+unnotifyNotes: "Deixar de notificar quan hi hagi notes noves"
+authentication: "Autenticació "
+authenticationRequiredToContinue: "Si us plau autentificat per continuar"
+dateAndTime: "Data i hora"
+showRenotes: "Mostrar impulsos"
+edited: "Editat"
+notificationRecieveConfig: "Paràmetres de notificacions"
+mutualFollow: "Seguidor mutu"
+fileAttachedOnly: "Només notes amb adjunts"
+showRepliesToOthersInTimeline: "Mostrar les respostes a altres a la línia de temps"
+hideRepliesToOthersInTimeline: "Amagar les respostes a altres a la línia de temps"
+showRepliesToOthersInTimelineAll: "Mostrar les respostes a altres a usuaris que segueixes a la línia de temps"
+hideRepliesToOthersInTimelineAll: "Ocultar les teves respostes a tots els usuaris que segueixes a la línia de temps"
+confirmShowRepliesAll: "Aquesta opció no té marxa enrere. Vols mostrar les teves respostes a tots els que segueixes a la teva línia de temps?"
+confirmHideRepliesAll: "Aquesta opció no té marxa enrere. Vols ocultar les teves respostes a tots els usuaris que segueixes a la línia de temps?"
+externalServices: "Serveis externs"
+sourceCode: "Codi font"
+impressum: "Impressum"
+impressumUrl: "Adreça URL impressum"
+impressumDescription: "A països, com Alemanya, la inclusió de la informació de contacte de l'operador (un Impressum) és requereix de manera legal per llocs comercials."
+privacyPolicy: "Política de privacitat"
+privacyPolicyUrl: "Adreça URL de la política de privacitat"
+tosAndPrivacyPolicy: "Termes d'ús i política de privacitat"
+avatarDecorations: "Decoracions dels avatars"
+attach: "Adjuntar"
+detach: "Eliminar"
+detachAll: "Treure tot"
+angle: "Angle"
+flip: "Girar"
+showAvatarDecorations: "Mostrar les decoracions dels avatars"
+releaseToRefresh: "Deixar anar per actualitzar"
+refreshing: "Recarregant..."
+pullDownToRefresh: "Llisca cap a baix per recarregar"
+disableStreamingTimeline: "Desactivar l'actualització en temps real de les línies de temps"
+useGroupedNotifications: "Mostrar les notificacions agrupades "
+signupPendingError: "Hi ha hagut un problema verificant l'adreça de correu electrònic. L'enllaç pot haver caducat."
+cwNotationRequired: "Si està activat \"Amagar contingut\" s'ha d'escriure una descripció "
+doReaction: "Afegeix una reacció "
+code: "Codi"
+reloadRequiredToApplySettings: "És necessari recarregar la pàgina per aplicar els canvis."
+remainingN: "Queden: {n}"
+overwriteContentConfirm: "Vols substituir el contingut actual?"
+seasonalScreenEffect: "Efectes de pantalla segons les estacions"
+decorate: "Decorar"
+addMfmFunction: "Afegeix funcions MFM"
+enableQuickAddMfmFunction: "Activar accés ràpid per afegir funcions MFM"
+bubbleGame: "Bubble Game"
+sfx: "Efectes de so"
+soundWillBePlayed: "Es reproduiran efectes de so"
+showReplay: "Veure reproducció"
+replay: "Reproduir"
+replaying: "Reproduint"
+ranking: "Classificació"
+lastNDays: "Últims {n} dies"
+backToTitle: "Torna al títol"
+hemisphere: "Geolocalització"
+withSensitive: "Incloure notes amb fitxers sensibles"
+userSaysSomethingSensitive: "La publicació de {name} conte material sensible"
+enableHorizontalSwipe: "Lliscar per canviar de pestanya"
+surrender: "Cancel·lar "
+_bubbleGame:
+ howToPlay: "Com es juga"
+ _howToPlay:
+ section1: "Ajusta la posició i deixa caure l'objecte dintre la caixa."
+ section2: "Quan dos objectes del mateix tipus es toquen, canviaran en un objecte diferent i guanyares punts."
+ section3: "El joc s'acabarà quan els objectes sobresurtin de la caixa. Intenta aconseguir la puntuació més gran possible fusionant objectes mentre impedeixes que sobresurtin de la caixa!"
+_announcement:
+ forExistingUsers: "Anunci per usuaris registrats"
+ forExistingUsersDescription: "Aquest avís només es mostrarà als usuaris existents fins al moment de la publicació. Si no també es mostrarà als usuaris que es registrin després de la publicació."
+ needConfirmationToRead: "Es necessita confirmació de lectura de la notificació "
+ needConfirmationToReadDescription: "Si s'activa es mostrarà un diàleg per confirmar la lectura d'aquesta notificació. A més aquesta notificació serà exclosa de qualsevol funcionalitat com \"Marcar tot com a llegit\"."
+ end: "Final de la notificació "
+ tooManyActiveAnnouncementDescription: "Tenir massa notificacions actives pot empitjorar l'experiència de l'usuari. Considera finalitzar els anuncis que siguin antics."
+ readConfirmTitle: "Marcar com llegida?"
+ readConfirmText: "Això marcarà el contingut de \"{title}\" com llegit."
+ shouldNotBeUsedToPresentPermanentInfo: "Ja que l'ús de notificacions pot impactar l'experiència dels nous usuaris, és recomanable fer servir les notificacions amb el flux d'informació en comptes de fer-les servir en un únic bloc."
+ dialogAnnouncementUxWarn: "Tenir dues o més notificacions amb l'estil de finestres pot impactar l'experiència de l'usuari, és per això que és recomana fer-lo servir amb cura."
+ silence: "Sense notificacions"
+ silenceDescription: "Activant aquesta opció la notificació no es mostrarà ni l'usuari l'haurà de llegir."
+_initialAccountSetting:
+ accountCreated: "S'ha completat la creació del compte!"
+ letsStartAccountSetup: "Posem ràpidament la configuració inicial del compte."
+ letsFillYourProfile: "Comencem establint el teu perfil."
+ profileSetting: "Configuració del perfil"
+ privacySetting: "Configuració de seguretat"
+ theseSettingsCanEditLater: "Aquests ajustos es poden canviar més tard."
+ youCanEditMoreSettingsInSettingsPageLater: "A més d'això, es poden fer diferents configuracions a través de la pàgina de configuració. Assegureu-vos de comprovar-ho més tard."
+ followUsers: "Prova de seguir usuaris que t'interessin per construir la teva línia de temps."
+ pushNotificationDescription: "Activant les notificacions emergents et permetrà rebre notificacions de {name} directament al teu dispositiu."
+ initialAccountSettingCompleted: "Configuració del perfil completada!"
+ haveFun: "Disfruta {name}!"
+ youCanContinueTutorial: "Pots continuar amb un tutorial per aprendre a Fer servir {name} (MissKey) o tu pots estalviar i començar a fer-lo servir ja."
+ startTutorial: "Començar el tutorial"
+ skipAreYouSure: "Et vols saltar la configuració del perfil?"
+ laterAreYouSure: "Vols continuar la configuració del perfil més tard?"
+_initialTutorial:
+ launchTutorial: "Començar tutorial"
+ title: "Tutorial"
+ wellDone: "Ben fet!"
+ skipAreYouSure: "Sortir del tutorial?"
+ _landing:
+ title: "Benvingut al tutorial"
+ description: "Aquí aprendràs el bàsic per poder fer servir Misskey i les seves característiques."
+ _note:
+ title: "Què és una Nota?"
+ description: "Les publicacions a Misskey es diuen 'Notes'. Les Notes s'ordenen cronològicament a la línia de temps i s'actualitzen de forma automàtica."
+ reply: "Fes clic en aquest botó per contestar a un missatge. També és possible contestar a una contestació, continuant la conversació en forma de fil."
+ renote: "Pots compartir una Nota a la teva pròpia línia de temps. Inclús pots citar-les amb els teus comentaris."
+ reaction: "Pots afegir reaccions a les Notes. Entrarem més en detall a la pròxima pàgina."
+ menu: "Pots veure els detalls de les Notes, copiar enllaços i fer diferents accions."
+ _reaction:
+ title: "Què són les Reaccions?"
+ description: "Es poden reaccionar a les Notes amb diferents emoticones. Les reaccions et permeten expressar matisos que hi són més enllà d'un simple m'agrada."
+ letsTryReacting: "Es poden afegir reaccions fent clic al botó '+'. Prova reaccionant a aquesta nota!"
+ reactToContinue: "Afegeix una reacció per continuar."
+ reactNotification: "Rebràs notificacions en temps real quan un usuari reaccioni a les teves notes."
+ reactDone: "Pots desfer una reacció fent clic al botó '-'."
+ _timeline:
+ title: "El concepte de les línies de temps"
+ description1: "Misskey mostra diferents línies de temps basades en l'ús (algunes poden no estar disponibles depenent de la política del servidor)"
+ home: "Pots veure notes dels comptes que segueixes"
+ local: "Pots veure les notes dels usuaris del servidor."
+ social: "Es mostren les notes de les línies de temps d'Inici i Local."
+ global: "Pots veure les notes de tots els servidors connectats."
+ description2: "Pots canviar la línia de temps en qualsevol moment fent servir la barra de la pantalla superior."
+ description3: "A més hi ha línies de temps per llistes i per canals. Si vols saber més {link}."
+ _postNote:
+ title: "Configuració de la publicació de les notes"
+ description1: "Quan públiques una nota a Misskey hi ha diferents opcions disponibles. El formulari de publicació es veu així"
+ _visibility:
+ description: "Pots limitar qui pot veure les teves notes."
+ public: "La teva nota serà visible per a tots els usuaris."
+ home: "Publicar només a línia de temps d'Inici. La gent que visiti el teu perfil o mitjançant les remotes també la podran veure."
+ followers: "Només visible per a seguidors. Només els teus seguidors la podran veure i ningú més. Ningú més podrà fer renotes."
+ direct: "Només visible per a alguns seguidors, el destinatari rebre una notificació. Es pot fer servir com una alternativa als missatges directes."
+ doNotSendConfidencialOnDirect1: "Tingues cura quan enviïs informació sensible."
+ doNotSendConfidencialOnDirect2: "Els administradors del servidor poden veure tot el que escrius. Ves compte quan enviïs informació sensible en enviar notes directes a altres usuaris en servidors de poca confiança."
+ localOnly: "Publicar amb aquesta opció activada farà que la nota no federi amb altres servidors. Els usuaris d'altres servidors no podran veure la nota directament, sense importar les opcions de visualització."
+ _cw:
+ title: "Avís de Contingut (CW)"
+ description: "En comptes del cos de la nota es mostrarà el que s'escrigui al camp de 'comentaris'. Fent clic a 'Llegir més' es mostrarà el cos."
+ _exampleNote:
+ cw: "Això et farà venir gana!"
+ note: "Acabo de menjar-me un donut de xocolata 🍩😋"
+ useCases: "Això es fa servir per seguir normes del servidor sobre certes notes o per ocultar contingut sensible O revelador."
+ _howToMakeAttachmentsSensitive:
+ title: "Com marcar adjunts com a contingut sensible?"
+ description: "Per adjunts que sigui requerit per les normes del servidor o que puguin contenir material sensible, s'ha d'afegir l'opció 'sensible'."
+ tryThisFile: "Prova de marcar la imatge adjunta en aquest formulari com a sensible!"
+ _exampleNote:
+ note: "Oops! L'he fet bona en obrir la tapa de Nocilla..."
+ method: "Per marcar un adjunt com a sensible, fes clic a la miniatura de l'adjunt, obre el menú i fes clic a 'Marcar com a sensible'."
+ sensitiveSucceeded: "Quan adjuntis fitxers si us plau marca la sensibilitat seguint les normes del servidor."
+ doItToContinue: "Marca el fitxer adjunt com a sensible per poder continuar."
+ _done:
+ title: "Has completat el tutorial 🎉"
+ description: "Les funcions explicades aquí és una petita mostra. Per una explicació més detallada de com fer servir MissKey consulta {link}."
+_timelineDescription:
+ home: "A la línia de temps d'Inici pots veure les notes dels usuaris que segueixes."
+ local: "A la línia de temps Local pots veure les notes de tots els usuaris d'aquest servidor."
+ social: "La línia de temps Social mostren les notes de les línies de temps d'Inici i Local."
+ global: "A la línia de temps Global pots veure les notes de tots els servidors connectats."
+_serverRules:
+ description: "Un conjunt de regles que seran mostrades abans de registrar-se. Es recomanable configurar un resum dels termes d'ús."
+_serverSettings:
+ iconUrl: "URL de la icona"
+ appIconDescription: "Especifica la icona que es mostrarà quan el {host} es mostri en una aplicació."
+ appIconUsageExample: "Per exemple com a PWA, o quan es mostri com un favorit a la pàgina d'inici del telèfon mòbil"
+ appIconStyleRecommendation: "Com la icona pot ser retallada com un cercle o un quadrat, es recomana fer servir una icona amb un marge acolorit que l'envolti."
+ appIconResolutionMustBe: "La resolució mínima és {resolution}."
+ manifestJsonOverride: "Sobreescriure manifest.json"
+ shortName: "Nom curt"
+ shortNameDescription: "Una abreviatura del nom de la instància que es poguí mostrar en cas que el nom oficial sigui massa llarg"
+ fanoutTimelineDescription: "Quan es troba activat millora bastant el rendiment quan es recuperen les línies de temps i redueix la carrega de la base de dades. Com a contrapunt, l'ús de memòria de Redis es veurà incrementada. Considera d'estabilitat aquesta opció en cas de tenir un servidor amb poca memòria o si tens problemes de inestabilitat."
+ fanoutTimelineDbFallback: "Carregar de la base de dades"
+ fanoutTimelineDbFallbackDescription: "Quan s'activa, la línia de temps fa servir la base de dades per consultes adicionals si la línia de temps no es troba a la memòria cau. Si és desactiva la càrrega del servidor és veure reduïda, però també és reduirà el nombre de línies de temps que és poden obtenir."
+_accountMigration:
+ moveFrom: "Migrar un altre compte a aquest"
+ moveFromSub: "Crear un àlies per un altre compte"
+ moveFromLabel: "Compte original #{n}"
+ moveFromDescription: "Has de crear un àlies del compte que vols migrar en aquest compte.\nFes servir aquest format per posar el compte que vols migrar: @nomusuari@servidor.exemple.com\nPer esborrar l'àlies deixa el camp en blanc (no és recomanable de fer)"
+ moveTo: "Migrar aquest compte a un altre"
+ moveToLabel: "Compte al qual es vol migrar:"
+ moveCannotBeUndone: "Les migracions dels comptes no es poden desfer."
+ moveAccountDescription: "Això migrarà la teva compte a un altre diferent.\n ・Els seguidors d'aquest compte és passaran al compte nou de forma automàtica\n ・Es deixaran de seguir a tots els usuaris que es segueixen actualment en aquest compte\n ・No es poden crear notes noves, etc. en aquest compte\n\nSi bé la migració de seguidors es automàtica, has de preparar alguns pasos manualment per migrar la llista d'usuaris que segueixes. Per fer això has d'exportar els seguidors que després importaraes al compte nou mitjançant el menú de configuració. El mateix procediment s'ha de seguir per less teves llistes i els teus usuaris silenciats i bloquejats.\n\n(Aquesta explicació s'aplica a Misskey v13.12.0 i posteriors. Altres aplicacions, com Mastodon, poden funcionar diferent.)"
+ moveAccountHowTo: "Per fer la migració, primer has de crear un àlies per aquest compte al compte al qual vols migrar.\nDesprés de crear l'àlies, introdueix el compte al qual vols migrar amb el format següent: @nomusuari@servidor.exemple.com"
+ startMigration: "Migrar"
+ migrationConfirm: "Vols migrar aquest compte a {account}? Una vegada comenci la migració no es podrà parar O fer marxa enrere i no podràs tornar a fer servir aquest compte mai més."
+ movedAndCannotBeUndone: "Aquest compte ha migrat.\nLes migracions no es poden desfer."
+ postMigrationNote: "Aquest compte deixarà de seguir tots els comptes que segueix 24 hores després de germinar la migració.\nEl nombre de seguidors i seguits passarà a ser de zero. Per evitar que els teus seguidors no puguin veure les publicacions marcades com a només seguidors continuaren seguint aquest compte."
+ movedTo: "Nou compte:"
+_achievements:
+ earnedAt: "Desbloquejat el"
+ _types:
+ _notes1:
+ title: "Aquí, configurant el meu msky"
+ description: "Publica la teva primera Nota"
+ flavor: "Passa-t'ho bé fent servir Miskey!"
+ _notes10:
+ title: "Algunes notes"
+ description: "Publica 10 notes"
+ _notes100:
+ title: "Un piló de notes"
+ description: "Publica 100 notes"
+ _notes500:
+ title: "Cobert de notes"
+ description: "Publica 500 notes"
+ _notes1000:
+ title: "Un piló de notes"
+ description: "1 000 notes publicades"
+ _notes5000:
+ title: "Desbordament de notes"
+ description: "5 000 notes publicades"
+ _notes10000:
+ title: "Supernota"
+ description: "10 000 notes publicades"
+ _notes20000:
+ title: "Necessito... Més... Notes!"
+ description: "20 000 notes publicades"
+ _notes30000:
+ title: "Notes notes notes!"
+ description: "30 000 notes publicades"
+ _notes40000:
+ title: "Fàbrica de notes"
+ description: "40 000 notes publicades"
+ _notes50000:
+ title: "Planeta de notes"
+ description: "50 000 notes publicades"
+ _notes60000:
+ title: "Quàsar de notes"
+ description: "60 000 notes publicades"
+ _notes70000:
+ title: "Forat negre de notes"
+ description: "70 000 notes publicades"
+ _notes80000:
+ title: "Galàxia de notes"
+ description: "80 000 notes publicades"
+ _notes90000:
+ title: "Univers de notes"
+ description: "90 000 notes publicades"
+ _notes100000:
+ title: "ALL YOUR NOTE ARE BELONG TO US"
+ description: "100 000 notes publicades"
+ flavor: "Segur que tens moltes coses a dir?"
+ _login3:
+ title: "Principiant I"
+ description: "Vas iniciar sessió fa tres dies"
+ flavor: "Des d'avui diguem Misskist"
+ _login7:
+ title: "Principiant II"
+ description: "Vas iniciar sessió fa set dies"
+ flavor: "Ja saps com va funcionant tot?"
+ _login15:
+ title: "Principiant III"
+ description: "Vas iniciar sessió fa quinze dies"
+ _login30:
+ title: "Misskist I"
+ description: "Vas iniciar sessió fa trenta dies"
+ _login60:
+ title: "Misskist II"
+ description: "Vas iniciar sessió fa seixanta dies"
+ _login100:
+ title: "Misskist III"
+ description: "Vas iniciar sessió fa cent dies"
+ flavor: "Misskist violent"
+ _login200:
+ title: "Regular I"
+ description: "Vas iniciar sessió fa dos-cents dies"
+ _login300:
+ title: "Regular II"
+ description: "Vas iniciar sessió fa tres-cents dies"
+ _login400:
+ title: "Regular III"
+ description: "Vas iniciar sessió fa quatre-cents dies"
+ _login500:
+ title: "Expert I"
+ description: "Vas iniciar sessió fa cinc-cents dies"
+ flavor: "Amics, he dit massa vegades que soc un amant de les notes"
+ _login600:
+ title: "Expert II"
+ description: "Vas iniciar sessió fa sis-cents dies"
+ _login700:
+ title: "Expert III"
+ description: "Vas iniciar sessió fa set-cents dies"
+ _login800:
+ title: "Mestre de les Notes I"
+ description: "Vas iniciar sessió fa vuit-cents dies "
+ _login900:
+ title: "Mestre de les Notes II"
+ description: "Vas iniciar sessió fa nou-cents dies"
+ _login1000:
+ title: "Mestre de les Notes III"
+ description: "Vas iniciar sessió fa mil dies"
+ flavor: "Gràcies per fer servir MissKey!"
+ _noteClipped1:
+ title: "He de retallar-te!"
+ description: "Retalla la teva primera nota"
+ _noteFavorited1:
+ title: "Quan miro les estrelles"
+ description: "La primera vegada que vaig registrar el meu favorit"
+ _myNoteFavorited1:
+ title: "Vull una estrella"
+ description: "La meva nota va ser registrada com favorita per una de les altres persones"
+ _profileFilled:
+ title: "Estic a punt"
+ description: "Vaig fer la configuració de perfil"
+ _markedAsCat:
+ title: "Soc un gat"
+ description: "He establert el meu compte com si fos un Gat"
+ flavor: "Encara no tinc nom"
+ _following1:
+ title: "És el meu primer seguiment"
+ description: "És la primera vegada que et segueixo"
+ _following10:
+ title: "Segueix-me... Segueix-me..."
+ description: "Seguir 10 usuaris"
+ _following50:
+ title: "Molts amics"
+ description: "Seguir 50 comptes"
+ _following100:
+ title: "100 amics"
+ description: "Segueixes 100 comptes"
+ _following300:
+ title: "Sobrecàrrega d'amics"
+ description: "Segueixes 300 comptes"
+ _followers1:
+ title: "Primer seguidor"
+ description: "1 seguidor guanyat"
+ _followers10:
+ title: "Segueix-me!"
+ description: "10 seguidors guanyats"
+ _followers50:
+ title: "Venen en manada"
+ description: "50 seguidors guanyats"
+ _followers100:
+ title: "Popular"
+ description: "100 seguidors guanyats"
+ _followers300:
+ title: "Si us plau, d'un en un!"
+ description: "300 seguidors guanyats"
+ _followers500:
+ title: "Torre de ràdio"
+ description: "500 seguidors guanyats"
+ _followers1000:
+ title: "Influenciador"
+ description: "1 000 seguidors guanyats"
+ _collectAchievements30:
+ title: "Col·leccionista d'èxits "
+ description: "Desbloqueja 30 assoliments"
+ _viewAchievements3min:
+ title: "M'agraden els èxits "
+ description: "Mira la teva llista d'assoliments durant més de 3 minuts"
+ _iLoveMisskey:
+ title: "Estimo Misskey"
+ description: "Publica \"I ❤ #Misskey\""
+ flavor: "L'equip de desenvolupament de Misskey agraeix el vostre suport!"
+ _foundTreasure:
+ title: "A la Recerca del Tresor"
+ description: "Has trobat el tresor amagat"
+ _client30min:
+ title: "Parem una estona"
+ description: "Mantingues obert Misskey per 30 minuts"
+ _client60min:
+ title: "A totes amb Misskey"
+ description: "Mantingues Misskey obert per 60 minuts"
+ _noteDeletedWithin1min:
+ title: "No et preocupis"
+ description: "Esborra una nota al minut de publicar-la"
+ _postedAtLateNight:
+ title: "Nocturn"
+ description: "Publica una nota a altes hores de la nit "
+ flavor: "És hora d'anar a dormir."
+ _postedAt0min0sec:
+ title: "Rellotge xerraire"
+ description: "Publica una nota a les 0:00"
+ flavor: "Tic tac, tic tac, tic tac, DING!"
+ _selfQuote:
+ title: "Autoreferència "
+ description: "Cita una nota teva"
+ _htl20npm:
+ title: "Línia de temps fluida"
+ description: "La teva línia de temps va a més de 20npm (notes per minut)"
+ _viewInstanceChart:
+ title: "Analista "
+ description: "Mira els gràfics de la teva instància "
+ _outputHelloWorldOnScratchpad:
+ title: "Hola, món!"
+ description: "Escriu \"hola, món\" al bloc de notes"
+ _open3windows:
+ title: "Multi finestres"
+ description: "I va obrir més de tres finestres"
+ _driveFolderCircularReference:
+ title: "Consulteu la secció de bucle"
+ description: "Intenta crear carpetes recursives al Disc"
+ _reactWithoutRead:
+ title: "De veritat has llegit això?"
+ description: "Reaccions a una nota de més de 100 caràcters publicada fa menys de 3 segons "
+ _clickedClickHere:
+ title: "Fer clic"
+ description: "Has fet clic aquí "
+ _justPlainLucky:
+ title: "Ha sigut sort"
+ description: "Oportunitat de guanyar-lo amb una probabilitat d'un 0.005% cada 10 segons"
+ _setNameToSyuilo:
+ title: "soc millor"
+ description: "Posat \"siuylo\" com a nom"
+ _passedSinceAccountCreated1:
+ title: "Primer aniversari"
+ description: "Ja ha passat un any d'ençà que vas crear el teu compte"
+ _passedSinceAccountCreated2:
+ title: "Segon aniversari"
+ description: "Ja han passat dos anys d'ençà que vas crear el teu compte"
+ _passedSinceAccountCreated3:
+ title: "Tres anys"
+ description: "Ja han passat tres anys d'ençà que vas crear el teu compte"
+ _loggedInOnBirthday:
+ title: "Felicitats!"
+ description: "T'has identificat el dia del teu aniversari"
+ _loggedInOnNewYearsDay:
+ title: "Bon any nou!"
+ description: "T'has identificat el primer dia de l'any "
+ flavor: "A per un altre any memorable a la teva instància "
+ _cookieClicked:
+ title: "Un joc en què fas clic a les galetes"
+ description: "Pica galetes"
+ flavor: "Espera, ets al lloc web correcte?"
+ _brainDiver:
+ title: "Busseja Ments"
+ description: "Publica un enllaç al Busseja Ments"
+ flavor: "Misskey-Misskey La-Tu-Ma"
+ _smashTestNotificationButton:
+ title: "Sobrecàrrega de proves"
+ description: "Envia moltes notificacions de prova en un període de temps molt curt"
+ _tutorialCompleted:
+ title: "Diploma del Curs Elemental de Misskey"
+ description: "Has completat el tutorial"
+ _bubbleGameExplodingHead:
+ title: "🤯"
+ description: "L'objecte més gran del joc de la bombolla "
+ _bubbleGameDoubleExplodingHead:
+ title: "Doble 🤯"
+ description: "Dos dels objectes més grans del joc de la bombolla al mateix temps"
+ flavor: "Pots emplenar una carmanyola com aquesta 🤯🤯 una mica"
_role:
+ new: "Nou rol"
+ edit: "Editar el rol"
+ name: "Nom del rol"
+ description: "Descripció del rol"
+ permission: "Permisos de rol"
+ descriptionOfPermission: "Els Moderadors poden fer operacions bàsiques de moderació.\nEls Administradors poden canviar tots els ajustos del servidor."
+ assignTarget: "Assignar "
+ descriptionOfAssignTarget: "Manual per canviar manualment qui és part d'aquest rol i qui no.\nCondicional per afegir o eliminar de manera automàtica els usuaris d'aquest rol basat en una determinada condició."
+ manual: "Manual"
+ manualRoles: "Rols manuals"
+ conditional: "Condicional"
+ conditionalRoles: "Rols condicionals"
+ condition: "Condició"
+ isConditionalRole: "Aquest és un rol condicional"
+ isPublic: "Rol públic"
+ descriptionOfIsPublic: "Aquest rol es mostrarà al perfil dels usuaris al que se'ls assigni."
+ options: "Opcions"
+ policies: "Polítiques"
+ baseRole: "Plantilla de rols"
+ useBaseValue: "Fer servir els valors de la plantilla de rols"
+ chooseRoleToAssign: "Selecciona els rols a assignar"
+ iconUrl: "URL de la icona "
+ asBadge: "Mostrar com a insígnia "
+ descriptionOfAsBadge: "La icona d'aquest rol es mostrarà al costat dels noms d'usuaris que tinguin assignats aquest rol."
+ isExplorable: "Fer el rol explorable"
+ descriptionOfIsExplorable: "La línia de temps d'aquest rol i la llista d'usuaris seran públics si s'activa."
+ displayOrder: "Posició "
+ descriptionOfDisplayOrder: "Com més gran és el número, més dalt la seva posició a la interfície."
+ canEditMembersByModerator: "Permetre que els moderadors editin la llista d'usuaris en aquest rol"
+ descriptionOfCanEditMembersByModerator: "Quan s'activa, els moderadors, així com els administradors, podran afegir i treure usuaris d'aquest rol. Si es troba desactivat, només els administradors poden assignar usuaris."
+ priority: "Prioritat"
+ _priority:
+ low: "Baixa"
+ middle: "Mitjà"
+ high: "Alta"
_options:
+ gtlAvailable: "Pot veure la línia de temps global"
+ ltlAvailable: "Pot veure la línia de temps local"
+ canPublicNote: "Pot enviar notes públiques"
+ canInvite: "Pot crear invitacions a la instància "
+ inviteLimit: "Límit d'invitacions "
+ inviteLimitCycle: "Temps de refresc de les invitacions"
+ inviteExpirationTime: "Interval de caducitat de les invitacions"
+ canManageCustomEmojis: "Gestiona els emojis personalitzats"
+ canManageAvatarDecorations: "Gestiona les decoracions dels avatars "
+ driveCapacity: "Capacitat del disc"
+ alwaysMarkNsfw: "Marca sempre els fitxers com a sensibles"
+ pinMax: "Nombre màxim de notes fixades"
antennaMax: "Nombre màxim d'antenes"
+ wordMuteMax: "Nombre màxim de caràcters permesos a les paraules silenciades"
+ webhookMax: "Nombre màxim de Webhooks"
+ clipMax: "Nombre màxim de clips"
+ noteEachClipsMax: "Nombre màxim de notes dintre d'un clip"
+ userListMax: "Nombre màxim de llistes d'usuaris "
+ userEachUserListsMax: "Nombre màxim d'usuaris dintre d'una llista d'usuaris "
+ rateLimitFactor: "Limitador"
+ descriptionOfRateLimitFactor: "Límits baixos són menys restrictius, límits alts són més restrictius."
+ canHideAds: "Pot amagar els anuncis"
+ canSearchNotes: "Pot cercar notes"
+ canUseTranslator: "Pot fer servir el traductor"
+ avatarDecorationLimit: "Nombre màxim de decoracions que es poden aplicar els avatars"
+ _condition:
+ isLocal: "Usuari local"
+ isRemote: "Usuari remot"
+ createdLessThan: "Han passat menys de X a passat des de la creació del compte"
+ createdMoreThan: "Han passat més de X des de la creació del compte"
+ followersLessThanOrEq: "Té menys de X seguidors"
+ followersMoreThanOrEq: "Té X o més seguidors"
+ followingLessThanOrEq: "Segueix X o menys comptes"
+ followingMoreThanOrEq: "Segueix a X o més comptes"
+ notesLessThanOrEq: "Les publicacions són menys o igual a "
+ notesMoreThanOrEq: "Les publicacions són més o igual a "
+ and: "AND condicional "
+ or: "OR condicional"
+ not: "NOT condicional"
+_sensitiveMediaDetection:
+ description: "Redueix els esforços de moderació gràcies al reconeixement automàtic dels fitxers amb contingut sensible mitjançant Machine Learing. Això augmentarà la càrrega del servidor."
+ sensitivity: "Sensibilitat de la detecció "
+ sensitivityDescription: "Reduint la sensibilitat provocarà menys falsos positius. D'altra banda incrementant-ho generarà més falsos negatius."
+ setSensitiveFlagAutomatically: "Marcar com a sensible"
+ setSensitiveFlagAutomaticallyDescription: "Els resultats de la detecció interna seran desats, inclòs si aquesta opció es troba desactivada."
+ analyzeVideos: "Activar anàlisis de vídeos "
+ analyzeVideosDescription: "Analitzar els vídeos a més de les imatges. Això incrementarà lleugerament la càrrega del servidor."
+_emailUnavailable:
+ used: "Aquest correu electrònic ja s'està fent servir"
+ format: "El format del correu electrònic és invàlid "
+ disposable: "No es poden fer servir adreces de correu electrònic d'un sol ús "
+ mx: "Aquest servidor de correu electrònic no és vàlid "
+ smtp: "Aquest servidor de correu electrònic no respon"
+ banned: "No pots registrar-te amb aquesta adreça de correu electrònic "
+_ffVisibility:
+ public: "Publicar"
+ followers: "Visible només per a seguidors "
+ private: "Privat"
+_signup:
+ almostThere: "Ja quasi estem"
+ emailAddressInfo: "Si us plau, escriu la teva adreça de correu electrònic. No es farà pública."
+ emailSent: "S'ha enviat un correu de confirmació a ({email}). Si us plau, fes clic a l'enllaç per completar el registre."
+_accountDelete:
+ accountDelete: "Eliminar el compte"
+ mayTakeTime: "Com l'eliminació d'un compte consumeix bastants recursos, pot trigar un temps perquè es completi l'esborrat, depenent si tens molt contingut i la quantitat de fitxer que hagis pujat."
+ sendEmail: "Una vegada hagi finalitzat l'esborrat del compte rebràs un correu electrònic a l'adreça que tinguis registrada en aquest compte."
+ requestAccountDelete: "Demanar l'eliminació del compte"
+ started: "Ha començat l'esborrat del compte."
+ inProgress: "L'esborrat es troba en procés "
+_ad:
+ back: "Tornar"
+ reduceFrequencyOfThisAd: "Mostrar menys aquest anunci"
+ hide: "No mostrar mai"
+ timezoneinfo: "El dia de la setmana ve determinat del fus horari del servidor."
+ adsSettings: "Configuració d'anuncis "
+ notesPerOneAd: "Interval d'emplaçament d'anuncis en temps real (Notes per anuncis)"
+ setZeroToDisable: "Ajusta aquest valor a 0 per deshabilitar l'actualització d'anuncis en temps real"
+ adsTooClose: "L'interval actual pot fer que l'experiència de l'usuari sigui dolenta perquè l'interval és molt baix."
+_forgotPassword:
+ enterEmail: "Escriu l'adreça de correu electrònic amb la que et vas registrar. S'enviarà un correu electrònic amb un enllaç perquè puguis canviar-la."
+ ifNoEmail: "Si no vas fer servir una adreça de correu electrònic per registrar-te, si us plau posa't en contacte amb l'administrador."
+ contactAdmin: "Aquesta instància no suporta registrar-se amb correu electrònic. Si us plau, contacta amb l'administrador del servidor."
+_gallery:
+ my: "La meva Galeria "
+ liked: "Publicacions que t'han agradat"
+ like: "M'agrada "
+ unlike: "Ja no m'agrada"
_email:
_follow:
title: "t'ha seguit"
+ _receiveFollowRequest:
+ title: "Has rebut una sol·licitud de seguiment"
+_plugin:
+ install: "Instal·lar un afegit "
+ installWarn: "Si us plau, no instal·lis afegits que no siguin de confiança."
+ manage: "Gestionar els afegits"
+ viewSource: "Veure l'origen "
+_preferencesBackups:
+ list: "Llista de còpies de seguretat"
+ saveNew: "Fer una còpia de seguretat nova"
+ loadFile: "Carregar des d'un fitxer"
+ apply: "Aplicar en aquest dispositiu"
+ save: "Desar els canvis"
+ inputName: "Escriu un nom per aquesta còpia de seguretat"
+ cannotSave: "No s'ha pogut desar"
+ nameAlreadyExists: "Ja existeix una còpia de seguretat anomenada \"{name}\". Escriu un nom diferent."
+ applyConfirm: "Vols aplicar la còpia de seguretat \"{name}\" a aquest dispositiu? La configuració actual del dispositiu serà esborrada."
+ saveConfirm: "Desar còpia de seguretat com {name}?"
+ deleteConfirm: "Esborrar la còpia de seguretat {name}?"
+ renameConfirm: "Vols canvia el nom de la còpia de seguretat de \"{old}\" a \"{new}\"?"
+ noBackups: "No hi ha còpies de seguretat. Pots fer una còpia de seguretat de la configuració d'aquest dispositiu al servidor fent servir \"Crear nova còpia de seguretat\""
+ createdAt: "Creat el: {date} {time}"
+ updatedAt: "Actualitzat el: {date} {time}"
+ cannotLoad: "Hi ha hagut un error al carregar"
+ invalidFile: "Format del fitxer no vàlid "
+_registry:
+ scope: "Àmbit "
+ key: "Clau"
+ keys: "Claus"
+ domain: "Domini"
+ createKey: "Crear una clau"
+_aboutMisskey:
+ about: "Misskey és un programa de codi obert desenvolupar per syuilo des de 2014"
+ contributors: "Col·laboradors principals"
+ allContributors: "Tots els col·laboradors "
+ source: "Codi font"
+ translation: "Tradueix Misskey"
+ donate: "Fes un donatiu a Misskey"
+ morePatrons: "També agraïm el suport d'altres col·laboradors que no surten en aquesta llista. Gràcies! 🥰"
+ patrons: "Patrocinadors"
+ projectMembers: "Membres del projecte"
+_displayOfSensitiveMedia:
+ respect: "Ocultar imatges o vídeos marcats com a sensibles"
+ ignore: "Mostrar imatges o vídeos marcats com a sensibles"
+ force: "Ocultar totes les imatges o vídeos "
+_instanceTicker:
+ none: "No mostrar mai"
+ remote: "Mostrar per usuaris remots"
+ always: "Mostrar sempre"
+_serverDisconnectedBehavior:
+ reload: "Recarregar automàticament "
+ dialog: "Mostrar finestres de confirmació "
+ quiet: "Mostrar un avís que no molesti"
+_channel:
+ create: "Crear un canal"
+ edit: "Editar canal"
+ setBanner: "Estableix el bàner "
+ removeBanner: "Eliminar el.bàner"
+ featured: "Popular"
+ owned: "Propietat"
+ following: "Seguin"
+ usersCount: "{n} Participants"
+ notesCount: "{n} Notes"
+ nameAndDescription: "Nom i descripció "
+ nameOnly: "Nom només "
+ allowRenoteToExternal: "Permet la citació i l'impuls fora del canal"
+_menuDisplay:
+ sideFull: "Horitzontal "
+ sideIcon: "Horitzontal (icones)"
+ top: "A dalt"
+ hide: "Amagar"
+_wordMute:
+ muteWords: "Paraules silenciades"
+ muteWordsDescription: "Separar amb espais per la condició AND o amb salts de línia per la condició OR."
+ muteWordsDescription2: "Envolta les paraules amb barres per fer servir expressions regulars."
_instanceMute:
instanceMuteDescription: "Silencia tots els impulsos dels servidors seleccionats, també els usuaris que responen a altres d'un servidor silenciat."
+ instanceMuteDescription2: "Separar amb salts de línia"
+ title: "Ocultar notes de les instàncies en la llista."
+ heading: "Llista d'instàncies a silenciar"
_theme:
+ explore: "Explorar els temes "
+ install: "Instal·lar un tema"
+ manage: "Gestionar els temes "
+ code: "Codi del tema"
+ description: "Descripció"
+ installed: "{name} Instal·lat "
+ installedThemes: "Temes instal·lats "
+ builtinThemes: "Temes integrats"
+ alreadyInstalled: "Aquest tema ja es troba instal·lat "
+ invalid: "El format d'aquest tema no és correcte"
+ make: "Crear un tema"
+ base: "Base"
+ addConstant: "Afegir constant "
+ constant: "Constant"
+ defaultValue: "Valor per defecte"
+ color: "Color"
+ refProp: "Referència a una propietat"
+ refConst: "Referència a una constant "
+ key: "Clau"
+ func: "Funcions"
+ funcKind: "Tipus de funció "
+ argument: "Argument"
+ basedProp: "Propietat referenciada"
+ alpha: "Opacitat"
+ darken: "Enfosquir "
+ lighten: "Brillantor"
+ inputConstantName: "Escriu un nom per aquesta constant"
+ importInfo: "Si escrius el codi del tema aquí, el podràs importar a l'editor del tema"
+ deleteConstantConfirm: "Vols esborrar la constant {const}?"
keys:
+ accent: "Accent"
+ bg: "Fons"
+ fg: "Text"
+ focus: "Enfocament"
+ indicator: "Indicador"
+ panel: "Taulell "
+ shadow: "Ombra"
+ header: "Capçalera"
+ navBg: "Fons de la barra lateral"
+ navFg: "Text de la barra lateral"
+ navHoverFg: "Text barra lateral (en passar per sobre)"
+ navActive: "Text barra lateral (actiu)"
+ navIndicator: "Indicador barra lateral"
+ link: "Enllaç"
+ hashtag: "Etiqueta"
mention: "Menció"
+ mentionMe: "Mencions (jo)"
renote: "Renotar"
+ modalBg: "Fons del modal"
+ divider: "Divisor"
+ scrollbarHandle: "Maneta de la barra de desplaçament"
+ scrollbarHandleHover: "Maneta de la barra de desplaçament (en passar-hi per sobre)"
+ dateLabelFg: "Text de l'etiqueta de la data"
+ infoBg: "Fons d'informació "
+ infoFg: "Text d'informació "
+ infoWarnBg: "Fons avís "
+ infoWarnFg: "Text avís "
+ toastBg: "Fons notificació "
+ toastFg: "Text notificació "
+ buttonBg: "Fons botó "
+ buttonHoverBg: "Fons botó (en passar-hi per sobre)"
+ inputBorder: "Contorn del cap d'introducció "
+ listItemHoverBg: "Fons dels elements d'una llista"
+ driveFolderBg: "Fons de la carpeta Disc"
+ wallpaperOverlay: "Superposició del fons de pantalla "
+ badge: "Insígnia "
+ messageBg: "Fons del xat"
+ accentDarken: "Accent (fosc)"
+ accentLighten: "Accent (clar)"
+ fgHighlighted: "Text ressaltat"
_sfx:
note: "Notes"
+ noteMy: "Nota (per mi)"
notification: "Notificacions"
antenna: "Antenes"
+ channel: "Notificacions dels canals"
+ reaction: "Quan se selecciona una reacció "
+_soundSettings:
+ driveFile: "Fer servir un fitxer d'àudio del disc"
+ driveFileWarn: "Seleccionar un fitxer d'àudio del disc"
+ driveFileTypeWarn: "Fitxer no suportat "
+ driveFileTypeWarnDescription: "Seleccionar un fitxer d'àudio "
+ driveFileDurationWarn: "L'àudio és massa llarg"
+ driveFileDurationWarnDescription: "Els àudios molt llargs pot interrompre l'ús de Misskey. Vols continuar?"
+_ago:
+ future: "Futur "
+ justNow: "Ara mateix"
+ secondsAgo: "Fa {n} segons"
+ minutesAgo: "Fa {n} minuts"
+ hoursAgo: "Fa {n} hores"
+ daysAgo: "Fa {n} dies"
+ weeksAgo: "Fa {n} setmanes"
+ monthsAgo: "Fa {n} mesos"
+ yearsAgo: "Fa {n} anys"
+ invalid: "Res"
+_timeIn:
+ seconds: "En {n} segons"
+ minutes: "En {n} minuts"
+ hours: "En {n} hores"
+ days: "En {n} dies"
+ weeks: "En {n} setmanes"
+ months: "En {n} mesos"
+ years: "En {n} anys"
+_time:
+ second: "Segon(s)"
+ minute: "Minut(s)"
+ hour: "Hor(a)(es)"
+ day: "Di(a)(es)"
_2fa:
+ alreadyRegistered: "J has registrat un dispositiu d'autenticació de doble factor."
+ registerTOTP: "Registrar una aplicació autenticadora"
+ step1: "Primer instal·la una aplicació autenticadora (com {a} o {b}) al teu dispositiu."
+ step2: "Després escaneja el codi QR que es mostra en aquesta pantalla."
+ step2Click: "Fent clic en aquest codi QR et permetrà registrar l'autenticació de doble factor a la teva clau de seguretat o en l'aplicació d'autenticació del teu dispositiu."
+ step2Uri: "Escriu la següent URI si estàs fent servir una aplicació d'escriptori "
+ step3Title: "Escriu un codi d'autenticació"
+ step3: "Escriu el codi d'autenticació (token) que es mostra a la teva aplicació per finalitzar la configuració."
+ setupCompleted: "Configuració terminada"
+ step4: "D'ara endavant quan accedeixis se't demanarà el token que has introduït."
+ securityKeyNotSupported: "El teu navegador no suporta claus de seguretat"
+ registerTOTPBeforeKey: "Configura una aplicació d'autenticació per registrar una clau de seguretat o una clau de pas."
+ securityKeyInfo: "A més de l'empremta digital o PIN per autenticar-te, pots configurar autenticació mitjançant maquinari que suporti claus de seguretat FIDO2, per protegir encara més el teu compte."
+ registerSecurityKey: "Registrar una clau de seguretat o clau de pas"
+ securityKeyName: "Escriu un nom per la clau"
+ tapSecurityKey: "Seguiu les instruccions del navegador i registrar les claus de seguretat o la clau de pas"
+ removeKey: "Esborrar la clau de seguretat"
+ removeKeyConfirm: "Esborrar la còpia de seguretat {name}?"
+ whyTOTPOnlyRenew: "L'aplicació d'autenticació no es pot eliminar mentre hi hagi una clau de seguretat registrada."
+ renewTOTP: "Reconfigurar l'aplicació d'autenticació "
+ renewTOTPConfirm: "Això farà que els codis de validació de l'antiga aplicació deixin de funcionar"
+ renewTOTPOk: "Reconfigurar"
renewTOTPCancel: "No, gràcies"
+ checkBackupCodesBeforeCloseThisWizard: "Abans de tancar aquesta finestra, comprova el següent codi de seguretat."
+ backupCodes: "Codi de seguretat."
+ backupCodesDescription: "Si l'aplicació d'autenticació no es pot utilitzar, es pot accedir al compte utilitzant els següents codis de còpia de seguretat. Assegura't de mantenir aquests codis en un lloc segur. Cada codi es pot utilitzar només una vegada."
+ backupCodeUsedWarning: "Es va utilitzar un codi de còpia de seguretat. Si l'aplicació de certificació està disponible, reconfigura l'aplicació d'autenticació tan aviat com sigui possible."
+ backupCodesExhaustedWarning: "Es van utilitzar tots els codis de còpia de seguretat. Si no es pot utilitzar l'aplicació d'autenticació, ja no es pot accedir al compte. Torna a registrar l'aplicació d'autenticació."
+_permissions:
+ "read:account": "Veure la informació del compte."
+ "write:account": "Editar la informació del compte."
+ "read:blocks": "Veure la llista d'usuaris bloquejats"
+ "write:blocks": "Editar la llista d'usuaris blocats"
+ "read:drive": "Accedeix als teus fitxers i carpetes del Disc"
+ "write:drive": "Editar o eliminar els teus fitxers i carpetes al Disc"
+ "read:favorites": "Veure la teva llista de favorits"
+ "write:favorites": "Editar la teva llista de favorits"
+ "read:following": "Veure informació de qui segueixes"
+ "write:following": "Segueix o deixa de seguir altres comptes"
+ "read:messaging": "Veure els teus xats"
+ "write:messaging": "Crear o esborrar missatges de xat"
+ "read:mutes": "Veure la teva llista d'usuaris silenciats"
+ "write:mutes": "Editar la teva llista d'usuaris silenciats"
+ "write:notes": "Crear o esborrar notes"
+ "read:notifications": "Veure les teves notificacions"
+ "write:notifications": "Gestionar les teves notificacions"
+ "read:reactions": "Veure les teves reaccions"
+ "write:reactions": "Editar les teves reaccions"
+ "write:votes": "Votar en una enquesta"
+ "read:pages": "Veure les teves pàgines "
+ "write:pages": "Editar o esborrar les teves pàgines "
+ "read:page-likes": "Veure la llista de les pàgines que t'han agradat"
+ "write:page-likes": "Editar la llista de les pàgines que t'han agradat"
+ "read:user-groups": "Veure els teus grups d'usuaris "
+ "write:user-groups": "Editar o esborrar els teus grups d'usuaris "
+ "read:channels": "Veure els teus canals"
+ "write:channels": "Editar els teus canals"
+ "read:gallery": "Veure la teva galeria "
+ "write:gallery": "Editar la teva galeria"
+ "read:gallery-likes": "Veure la llista de publicacions de galeries que t'han agradat"
+ "write:gallery-likes": "Editar la llista de publicacions de galeries que t'han agradat"
+ "read:flash": "Veure reproduccions"
+ "write:flash": "Editar reproduccions"
+ "read:flash-likes": "Veure la llista de reproduccions que t'han agradat"
+ "write:flash-likes": "Editar la llista de reproduccions que t'han agradat"
+ "read:admin:abuse-user-reports": "Veure informes d'usuaris "
+ "write:admin:delete-account": "Esborrar compte d'usuari "
+ "write:admin:delete-all-files-of-a-user": "Esborrar tots els fitxers d'un usuari"
+ "read:admin:index-stats": "Veure l'índex de la base de dades"
+ "read:admin:table-stats": "Veure la informació de les taules a la base de dades"
+ "read:admin:user-ips": "Veure adreça IP de l'usuari "
+ "read:admin:meta": "Veure meta-informació del servidor"
+ "write:admin:reset-password": "Reiniciar contrasenya d'usuari "
+ "write:admin:resolve-abuse-user-report": "Resoldre informes d'usuaris "
+ "write:admin:send-email": "Enviar correu electrònic "
+ "read:admin:server-info": "Veure informació del servidor"
+ "read:admin:show-moderation-log": "Veure registre de moderació "
+ "read:admin:show-user": "Veure informació privada de l'usuari "
+ "read:admin:show-users": "Veure informació privada de l'usuari "
+ "write:admin:suspend-user": "Suspendre usuari"
+ "write:admin:unset-user-avatar": "Esborrar avatar d'usuari "
+ "write:admin:unset-user-banner": "Esborrar bàner de l'usuari "
+ "write:admin:unsuspend-user": "Treure la suspensió d'un usuari"
+ "write:admin:meta": "Gestionar les metadades de la instància"
+ "write:admin:user-note": "Gestionar les notes de moderació "
+ "write:admin:roles": "Gestionar rols"
+ "read:admin:roles": "Veure rols"
+ "write:admin:relays": "Gestionar relé"
+ "read:admin:relays": "Veure relés"
+ "write:admin:invite-codes": "Gestionar codis d'invitació "
+ "read:admin:invite-codes": "Veure codis d'invitació "
+ "write:admin:announcements": "Gestionar anuncis"
+ "read:admin:announcements": "Veure anuncis"
+ "write:admin:avatar-decorations": "Gestionar la decoració dels avatars"
+ "read:admin:avatar-decorations": "Veure les decoracions dels avatars"
+ "write:admin:federation": "Gestionar la federació d'instàncies "
+ "write:admin:account": "Gestionar els comptes d'usuaris "
+ "read:admin:account": "Veure els comptes d'usuaris "
+ "write:admin:emoji": "Edició d'emojis"
+ "read:admin:emoji": "Veure emojis"
+ "write:admin:queue": "Gestionar la cua de feines"
+ "read:admin:queue": "Veure la cua de feines"
_antennaSources:
all: "Totes les publicacions"
homeTimeline: "Publicacions dels usuaris seguits"
@@ -420,18 +2025,76 @@ _widgets:
timeline: "Línia de temps"
activity: "Activitat"
federation: "Federació"
+ button: "Botó "
jobQueue: "Cua de tasques"
_userList:
chooseList: "Tria una llista"
_cw:
+ hide: "Amagar"
show: "Carregar més"
+ chars: "{count} caràcters "
+ files: "{count} fitxer(s)"
+_poll:
+ noOnlyOneChoice: "Es necessita escollir dues opcions com a mínim "
+ choiceN: "Opció {n}"
+ noMore: "No pots afegir més opcions"
+ canMultipleVote: "Permetre escollir diferents opcions"
+ expiration: "Finalitza el"
+ infinite: "Mai"
+ at: "Finalitza en..."
+ after: "Finalitza després..."
+ deadlineDate: "Data de finalització "
+ deadlineTime: "Hor(a)(es)"
+ duration: "Duració "
+ votesCount: "{n} vots"
+ totalVotes: "{n} vots en total"
+ vote: "Votar en una enquesta"
+ showResult: "Veure resultats"
+ voted: "Has votat"
+ closed: "Finalitzada"
+ remainingDays: "Queden {d} dies i {h} hores per finalitzar"
+ remainingHours: "Queden {h} hores i {m} minuts"
+ remainingMinutes: "Queden {m} minuts i {s} segons"
+ remainingSeconds: "Queden {s} segons"
_visibility:
+ public: "Públic "
+ publicDescription: "La teva nota la podrà veure tothom "
home: "Inici"
+ homeDescription: "Publicar només a la línia de temps d'Inici "
followers: "Seguidors"
+ followersDescription: "Fes només visible per als teus seguidors"
+ specified: "Directe"
+ specifiedDescription: "Fer visible només per alguns usuaris"
+ disableFederation: "Sense federar"
+ disableFederationDescription: "No enviar a altres servidors"
+_postForm:
+ replyPlaceholder: "Contestar..."
+ quotePlaceholder: "Citar..."
+ channelPlaceholder: "Publicar a un canal..."
+ _placeholders:
+ a: "Que vols dir?..."
+ b: "Alguna cosa interessant al teu voltant?..."
+ c: "Què et passa pel cap?..."
+ d: "Què vols dir?..."
+ e: "Escriu alguna cosa..."
+ f: "Esperant que escriguis qualsevol cosa..."
_profile:
+ name: "Nom"
username: "Nom d'usuari"
+ description: "Biografia "
+ youCanIncludeHashtags: "Pots posar etiquetes a la teva biografia "
+ metadata: "Informació adicional "
+ metadataEdit: "Editar la informació adicional "
+ metadataDescription: "Amb això podràs mostrar camps d'informació adicional al teu perfil."
+ metadataLabel: "Etiqueta "
+ metadataContent: "Contingut"
+ changeAvatar: "Canviar l'avatar "
+ changeBanner: "Canviar el bàner "
+ verifiedLinkDescription: "Escrivint una adreça URL que enllaci a aquest perfil, una icona de propietat verificada es mostrarà al costat del camp."
+ avatarDecorationMax: "Pot afegir un màxim de {max} decoracions."
_exportOrImport:
allNotes: "Totes les publicacions"
+ clips: "Retalls"
followingList: "Seguint"
muteList: "Silencia"
blockingList: "Bloqueja"
@@ -443,17 +2106,75 @@ _timelines:
local: "Local"
social: "Social"
global: "Global"
+_play:
+ viewSource: "Veure l'origen "
+ featured: "Popular"
+ title: "Títol "
+ script: "Script"
+ summary: "Descripció"
_pages:
+ viewSource: "Veure l'origen "
+ viewPage: "Veure les teves pàgines "
+ like: "M'agrada "
+ unlike: "Treure m'agrada "
+ my: "Les meves pàgines "
+ liked: "Pàgines que m'agraden "
+ featured: "Popular"
+ inspector: "Inspeccionar"
contents: "Contingut"
+ content: "Bloquejar la pàgina "
+ variables: "Variables"
+ title: "Títol "
+ url: "URL de la pàgina "
+ summary: "Resum de la pàgina "
+ alignCenter: "Centrar elements"
+ hideTitleWhenPinned: "Amagar el títol de la pàgina quan estigui fixada al perfil"
+ font: "Lletra tipogràfica"
+ fontSerif: "Serif"
+ fontSansSerif: "Sans Serif"
+ eyeCatchingImageSet: "Escull una miniatura"
+ eyeCatchingImageRemove: "Esborrar la miniatura"
+ chooseBlock: "Afegeix un bloc"
+ selectType: "Seleccionar tipus"
+ contentBlocks: "Contingut"
+ inputBlocks: "Entrada "
+ specialBlocks: "Especial"
blocks:
+ text: "Text"
+ textarea: "Àrea de text"
+ section: "Secció "
image: "Imatges"
+ button: "Botó "
+ note: "Incorporar una Nota"
_note:
id: "ID de la publicació"
+ idDescription: "Alternativament pots enganxar l'adreça URL de la nota aquí."
detailed: "Mostra els detalls"
+_relayStatus:
+ requesting: "Pendent"
+ accepted: "Acceptat"
+ rejected: "Rebutjat"
_notification:
+ fileUploaded: "Fitxer pujat sense cap problema"
+ youGotMention: "{name} t'ha mencionat"
+ youGotReply: "{name} t'ha contestat"
+ youGotQuote: "{name} t'ha citat"
youRenoted: "Impulsat per {name}"
youWereFollowed: "t'ha seguit"
+ youReceivedFollowRequest: "Has rebut una petició de seguiment"
+ yourFollowRequestAccepted: "La teva petició de seguiment ha sigut acceptada"
+ pollEnded: "Ja pots veure els resultats de l'enquesta "
+ newNote: "Nota nova"
unreadAntennaNote: "Antena {name}"
+ roleAssigned: "Rol assignat "
+ emptyPushNotificationMessage: "Les notificacions han sigut actualitzades"
+ achievementEarned: "Aconseguiment desblocat"
+ testNotification: "Notificació de prova"
+ checkNotificationBehavior: "Comprova el comportament de la notificació "
+ sendTestNotification: "Enviar notificació de prova"
+ notificationWillBeDisplayedLikeThis: "Les notificacions és veure'n així "
+ reactedBySomeUsers: "Han reaccionat {n} usuaris"
+ renotedBySomeUsers: "L'han impulsat {n} usuaris"
_types:
all: "Tots"
follow: "Seguint"
@@ -483,8 +2204,55 @@ _deck:
tl: "Línia de temps"
antenna: "Antena"
list: "Llistes"
+ channel: "Canals"
mentions: "Mencions"
direct: "Publicacions directes"
+_webhookSettings:
+ name: "Nom"
+ active: "Activat"
_moderationLogTypes:
suspend: "Suspèn"
resetPassword: "Restableix la contrasenya"
+ suspendRemoteInstance: "Servidor remot suspès "
+ unsuspendRemoteInstance: "S'ha tret la suspensió del servidor remot"
+ markSensitiveDriveFile: "Fitxer marcat com a sensible"
+ unmarkSensitiveDriveFile: "S'ha tret la marca de sensible del fitxer"
+ resolveAbuseReport: "Informe resolt"
+ createInvitation: "Crear codi d'invitació "
+ createAd: "Anunci creat"
+ deleteAd: "Anunci esborrat"
+ updateAd: "Anunci actualitzat"
+ createAvatarDecoration: "Decoració de l'avatar creada"
+ updateAvatarDecoration: "S'ha actualitzat la decoració de l'avatar "
+ deleteAvatarDecoration: "S'ha esborrat la decoració de l'avatar "
+ unsetUserAvatar: "Esborrar l'avatar d'aquest usuari"
+ unsetUserBanner: "Esborrar el bàner d'aquest usuari"
+_fileViewer:
+ title: "Detall del fitxer"
+ type: "Tipus de fitxer"
+ size: "Mida"
+ url: "URL"
+ uploadedAt: "Pujat el"
+ attachedNotes: "Notes amb aquest fitxer"
+ thisPageCanBeSeenFromTheAuthor: "Aquesta pàgina només la pot veure l'usuari que ha pujat aquest fitxer."
+_externalResourceInstaller:
+ title: "Instal·lar des d'un lloc extern"
+ checkVendorBeforeInstall: "Assegura't que qui distribueix aquest recurs és fiable abans d'instal·lar-ho."
+ _plugin:
+ title: "Vols instal·lar aquest afegit?"
+ metaTitle: "Informació de l'afegit "
+ _theme:
+ title: "Vols instal·lar aquest tema?"
+ metaTitle: "Informació del tema"
+ _meta:
+ base: "Paleta de colors base"
+ _vendorInfo:
+ title: "Informació del distribuïdor "
+ endpoint: "Punt final referenciat"
+ hashVerify: "Verificació d'integritat "
+ _errors:
+ _invalidParams:
+ title: "Paràmetres no vàlids "
+_reversi:
+ total: "Total"
+
diff --git a/locales/cs-CZ.yml b/locales/cs-CZ.yml
index 5d6487d6d..cbf5c33c1 100644
--- a/locales/cs-CZ.yml
+++ b/locales/cs-CZ.yml
@@ -120,7 +120,6 @@ sensitive: "NSFW"
add: "Přidat"
reaction: "Reakce"
reactions: "Reakce"
-reactionSetting: "Reakce zobrazené ve výběru reakcí"
reactionSettingDescription2: "Přetažením změníte pořadí, kliknutím smažete, zmáčkněte \"+\" k přidání"
rememberNoteVisibility: "Zapamatovat nastavení zobrazení poznámky"
attachCancel: "Odstranit přílohu"
@@ -367,6 +366,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Aktivovat hCaptchu"
hcaptchaSiteKey: "Klíč stránky"
hcaptchaSecretKey: "Tajný Klíč (Secret Key)"
+mcaptchaSiteKey: "Klíč stránky"
+mcaptchaSecretKey: "Tajný Klíč (Secret Key)"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Zapnout ReCAPTCHu"
recaptchaSiteKey: "Klíč stránky"
@@ -428,7 +429,6 @@ share: "Sdílet"
notFound: "Nenalezeno"
notFoundDescription: "Nebyla nalezená žádná stránka korespondující se zadanou URL."
uploadFolder: "Výchozí lokace pro upload"
-cacheClear: "Vymazat cache"
markAsReadAllNotifications: "Označit všechna oznámení za přečtená"
markAsReadAllUnreadNotes: "Označit všechny příspěvky za přečtené"
markAsReadAllTalkMessages: "Označit všechny zprávy za přečtené"
@@ -856,8 +856,6 @@ makeReactionsPublicDescription: "Tohle zviditelný seznam vašich předchozích
classic: "Klasický"
muteThread: "Ztlumit vlákno"
unmuteThread: "Zrušit ztlumení vlákna"
-ffVisibility: "Viditelnost Sledovaných/Sledujících"
-ffVisibilityDescription: "Umožní vám nastavit kdo uvidí koho sledujete a kdo vás sleduje."
continueThread: "Zobrazit pokračování vlákna"
deleteAccountConfirm: "Tohle nenávratně smaže váš účet, chcete pokračovat?"
incorrectPassword: "Nesprávné heslo."
@@ -1007,6 +1005,7 @@ resetPasswordConfirm: "Opravdu chcete resetovat heslo?"
sensitiveWords: "Citlivá slova"
sensitiveWordsDescription: "Viditelnost všech poznámek obsahujících některé z nakonfigurovaných slov bude automaticky nastavena na \"Domů\". Můžete jich uvést více tak, že je oddělíte pomocí řádků."
sensitiveWordsDescription2: "Použití mezer vytvoří výrazy AND a obklopení klíčových slov lomítky je změní na regulární výraz."
+prohibitedWordsDescription2: "Použití mezer vytvoří výrazy AND a obklopení klíčových slov lomítky je změní na regulární výraz."
notesSearchNotAvailable: "Vyhledávání poznámek je nedostupné."
license: "Licence"
unfavoriteConfirm: "Opravdu chcete odstranit z oblíbených?"
@@ -1096,7 +1095,10 @@ iHaveReadXCarefullyAndAgree: "Přečetl jsem si text \"{x}\" a souhlasím s ním
icon: "Avatar"
replies: "Odpovědět"
renotes: "Přeposlat"
+sourceCode: "Zdrojový kód"
flip: "Otočit"
+lastNDays: "Posledních {n} dnů"
+surrender: "Zrušit"
_initialAccountSetting:
accountCreated: "Váš účet byl úspěšně vytvořen!"
letsStartAccountSetup: "Pro začátek si nastavte svůj profil."
@@ -1829,6 +1831,7 @@ _profile:
_exportOrImport:
allNotes: "Všechny poznámky"
favoritedNotes: "Oblíbené poznámky"
+ clips: "Oříznout"
followingList: "Sledovaní"
muteList: "Ztlumit"
blockingList: "Zablokovat"
@@ -2020,3 +2023,6 @@ _moderationLogTypes:
suspend: "Zmrazit"
resetPassword: "Resetovat heslo"
createInvitation: "Vygenerovat pozvánku"
+_reversi:
+ total: "Celkem"
+
diff --git a/locales/da-DK.yml b/locales/da-DK.yml
index 08c15ed09..d1fbec9f6 100644
--- a/locales/da-DK.yml
+++ b/locales/da-DK.yml
@@ -1,2 +1,3 @@
---
_lang_: "Dansk"
+
diff --git a/locales/de-DE.yml b/locales/de-DE.yml
index af927586d..9a22a7b44 100644
--- a/locales/de-DE.yml
+++ b/locales/de-DE.yml
@@ -121,10 +121,15 @@ sensitive: "Sensibel"
add: "Hinzufügen"
reaction: "Reaktionen"
reactions: "Reaktionen"
-reactionSetting: "In der Reaktionsauswahl anzuzeigende Reaktionen"
+emojiPicker: "Emoji auswählen"
+pinnedEmojisForReactionSettingDescription: "Lege Emojis fest, die angepinnt werden sollen, um sie beim Reagieren als Erstes anzuzeigen."
+pinnedEmojisSettingDescription: "Lege Emojis fest, die angepinnt werden sollen, um sie in der Emoji-Auswahl als Erstes anzuzeigen"
+overwriteFromPinnedEmojisForReaction: "Überschreiben mit den Reaktions-Einstellungen"
+overwriteFromPinnedEmojis: "Überschreiben mit den allgemeinen Einstellungen"
reactionSettingDescription2: "Ziehe um Anzuordnen, klicke um zu löschen, drücke „+“ um hinzuzufügen"
rememberNoteVisibility: "Notizsichtbarkeit merken"
attachCancel: "Anhang entfernen"
+deleteFile: "Datei gelöscht"
markAsSensitive: "Als sensibel markieren"
unmarkAsSensitive: "Als nicht sensibel markieren"
enterFileName: "Dateinamen eingeben"
@@ -179,7 +184,7 @@ searchWith: "Suchen: {q}"
youHaveNoLists: "Du hast keine Listen"
followConfirm: "Möchtest du {name} wirklich folgen?"
proxyAccount: "Proxy-Benutzerkonto"
-proxyAccountDescription: "Ein Proxy-Benutzerkonto ist ein Benutzerkonto, das sich für Nutzer unter bestimmten Konditionen wie ein Follower aus einer fremden Instanz verhält. Zum Beispiel wird die Aktivität eines Nutzers aus einer fremden Instanz nicht an diese Instanz übermittelt, falls es keinen Benutzer dieser Instanz gibt, der diesem Nutzer aus fremder Instanz folgt. In diesem Fall folgt stattdessen das Proxy-Benutzerkonto."
+proxyAccountDescription: "Ein Proxy-Konto ist ein Benutzerkonto, das unter bestimmten Bedingungen als Follower für Benutzer fremder Instanzen fungiert. Wenn zum Beispiel ein Benutzer einen Benutzer einer fremden Instanz zu einer Liste hinzufügt, werden die Aktivitäten des entfernten Benutzers nicht an die Instanz übermittelt, wenn kein lokaler Benutzer diesem Benutzer folgt; stattdessen folgt das Proxy-Konto."
host: "Hostname"
selectUser: "Benutzer auswählen"
recipient: "Empfänger"
@@ -261,6 +266,7 @@ removed: "Erfolgreich gelöscht"
removeAreYouSure: "Möchtest du „{x}“ wirklich entfernen?"
deleteAreYouSure: "Möchtest du „{x}“ wirklich löschen?"
resetAreYouSure: "Wirklich zurücksetzen?"
+areYouSure: "Bist du sicher?"
saved: "Erfolgreich gespeichert"
messaging: "Chat"
upload: "Hochladen"
@@ -311,6 +317,7 @@ folderName: "Ordnername"
createFolder: "Ordner erstellen"
renameFolder: "Ordner umbenennen"
deleteFolder: "Ordner löschen"
+folder: "Ordner"
addFile: "Datei hinzufügen"
emptyDrive: "Deine Drive ist leer"
emptyFolder: "Dieser Ordner ist leer"
@@ -354,7 +361,7 @@ enableLocalTimeline: "Lokale Chronik aktivieren"
enableGlobalTimeline: "Globale Chronik aktivieren"
disablingTimelinesInfo: "Administratoren und Moderatoren haben immer Zugriff auf alle Chroniken, auch wenn diese deaktiviert sind."
registration: "Registrieren"
-enableRegistration: "Registration neuer Benutzer erlauben"
+enableRegistration: "Registrierung neuer Benutzer erlauben"
invite: "Einladen"
driveCapacityPerLocalAccount: "Drive-Kapazität pro lokalem Benutzerkonto"
driveCapacityPerRemoteAccount: "Drive-Kapazität pro Benutzer fremder Instanzen"
@@ -372,6 +379,11 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "hCaptcha aktivieren"
hcaptchaSiteKey: "Site key"
hcaptchaSecretKey: "Secret key"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "mCaptcha aktivieren"
+mcaptchaSiteKey: "Site key"
+mcaptchaSecretKey: "Secret key"
+mcaptchaInstanceUrl: "mCaptcha Instanz-URL"
recaptcha: "reCAPTCHA"
enableRecaptcha: "reCAPTCHA aktivieren"
recaptchaSiteKey: "Site key"
@@ -429,7 +441,7 @@ lastUsed: "Zuletzt benutzt"
lastUsedAt: "Zuletzt verwendet: {t}"
unregister: "Deaktivieren"
passwordLessLogin: "Passwortloses Anmelden"
-passwordLessLoginDescription: "Ermöglicht passwortfreies Einloggen, nur via Security-Token oder Passkey"
+passwordLessLoginDescription: "Ermöglicht passwortloses Einloggen mit einem Security-Token oder Passkey"
resetPassword: "Passwort zurücksetzen"
newPasswordIs: "Das neue Passwort ist „{password}“"
reduceUiAnimation: "Animationen der Benutzeroberfläche reduzieren"
@@ -437,7 +449,6 @@ share: "Teilen"
notFound: "Nicht gefunden"
notFoundDescription: "Es konnte keine Seite unter dieser URL gefunden werden."
uploadFolder: "Standardordner für Uploads"
-cacheClear: "Cache leeren"
markAsReadAllNotifications: "Alle Benachrichtigungen als gelesen markieren"
markAsReadAllUnreadNotes: "Alle Notizen als gelesen markieren"
markAsReadAllTalkMessages: "Alle Chats als gelesen markieren"
@@ -544,6 +555,8 @@ showInPage: "In einer Seite anzeigen"
popout: "Pop-Up"
volume: "Lautstärke"
masterVolume: "Gesamtlautstärke"
+notUseSound: "Gebe kein Ton aus"
+useSoundOnlyWhenActive: "Gebe nur Ton aus, wenn Misskey aktiv ist"
details: "Details"
chooseEmoji: "Emoji auswählen"
unableToProcess: "Der Vorgang konnte nicht abgeschlossen werden"
@@ -564,6 +577,10 @@ output: "Ausgabe"
script: "Skript"
disablePagesScript: "AiScript auf Seiten deaktivieren"
updateRemoteUser: "Benutzerinformationen aktualisieren"
+unsetUserAvatar: "Entferne Profilbild"
+unsetUserAvatarConfirm: "Möchtest du dein Profilbild entfernen?"
+unsetUserBanner: "Entferne Profilbanner"
+unsetUserBannerConfirm: "Möchtest du dein Profilbanner entfernen?"
deleteAllFiles: "Alle Dateien löschen"
deleteAllFilesConfirm: "Möchtest du wirklich alle Dateien löschen?"
removeAllFollowing: "Allen gefolgten Benutzern entfolgen"
@@ -614,6 +631,7 @@ medium: "Mittel"
small: "Klein"
generateAccessToken: "Zugriffstoken generieren"
permission: "Berechtigungen"
+adminPermission: "Administratorberechtigung"
enableAll: "Alle aktivieren"
disableAll: "Alle deaktivieren"
tokenRequested: "Zugriff zum Benutzerkonto gewähren"
@@ -868,8 +886,6 @@ makeReactionsPublicDescription: "Jeder wird die Liste deiner gesendeten Reaktion
classic: "Classic"
muteThread: "Thread stummschalten"
unmuteThread: "Threadstummschaltung aufheben"
-ffVisibility: "Sichtbarkeit von Gefolgten/Followern"
-ffVisibilityDescription: "Konfiguriere wer sehen kann, wem du folgst sowie wer dir folgt."
continueThread: "Weiteren Threadverlauf anzeigen"
deleteAccountConfirm: "Dein Benutzerkonto wird unwiderruflich gelöscht. Trotzdem fortfahren?"
incorrectPassword: "Falsches Passwort."
@@ -1020,6 +1036,9 @@ resetPasswordConfirm: "Wirklich Passwort zurücksetzen?"
sensitiveWords: "Sensible Wörter"
sensitiveWordsDescription: "Die Notizsichtbarkeit aller Notizen, die diese Wörter enthalten, wird automatisch auf \"Startseite\" gesetzt. Durch Zeilenumbrüche können mehrere konfiguriert werden."
sensitiveWordsDescription2: "Durch die Verwendung von Leerzeichen können AND-Verknüpfungen angegeben werden und durch das Umgeben von Schrägstrichen können reguläre Ausdrücke verwendet werden."
+prohibitedWordsDescription2: "Durch die Verwendung von Leerzeichen können AND-Verknüpfungen angegeben werden und durch das Umgeben von Schrägstrichen können reguläre Ausdrücke verwendet werden."
+hiddenTags: "Ausgeblendete Hashtags"
+hiddenTagsDescription: "Die hier eingestellten Tags werden nicht mehr in den Trends angezeigt. Mit der Umschalttaste können mehrere ausgewählt werden."
notesSearchNotAvailable: "Die Notizsuche ist nicht verfügbar."
license: "Lizenz"
unfavoriteConfirm: "Wirklich aus Favoriten entfernen?"
@@ -1032,6 +1051,7 @@ enableChartsForRemoteUser: "Diagramme für Nutzer fremder Instanzen erstellen"
enableChartsForFederatedInstances: "Diagramme für fremde Instanzen erstellen"
showClipButtonInNoteFooter: "\"Clip\" zum Notizmenu hinzufügen"
reactionsDisplaySize: "Reaktionsanzeigegröße"
+limitWidthOfReaction: "Begrenze die Breite der Reaktion und zeige sie verkleinert an"
noteIdOrUrl: "Notiz-ID oder URL"
video: "Video"
videos: "Videos"
@@ -1138,6 +1158,7 @@ hideRepliesToOthersInTimelineAll: "Antworten von allen momentan gefolgten Benutz
confirmShowRepliesAll: "Dies ist eine unwiderrufliche Aktion. Wirklich Antworten von allen momentan gefolgten Benutzern in der Chronik anzeigen?"
confirmHideRepliesAll: "Dies ist eine unwiderrufliche Aktion. Wirklich Antworten von allen momentan gefolgten Benutzern nicht in der Chronik anzeigen?"
externalServices: "Externe Dienste"
+sourceCode: "Quellcode"
impressum: "Impressum"
impressumUrl: "Impressums-URL"
impressumDescription: "In manchen Ländern, wie Deutschland und dessen Umgebung, ist die Angabe von Betreiberinformationen (ein Impressum) bei kommerziellem Betrieb zwingend."
@@ -1155,7 +1176,15 @@ refreshing: "Wird aktualisiert..."
pullDownToRefresh: "Zum Aktualisieren ziehen"
disableStreamingTimeline: "Echtzeitaktualisierung der Chronik deaktivieren"
useGroupedNotifications: "Benachrichtigungen gruppieren"
+signupPendingError: "Beim Überprüfen der Mailadresse ist etwas schiefgelaufen. Der Link könnte abgelaufen sein."
cwNotationRequired: "Ist \"Inhaltswarnung verwenden\" aktiviert, muss eine Beschreibung gegeben werden."
+doReaction: "Reagieren"
+code: "Code"
+decorate: "Dekorieren"
+addMfmFunction: "MFM hinzufügen"
+sfx: "Soundeffekte"
+lastNDays: "Letzten {n} Tage"
+surrender: "Abbrechen"
_announcement:
forExistingUsers: "Nur für existierende Nutzer"
forExistingUsersDescription: "Ist diese Option aktiviert, wird diese Ankündigung nur Nutzern angezeigt, die zum Zeitpunkt der Ankündigung bereits registriert sind. Ist sie deaktiviert, wird sie auch Nutzern, die sich nach dessen Veröffentlichung registrieren, angezeigt."
@@ -1165,6 +1194,10 @@ _announcement:
tooManyActiveAnnouncementDescription: "Zu viele aktive Ankündigungen können die Benutzerfreundlichkeit verschlechtern. Es wird empfohlen, veraltete Ankündigungen zu archivieren."
readConfirmTitle: "Als gelesen markieren?"
readConfirmText: "Dies markiert den Inhalt von \"{title}\" als gelesen."
+ shouldNotBeUsedToPresentPermanentInfo: "Es wird empfohlen, Ankündigungen für aktuelle und zeitlich begrenzte Neuigkeiten zu nutzen, statt für Informationen, die langfristig relevant sind."
+ dialogAnnouncementUxWarn: "Bei der Verwendung von mehr als zwei Meldungen im Dialog-Format wird um Vorsicht geboten, da dies negative Auswirkungen auf die UX haben kann."
+ silence: "Keine Benachrichtigung"
+ silenceDescription: "Wenn aktiviert, gibt diese Meldung keine Nachricht aus und muss nicht als \"gelesen\" markiert werden."
_initialAccountSetting:
accountCreated: "Dein Konto wurde erfolgreich erstellt!"
letsStartAccountSetup: "Lass uns nun dein Konto einrichten."
@@ -1177,8 +1210,38 @@ _initialAccountSetting:
pushNotificationDescription: "Durch die Aktivierung von Push-Benachrichtigungen kannst du von {name} Benachrichtigungen direkt auf dein Gerät erhalten."
initialAccountSettingCompleted: "Kontoeinrichtung abgeschlossen!"
haveFun: "Viel Spaß mit {name}!"
+ youCanContinueTutorial: "Du kannst mit dem Tutorial von {name}(Misskey) fortfahren, oder auch abbrechen und gleich anfangen Misskey zu benutzen."
+ startTutorial: "Fange mit dem Tutorial an"
skipAreYouSure: "Die Kontoeinrichtung wirklich überspringen?"
laterAreYouSure: "Die Kontoeinrichtung wirklich später erledigen?"
+_initialTutorial:
+ launchTutorial: "Tutorial ansehen"
+ title: "Tutorial"
+ wellDone: "Gut gemacht!"
+ skipAreYouSure: "Möchtest du das Tutorial verlassen?"
+ _landing:
+ title: "Willkommen zum Tutorial"
+ description: "Hier kannst du sehen, wie Misskey funktioniert"
+ _note:
+ title: "Was sind Notizen?"
+ description: "Beiträge auf Misskey heißen \"Notizen\". Notizen werden chronologisch in der Chronik angeordnet und in Echtzeit aktualisiert."
+ reply: "Klicke auf diesen Button, um auf eine Nachricht zu antworten. Es ist auch möglich, auf Antworten zu antworten und die Unterhaltung wie einen Thread fortzusetzen."
+ _reaction:
+ title: "Was sind Reaktionen?"
+ reactToContinue: "Füge eine Reaktion hinzu, um fortzufahren."
+ reactNotification: "Du erhältst Echtzeit-Benachrichtigungen, wenn jemand auf deine Notiz reagiert."
+ _postNote:
+ _visibility:
+ description: "Du kannst einschränken, wer deine Notiz sehen kann."
+ public: "Deine Notiz wird für alle Nutzer sichtbar sein."
+ doNotSendConfidencialOnDirect1: "Sei vorsichtig, wenn du sensible Informationen verschickst!"
+ _cw:
+ title: "Inhaltswarnung"
+ _done:
+ title: "Du hast das Tutorial abgeschlossen! 🎉"
+_timelineDescription:
+ local: "In der lokalen Chronik siehst du Notizen von allen Benutzern auf diesem Server."
+ global: "In der globalen Chronik siehst du Notizen von allen föderierten Servern."
_serverRules:
description: "Eine Reihe von Regeln, die vor der Registrierung angezeigt werden. Eine Zusammenfassung der Nutzungsbedingungen anzuzeigen ist empfohlen."
_serverSettings:
@@ -1191,6 +1254,8 @@ _serverSettings:
shortName: "Abkürzung"
shortNameDescription: "Ein Kürzel für den Namen der Instanz, der angezeigt werden kann, falls der volle Instanzname lang ist."
fanoutTimelineDescription: "Ist diese Option aktiviert, kann eine erhebliche Verbesserung im Abrufen von Chroniken und eine Reduzierung der Datenbankbelastung erzielt werden, im Gegenzug zu einer Steigerung in der Speichernutzung von Redis. Bei geringem Serverspeicher oder Serverinstabilität kann diese Option deaktiviert werden."
+ fanoutTimelineDbFallback: "Auf die Datenbank zurückfallen"
+ fanoutTimelineDbFallbackDescription: "Ist diese Option aktiviert, wird die Chronik auf zusätzliche Abfragen in der Datenbank zurückgreifen, wenn sich die Chronik nicht im Cache befindet. Eine Deaktivierung führt zu geringerer Serverlast, aber schränkt den Zeitraum der abrufbaren Chronik ein. "
_accountMigration:
moveFrom: "Von einem anderen Konto zu diesem migrieren"
moveFromSub: "Alias für ein anderes Konto erstellen"
@@ -1448,6 +1513,8 @@ _achievements:
_smashTestNotificationButton:
title: "Testüberfluss"
description: "Betätige den Benachrichtigungstest mehrfach innerhalb einer extrem kurzen Zeitspanne"
+ _tutorialCompleted:
+ description: "Tutorial abgeschlossen"
_role:
new: "Rolle erstellen"
edit: "Rolle bearbeiten"
@@ -1458,7 +1525,9 @@ _role:
assignTarget: "Zuweisungsart"
descriptionOfAssignTarget: "Manuell bedeutet, dass die Liste der Benutzer einer Rolle manuell verwaltet wird.\nKonditional bedeutet, dass die Liste der Benutzer einer Rolle durch eine Bedingung automatisch verwaltet wird."
manual: "Manuell"
+ manualRoles: "Manuelle Rollen"
conditional: "Konditional"
+ conditionalRoles: "Bedingte Rolle"
condition: "Bedingung"
isConditionalRole: "Dies ist eine konditionale Rolle."
isPublic: "Öffentliche Rolle"
@@ -1500,13 +1569,14 @@ _role:
webhookMax: "Maximale Anzahl an Webhooks"
clipMax: "Maximale Anzahl an Clips"
noteEachClipsMax: "Maximale Anzahl an Notizen innerhalb eines Clips"
- userListMax: "Maximale Anzahl an Benutzern in einer Benutzerliste"
- userEachUserListsMax: "Maximale Anzahl an Benutzerlisten"
+ userListMax: "Maximale Anzahl an Benutzerlisten"
+ userEachUserListsMax: "Maximale Anzahl an Benutzern in einer Benutzerliste"
rateLimitFactor: "Versuchsanzahl"
descriptionOfRateLimitFactor: "Je niedriger desto weniger restriktiv, je höher destro restriktiver."
canHideAds: "Kann Werbung ausblenden"
canSearchNotes: "Nutzung der Notizsuchfunktion"
canUseTranslator: "Verwendung des Übersetzers"
+ avatarDecorationLimit: "Maximale Anzahl an Profilbilddekorationen, die angebracht werden können"
_condition:
isLocal: "Lokaler Benutzer"
isRemote: "Benutzer fremder Instanz"
@@ -1535,6 +1605,7 @@ _emailUnavailable:
disposable: "Wegwerf-Email-Adressen können nicht verwendet werden"
mx: "Dieser Email-Server ist ungültig"
smtp: "Dieser Email-Server antwortet nicht"
+ banned: "Du kannst dich mit dieser E-Mail-Adresse nicht registrieren"
_ffVisibility:
public: "Öffentlich"
followers: "Nur für Follower sichtbar"
@@ -1863,6 +1934,7 @@ _widgets:
_userList:
chooseList: "Liste auswählen"
clicker: "Klickzähler"
+ birthdayFollowings: "Nutzer, die heute Geburtstag haben"
_cw:
hide: "Inhalt verbergen"
show: "Inhalt anzeigen"
@@ -1928,6 +2000,7 @@ _profile:
_exportOrImport:
allNotes: "Alle Notizen"
favoritedNotes: "Als Favorit markierte Notizen"
+ clips: "Clip erstellen"
followingList: "Gefolgte Benutzer"
muteList: "Stummschaltungen"
blockingList: "Blockierungen"
@@ -2210,3 +2283,10 @@ _externalResourceInstaller:
_themeInstallFailed:
title: "Das Farbschema konnte nicht installiert werden"
description: "Während der Installation des Farbschemas ist ein Problem aufgetreten. Bitte versuche es erneut. Detaillierte Fehlerinformationen können über die Javascript-Konsole abgerufen werden."
+_reversi:
+ blackOrWhite: "Schwarz/Weiß"
+ rules: "Regeln"
+ black: "Schwarz"
+ white: "Weiß"
+ total: "Gesamt"
+
diff --git a/locales/el-GR.yml b/locales/el-GR.yml
index 9392fd12f..bb5639a74 100644
--- a/locales/el-GR.yml
+++ b/locales/el-GR.yml
@@ -104,7 +104,6 @@ clickToShow: "Κάντε κλικ για εμφάνιση"
add: "Προσθέστε"
reaction: "Αντιδράσεις"
reactions: "Αντιδράσεις"
-reactionSetting: "Αντιδράσεις για εμφάνιση στην επιλογή αντίδρασης"
reactionSettingDescription2: "Σύρετε για να αλλάξετε τη σειρά, κάντε κλικ για να διαγράψετε, πατήστε \"+\" για να προσθέσετε."
rememberNoteVisibility: "Θυμήσου τις ρυθμίσεις ορατότητας σημειώματος"
attachCancel: "Διαγραφή αρχείου"
@@ -228,7 +227,6 @@ userList: "Λίστες"
about: "Πληροφορίες"
moderator: "Συντονιστής"
moderation: "Συντονισμός"
-cacheClear: "Εκκαθάριση προσωρινής μνήμης"
markAsReadAllNotifications: "Όλες οι ειδοποιήσεις διαβάστηκαν"
members: "Μέλη"
transfer: "Μεταφορά"
@@ -358,6 +356,7 @@ _profile:
username: "Όνομα μέλους"
_exportOrImport:
allNotes: "Όλα τα σημειώματα"
+ clips: "Κλιπ"
followingList: "Ακολουθεί"
muteList: "Μέλη σε σίγαση"
blockingList: "Μπλοκαρισμένα μέλη"
@@ -397,3 +396,6 @@ _webhookSettings:
name: "Όνομα"
_moderationLogTypes:
suspend: "Αποβολή"
+_reversi:
+ total: "Σύνολο"
+
diff --git a/locales/en-US.yml b/locales/en-US.yml
index b14592b20..104dcadcf 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -121,10 +121,16 @@ sensitive: "Sensitive"
add: "Add"
reaction: "Reactions"
reactions: "Reactions"
-reactionSetting: "Reactions to show in the reaction picker"
+emojiPicker: "Emoji picker"
+pinnedEmojisForReactionSettingDescription: "Set the emojis which should be pinned and displayed immediately when reacting."
+pinnedEmojisSettingDescription: "Set the emojis to be pinned and displayed when viewing emoji picker"
+emojiPickerDisplay: "Emoji picker display"
+overwriteFromPinnedEmojisForReaction: "Override from reaction settings"
+overwriteFromPinnedEmojis: "Override from general settings"
reactionSettingDescription2: "Drag to reorder, click to delete, press \"+\" to add."
rememberNoteVisibility: "Remember note visibility settings"
attachCancel: "Remove attachment"
+deleteFile: "File deleted"
markAsSensitive: "Mark as sensitive"
unmarkAsSensitive: "Unmark as sensitive"
enterFileName: "Enter filename"
@@ -196,6 +202,7 @@ perDay: "Per Day"
stopActivityDelivery: "Stop sending activities"
blockThisInstance: "Block this instance"
silenceThisInstance: "Silence this instance"
+sensitiveMediaThisInstance: "Mark media from this instance as sensitive"
operations: "Operations"
software: "Software"
version: "Version"
@@ -217,6 +224,8 @@ blockedInstances: "Blocked Instances"
blockedInstancesDescription: "List the hostnames of the instances you want to block separated by linebreaks. Listed instances will no longer be able to communicate with this instance."
silencedInstances: "Silenced instances"
silencedInstancesDescription: "List the hostnames of the instances that you want to silence. All accounts of the listed instances will be treated as silenced, can only make follow requests, and cannot mention local accounts if not followed. This will not affect blocked instances."
+sensitiveMediaInstances: "Instances with sensitive media"
+sensitiveMediaInstancesDescription: "List the hostnames of the instances that you want to mark all media from this instance as sensitive."
muteAndBlock: "Mutes and Blocks"
mutedUsers: "Muted users"
blockedUsers: "Blocked users"
@@ -256,11 +265,13 @@ noSuchUser: "User not found"
lookup: "Lookup"
announcements: "Announcements"
imageUrl: "Image URL"
+displayOrder: "Position"
remove: "Delete"
removed: "Successfully deleted"
removeAreYouSure: "Are you sure that you want to remove \"{x}\"?"
deleteAreYouSure: "Are you sure that you want to delete \"{x}\"?"
resetAreYouSure: "Really reset?"
+areYouSure: "Are you sure?"
saved: "Saved"
messaging: "Chat"
upload: "Upload"
@@ -311,6 +322,7 @@ folderName: "Folder name"
createFolder: "Create a folder"
renameFolder: "Rename this folder"
deleteFolder: "Delete this folder"
+folder: "Folder"
addFile: "Add a file"
emptyDrive: "Your Drive is empty"
emptyFolder: "This folder is empty"
@@ -368,10 +380,17 @@ pinnedPages: "Pinned Pages"
pinnedPagesDescription: "Enter the paths of the Pages you want to pin to the top page of this instance, separated by line breaks."
pinnedClipId: "ID of the clip to pin"
pinnedNotes: "Pinned notes"
+featuredGameChannels: "Featured Misskey Games Channels"
+featuredGameChannelsDescription: "Enter the channels you want to pin to Misskey Games, separated by line breaks."
hcaptcha: "hCaptcha"
enableHcaptcha: "Enable hCaptcha"
hcaptchaSiteKey: "Site key"
hcaptchaSecretKey: "Secret key"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "Enable mCaptcha"
+mcaptchaSiteKey: "Site key"
+mcaptchaSecretKey: "Secret key"
+mcaptchaInstanceUrl: "mCaptcha instance URL"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Enable reCAPTCHA"
recaptchaSiteKey: "Site key"
@@ -437,7 +456,6 @@ share: "Share"
notFound: "Not found"
notFoundDescription: "No page corresponding to this URL could be found."
uploadFolder: "Default folder for uploads"
-cacheClear: "Clear cache"
markAsReadAllNotifications: "Mark all notifications as read"
markAsReadAllUnreadNotes: "Mark all notes as read"
markAsReadAllTalkMessages: "Mark all messages as read"
@@ -482,6 +500,9 @@ emojiStyle: "Emoji style"
native: "Native"
disableDrawer: "Don't use drawer-style menus"
showNoteActionsOnlyHover: "Only show note actions on hover"
+showRepliesCount: "Show note's count of replies"
+showRenotesCount: "Show note's count of renotes"
+showReactionsCount: "Show note's count of reactions"
noHistory: "No history available"
signinHistory: "Login history"
enableAdvancedMfm: "Enable advanced MFM"
@@ -544,6 +565,8 @@ showInPage: "Show in page"
popout: "Pop-out"
volume: "Volume"
masterVolume: "Master volume"
+notUseSound: "Disable sound"
+useSoundOnlyWhenActive: "Output sounds only if Misskey is active."
details: "Details"
chooseEmoji: "Select an emoji"
unableToProcess: "The operation could not be completed"
@@ -564,16 +587,17 @@ output: "Output"
script: "Script"
disablePagesScript: "Disable AiScript on Pages"
updateRemoteUser: "Update remote user information"
-unsetUserAvatar: "Delete user icon"
-unsetUserAvatarConfirm: "Are you sure that you want to delete this user's icon?"
-unsetUserBanner: "Delete user banner"
-unsetUserBannerConfirm: "Are you sure that you want to delete this user's banner?"
+unsetUserAvatar: "Unset avatar"
+unsetUserAvatarConfirm: "Are you sure you want to unset the avatar?"
+unsetUserBanner: "Unset banner"
+unsetUserBannerConfirm: "Are you sure you want to unset the banner?"
deleteAllFiles: "Delete all files"
deleteAllFilesConfirm: "Are you sure that you want to delete all files?"
removeAllFollowing: "Unfollow all followed users"
removeAllFollowingDescription: "Executing this unfollows all accounts from {host}. Please run this if the instance e.g. no longer exists."
userSuspended: "This user has been suspended."
-userSilenced: "This user is being silenced."
+userLimited: "This user has been limited."
+userSilenced: "This user has been silenced."
yourAccountSuspendedTitle: "This account is suspended"
yourAccountSuspendedDescription: "This account has been suspended due to breaking the server's terms of services or similar. Contact the administrator if you would like to know a more detailed reason. Please do not create a new account."
tokenRevoked: "Invalid token"
@@ -618,6 +642,7 @@ medium: "Medium"
small: "Small"
generateAccessToken: "Generate access token"
permission: "Permissions"
+adminPermission: "Admin Permissions"
enableAll: "Enable all"
disableAll: "Disable all"
tokenRequested: "Grant access to account"
@@ -634,11 +659,12 @@ smtpHost: "Host"
smtpPort: "Port"
smtpUser: "Username"
smtpPass: "Password"
-emptyToDisableSmtpAuth: "Leave username and password empty to disable SMTP verification"
+emptyToDisableSmtpAuth: "Leave username and password empty to disable SMTP authentication"
smtpSecure: "Use implicit SSL/TLS for SMTP connections"
smtpSecureInfo: "Turn this off when using STARTTLS"
testEmail: "Test email delivery"
wordMute: "Word mute"
+hardWordMute: "Hard word mute"
regexpError: "Regular Expression error"
regexpErrorDescription: "An error occurred in the regular expression on line {line} of your {tab} word mutes:"
instanceMute: "Instance Mutes"
@@ -660,6 +686,7 @@ useGlobalSettingDesc: "If turned on, your account's notification settings will b
other: "Other"
regenerateLoginToken: "Regenerate login token"
regenerateLoginTokenDescription: "Regenerates the token used internally during login. Normally this action is not necessary. If regenerated, all devices will be logged out."
+theKeywordWhenSearchingForCustomEmoji: "This is the keyword when searching for custom emojis."
setMultipleBySeparatingWithSpace: "Separate multiple entries with spaces."
fileIdOrUrl: "File ID or URL"
behavior: "Behavior"
@@ -872,8 +899,8 @@ makeReactionsPublicDescription: "This will make the list of all your past reacti
classic: "Classic"
muteThread: "Mute thread"
unmuteThread: "Unmute thread"
-ffVisibility: "Follows/Followers Visibility"
-ffVisibilityDescription: "Allows you to configure who can see who you follow and who follows you."
+followingVisibility: "Visibility of follows"
+followersVisibility: "Visibility of followers"
continueThread: "View thread continuation"
deleteAccountConfirm: "This will irreversibly delete your account. Proceed?"
incorrectPassword: "Incorrect password."
@@ -974,6 +1001,7 @@ neverShow: "Don't show again"
remindMeLater: "Maybe later"
didYouLikeMisskey: "Have you taken a liking to Misskey?"
pleaseDonate: "{host} uses the free software, Misskey. We would highly appreciate your donations so development of Misskey can continue!"
+correspondingSourceIsAvailable: "The corresponding source code is available at {anchor}"
roles: "Roles"
role: "Role"
noRole: "Role not found"
@@ -1024,8 +1052,14 @@ resetPasswordConfirm: "Really reset your password?"
sensitiveWords: "Sensitive words"
sensitiveWordsDescription: "The visibility of all notes containing any of the configured words will be set to \"Home\" automatically. You can list multiple by separating them via line breaks."
sensitiveWordsDescription2: "Using spaces will create AND expressions and surrounding keywords with slashes will turn them into a regular expression."
+prohibitedWords: "Prohibited words"
+prohibitedWordsDescription: "Enables an error when attempting to post a note containing the set word(s). Multiple words can be set, separated by a new line."
+prohibitedWordsDescription2: "Using spaces will create AND expressions and surrounding keywords with slashes will turn them into a regular expression."
+hiddenTags: "Hidden hashtags"
+hiddenTagsDescription: "Select tags which will not shown on trend list.\nMultiple tags could be registered by lines."
notesSearchNotAvailable: "Note search is unavailable."
license: "License"
+request: "Request"
unfavoriteConfirm: "Really remove from favorites?"
myClips: "My clips"
drivecleaner: "Drive Cleaner"
@@ -1036,9 +1070,12 @@ enableChartsForRemoteUser: "Generate remote user data charts"
enableChartsForFederatedInstances: "Generate remote instance data charts"
showClipButtonInNoteFooter: "Add \"Clip\" to note action menu"
reactionsDisplaySize: "Reaction display size"
+limitWidthOfReaction: "Limits the maximum width of reactions and display them in reduced size."
noteIdOrUrl: "Note ID or URL"
video: "Video"
videos: "Videos"
+audio: "Audio"
+audioFiles: "Audio"
dataSaver: "Data Saver"
accountMigration: "Account Migration"
accountMoved: "This user has moved to a new account:"
@@ -1081,6 +1118,7 @@ update: "Update"
rolesThatCanBeUsedThisEmojiAsReaction: "Roles that can use this emoji as reaction"
rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "If no roles are specified, anyone can use this emoji as reaction."
rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "These roles must be public."
+rolesThatCanNotBeUsedThisEmojiAsReaction: "Roles that can not use this emoji as reaction"
cancelReactionConfirm: "Really delete your reaction?"
changeReactionConfirm: "Really change your reaction?"
later: "Later"
@@ -1134,6 +1172,7 @@ showRenotes: "Show renotes"
edited: "Edited"
notificationRecieveConfig: "Notification Settings"
mutualFollow: "Mutual follow"
+followingOrFollower: "Following or follower"
fileAttachedOnly: "Only notes with files"
showRepliesToOthersInTimeline: "Show replies to others in timeline"
hideRepliesToOthersInTimeline: "Hide replies to others from timeline"
@@ -1142,6 +1181,15 @@ hideRepliesToOthersInTimelineAll: "Hide replies to others from everyone you foll
confirmShowRepliesAll: "This operation is irreversible. Would you really like to show replies to others from everyone you follow in your timeline?"
confirmHideRepliesAll: "This operation is irreversible. Would you really like to hide replies to others from everyone you follow in your timeline?"
externalServices: "External Services"
+sourceCode: "Source code"
+sourceCodeIsNotYetProvided: "Source code is not yet available. Contact the administrator to fix this problem."
+repositoryUrl: "Repository URL"
+repositoryUrlDescription: "If you are using Misskey as is (without any changes to the source code), enter https://github.com/misskey-dev/misskey"
+repositoryUrlOrTarballRequired: "If you have not published a repository, you must provide a tarball instead. See .config/example.yml for more information."
+feedback: "Feedback"
+feedbackUrl: "Feedback URL"
+support: "Helpdesk"
+supportThisInstance: "Support {name}"
impressum: "Impressum"
impressumUrl: "Impressum URL"
impressumDescription: "In some countries, like germany, the inclusion of operator contact information (an Impressum) is legally required for commercial websites."
@@ -1151,6 +1199,7 @@ tosAndPrivacyPolicy: "Terms of Service and Privacy Policy"
avatarDecorations: "Avatar decorations"
attach: "Attach"
detach: "Remove"
+detachAll: "Remove All"
angle: "Angle"
flip: "Flip"
showAvatarDecorations: "Show avatar decorations"
@@ -1162,6 +1211,65 @@ useGroupedNotifications: "Display grouped notifications"
signupPendingError: "There was a problem verifying the email address. The link may have expired."
cwNotationRequired: "If \"Hide content\" is enabled, a description must be provided."
doReaction: "Add reaction"
+code: "Code"
+reloadRequiredToApplySettings: "Reloading is required to apply the settings."
+remainingN: "Remaining: {n}"
+overwriteContentConfirm: "Are you sure you want to overwrite the current content?"
+seasonalScreenEffect: "Seasonal Screen Effect"
+decorate: "Decorate"
+addMfmFunction: "Add MFM"
+enableQuickAddMfmFunction: "Show advanced MFM picker"
+bubbleGame: "Bubble Game"
+sfx: "Sound Effects"
+soundWillBePlayed: "Sound will be played"
+showReplay: "View Replay"
+replay: "Replay"
+replaying: "Showing replay"
+endReplay: "Exit Replay"
+copyReplayData: "Copy replay data"
+ranking: "Ranking"
+lastNDays: "Last {n} days"
+backToTitle: "Go back to title"
+hemisphere: "Where are you located"
+withSensitive: "Include notes with sensitive files"
+userSaysSomethingSensitive: "Post by {name} contains sensitive content"
+enableHorizontalSwipe: "Swipe to switch tabs"
+loading: "Loading"
+surrender: "Cancel"
+gameRetry: "Retry"
+_bubbleGame:
+ howToPlay: "How to play"
+ hold: "Hold"
+ _score:
+ score: "Score"
+ scoreYen: "Amount of money earned"
+ highScore: "High score"
+ maxChain: "Maximum number of chains"
+ yen: "{yen} Yen"
+ estimatedQty: "{qty} Pieces"
+ scoreSweets: "{onigiriQtyWithUnit} Onigiri"
+ _howToPlay:
+ section1: "Adjust the position and drop the object into the box."
+ section2: "When two objects of the same type touch each other, they will change into a different object and you score points."
+ section3: "The game is over when objects overflow from the box. Aim for a high score by fusing objects together while you avoid overflowing the box!"
+abuseReportCategory: "Type of Report"
+selectCategory: "Select Category"
+reportComplete: "Report Completed"
+blockThisUser: "Block This User"
+muteThisUser: "Mute This User"
+_abuseReportCategory:
+ nsfw: "Posts containing sensitive content"
+ spam: "Spam"
+ explicit: "Violent or aggressive posts"
+ phishing: "Phishing or fraudulent activities"
+ personalInfoLeak: "Leak of personal information of oneself or others"
+ selfHarm: "Issues related to suicide or self-harm"
+ criticalBreach: "Serious violation of terms"
+ otherBreach: "Other violations of terms"
+ violationRights: "Infringement of rights or impersonation (self)"
+ violationRightsOther: "Infringement of rights (others)"
+ notLike: "Dislike of this person"
+ other: "Other"
_announcement:
forExistingUsers: "Existing users only"
forExistingUsersDescription: "This announcement will only be shown to users existing at the point of publishment if enabled. If disabled, those newly signing up after it has been posted will also see it."
@@ -1171,7 +1279,7 @@ _announcement:
tooManyActiveAnnouncementDescription: "Having too many active announcements may worsen the user experience. Please consider archiving announcements that have become obsolete."
readConfirmTitle: "Mark as read?"
readConfirmText: "This will mark the contents of \"{title}\" as read."
- shouldNotBeUsedToPresentPermanentInfo: "As it may significantly impact the user experience for new users, it is recommended to use notifications in the flow information rather than stock information."
+ shouldNotBeUsedToPresentPermanentInfo: "It's best to use announcements to publish fresh and time-bound information, not for information that will be relevant in the long term."
dialogAnnouncementUxWarn: "Having two or more dialog-style notifications simultaneously can significantly impact the user experience, so please use them carefully."
silence: "No notification"
silenceDescription: "Turning this on will skip the notification of this announcement and the user won't need to read it."
@@ -1251,7 +1359,7 @@ _initialTutorial:
sensitiveSucceeded: "When attaching files, please set sensitivities in accordance with the server guidelines."
doItToContinue: "Mark the attachment file as sensitive to proceed."
_done:
- title: "The tutorial is complete! 🎉"
+ title: "You've completed the tutorial! 🎉"
description: "The functions introduced here are just a small part. For a more detailed understanding of using Misskey, please refer to {link}."
_timelineDescription:
home: "In the Home timeline, you can see notes from accounts you follow."
@@ -1270,6 +1378,8 @@ _serverSettings:
shortName: "Short name"
shortNameDescription: "A shorthand for the instance's name that can be displayed if the full official name is long."
fanoutTimelineDescription: "Greatly increases performance of timeline retrieval and reduces load on the database when enabled. In exchange, memory usage of Redis will increase. Consider disabling this in case of low server memory or server instability."
+ fanoutTimelineDbFallback: "Fallback to database"
+ fanoutTimelineDbFallbackDescription: "When enabled, the timeline will fall back to the database for additional queries if the timeline is not cached. Disabling it further reduces the server load by eliminating the fallback process, but limits the range of timelines that can be retrieved."
_accountMigration:
moveFrom: "Migrate another account to this one"
moveFromSub: "Create alias to another account"
@@ -1530,6 +1640,13 @@ _achievements:
_tutorialCompleted:
title: "Misskey Elementary Course Diploma"
description: "Tutorial completed"
+ _bubbleGameExplodingHead:
+ title: "🤯"
+ description: "The biggest object in the bubble game"
+ _bubbleGameDoubleExplodingHead:
+ title: "Double🤯"
+ description: "Two of the biggest objects in the bubble game at the same time"
+ flavor: "You can fill a lunch box like this 🤯 🤯 a bit."
_role:
new: "New role"
edit: "Edit role"
@@ -1540,7 +1657,9 @@ _role:
assignTarget: "Assignment type"
descriptionOfAssignTarget: "Manual to manually change who is part of this role and who is not.\nConditional to have users be automatically assigned and removed from this role based on a condition."
manual: "Manual"
+ manualRoles: "Manual roles"
conditional: "Conditional"
+ conditionalRoles: "Conditional roles"
condition: "Condition"
isConditionalRole: "This is a conditional role."
isPublic: "Public role"
@@ -1568,6 +1687,14 @@ _role:
gtlAvailable: "Can view the global timeline"
ltlAvailable: "Can view the local timeline"
canPublicNote: "Can send public notes"
+ canInitiateConversation: "Can mention, reply or quote"
+ canCreateContent: "Can create contents"
+ canUpdateContent: "Can edit contents"
+ canDeleteContent: "Can delete contents"
+ canPurgeAccount: "Can delete account completely"
+ canUpdateAvatar: "Can change avatar"
+ canUpdateBanner: "Can change banner"
+ mentionMax: "Maximum number of mentions in a note"
canInvite: "Can create instance invite codes"
inviteLimit: "Invite limit"
inviteLimitCycle: "Invite limit cooldown"
@@ -1576,8 +1703,10 @@ _role:
canManageAvatarDecorations: "Manage avatar decorations"
driveCapacity: "Drive capacity"
alwaysMarkNsfw: "Always mark files as NSFW"
+ skipNsfwDetection: "Skip NSFW detection by AI"
pinMax: "Maximum number of pinned notes"
antennaMax: "Maximum number of antennas"
+ antennaNotesMax: "Maximum number of notes stored in antennas"
wordMuteMax: "Maximum number of characters allowed in word mutes"
webhookMax: "Maximum number of Webhooks"
clipMax: "Maximum number of Clips"
@@ -1588,8 +1717,11 @@ _role:
descriptionOfRateLimitFactor: "Lower rate limits are less restrictive, higher ones more restrictive. "
canHideAds: "Can hide ads"
canSearchNotes: "Usage of note search"
- canUseTranslator: "Translator usage"
+ canUseTranslator: "Can use Translator"
+ avatarDecorationLimit: "Maximum number of avatar decorations that can be applied"
+ canUseDriveFileInSoundSettings: "Can use Drive File in Sound Settings"
_condition:
+ roleAssignedTo: "Assigned to manual roles"
isLocal: "Local user"
isRemote: "Remote user"
createdLessThan: "Less than X has passed since account creation"
@@ -1617,6 +1749,7 @@ _emailUnavailable:
disposable: "Disposable email addresses may not be used"
mx: "This email server is invalid"
smtp: "This email server is not responding"
+ banned: "You cannot register with this email address"
_ffVisibility:
public: "Public"
followers: "Visible to followers only"
@@ -1689,6 +1822,8 @@ _aboutMisskey:
contributors: "Main contributors"
allContributors: "All contributors"
source: "Source code"
+ original: "Original"
+ thisIsModifiedVersion: "{name} uses a modified version of the original Misskey."
translation: "Translate Misskey"
donate: "Donate to Misskey"
morePatrons: "We also appreciate the support of many other helpers not listed here. Thank you! 🥰"
@@ -1728,6 +1863,7 @@ _wordMute:
muteWords: "Muted words"
muteWordsDescription: "Separate with spaces for an AND condition or with line breaks for an OR condition."
muteWordsDescription2: "Surround keywords with slashes to use regular expressions."
+ hideMutedNotes: "Hide notes containing muted words"
_instanceMute:
instanceMuteDescription: "This will mute any notes/renotes from the listed instances, including those of users replying to a user from a muted instance."
instanceMuteDescription2: "Separate with newlines"
@@ -1810,6 +1946,14 @@ _sfx:
notification: "Notifications"
antenna: "Antennas"
channel: "Channel notifications"
+ reaction: "On choosing a reaction"
+_soundSettings:
+ driveFile: "Use an audio file in Drive."
+ driveFileWarn: "Select an audio file from Drive."
+ driveFileTypeWarn: "This file is not supported"
+ driveFileTypeWarnDescription: "Select an audio file"
+ driveFileDurationWarn: "The audio is too long."
+ driveFileDurationWarnDescription: "Long audio may disrupt using Misskey. Still continue?"
_ago:
future: "Future"
justNow: "Just now"
@@ -1821,6 +1965,14 @@ _ago:
monthsAgo: "{n}mo ago"
yearsAgo: "{n}y ago"
invalid: "None"
+_timeIn:
+ seconds: "In {n}s"
+ minutes: "In {n}m"
+ hours: "In {n}h"
+ days: "In {n}d"
+ weeks: "In {n}w"
+ months: "In {n}mo"
+ years: "In {n}y"
_time:
second: "Second(s)"
minute: "Minute(s)"
@@ -1847,7 +1999,7 @@ _2fa:
removeKeyConfirm: "Really delete the {name} key?"
whyTOTPOnlyRenew: "The authenticator app cannot be removed as long as a security key is registered."
renewTOTP: "Reconfigure authenticator app"
- renewTOTPConfirm: "This will cause verification codes from your previous app to stop working"
+ renewTOTPConfirm: "This will cause verification codes from your previous app and backup codes to stop working"
renewTOTPOk: "Reconfigure"
renewTOTPCancel: "Cancel"
checkBackupCodesBeforeCloseThisWizard: "Before you close this window, please note the following backup codes."
@@ -1892,6 +2044,55 @@ _permissions:
"write:flash": "Edit Plays"
"read:flash-likes": "View list of liked Plays"
"write:flash-likes": "Edit list of liked Plays"
+ "read:admin:abuse-user-reports": "View user reports"
+ "write:admin:delete-account": "Delete user account"
+ "write:admin:delete-all-files-of-a-user": "Delete all files of a user"
+ "read:admin:index-stats": "View database index stats"
+ "read:admin:table-stats": "View database table stats"
+ "read:admin:user-ips": "View user IP addresses"
+ "read:admin:meta": "View instance metadata"
+ "write:admin:reset-password": "Reset user password"
+ "write:admin:resolve-abuse-user-report": "Resolve user report"
+ "write:admin:send-email": "Send email"
+ "read:admin:server-info": "View server info"
+ "read:admin:show-moderation-log": "View moderation log"
+ "read:admin:show-user": "View private user info"
+ "read:admin:show-users": "View private user info"
+ "write:admin:suspend-user": "Suspend user"
+ "write:admin:unset-user-avatar": "Remove user avatar"
+ "write:admin:unset-user-banner": "Remove user banner"
+ "write:admin:unsuspend-user": "Unsuspend user"
+ "write:admin:meta": "Manage instance metadata"
+ "write:admin:user-note": "Manage moderation note"
+ "write:admin:roles": "Manage roles"
+ "read:admin:roles": "View roles"
+ "write:admin:relays": "Manage relays"
+ "read:admin:relays": "View relays"
+ "write:admin:invite-codes": "Manage invite codes"
+ "read:admin:invite-codes": "View invite codes"
+ "write:admin:announcements": "Manage announcements"
+ "read:admin:announcements": "View announcements"
+ "write:admin:avatar-decorations": "Manage avatar decorations"
+ "read:admin:avatar-decorations": "View avatar decorations"
+ "write:admin:federation": "Manage federation data"
+ "write:admin:account": "Manage user account"
+ "read:admin:account": "View user account"
+ "write:admin:emoji": "Manage emoji"
+ "read:admin:emoji": "View emoji"
+ "write:admin:queue": "Manage job queue"
+ "read:admin:queue": "View job queue info"
+ "write:admin:promo": "Manage promotion notes"
+ "write:admin:drive": "Manage user drive"
+ "read:admin:drive": "View user drive info"
+ "read:admin:stream": "Use WebSocket API for Admin"
+ "write:admin:ad": "Manage ads"
+ "read:admin:ad": "View ads"
+ "write:invite-codes": "Create invite codes"
+ "read:invite-codes": "Get invite codes"
+ "write:clip-favorite": "Manage favorited clips"
+ "read:clip-favorite": "View favorited clips"
+ "read:federation": "Get federation data"
+ "write:report-abuse": "Report violation"
_auth:
shareAccessTitle: "Granting application permissions"
shareAccess: "Would you like to authorize \"{name}\" to access this account?"
@@ -1946,6 +2147,7 @@ _widgets:
_userList:
chooseList: "Select a list"
clicker: "Clicker"
+ birthdayFollowings: "Users who celebrate their birthday today"
_cw:
hide: "Hide"
show: "Show content"
@@ -2008,9 +2210,11 @@ _profile:
changeAvatar: "Change avatar"
changeBanner: "Change banner"
verifiedLinkDescription: "By entering an URL that contains a link to your profile here, an ownership verification icon can be displayed next to the field."
+ avatarDecorationMax: "You can add up to {max} decorations."
_exportOrImport:
allNotes: "All notes"
favoritedNotes: "Favorite notes"
+ clips: "Clip"
followingList: "Followed users"
muteList: "Muted users"
blockingList: "Blocked users"
@@ -2047,6 +2251,7 @@ _instanceCharts:
_timelines:
home: "Home"
local: "Local"
+ media: "Media"
social: "Social"
global: "Global"
_play:
@@ -2129,6 +2334,7 @@ _notification:
pollEnded: "Poll results have become available"
newNote: "New note"
unreadAntennaNote: "Antenna {name}"
+ roleAssigned: "Role given"
emptyPushNotificationMessage: "Push notifications have been updated"
achievementEarned: "Achievement unlocked"
testNotification: "Test notification"
@@ -2136,8 +2342,10 @@ _notification:
sendTestNotification: "Send test notification"
notificationWillBeDisplayedLikeThis: "Notifications look like this"
reactedBySomeUsers: "{n} users reacted"
+ likedBySomeUsers: "{n} users liked"
renotedBySomeUsers: "Renote from {n} users"
followedBySomeUsers: "Followed by {n} users"
+ flushNotification: "Clear notifications"
_types:
all: "All"
note: "New notes"
@@ -2150,6 +2358,7 @@ _notification:
pollEnded: "Polls ending"
receiveFollowRequest: "Received follow requests"
followRequestAccepted: "Accepted follow requests"
+ roleAssigned: "Role given"
achievementEarned: "Achievement unlocked"
app: "Notifications from linked apps"
_actions:
@@ -2234,6 +2443,7 @@ _moderationLogTypes:
resetPassword: "Password reset"
suspendRemoteInstance: "Remote instance suspended"
unsuspendRemoteInstance: "Remote instance unsuspended"
+ updateRemoteInstanceNote: "Moderation note updated for remote instance."
markSensitiveDriveFile: "File marked as sensitive"
unmarkSensitiveDriveFile: "File unmarked as sensitive"
resolveAbuseReport: "Report resolved"
@@ -2244,6 +2454,8 @@ _moderationLogTypes:
createAvatarDecoration: "Avatar decoration created"
updateAvatarDecoration: "Avatar decoration updated"
deleteAvatarDecoration: "Avatar decoration deleted"
+ unsetUserAvatar: "Unset this user's avatar"
+ unsetUserBanner: "Unset this user's banner"
_fileViewer:
title: "File details"
type: "File type"
@@ -2293,3 +2505,68 @@ _externalResourceInstaller:
_themeInstallFailed:
title: "Failed to install theme"
description: "A problem occurred during theme installation. Please try again. Error details can be viewed in the Javascript console."
+_dataSaver:
+ _media:
+ title: "Loading Media"
+ description: "Prevents images/videos from being loaded automatically. Hidden images/videos will be loaded when tapped."
+ _avatar:
+ title: "Avatar image"
+ description: "Stop avatar image animation. Animated images can be larger in file size than normal images, potentially leading to further reductions in data traffic."
+ _urlPreview:
+ title: "URL preview thumbnails"
+ description: "URL preview thumbnail images will no longer be loaded."
+ _code:
+ title: "Code highlighting"
+ description: "If code highlighting notations are used in MFM, etc., they will not load until tapped. Syntax highlighting requires downloading the highlight definition files for each programming language. Therefore, disabling the automatic loading of these files is expected to reduce the amount of communication data."
+_hemisphere:
+ N: "Northern Hemisphere"
+ S: "Southern Hemisphere"
+ caption: "Used in some client settings to determine season."
+_reversi:
+ reversi: "Reversi"
+ gameSettings: "Game settings"
+ chooseBoard: "Choose a board"
+ blackOrWhite: "Black/White"
+ blackIs: "{name} is playing Black"
+ rules: "Rules"
+ thisGameIsStartedSoon: "The game will begin shortly"
+ waitingForOther: "Waiting for opponent's turn"
+ waitingForMe: "Waiting for your turn"
+ waitingBoth: "Get ready"
+ ready: "Ready"
+ cancelReady: "Not ready"
+ opponentTurn: "Opponent's turn"
+ myTurn: "Your turn"
+ turnOf: "It's {name}'s turn"
+ pastTurnOf: "{name}'s turn"
+ surrender: "Surrender"
+ surrendered: "Surrendered"
+ timeout: "Out of time"
+ drawn: "Draw"
+ won: "{name} wins"
+ black: "Black"
+ white: "White"
+ total: "Total"
+ turnCount: "Turn {count}"
+ myGames: "My rounds"
+ allGames: "All rounds"
+ ended: "Ended"
+ playing: "Currently playing"
+ isLlotheo: "The one with fewer stones wins (Llotheo)"
+ loopedMap: "Looping map"
+ canPutEverywhere: "Tiles are placeable everywhere"
+ timeLimitForEachTurn: "Time limit for turn"
+ freeMatch: "Free Match"
+ lookingForPlayer: "Finding opponent..."
+ gameCanceled: "The game has been cancelled."
+ shareToTlTheGameWhenStart: "Share Game to timeline when started"
+ iStartedAGame: "The game has begun! #MisskeyReversi"
+ opponentHasSettingsChanged: "The opponent has changed their settings."
+ allowIrregularRules: "Irregular rules (completely free)"
+ disallowIrregularRules: "No irregular rules"
+ showBoardLabels: "Display row and column numbering on the board"
+ useAvatarAsStone: "Turn stones into user avatars"
+_offlineScreen:
+ title: "Offline - cannot connect to the server"
+ header: "Unable to connect to the server"
+
diff --git a/locales/es-ES.yml b/locales/es-ES.yml
index df611c235..246ec2360 100644
--- a/locales/es-ES.yml
+++ b/locales/es-ES.yml
@@ -11,7 +11,7 @@ password: "Contraseña"
forgotPassword: "Olvidé mi contraseña"
fetchingAsApObject: "Buscando en el fediverso"
ok: "OK"
-gotIt: "Entendido"
+gotIt: "¡Lo tengo!"
cancel: "Cancelar"
noThankYou: "No gracias"
enterUsername: "Introduce el nombre de usuario"
@@ -121,10 +121,16 @@ sensitive: "Marcado como sensible"
add: "Agregar"
reaction: "Reacción"
reactions: "Reacción"
-reactionSetting: "Reacciones para mostrar en el menú de reacciones"
+emojiPicker: "Selector de emojis"
+pinnedEmojisForReactionSettingDescription: "Puedes seleccionar reacciones para fijarlos en el selector"
+pinnedEmojisSettingDescription: "Puedes seleccionar emojis para fijarlos en el selector"
+emojiPickerDisplay: "Mostrar el selector de emojis"
+overwriteFromPinnedEmojisForReaction: "Sobreescribir las reacciones fijadas"
+overwriteFromPinnedEmojis: "Sobreescribir los emojis fijados"
reactionSettingDescription2: "Arrastre para reordenar, click para borrar, apriete la tecla + para añadir."
rememberNoteVisibility: "Recordar visibilidad"
attachCancel: "Quitar adjunto"
+deleteFile: "Archivo eliminado"
markAsSensitive: "Marcar como sensible"
unmarkAsSensitive: "Desmarcar como sensible"
enterFileName: "Ingrese el nombre del archivo"
@@ -261,6 +267,7 @@ removed: "Borrado"
removeAreYouSure: "¿Desea borrar \"{x}\"?"
deleteAreYouSure: "¿Desea borrar \"{x}\"?"
resetAreYouSure: "¿Desea reestablecer?"
+areYouSure: "¿Estás conforme?"
saved: "Guardado"
messaging: "Chat"
upload: "Subir"
@@ -311,6 +318,7 @@ folderName: "Nombre de la carpeta"
createFolder: "Crear carpeta"
renameFolder: "Renombrar carpeta"
deleteFolder: "Borrar carpeta"
+folder: "Carpeta"
addFile: "Agregar archivo"
emptyDrive: "El drive está vacío"
emptyFolder: "La carpeta está vacía"
@@ -372,6 +380,11 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Habilitar hCaptcha"
hcaptchaSiteKey: "Clave del sitio"
hcaptchaSecretKey: "Clave secreta"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "Activar mCaptcha"
+mcaptchaSiteKey: "Clave del sitio"
+mcaptchaSecretKey: "Clave secreta"
+mcaptchaInstanceUrl: "URL del servidor mCaptcha"
recaptcha: "reCAPTCHA"
enableRecaptcha: "activar reCAPTCHA"
recaptchaSiteKey: "Clave del sitio"
@@ -437,7 +450,6 @@ share: "Compartir"
notFound: "No se encuentra"
notFoundDescription: "No se encontró la página correspondiente a la URL elegida"
uploadFolder: "Carpeta de subidas por defecto"
-cacheClear: "Borrar caché"
markAsReadAllNotifications: "Marcar todas las notificaciones como leídas"
markAsReadAllUnreadNotes: "Marcar todas las notas como leídas"
markAsReadAllTalkMessages: "Marcar todos los chats como leídos"
@@ -544,6 +556,8 @@ showInPage: "Mostrar en la página"
popout: "Popout"
volume: "Volumen"
masterVolume: "Volumen principal"
+notUseSound: "Sin sonido"
+useSoundOnlyWhenActive: "Sonar solo cuando Misskey esté activo"
details: "Detalles"
chooseEmoji: "Elije un emoji"
unableToProcess: "La operación no se puede llevar a cabo"
@@ -564,6 +578,10 @@ output: "Salida"
script: "Script"
disablePagesScript: "Deshabilitar AiScript en Páginas"
updateRemoteUser: "Actualizar información de usuario remoto"
+unsetUserAvatar: "Quitar avatar"
+unsetUserAvatarConfirm: "¿Confirmas que quieres quitar tu avatar?"
+unsetUserBanner: "Quitar banner"
+unsetUserBannerConfirm: "¿Confirmas que quieres quitar tu banner?"
deleteAllFiles: "Borrar todos los archivos"
deleteAllFilesConfirm: "¿Desea borrar todos los archivos?"
removeAllFollowing: "Retener todos los siguientes"
@@ -614,6 +632,7 @@ medium: "Mediano"
small: "Pequeño"
generateAccessToken: "Generar token de acceso"
permission: "Permisos"
+adminPermission: "Permiso de administrador"
enableAll: "Activar todo"
disableAll: "Desactivar todo"
tokenRequested: "Permiso de acceso a la cuenta"
@@ -635,6 +654,7 @@ smtpSecure: "Usar SSL/TLS implícito en la conexión SMTP"
smtpSecureInfo: "Apagar cuando se use STARTTLS"
testEmail: "Prueba de envío"
wordMute: "Silenciar palabras"
+hardWordMute: "Filtro de palabra fuerte"
regexpError: "Error de la expresión regular"
regexpErrorDescription: "Ocurrió un error en la expresión regular en la linea {line} de las palabras muteadas {tab}"
instanceMute: "Instancias silenciadas"
@@ -656,6 +676,7 @@ useGlobalSettingDesc: "Al activarse, se usará la configuración de notificacion
other: "Otro"
regenerateLoginToken: "Regenerar token de login"
regenerateLoginTokenDescription: "Regenerar el token usado internamente durante el login. No siempre es necesario hacerlo. Al hacerlo de nuevo, se deslogueará en todos los dispositivos."
+theKeywordWhenSearchingForCustomEmoji: "Palabra clave para buscar el emoji personalizado."
setMultipleBySeparatingWithSpace: "Puedes añadir mas de uno, separado por espacios."
fileIdOrUrl: "Id del archivo o URL"
behavior: "Comportamiento"
@@ -868,8 +889,8 @@ makeReactionsPublicDescription: "Todas las reacciones que hayas hecho serán pú
classic: "Clásico"
muteThread: "Silenciar hilo"
unmuteThread: "Mostrar hilo"
-ffVisibility: "Visibilidad de seguidores y seguidos"
-ffVisibilityDescription: "Puedes configurar quien puede ver a quienes sigues y quienes te siguen"
+followingVisibility: "Visibilidad de seguidos"
+followersVisibility: "Visibilidad de seguidores"
continueThread: "Ver la continuación del hilo"
deleteAccountConfirm: "La cuenta será borrada. ¿Está seguro?"
incorrectPassword: "La contraseña es incorrecta"
@@ -979,6 +1000,7 @@ assign: "Asignar"
unassign: "Quitar"
color: "Color"
manageCustomEmojis: "Administrar emojis personalizados"
+manageAvatarDecorations: "Administrar decoraciones de avatar"
youCannotCreateAnymore: "Has llegado al límite de creaciones."
cannotPerformTemporary: "Temporalmente no disponible"
cannotPerformTemporaryDescription: "Esta acción no se puede realizar porque se excedió el límite de ejecución. Espera un poco y prueba de nuevo."
@@ -1019,6 +1041,10 @@ resetPasswordConfirm: "¿Realmente quieres cambiar la contraseña?"
sensitiveWords: "Palabras sensibles"
sensitiveWordsDescription: "La visibilidad de todas las notas que contienen cualquiera de las palabras configuradas serán puestas en \"Inicio\" automáticamente. Puedes enumerás varias separándolas con saltos de línea"
sensitiveWordsDescription2: "Si se usan espacios se crearán expresiones AND y las palabras subsecuentes con barras inclinadas se convertirán en expresiones regulares."
+prohibitedWords: "Palabras explícitas"
+prohibitedWordsDescription2: "Si se usan espacios se crearán expresiones AND y las palabras subsecuentes con barras inclinadas se convertirán en expresiones regulares."
+hiddenTags: "Hashtags ocultos"
+hiddenTagsDescription: "Selecciona las etiquetas que no se mostrarán en tendencias. Una etiqueta por línea."
notesSearchNotAvailable: "No se puede buscar una nota"
license: "Licencia"
unfavoriteConfirm: "¿Desea quitar de favoritos?"
@@ -1031,9 +1057,12 @@ enableChartsForRemoteUser: "Generar gráficas de usuarios remotos."
enableChartsForFederatedInstances: "Generar gráficos de servidores remotos"
showClipButtonInNoteFooter: "Añadir \"Clip\" al menú de notas"
reactionsDisplaySize: "Tamaño de las reacciones"
+limitWidthOfReaction: "Limitar ancho de las reacciones"
noteIdOrUrl: "ID o URL de la nota"
video: "Video"
videos: "Video"
+audio: "Sonido"
+audioFiles: "Sonido"
dataSaver: "Ahorro de datos"
accountMigration: "Migración de cuenta"
accountMoved: "Este usuario se movió a una nueva cuenta:"
@@ -1132,14 +1161,61 @@ mutualFollow: "Os seguís mutuamente"
fileAttachedOnly: "Solo notas con archivos"
showRepliesToOthersInTimeline: "Mostrar respuestas a otros en la línea de tiempo"
hideRepliesToOthersInTimeline: "Ocultar respuestas a otros en la línea de tiempo"
+showRepliesToOthersInTimelineAll: "Muestra tus respuestas a otros usuarios que sigues en la línea de tiempo"
+hideRepliesToOthersInTimelineAll: "Ocultar tus respuestas a otros usuarios que sigues en la línea de tiempo"
+confirmShowRepliesAll: "Esta operación es irreversible. ¿Confirmas que quieres mostrar tus respuestas a otros usuarios que sigues en tu línea de tiempo?"
+confirmHideRepliesAll: "Esta operación es irreversible. ¿Confirmas que quieres ocultar tus respuestas a otros usuarios que sigues en tu línea de tiempo?"
externalServices: "Servicios Externos"
+sourceCode: "Código fuente"
impressum: "Impressum"
impressumUrl: "Impressum URL"
impressumDescription: "En algunos países, como Alemania, la inclusión del operador de datos (el Impressum) es requerido legalmente para sitios web comerciales."
privacyPolicy: "Política de Privacidad"
privacyPolicyUrl: "URL de la Política de Privacidad"
tosAndPrivacyPolicy: "Condiciones de Uso y Política de Privacidad"
+avatarDecorations: "Decoraciones de avatar"
+attach: "Acoplar"
+detach: "Quitar"
+detachAll: "Quitar todo"
+angle: "Ángulo"
flip: "Echar de un capirotazo"
+showAvatarDecorations: "Mostrar decoraciones de avatar"
+releaseToRefresh: "Soltar para recargar"
+refreshing: "Recargando..."
+pullDownToRefresh: "Tira hacia abajo para recargar"
+disableStreamingTimeline: "Desactivar actualizaciones en tiempo real de la línea de tiempo"
+useGroupedNotifications: "Mostrar notificaciones agrupadas"
+signupPendingError: "Ha habido un problema al verificar tu dirección de correo electrónico. Es posible que el enlace haya caducado."
+cwNotationRequired: "Si se ha activado \"ocultar contenido\", es necesario proporcionar una descripción."
+doReaction: "Añadir reacción"
+code: "Código"
+reloadRequiredToApplySettings: "Es necesario recargar para que se aplique la configuración."
+remainingN: "Faltan: {n}"
+overwriteContentConfirm: "¿Quieres sustituir todo el contenido actual?"
+seasonalScreenEffect: "Efectos de pantalla asociados a estaciones"
+decorate: "Decorar"
+addMfmFunction: "Añadir función MFM"
+enableQuickAddMfmFunction: "Activar acceso rápido para añadir funciones MFM"
+bubbleGame: "Bubble Game"
+sfx: "Efectos de sonido"
+soundWillBePlayed: "Se reproducirán efectos sonoros"
+showReplay: "Ver reproducción"
+replay: "Reproducir"
+replaying: "Reproduciendo"
+ranking: "Clasificación"
+lastNDays: "Últimos {n} días"
+backToTitle: "Regresar al inicio"
+hemisphere: "Región"
+withSensitive: "Mostrar notas que contengan material sensible"
+userSaysSomethingSensitive: "La publicación de {name} contiene material sensible"
+enableHorizontalSwipe: "Deslice para cambiar de pestaña"
+surrender: "detener"
+_bubbleGame:
+ howToPlay: "Cómo jugar"
+ _howToPlay:
+ section1: "Ajuste la posición y deje caer el objeto en la caja"
+ section2: "Cuando dos objetos del mismo tipo se tocan, cambian a otro tipo y consigues puntos"
+ section3: "El juego termina cuando la caja se desborda de objetos. ¡Intenta conseguir una puntuación alta al juntar objetos mientras evitas desbordar la caja!"
_announcement:
forExistingUsers: "Solo para usuarios registrados"
forExistingUsersDescription: "Este anuncio solo se mostrará a aquellos usuarios registrados en el momento de su publicación. Si se deshabilita esta opción, aquellos usuarios que se registren tras su publicación también lo verán."
@@ -1149,6 +1225,10 @@ _announcement:
tooManyActiveAnnouncementDescription: "Tener demasiados anuncios activos empeora la experiencia de usuario. Por favor, considera archivar aquellos anuncios que hayan quedado obsoletos."
readConfirmTitle: "¿Marcar como leído?"
readConfirmText: "Esto marcará el contenido de \"{title}\" como leído."
+ shouldNotBeUsedToPresentPermanentInfo: "Dado que puede impactar en la experiencia de usuario de forma significativa, es recomendable usar notificaciones en el flujo de información en vez de información persistente."
+ dialogAnnouncementUxWarn: "Mostrar dos o más notificaciones en formato diálogo a la vez puede impactar en la experiencia de usuario de forma significativa, úsalos con cuidado."
+ silence: "Silenciar notificaciones"
+ silenceDescription: "Si lo activas, no enviarás notificación sobre este anuncio y el usuario no tendrá que leerlo."
_initialAccountSetting:
accountCreated: "¡La cuenta ha sido creada!"
letsStartAccountSetup: "Para empezar, creemos tu perfil."
@@ -1161,8 +1241,77 @@ _initialAccountSetting:
pushNotificationDescription: "Habilitar las notificaciones push te permitirá recibir notificaciones de {name} directamente en tu dispositivo."
initialAccountSettingCompleted: "¡Configuración del perfil completada!"
haveFun: "¡Disfruta de {name}!"
+ youCanContinueTutorial: "Puedes proceder a un tutorial sobre cómo usar {name} (Misskey) o puedes terminar la instalación aquí y empezar a usarlo ya mismo."
+ startTutorial: "Comenzar tutorial"
skipAreYouSure: "¿Realmente quieres saltarte la configuración del perfil?"
laterAreYouSure: "¿Realmente quieres configurar tu perfil después?"
+_initialTutorial:
+ launchTutorial: "Comenzar tutorial"
+ title: "Tutorial"
+ wellDone: "¡Bien hecho!"
+ skipAreYouSure: "¿Salir del tutorial?"
+ _landing:
+ title: "Bienvenid@ al tutorial"
+ description: "Aquí podrás aprender las nociones básicas sobre cómo usar Misskey y sus funciones."
+ _note:
+ title: "¿Qué es una nota?"
+ description: "Las publicaciones en Misskey se llaman 'Notas'. Las notas se ordenan de forma cronológica en la línea de tiempo y se actualizan en tiempo real."
+ reply: "Pulsa en este botón para contestar a un mensaje. También es posible contestar a otras contestaciones, continuando así la conversación como un hilo."
+ renote: "Puedes compartir esa nota en tu propia línea de tiempo. También puedes añadir una cita con tus comentarios."
+ reaction: "Puedes añadir reacciones a la Nota. Se explicarán más detalles en la siguiente página."
+ menu: "Puedes ver los detalles de la Nota, copiar enlaces, y realizar otras acciones."
+ _reaction:
+ title: "¿Qué son las reacciones?"
+ description: "Se puede reaccionar a las Notas con diferentes emojis. Las reacciones te permiten expresar matices que no se pueden transmitir con un simple 'me gusta'."
+ letsTryReacting: "Puedes añadir reacciones pulsando en el botón '+' de la nota. ¡Intenta reaccionar a esta nota de ejemplo!"
+ reactToContinue: "Añade una reacción para continuar."
+ reactNotification: "Recibirás notificaciones en tiempo real cuando alguien reaccione a tu nota."
+ reactDone: "Puedes deshacer una reacción pulsando en el botón '-'."
+ _timeline:
+ title: "El concepto de Línea de tiempo"
+ description1: "Misskey proporciona múltiples líneas de tiempo basadas en su uso (algunas pueden no estar disponibles dependiendo de las políticas de la instancia)."
+ home: "Puedes ver los posts de las cuentas que sigues."
+ local: "Puedes ver los posts de todos los usuarios de este servidor."
+ social: "Se ven los posts de la línea de tiempo de inicio junto con los de la línea de tiempo local."
+ global: "Puedes ver notas de todos los servidores conectados."
+ description2: "Puedes cambiar la línea de tiempo en la parte superior de la pantalla cuando quieras."
+ description3: "Además, hay listas de líneas de tiempo y listas de canales. Para más detalle, por favor visita este enlace: {link}"
+ _postNote:
+ title: "Ajustes de publicación de nota"
+ description1: "Cuando publicas una nota en Misskey, hay varias opciones disponibles. El formulario tiene este aspecto."
+ _visibility:
+ description: "Puedes limitar quién puede ver tu nota."
+ public: "Tu nota será visible para todos los usuarios."
+ home: "Publicar solo en la línea de tiempo de Inicio. La nota se verá en tu perfil, la verán tus seguidores y también cuando sea renotada."
+ followers: "Visible solo para seguidores. Sólo tus seguidores podrán ver la nota, y no podrá ser renotada por otras personas."
+ direct: "Visible sólo para usuarios específicos, y el destinatario será notificado. Puede usarse como alternativa a la mensajería directa."
+ doNotSendConfidencialOnDirect1: "¡Ten cuidado cuando vayas a enviar información sensible!"
+ doNotSendConfidencialOnDirect2: "Los administradores del servidor pueden leer lo que escribes. Ten cuidado cuando envíes información sensible en notas directas en servidores no confiables."
+ localOnly: "Publicando con esta opción seleccionada, la nota no se federará hacia otros servidores. Los usuarios de otros servidores no podrán ver estas notas directamente, sin importar los ajustes seleccionados más arriba."
+ _cw:
+ title: "Alerta de contenido (CW)"
+ description: "En lugar de mostrarse el contenido de la nota, se mostrará lo que escribas en el campo \"comentarios\". Pulsando en \"leer más\" desplegará el contenido de la nota."
+ _exampleNote:
+ cw: "¡Esto te hará tener hambre!"
+ note: "Acabo de comerme un donut de chocolate glaseado 🍩😋"
+ useCases: "Esto se usa cuando las normas del servidor lo requieren, o para ocultar spoilers o contenido sensible."
+ _howToMakeAttachmentsSensitive:
+ title: "¿Cómo puedo marcar adjuntos como contenido sensible?"
+ description: "Cuando las normas del servidor lo requieran, o el contenido lo requiera, marca la opción de \"contenido sensible\" para el adjunto."
+ tryThisFile: "¡Prueba a marcar la imagen adjunta como contenido sensible!"
+ _exampleNote:
+ note: "Ups, la he liado al abrir la tapa del natto..."
+ method: "Para marcar un adjunto como sensible, haz clic en la miniatura, abre el menú, y haz clic en \"Marcar como sensible\"."
+ sensitiveSucceeded: "Cuando adjuntes archivos, por favor, ten en cuenta las normas del servidor para marcarlos como contenido sensible."
+ doItToContinue: "Marca el archivo adjunto como sensible para continuar."
+ _done:
+ title: "¡Has completado el tutorial! 🎉"
+ description: "Las funciones que mostramos aquí son sólo una pequeña parte. Para más detalles sobre el funcionamiento de Misskey, pulsa en este enlace: {link}"
+_timelineDescription:
+ home: "En la línea de tiempo de Inicio puedes ver las notas de las cuentas a las que sigues."
+ local: "En la línea de tiempo Local puedes ver las notas de todos los usuarios del servidor."
+ social: "En la línea de tiempo Social verás las notas de Inicio y Local a la vez."
+ global: "En la línea de tiempo Global verás las notas de todos los servidores conectados."
_serverRules:
description: "Un conjunto de reglas que serán mostradas antes del registro. Configurar un sumario de términos de servicio es recomendado."
_serverSettings:
@@ -1174,6 +1323,9 @@ _serverSettings:
manifestJsonOverride: "Sobreescribir manifest.json"
shortName: "Nombre corto"
shortNameDescription: "Forma corta del nombre de la instancia que puede mostrarse si el nombre completo es demasiado largo."
+ fanoutTimelineDescription: "Incrementa el rendimiento de forma significativa cuando se obtienen las líneas de tiempo y reduce la carga en la base de datos. A cambio, el uso de la memoria en Redis incrementará. Considera desactivar esta opción en caso de que tu servidor tenga poca memoria o detectes inestabilidad."
+ fanoutTimelineDbFallback: "Cargar desde la base de datos"
+ fanoutTimelineDbFallbackDescription: "Cuando esta opción está habilitada, la carga de peticiones adicionales de la línea de tiempo se hará desde la base de datos cuando éstas no se encuentren en la caché. Al deshabilitar esta opción se reduce la carga del servidor, pero limita el número de líneas de tiempo que pueden obtenerse."
_accountMigration:
moveFrom: "Trasladar de otra cuenta a ésta"
moveFromSub: "Crear un alias para otra cuenta."
@@ -1431,6 +1583,13 @@ _achievements:
_smashTestNotificationButton:
title: "Sobrecarga de pruebas"
description: "Envía muchas notificaciones de prueba en un corto espacio de tiempo"
+ _tutorialCompleted:
+ title: "Diploma del Curso Básico de Misskey"
+ description: "Tutorial completado"
+ _bubbleGameExplodingHead:
+ title: "🤯"
+ _bubbleGameDoubleExplodingHead:
+ title: "Doble 🤯"
_role:
new: "Crear rol"
edit: "Editar rol"
@@ -1441,7 +1600,9 @@ _role:
assignTarget: "Asignar objetivo"
descriptionOfAssignTarget: "Manual Para cambiar manualmente lo que se incluye en este rol.\nCondicional configura una condición, y los usuarios que cumplan la condición serán incluídos automáticamente."
manual: "manual"
+ manualRoles: "Roles manuales"
conditional: "condicional"
+ conditionalRoles: "Roles condicionales"
condition: "condición"
isConditionalRole: "Esto es un rol condicional"
isPublic: "Publicar rol"
@@ -1474,6 +1635,7 @@ _role:
inviteLimitCycle: "Enfriamiento del límite de invitaciones"
inviteExpirationTime: "Intervalo de caducidad de invitaciones"
canManageCustomEmojis: "Administrar emojis personalizados"
+ canManageAvatarDecorations: "Administrar decoraciones de avatar"
driveCapacity: "Capacidad del drive"
alwaysMarkNsfw: "Siempre marcar archivos como NSFW"
pinMax: "Máximo de notas fijadas"
@@ -1489,6 +1651,7 @@ _role:
canHideAds: "Puede ocultar anuncios"
canSearchNotes: "Uso de la búsqueda de notas"
canUseTranslator: "Uso de traductor"
+ avatarDecorationLimit: "Número máximo de decoraciones de avatar"
_condition:
isLocal: "Usuario local"
isRemote: "Usuario remoto"
@@ -1517,6 +1680,7 @@ _emailUnavailable:
disposable: "No es un correo reutilizable"
mx: "Servidor de correo inválido"
smtp: "Servidor de correo no disponible"
+ banned: "Email no disponible"
_ffVisibility:
public: "Publicar"
followers: "Visible solo para seguidores"
@@ -1593,6 +1757,7 @@ _aboutMisskey:
donate: "Donar a Misskey"
morePatrons: "Muchas más personas nos apoyan. Muchas gracias🥰"
patrons: "Patrocinadores"
+ projectMembers: "Miembros del proyecto"
_displayOfSensitiveMedia:
respect: "Esconder medios marcados como sensibles"
ignore: "Mostrar medios marcados como sensibles"
@@ -1617,6 +1782,7 @@ _channel:
notesCount: "{n} notas"
nameAndDescription: "Nombre y descripción"
nameOnly: "Sólo nombre"
+ allowRenoteToExternal: "Permitir renotas y menciones fuera del canal"
_menuDisplay:
sideFull: "Horizontal"
sideIcon: "Horizontal (ícono)"
@@ -1708,6 +1874,14 @@ _sfx:
notification: "Notificaciones"
antenna: "Antena receptora"
channel: "Notificaciones del canal"
+ reaction: "Al seleccionar una reacción"
+_soundSettings:
+ driveFile: "Usar un archivo de audio en Drive"
+ driveFileWarn: "Selecciona un archivo de audio en Drive."
+ driveFileTypeWarn: "Este archivo es incompatible"
+ driveFileTypeWarnDescription: "Selecciona un archivo de audio"
+ driveFileDurationWarn: "La duración del audio es demasiado larga."
+ driveFileDurationWarnDescription: "Usar un audio de larga duración puede llegar a molestar mientras usas Misskey. ¿Quieres continuar?"
_ago:
future: "Futuro"
justNow: "Justo ahora"
@@ -1719,6 +1893,14 @@ _ago:
monthsAgo: "Hace {n} meses"
yearsAgo: "Hace {n} años"
invalid: "No hay nada que ver aqui"
+_timeIn:
+ seconds: "En {n} segundos"
+ minutes: "En {n}m"
+ hours: "En {n}h"
+ days: "En {n}d"
+ weeks: "En {n}sem."
+ months: "En {n}M"
+ years: "En {n} años"
_time:
second: "Segundos"
minute: "Minutos"
@@ -1790,6 +1972,54 @@ _permissions:
"write:flash": "Editar Plays"
"read:flash-likes": "Ver los Play que me gustan"
"write:flash-likes": "Editar lista de Play que me gustan"
+ "read:admin:abuse-user-reports": "Ver reportes de usuarios"
+ "write:admin:delete-account": "Eliminar cuentas de usuario"
+ "write:admin:delete-all-files-of-a-user": "Eliminar todos los archivos de un usuario"
+ "read:admin:index-stats": "Ver datos indexados"
+ "read:admin:user-ips": "Ver dirección IP de usuario"
+ "read:admin:meta": "Ver metadatos de la instancia"
+ "write:admin:reset-password": "Restablecer contraseñas de usuario"
+ "write:admin:resolve-abuse-user-report": "Resolución de reportes de usuario"
+ "write:admin:send-email": "Enviar email"
+ "read:admin:server-info": "Ver información del servidor"
+ "read:admin:show-moderation-log": "Ver log de moderación"
+ "read:admin:show-user": "Ver información privada de usuario"
+ "read:admin:show-users": "Ver información privada de usuario"
+ "write:admin:suspend-user": "Suspender cuentas de usuario"
+ "write:admin:unset-user-avatar": "Quitar avatares de usuario"
+ "write:admin:unset-user-banner": "Quitar banner de usuarios"
+ "write:admin:unsuspend-user": "Quitar suspensión de cuentas de usuario"
+ "write:admin:meta": "Edición de metadatos de la instancia"
+ "write:admin:user-note": "Moderación de notas"
+ "write:admin:roles": "Edición de roles de usuario"
+ "read:admin:roles": "Ver roles de usuario"
+ "write:admin:relays": "Edición de relays"
+ "read:admin:relays": "Ver relays"
+ "write:admin:invite-codes": "Edición de códigos de invitación"
+ "read:admin:invite-codes": "Ver códigos de invitación"
+ "write:admin:announcements": "Edición de anuncios"
+ "read:admin:announcements": "Ver anuncios"
+ "write:admin:avatar-decorations": "Edición de decoración de avatares"
+ "read:admin:avatar-decorations": "Ver decoraciones de avatar"
+ "write:admin:federation": "Edición de federación de instancias"
+ "write:admin:account": "Edición de cuentas de usuario"
+ "read:admin:account": "Ver cuentas de usuario"
+ "write:admin:emoji": "Edición de emojis"
+ "read:admin:emoji": "Ver emojis"
+ "write:admin:queue": "Edición de cola de tareas"
+ "read:admin:queue": "Ver cola de tareas"
+ "write:admin:promo": "Edición de promociones"
+ "write:admin:drive": "Edición de Drive de usuarios"
+ "read:admin:drive": "Ver Drive de usuarios"
+ "read:admin:stream": "Usar la API de Websocket para administradores"
+ "write:admin:ad": "Edición de anuncios"
+ "read:admin:ad": "Ver anuncios"
+ "write:invite-codes": "Crear códigos de invitación"
+ "read:invite-codes": "Ver códigos de invitación"
+ "write:clip-favorite": "Marcar me gusta en clips"
+ "read:clip-favorite": "Ver los clips que me gustan"
+ "read:federation": "Ver instancias federadas"
+ "write:report-abuse": "Crear reportes de usuario"
_auth:
shareAccessTitle: "Permisos de la aplicación"
shareAccess: "¿Desea permitir el acceso a la cuenta \"{name}\"?"
@@ -1844,6 +2074,7 @@ _widgets:
_userList:
chooseList: "Seleccione una lista"
clicker: "Cliqueador"
+ birthdayFollowings: "Hoy cumplen años"
_cw:
hide: "Ocultar"
show: "Ver más"
@@ -1906,9 +2137,11 @@ _profile:
changeAvatar: "Cambiar avatar"
changeBanner: "Cambiar banner"
verifiedLinkDescription: "Introduciendo una URL que contiene un enlace a tu perfil, se puede mostrar un icono de verificación de propiedad al lado del campo."
+ avatarDecorationMax: "Puedes añadir un máximo de {max} decoraciones de avatar."
_exportOrImport:
allNotes: "Todas las notas"
favoritedNotes: "Notas favoritas"
+ clips: "Clip"
followingList: "Siguiendo"
muteList: "Silenciados"
blockingList: "Bloqueados"
@@ -2027,12 +2260,16 @@ _notification:
pollEnded: "Estan disponibles los resultados de la encuesta"
newNote: "Nueva nota"
unreadAntennaNote: "Antena {name}"
+ roleAssigned: "Rol asignado"
emptyPushNotificationMessage: "Se han actualizado las notificaciones push"
achievementEarned: "Logro desbloqueado"
testNotification: "Notificación de prueba"
checkNotificationBehavior: "Comprobar comportamiento de la notificación"
sendTestNotification: "Enviar notificación de prueba"
notificationWillBeDisplayedLikeThis: "Las notificaciones tendrán este aspecto"
+ reactedBySomeUsers: "{n} usuarios han reaccionado"
+ renotedBySomeUsers: "{n} usuarios han renotado"
+ followedBySomeUsers: "Seguido por {n} usuarios"
_types:
all: "Todo"
note: "Nuevas notas"
@@ -2045,6 +2282,7 @@ _notification:
pollEnded: "La encuesta terminó"
receiveFollowRequest: "Recibió una solicitud de seguimiento"
followRequestAccepted: "El seguimiento fue aceptado"
+ roleAssigned: "Rol asignado"
achievementEarned: "Logro desbloqueado"
app: "Notificaciones desde aplicaciones"
_actions:
@@ -2136,6 +2374,11 @@ _moderationLogTypes:
createAd: "Anuncio creado"
deleteAd: "Anuncio eliminado"
updateAd: "Anuncio actualizado"
+ createAvatarDecoration: "Decoración de avatar creada"
+ updateAvatarDecoration: "Decoración de avatar actualizada"
+ deleteAvatarDecoration: "Decoración de avatar eliminada"
+ unsetUserAvatar: "Quitar decoración de avatar de este usuario"
+ unsetUserBanner: "Quitar banner de este usuario"
_fileViewer:
title: "Detalles del archivo"
type: "Tipo de archivo"
@@ -2144,3 +2387,65 @@ _fileViewer:
uploadedAt: "Subido el"
attachedNotes: "Notas adjuntas"
thisPageCanBeSeenFromTheAuthor: "Esta página solo puede ser vista por el autor."
+_externalResourceInstaller:
+ title: "Instalar desde sitio externo"
+ checkVendorBeforeInstall: "Asegúrate de que el distribuidor de este recurso es de confianza antes de proceder a la instalación."
+ _plugin:
+ title: "¿Quieres instalar este plugin?"
+ metaTitle: "Información del plugin"
+ _theme:
+ title: "¿Quieres instalar este tema?"
+ metaTitle: "Información del tema"
+ _meta:
+ base: "Esquema de color base"
+ _vendorInfo:
+ title: "Información del distribuidor"
+ endpoint: "Terminal referenciada"
+ hashVerify: "Verificación de hash"
+ _errors:
+ _invalidParams:
+ title: "Parámetros inválidos"
+ description: "No hay información suficiente para cargar datos de un sitio externo. Por favor, confirma la URL introducida."
+ _resourceTypeNotSupported:
+ title: "Este recurso externo no es compatible"
+ description: "El tipo de este recurso externo no es compatible. Por favor, contacta con el administrador del sitio."
+ _failedToFetch:
+ title: "No se pudo obtener los datos"
+ fetchErrorDescription: "Ha ocurrido un error al comunicarse con el sitio externo. Si no se soluciona tras intentarlo otra vez, por favor, contacta con el administrador del sitio."
+ parseErrorDescription: "Ha ocurrido un error al procesar los datos obtenidos del sitio externo. Por favor, contacta con el administrador del sitio."
+ _hashUnmatched:
+ title: "Verificación de datos fallida"
+ description: "Ha ocurrido un error al verificar la integridad de los datos obtenidos. Por seguridad, la instalación no se puede realizar. Por favor, contacta con el administrador del sitio."
+ _pluginParseFailed:
+ title: "Error de AiScript"
+ description: "Los datos se han obtenido correctamente, pero ha ocurrido un error de AiScript al procesarlos. Por favor, contacta con el autor del plugin. Se pueden ver más detalles del error en la consola de Javascript."
+ _pluginInstallFailed:
+ title: "Instalación del plugin fallida."
+ description: "Ha ocurrido un problema al instalar el plugin. Por favor, inténtalo de nuevo. Se pueden ver más detalles del error en la consola de Javascript."
+ _themeParseFailed:
+ title: "Análisis del tema fallido"
+ description: "Los datos se han obtenido correctamente, pero ha ocurrido un error al analizar el tema. Por favor, contacta con el autor. Se pueden ver más detalles del error en la consola de Javascript."
+ _themeInstallFailed:
+ title: "Instalación de tema fallida"
+ description: "Ha ocurrido un problema al instalar el tema. Por favor, inténtalo de nuevo. Se pueden ver más detalles del error en la consola de Javascript."
+_dataSaver:
+ _media:
+ title: "Cargando Multimedia"
+ description: "Desactiva la carga automática de imágenes y vídeos. Tendrás que tocar en las imágenes y vídeos ocultos para cargarlos."
+ _avatar:
+ title: "Avatares animados"
+ description: "Desactiva la animación de los avatares. Las imágenes animadas pueden llegar a ser de mayor tamaño que las normales, por lo que al desactivarlas puedes reducir el consumo de datos."
+ _urlPreview:
+ title: "Vista previa de URLs"
+ description: "Desactiva la carga de vistas previas de las URLs."
+ _code:
+ title: "Resaltar código"
+ description: "Si se usa resaltado de código en MFM, etc., no se cargará hasta pulsar en ello. El resaltado de sintaxis requiere la descarga de archivos de definición para cada lenguaje de programación. Debido a esto, al deshabilitar la carga automática de estos archivos reducirás el consumo de datos."
+_hemisphere:
+ N: "Hemisferio norte"
+ S: "Hemisferio sur"
+_reversi:
+ reversi: "Reversi"
+ won: "{name} ha ganado"
+ total: "Total"
+
diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml
index 94254fd99..9629726f5 100644
--- a/locales/fr-FR.yml
+++ b/locales/fr-FR.yml
@@ -2,7 +2,7 @@
_lang_: "Français"
headlineMisskey: "Réseau relié par des notes"
introMisskey: "Bienvenue ! Misskey est un service de microblogage décentralisé, libre et ouvert.\nÉcrivez des « notes » et partagez ce qui se passe à l’instant présent, autour de vous avec les autres 📡\nLa fonction « réactions », vous permet également d’ajouter une réaction rapide aux notes des autres utilisateur·rice·s 👍\nExplorons un nouveau monde 🚀"
-poweredByMisskeyDescription: "{nom} est l'un des services propulsés par la plateforme ouverte Misskey (appelée \"instance Misskey\")."
+poweredByMisskeyDescription: "{name} est l'un des services propulsés par la plateforme ouverte Misskey (appelée \"instance Misskey\")."
monthAndDay: "{day}/{month}"
search: "Rechercher"
notifications: "Notifications"
@@ -75,7 +75,7 @@ import: "Importer"
export: "Exporter"
files: "Fichiers"
download: "Télécharger"
-driveFileDeleteConfirm: "Êtes-vous sûr de vouloir supprimer le fichier \"{name}\" ? Les notes liées à ce fichier seront aussi supprimées."
+driveFileDeleteConfirm: "Êtes-vous sûr·e de vouloir supprimer le fichier « {name} » ? Les notes avec ce fichier joint seront aussi supprimées."
unfollowConfirm: "Désirez-vous vous désabonner de {name} ?"
exportRequested: "Vous avez demandé une exportation. L’opération pourrait prendre un peu de temps. Une fois terminée, le fichier sera ajouté au Drive."
importRequested: "Vous avez initié un import. Cela pourrait prendre un peu de temps."
@@ -121,10 +121,16 @@ sensitive: "Contenu sensible"
add: "Ajouter"
reaction: "Réactions"
reactions: "Réactions"
-reactionSetting: "Réactions à afficher dans le sélecteur de réactions"
+emojiPicker: "Sélecteur d’émojis"
+pinnedEmojisForReactionSettingDescription: "Vous pouvez définir les émojis épinglés lors de la réaction"
+pinnedEmojisSettingDescription: "Vous pouvez définir les émojis épinglés lors de la saisie de l'émoji"
+emojiPickerDisplay: "Affichage du sélecteur d'émojis"
+overwriteFromPinnedEmojisForReaction: "Remplacer par les émojis épinglés pour la réaction"
+overwriteFromPinnedEmojis: "Remplacer par les émojis épinglés globalement"
reactionSettingDescription2: "Déplacer pour réorganiser, cliquer pour effacer, utiliser « + » pour ajouter."
rememberNoteVisibility: "Se souvenir de la visibilité des notes"
attachCancel: "Supprimer le fichier attaché"
+deleteFile: "Fichier supprimé"
markAsSensitive: "Marquer comme sensible"
unmarkAsSensitive: "Supprimer le marquage comme sensible"
enterFileName: "Entrer le nom du fichier"
@@ -157,12 +163,13 @@ addEmoji: "Ajouter un émoji"
settingGuide: "Configuration proposée"
cacheRemoteFiles: "Mise en cache des fichiers distants"
cacheRemoteFilesDescription: "Lorsque cette option est désactivée, les fichiers distants sont chargés directement depuis l’instance distante. La désactiver diminuera certes l’utilisation de l’espace de stockage local mais augmentera le trafic réseau puisque les miniatures ne seront plus générées."
+youCanCleanRemoteFilesCache: "Vous pouvez supprimer tous les caches en cliquant le bouton 🗑️ dans la gestion des fichiers."
cacheRemoteSensitiveFiles: "Mettre en cache les fichiers distants sensibles"
cacheRemoteSensitiveFilesDescription: "Si vous désactivez ce paramètre, les fichiers sensibles distants ne seront pas mis en cache et un lien direct sera utilisé à la place"
flagAsBot: "Ce compte est un robot"
flagAsBotDescription: "Si ce compte est géré de manière automatisée, choisissez cette option. Si elle est activée, elle agira comme un marqueur pour les autres développeurs afin d'éviter des chaînes d'interaction sans fin avec d'autres robots et d'ajuster les systèmes internes de Misskey pour traiter ce compte comme un robot."
flagAsCat: "Ce compte est un chat"
-flagAsCatDescription: "Activer l'option \" Je suis un chat \" pour ce compte."
+flagAsCatDescription: "Miaou miaou miaou ?"
flagShowTimelineReplies: "Afficher les réponses dans le fil"
flagShowTimelineRepliesDescription: "Affiche les réponses des utilisateurs aux notes des autres utilisateurs dans la timeline si cette option est activée."
autoAcceptFollowed: "Accepter automatiquement les demandes d’abonnement venant d’utilisateur·rice·s que vous suivez"
@@ -258,14 +265,15 @@ imageUrl: "URL de l’image"
remove: "Supprimer"
removed: "Supprimé"
removeAreYouSure: "Êtes-vous sûr·e de vouloir supprimer « {x} » ?"
-deleteAreYouSure: "Êtes-vous sûr·e de vouloir supprimer「{x}」?"
+deleteAreYouSure: "Êtes-vous sûr·e de vouloir supprimer « {x} » ?"
resetAreYouSure: "Voulez-vous réinitialiser ?"
+areYouSure: "Êtes-vous sûr·e ?"
saved: "Enregistré"
messaging: "Discuter"
upload: "Téléverser"
keepOriginalUploading: "Garder l’image d’origine"
keepOriginalUploadingDescription: "Conserve la version originale lors du téléchargement d'images. S'il est désactivé, le navigateur génère l'image pour la publication web lors du téléchargement."
-fromDrive: "Depuis le Drive"
+fromDrive: "Depuis le Disque"
fromUrl: "Depuis une URL"
uploadFromUrl: "Téléverser via une URL"
uploadFromUrlDescription: "URL du fichier que vous souhaitez téléverser"
@@ -299,7 +307,7 @@ dark: "Sombre"
lightThemes: "Thèmes clairs"
darkThemes: "Thèmes sombres"
syncDeviceDarkMode: "Utiliser le mode sombre de votre appareil"
-drive: "Drive"
+drive: "Disque"
fileName: "Nom du fichier"
selectFile: "Choisir le fichier"
selectFiles: "Choisir les fichiers"
@@ -310,8 +318,9 @@ folderName: "Nom du dossier"
createFolder: "Créer un dossier"
renameFolder: "Renommer le dossier"
deleteFolder: "Supprimer le dossier"
+folder: "Dossier"
addFile: "Ajouter un fichier"
-emptyDrive: "Le Drive est vide"
+emptyDrive: "Le Disque est vide"
emptyFolder: "Le dossier est vide"
unableToDelete: "Suppression impossible"
inputNewFileName: "Entrez un nouveau nom de fichier"
@@ -355,8 +364,8 @@ disablingTimelinesInfo: "Même si vous désactivez ces fils, les administrateur
registration: "S’inscrire"
enableRegistration: "Autoriser les nouvelles inscriptions"
invite: "Inviter"
-driveCapacityPerLocalAccount: "Volume du Drive par utilisateur local"
-driveCapacityPerRemoteAccount: "Volume du Drive par utilisateur distant"
+driveCapacityPerLocalAccount: "Capacité de stockage du Disque par utilisateur local"
+driveCapacityPerRemoteAccount: "Capacité de stockage du Disque par utilisateur distant"
inMb: "en mégaoctets"
bannerUrl: "URL de l’image de la bannière"
backgroundImageUrl: "URL de l'image d'arrière-plan"
@@ -371,6 +380,11 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Activer hCaptcha"
hcaptchaSiteKey: "Clé du site"
hcaptchaSecretKey: "Clé secrète"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "Activer mCaptcha"
+mcaptchaSiteKey: "Clé du site"
+mcaptchaSecretKey: "Clé secrète"
+mcaptchaInstanceUrl: "URL de l'instance de mCaptcha"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Activer reCAPTCHA"
recaptchaSiteKey: "Clé du site"
@@ -388,7 +402,7 @@ antennaKeywords: "Mots clés à recevoir"
antennaExcludeKeywords: "Mots clés à exclure"
antennaKeywordsDescription: "Séparer avec des espaces pour la condition AND. Séparer avec un saut de ligne pour une condition OR."
notifyAntenna: "Me notifier pour les nouvelles notes"
-withFileAntenna: "Notes ayant des attachements uniquement"
+withFileAntenna: "Notes ayant des fichiers joints uniquement"
enableServiceworker: "Activer ServiceWorker"
antennaUsersDescription: "Saisissez un seul nom d’utilisateur·rice par ligne"
caseSensitive: "Sensible à la casse"
@@ -428,6 +442,7 @@ lastUsed: "Dernier utilisé"
lastUsedAt: "Dernière utilisation : {t}"
unregister: "Se désinscrire"
passwordLessLogin: "Se connecter sans mot de passe"
+passwordLessLoginDescription: "Se connecter uniquement avec une clé de sécurité ou une clé d'accès sans utiliser de mot de passe"
resetPassword: "Réinitialiser le mot de passe"
newPasswordIs: "Votre nouveau mot de passe est \"{password}\""
reduceUiAnimation: "Réduire les animations dans l’interface"
@@ -435,7 +450,6 @@ share: "Partager"
notFound: "Non trouvé"
notFoundDescription: "Aucune page ne correspond à l’URL spécifiée."
uploadFolder: "Emplacement de téléversement par défaut"
-cacheClear: "Vider le cache"
markAsReadAllNotifications: "Marquer toutes les notifications comme lues"
markAsReadAllUnreadNotes: "Marquer toutes les notes comme lues"
markAsReadAllTalkMessages: "Marquer toutes les discussions comme lues"
@@ -483,6 +497,7 @@ showNoteActionsOnlyHover: "Afficher les actions de note uniquement au survol"
noHistory: "Pas d'historique"
signinHistory: "Historique de connexion"
enableAdvancedMfm: "Activer la MFM avancée"
+enableAnimatedMfm: "Activer le MFM animé"
doing: "En cours..."
category: "Catégorie"
tags: "Étiquettes"
@@ -491,6 +506,7 @@ createAccount: "Créer un compte"
existingAccount: "Compte existant"
regenerate: "Générer à nouveau"
fontSize: "Taille de la police"
+mediaListWithOneImageAppearance: "Hauteur des listes de médias n'ayant qu'une image "
limitTo: "Limiter à {x}"
noFollowRequests: "Vous n’avez aucune demande d’abonnement en attente"
openImageInNewTab: "Ouvrir les images dans un nouvel onglet"
@@ -510,7 +526,7 @@ hideThisNote: "Masquer cette note"
showFeaturedNotesInTimeline: "Afficher les notes des Tendances dans le fil d'actualité"
objectStorage: "Stockage d'objets"
useObjectStorage: "Utiliser le stockage d'objets"
-objectStorageBaseUrl: "Base URL"
+objectStorageBaseUrl: "URL de base"
objectStorageBaseUrlDesc: "Préfixe d’URL utilisé pour construire l’URL vers le référencement d’objet (média). Spécifiez son URL si vous utilisez un CDN ou un proxy, sinon spécifiez l’adresse accessible au public selon le guide de service que vous allez utiliser. P.ex. 'https://.s3.amazonaws.com' pour AWS S3 et 'https://storage.googleapis.com/' pour GCS."
objectStorageBucket: "Bucket"
objectStorageBucketDesc: "Veuillez spécifier le nom du compartiment utilisé sur le service configuré."
@@ -528,6 +544,7 @@ objectStorageSetPublicRead: "Régler sur « public » lors de l'envoi"
serverLogs: "Journal du serveur"
deleteAll: "Supprimer tout"
showFixedPostForm: "Afficher le formulaire de publication en haut du fil d'actualité"
+showFixedPostFormInChannel: "Afficher le formulaire de publication en haut du fil (canaux)"
withRepliesByDefaultForNewlyFollowed: "Afficher les réponses des nouvelles personnes que vous suivez dans le fil par défaut"
newNoteRecived: "Voir les nouvelles notes"
sounds: "Sons"
@@ -538,6 +555,8 @@ showInPage: "Afficher dans la page"
popout: "Fenêtre contextuelle"
volume: "Volume"
masterVolume: "Volume principal"
+notUseSound: "Ne pas émettre de son"
+useSoundOnlyWhenActive: "Émettre des sons uniquement quand Misskey est active"
details: "Détails"
chooseEmoji: "Choisissez un émoji"
unableToProcess: "L’opération n’a pas pu être complétée."
@@ -558,9 +577,13 @@ output: "Sortie"
script: "Script"
disablePagesScript: "Désactiver AiScript sur les Pages"
updateRemoteUser: "Mettre à jour les informations de l’utilisateur·rice distant·e"
+unsetUserAvatar: "Supprimer l’avatar"
+unsetUserAvatarConfirm: "Êtes-vous sûr·e de vouloir supprimer l'avatar ?"
+unsetUserBanner: "Supprimer la bannière"
+unsetUserBannerConfirm: "Êtes-vous sûr·e de vouloir supprimer la bannière ?"
deleteAllFiles: "Supprimer tous les fichiers"
deleteAllFilesConfirm: "Êtes-vous sûr·e de vouloir supprimer tous les fichiers ?"
-removeAllFollowing: "Retenir tous les abonnements"
+removeAllFollowing: "Se désabonner de tous les utilisateurs auxquels vous êtes abonné·e"
removeAllFollowingDescription: "Se désabonner de tous les comptes de {host}. Veuillez lancer cette action dans les cas où l’instance n’existe plus, etc."
userSuspended: "Cet·te utilisateur·rice a été suspendu·e."
userSilenced: "Cette utilisateur·trice a été mis·e en sourdine."
@@ -608,6 +631,7 @@ medium: "Moyen"
small: "Petit"
generateAccessToken: "Générer un jeton d'accès"
permission: "Autorisations "
+adminPermission: "Droits de l'administrateur"
enableAll: "Tout activer"
disableAll: "Tout désactiver"
tokenRequested: "Autoriser l'accès au compte"
@@ -629,6 +653,7 @@ smtpSecure: "Utiliser SSL/TLS implicitement dans les connexions SMTP"
smtpSecureInfo: "Désactiver cette option lorsque STARTTLS est utilisé"
testEmail: "Tester la distribution de courriel"
wordMute: "Filtre de mots"
+hardWordMute: "Filtre de mots dur"
regexpError: "Erreur d’expression régulière"
regexpErrorDescription: "Une erreur s'est produite dans l'expression régulière sur la ligne {ligne} de votre mot muet {tab} :"
instanceMute: "Instance en sourdine"
@@ -678,7 +703,7 @@ system: "Système"
switchUi: "Modifier l'interface utilisateur"
desktop: "Bureau"
clip: "Clip"
-createNew: "Créer nouveau"
+createNew: "Créer"
optional: "Facultatif"
createNewClip: "Créer un nouveau clip"
unclip: "Supprimer le clip"
@@ -701,14 +726,15 @@ pollVotesCount: "Nombre de votes envoyés"
pollVotedCount: "Nombre de votes reçus"
yes: "Oui"
no: "Non"
-driveFilesCount: "Nombre de fichiers dans le Drive"
-driveUsage: "Utilisation du Drive"
+driveFilesCount: "Nombre de fichiers sur le Disque"
+driveUsage: "Utilisation du Disque"
noCrawle: "Refuser l'indexation par les robots"
noCrawleDescription: "Demandez aux moteurs de recherche de ne pas indexer votre page de profil, vos notes, vos pages, etc."
lockedAccountInfo: "À moins que vous ne définissiez la visibilité de votre note sur \"Abonné-e-s\", vos notes sont visibles par tous, même si vous exigez que les demandes d'abonnement soient approuvées manuellement."
alwaysMarkSensitive: "Marquer les médias comme contenu sensible par défaut"
loadRawImages: "Affichage complet des images jointes au lieu des vignettes"
disableShowingAnimatedImages: "Désactiver l'animation des images"
+highlightSensitiveMedia: "Mettre en évidence les médias sensibles"
verificationEmailSent: "Un e-mail de vérification a été envoyé. Veuillez accéder au lien pour compléter la vérification."
notSet: "Non défini"
emailVerified: "Votre adresse e-mail a été vérifiée."
@@ -845,7 +871,7 @@ pubSub: "Comptes Pub/Sub"
lastCommunication: "Dernière communication"
resolved: "Résolu"
unresolved: "En attente"
-breakFollow: "Ne plus suivre"
+breakFollow: "Supprimer l'abonné·e"
breakFollowConfirm: "Êtes-vous sûr de vouloir vous désabonner ?"
itsOn: "Activé"
itsOff: "Désactivé"
@@ -861,8 +887,8 @@ makeReactionsPublicDescription: "Ceci rendra la liste de toutes vos réactions d
classic: "Classique"
muteThread: "Masquer cette discussion"
unmuteThread: "Ne plus masquer le fil"
-ffVisibility: "Visibilité des abonnés/abonnements"
-ffVisibilityDescription: "Permet de configurer qui peut voir les personnes que tu suis et les personnes qui te suivent."
+followingVisibility: "Visibilité des abonnements"
+followersVisibility: "Visibilité des abonnés"
continueThread: "Afficher la suite du fil"
deleteAccountConfirm: "Votre compte sera supprimé. Êtes vous certain ?"
incorrectPassword: "Le mot de passe est incorrect."
@@ -904,7 +930,7 @@ noEmailServerWarning: "Serveur de courrier non configuré."
thereIsUnresolvedAbuseReportWarning: "Il n’y a aucun rapport non résolu."
recommended: "Recommandé"
check: "Vérifier"
-driveCapOverrideLabel: "Modifier la capacité de stockage du drive de cet·te utilisateur·rice"
+driveCapOverrideLabel: "Modifier la capacité de stockage du Disque de cet·te utilisateur·rice"
driveCapOverrideCaption: "Si une valeur inférieure à 0 est spécifiée, elle est annulée."
requireAdminForView: "Vous devez être connecté avec un compte administrateur pour les visualiser."
isSystemAccount: "Ces comptes sont automatiquement créés et gérés par le système."
@@ -962,6 +988,7 @@ show: "Affichage"
neverShow: "Ne plus afficher"
remindMeLater: "Peut-être plus tard"
didYouLikeMisskey: "Avez-vous aimé Misskey ?"
+pleaseDonate: "Misskey est le logiciel libre utilisé par {host}. Merci de faire un don pour que nous puissions continuer à le développer !"
roles: "Rôles"
role: "Rôles"
noRole: "Aucun rôle"
@@ -974,12 +1001,15 @@ manageCustomEmojis: "Gestion des émojis personnalisés"
manageAvatarDecorations: "Gérer les décorations d'avatar"
youCannotCreateAnymore: "Vous avez atteint la limite de création."
cannotPerformTemporary: "Temporairement indisponible"
+cannotPerformTemporaryDescription: "Temporairement indisponible puisque le nombre d'opérations dépasse la limite. Veuillez patienter un peu, puis réessayer."
invalidParamError: "Paramètres invalides"
permissionDeniedError: "Opération refusée"
+permissionDeniedErrorDescription: "Ce compte n'a pas la permission d'effectuer cette opération."
preset: "Préréglage"
selectFromPresets: "Sélectionner à partir des préréglages"
achievements: "Accomplissements"
gotInvalidResponseError: "Réponse du serveur invalide"
+gotInvalidResponseErrorDescription: "Il se peut que le serveur soit hors ligne ou en maintenance. Veuillez réessayer plus tard."
thisPostMayBeAnnoying: "Cette note peut gêner d'autres personnes."
thisPostMayBeAnnoyingHome: "Publier vers le fil principal"
thisPostMayBeAnnoyingCancel: "Annuler"
@@ -989,19 +1019,45 @@ internalServerError: "Erreur interne du serveur"
copyErrorInfo: "Copier les détails de l’erreur"
joinThisServer: "S'inscrire à cette instance"
exploreOtherServers: "Trouver une autre instance"
+letsLookAtTimeline: "Jetez un coup d'œil au fil"
+disableFederationConfirm: "Voulez-vous vraiment désactiver la fédération ?"
+disableFederationConfirmWarn: "Même sans fédération, la note ne sera pas privée. Dans la plupart des cas, ce n'est pas nécessaire de désactiver la fédération."
disableFederationOk: "Désactiver"
+invitationRequiredToRegister: "Actuellement, cette instance est uniquement sur invitation. Seuls ceux qui ont un code d'invitation peuvent s'inscrire."
+emailNotSupported: "Cette instance ne prend pas en charge l'envoi de courriels"
postToTheChannel: "Publier au canal"
+cannotBeChangedLater: "Cela ne peut pas être modifié plus tard."
+reactionAcceptance: "Acceptation des réactions"
likeOnly: "Les favoris uniquement"
+likeOnlyForRemote: "Toutes (mentions j'aime seulement pour les instances distantes)"
+nonSensitiveOnly: "Non sensibles seulement"
+nonSensitiveOnlyForLocalLikeOnlyForRemote: "Non sensibles seulement (mentions j'aime seulement pour les instances distantes)"
+rolesAssignedToMe: "Rôles attribués à moi"
+resetPasswordConfirm: "Souhaitez-vous réinitialiser votre mot de passe ?"
sensitiveWords: "Mots sensibles"
+sensitiveWordsDescription2: "Séparer par une espace pour créer une expression AND ; entourer de barres obliques pour créer une expression régulière."
+prohibitedWords: "Mots interdits"
+prohibitedWordsDescription2: "Séparer par une espace pour créer une expression AND ; entourer de barres obliques pour créer une expression régulière."
+hiddenTags: "Hashtags cachés"
+hiddenTagsDescription: "Les hashtags définis ne s'afficheront pas dans les tendances. Vous pouvez définir plusieurs hashtags en faisant un saut de ligne."
notesSearchNotAvailable: "La recherche de notes n'est pas disponible."
license: "Licence"
+unfavoriteConfirm: "Vraiment supprimer des favoris ?"
myClips: "Mes clips"
+drivecleaner: "Nettoyeur du Disque"
+retryAllQueuesNow: "Réessayer tous les fils d'attente immédiatement"
+retryAllQueuesConfirmTitle: "Vraiment réessayer ?"
retryAllQueuesConfirmText: "Cela peut augmenter temporairement la charge du serveur."
+enableChartsForRemoteUser: "Générer les graphiques pour les utilisateurs distants"
+enableChartsForFederatedInstances: "Générer les graphiques pour les instances distantes"
showClipButtonInNoteFooter: "Ajouter « Clip » au menu d'action de la note"
reactionsDisplaySize: "Taille de l'affichage des réactions"
+limitWidthOfReaction: "Limiter la largeur maximale des réactions et les afficher en taille réduite"
noteIdOrUrl: "Identifiant de la note ou URL"
video: "Vidéo"
videos: "Vidéos"
+audio: "Audio"
+audioFiles: "Fichiers audio"
dataSaver: "Économiseur de données"
accountMigration: "Migration de compte"
accountMoved: "Cet·te utilisateur·rice a migré son compte vers :"
@@ -1009,6 +1065,7 @@ accountMovedShort: "Ce compte a migré"
operationForbidden: "Opération non autorisée"
forceShowAds: "Toujours afficher les publicités"
addMemo: "Ajouter un mémo"
+editMemo: "Éditer le mémo"
reactionsList: "Réactions"
renotesList: "Liste de renotes"
notificationDisplay: "Style des notifications"
@@ -1021,10 +1078,13 @@ vertical: "Vertical"
horizontal: "Latéral"
position: "Position"
serverRules: "Règles du serveur"
+pleaseConfirmBelowBeforeSignup: "Pour vous inscrire sur cette instance, vous devez confirmer et accepter le contenu suivant."
pleaseAgreeAllToContinue: "Pour continuer, veuillez accepter tous les champs ci-dessus."
continue: "Continuer"
preservedUsernames: "Noms d'utilisateur·rice réservés"
+createNoteFromTheFile: "Rédiger une note de ce fichier"
archive: "Archive"
+channelArchiveConfirmTitle: "Voulez-vous vraiment archiver {name} ?"
thisChannelArchived: "Ce canal a été archivé."
displayOfNote: "Affichage de la note"
initialAccountSetting: "Configuration initiale du profil"
@@ -1035,28 +1095,50 @@ options: "Options"
specifyUser: "Spécifier l'utilisateur·rice"
failedToPreviewUrl: "Aperçu d'URL échoué"
update: "Mettre à jour"
+rolesThatCanBeUsedThisEmojiAsReaction: "Rôles qui peuvent utiliser cet émoji comme réaction"
+rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "Si aucun rôle n'est spécifié, tout le monde peut utiliser cet émoji comme réaction."
+rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "Il faut un rôle public."
+cancelReactionConfirm: "Supprimez la réaction ?"
+changeReactionConfirm: "Changer la réaction ?"
later: "Plus tard"
goToMisskey: "Retour vers Misskey"
+additionalEmojiDictionary: "Dictionnaires d'émojis additionnels"
installed: "Installé"
+branding: "Image de marque"
+enableServerMachineStats: "Publier les statistiques du matériel du serveur"
+enableIdenticonGeneration: "Générer les identicons des utilisateurs"
+turnOffToImprovePerformance: "Désactiver peut améliorer la performance."
+createInviteCode: "Créer un code d'invitation"
+createWithOptions: "Options"
+createCount: "Quantité à créer"
+inviteCodeCreated: "Code d'invitation créé"
+inviteLimitExceeded: "Vous avez atteint la limite de codes d'invitation que vous pouvez générer."
expirationDate: "Date d’expiration"
+noExpirationDate: "Ne pas expirer"
+inviteCodeUsedAt: "Code d'invitation utilisé à"
+registeredUserUsingInviteCode: "Code d'invitation utilisé par"
waitingForMailAuth: "En attente de la vérification de l'adresse courriel"
+inviteCodeCreator: "Créateur·rice de ce code d'invitation"
usedAt: "Utilisé le"
unused: "Non-utilisé"
used: "Utilisé"
expired: "Expiré"
doYouAgree: "Êtes-vous d’accord ?"
beSureToReadThisAsItIsImportant: "Assurez-vous de le lire ; c'est important."
+iHaveReadXCarefullyAndAgree: "J'ai lu le contenu de « {x} » et donne mon accord."
dialog: "Dialogue"
icon: "Avatar"
forYou: "Pour vous"
currentAnnouncements: "Annonces actuelles"
pastAnnouncements: "Annonces passées"
-replies: "Répondre"
-renotes: "Renoter"
+youHaveUnreadAnnouncements: "Il y a des annonces non lues."
+replies: "Réponses"
+renotes: "Renotes"
loadReplies: "Inclure les réponses"
loadConversation: "Afficher la conversation"
pinnedList: "Liste épinglée"
notifyNotes: "Notifier à propos des nouvelles notes"
+unnotifyNotes: "Ne pas notifier pour la publication des notes"
authentication: "Authentification"
authenticationRequiredToContinue: "Veuillez vous authentifier pour continuer"
dateAndTime: "Date et heure"
@@ -1064,6 +1146,7 @@ showRenotes: "Afficher les renotes"
edited: "Modifié"
notificationRecieveConfig: "Paramètres des notifications"
mutualFollow: "Abonnement mutuel"
+fileAttachedOnly: "Avec fichiers joints seulement"
showRepliesToOthersInTimeline: "Afficher les réponses aux autres dans le fil"
hideRepliesToOthersInTimeline: "Masquer les réponses aux autres dans le fil"
showRepliesToOthersInTimelineAll: "Afficher les réponses de toutes les personnes que vous suivez dans le fil"
@@ -1071,6 +1154,12 @@ hideRepliesToOthersInTimelineAll: "Masquer les réponses de toutes les personnes
confirmShowRepliesAll: "Cette opération est irréversible. Voulez-vous vraiment afficher les réponses de toutes les personnes que vous suivez dans le fil ?"
confirmHideRepliesAll: "Cette opération est irréversible. Voulez-vous vraiment masquer les réponses de toutes les personnes que vous suivez dans le fil ?"
externalServices: "Services externes"
+sourceCode: "Code source"
+sourceCodeIsNotYetProvided: "Le code source n'est pas encore disponible. Veuillez signaler ce problème aux administrateurs."
+repositoryUrl: "URL du dépôt"
+repositoryUrlDescription: "Entrez l'URL du dépôt où se trouve le code source ici. Si vous utilisez Misskey tel quel (sans changer le code source), entrez https://github.com/misskey-dev/misskey"
+feedback: "Commentaires"
+feedbackUrl: "URL pour les commentaires"
impressum: "Impressum"
impressumUrl: "URL de l'impressum"
impressumDescription: "Dans certains pays comme l'Allemagne, il est obligatoire d'afficher les informations sur l'opérateur d'un site (un impressum)."
@@ -1080,6 +1169,7 @@ tosAndPrivacyPolicy: "Conditions d'utilisation et politique de confidentialité"
avatarDecorations: "Décorations d'avatar"
attach: "Mettre"
detach: "Enlever"
+detachAll: "Tout enlever"
angle: "Angle"
flip: "Inverser"
showAvatarDecorations: "Afficher les décorations d'avatar"
@@ -1091,7 +1181,40 @@ useGroupedNotifications: "Grouper les notifications"
signupPendingError: "Un problème est survenu lors de la vérification de votre adresse e-mail. Le lien a peut-être expiré."
cwNotationRequired: "Si « Masquer le contenu » est activé, une description doit être fournie."
doReaction: "Réagir"
+code: "Code"
+reloadRequiredToApplySettings: "Le rafraîchissement est nécessaire pour que les paramètres prennent effet."
+remainingN: "Restants : {n}"
+overwriteContentConfirm: "Voulez-vous remplacer le contenu actuel ?"
+seasonalScreenEffect: "Effet d'écran saisonnier"
+decorate: "Décorer"
+addMfmFunction: "Insérer MFM"
+enableQuickAddMfmFunction: "Afficher le sélecteur de MFM avancé"
+bubbleGame: "Jeu de bulles"
+sfx: "Effets sonores"
+soundWillBePlayed: "Le son sera joué"
+showReplay: "Voir le replay"
+replay: "Rediffusion"
+replaying: "En cours de rediffusion"
+endReplay: "Arrêter la rediffusion"
+copyReplayData: "Copier les données de la rediffusion"
+ranking: "Classement"
+lastNDays: "Derniers {n} jours"
+backToTitle: "Retourner au titre"
+hemisphere: "Votre région"
+enableHorizontalSwipe: "Glisser pour changer d'onglet"
+loading: "Chargement en cours"
+surrender: "Annuler"
+gameRetry: "Réessayer"
+_bubbleGame:
+ howToPlay: "Comment jouer"
+ hold: "Réserver"
+ _score:
+ score: "Score"
+ scoreYen: "Montant gagné"
+ highScore: "Meilleur score"
+ yen: "{yen} yens"
_announcement:
+ forExistingUsers: "Pour les utilisateurs existants seulement"
readConfirmTitle: "Marquer comme lu ?"
shouldNotBeUsedToPresentPermanentInfo: "Puisque cela pourrait nuire considérablement à l'expérience utilisateur pour les nouveaux utilisateurs, il est recommandé d'utiliser les annonces pour afficher des informations temporaires plutôt que des informations persistantes."
dialogAnnouncementUxWarn: "Avoir deux ou plus annonces de style dialogue en même temps pourrait nuire considérablement à l'expérience utilisateur. Veuillez les utiliser avec caution."
@@ -1101,7 +1224,7 @@ _initialAccountSetting:
profileSetting: "Paramètres du profil"
privacySetting: "Paramètres de confidentialité"
initialAccountSettingCompleted: "Configuration du profil terminée avec succès !"
- youCanContinueTutorial: "Vous pouvez procéder au tutoriel sur l'utilisation de {nom}(Misskey) ou vous arrêter ici et commencer à l'utiliser immédiatement."
+ youCanContinueTutorial: "Vous pouvez procéder au tutoriel sur l'utilisation de {name}(Misskey) ou vous arrêter ici et commencer à l'utiliser immédiatement."
startTutorial: "Démarrer le tutoriel"
skipAreYouSure: "Désirez-vous ignorer la configuration du profil ?"
_initialTutorial:
@@ -1160,7 +1283,7 @@ _initialTutorial:
tryThisFile: "Essayez de marquer l'image jointe à ce formulaire de publication comme sensible !"
_exampleNote:
note: "Oups, j'ai échoué à ouvrir le couvercle du natto..."
- method: "Pour marquer un fichier joint comme sensible, cliquez sur la vignette du fichier, ouvrez le menu et cliquez sur « marquer comme sensible » ."
+ method: "Pour marquer un fichier joint comme sensible, cliquez sur la vignette du fichier pour ouvrir le menu et cliquez sur « marquer comme sensible » ."
sensitiveSucceeded: "Quand vous joignez des fichiers, veuillez indiquer la sensibilité selon les règles du serveur."
doItToContinue: "Marquez le fichier joint comme sensible pour procéder."
_done:
@@ -1186,6 +1309,7 @@ _accountMigration:
startMigration: "Migrer"
movedTo: "Compte vers lequel vous migrez :"
_achievements:
+ earnedAt: "Date d'obtention"
_types:
_notes1:
title: "Je viens tout juste de configurer mon msky"
@@ -1226,10 +1350,13 @@ _achievements:
title: "Régulier III"
description: "Se connecter pour un total de 400 jours"
_login500:
+ title: "Expert I"
description: "Se connecter pour un total de 500 jours"
_login600:
+ title: "Expert II"
description: "Se connecter pour un total de 600 jours"
_login700:
+ title: "Expert III"
description: "Se connecter pour un total de 700 jours"
_login800:
description: "Se connecter pour un total de 800 jours"
@@ -1324,7 +1451,12 @@ _role:
description: "Description du rôle"
permission: "Rôle et autorisations"
assignTarget: "Attribuer"
+ manual: "Manuel"
+ manualRoles: "Rôles manuels"
+ conditional: "Conditionnel"
+ conditionalRoles: "Rôles conditionnels"
condition: "Condition"
+ isConditionalRole: "Ceci est un rôle conditionnel."
isPublic: "Rôle public"
options: "Options"
policies: "Stratégies"
@@ -1341,8 +1473,10 @@ _role:
_options:
canManageCustomEmojis: "Gestion des émojis personnalisés"
canManageAvatarDecorations: "Gestion des décorations d'avatar"
+ driveCapacity: "Capacité de stockage du Disque"
wordMuteMax: "Nombre maximal de caractères dans le filtre de mots"
canUseTranslator: "Usage de la fonctionnalité de traduction"
+ avatarDecorationLimit: "Nombre maximal de décorations d'avatar"
_sensitiveMediaDetection:
description: "L'apprentissage automatique peut être utilisé pour détecter automatiquement les médias sensibles à modérer. La sollicitation des serveurs augmente légèrement."
sensitivity: "Sensibilité de la détection"
@@ -1410,7 +1544,7 @@ _preferencesBackups:
nameAlreadyExists: "Le nom de sauvegarde \"{name}\" existe déjà. Veuillez spécifier un autre nom."
applyConfirm: "Voulez-vous appliquer la sauvegarde '{name}' au dispositif actuel ? La configuration actuelle de l'appareil sera perdue."
saveConfirm: "Voulez-vous écraser {name} ?"
- deleteConfirm: "Voulez-vous supprimer {name} ?"
+ deleteConfirm: "Êtes-vous sûr·e de vouloir supprimer {name} ?"
renameConfirm: "Voulez-vous remplacer \"{old}\" par \"{new}\" ?"
noBackups: "Aucune sauvegarde n'est disponible. L'option \"Nouvelle sauvegarde\" vous permet de sauvegarder la configuration actuelle du client sur le serveur."
createdAt: "Créé : {date} {time}"
@@ -1547,6 +1681,14 @@ _sfx:
notification: "Notifications"
antenna: "Réception de l’antenne"
channel: "Notifications de canal"
+ reaction: "Lors de la sélection de la réaction"
+_soundSettings:
+ driveFile: "Utiliser un effet sonore sur le Disque"
+ driveFileWarn: "Veuillez sélectionner le fichier sur le Disque"
+ driveFileTypeWarn: "Ce fichier n'est pas pris en charge"
+ driveFileTypeWarnDescription: "Veuillez sélectionner un fichier audio"
+ driveFileDurationWarn: "L'effet sonore est trop long"
+ driveFileDurationWarnDescription: "Utiliser un effet sonore long peut affecter l'utilisation de Misskey. Voulez-vous encore continuer ?"
_ago:
future: "Futur"
justNow: "à l’instant"
@@ -1558,6 +1700,14 @@ _ago:
monthsAgo: "Il y a {n} mois"
yearsAgo: "Il y a {n} ans"
invalid: "Il n'y a rien à voir ici"
+_timeIn:
+ seconds: "Dans {n}s"
+ minutes: "Dans {n}min"
+ hours: "Dans {n}h"
+ days: "Dans {n}j"
+ weeks: "Dans {n} sem."
+ months: "Dans {n} mois"
+ years: "Dans {n}a"
_time:
second: "s"
minute: "min"
@@ -1575,7 +1725,7 @@ _2fa:
securityKeyInfo: "Vous pouvez configurer l'authentification WebAuthN pour sécuriser davantage le processus de connexion grâce à une clé de sécurité matérielle qui prend en charge FIDO2, ou bien en configurant l'authentification par empreinte digitale ou par code PIN sur votre appareil."
securityKeyName: "Nom de la clé"
removeKey: "Supprimer la clé de sécurité"
- removeKeyConfirm: "Voulez-vous supprimer {name} ?"
+ removeKeyConfirm: "Êtes-vous sûr·e de vouloir supprimer {name} ?"
renewTOTPOk: "Reconfigurer"
renewTOTPCancel: "Pas maintenant"
backupCodes: "Codes de Secours"
@@ -1584,8 +1734,8 @@ _permissions:
"write:account": "Mettre à jour les informations de votre compte"
"read:blocks": "Voir les comptes bloqués"
"write:blocks": "Gérer les comptes bloqués"
- "read:drive": "Parcourir le Drive"
- "write:drive": "Écrire sur le Drive"
+ "read:drive": "Parcourir le Disque"
+ "write:drive": "Modifier le Disque"
"read:favorites": "Afficher les favoris"
"write:favorites": "Gérer les favoris"
"read:following": "Voir les informations de vos abonnements"
@@ -1605,7 +1755,7 @@ _permissions:
"read:page-likes": "Voir les mentions « J'aime » des pages"
"write:page-likes": "Gérer les mentions « J'aime » sur les pages"
"read:user-groups": "Voir les groupes d'utilisateur·rice·s"
- "write:user-groups": "Éditer les groupes des utilisateur·rice·s"
+ "write:user-groups": "Éditer les groupes d'utilisateur·rice·s"
"read:channels": "Lire les canaux"
"write:channels": "Gérer les canaux"
"read:gallery": "Voir la galerie"
@@ -1659,6 +1809,7 @@ _widgets:
userList: "Liste utilisateur"
_userList:
chooseList: "Sélectionner une liste"
+ birthdayFollowings: "Utilisateurs qui fêtent l'anniversaire aujourd'hui"
_cw:
hide: "Masquer"
show: "Afficher le contenu"
@@ -1695,6 +1846,7 @@ _visibility:
followersDescription: "Publier à vos abonné·e·s uniquement"
specified: "Direct"
specifiedDescription: "Publier uniquement aux utilisateur·rice·s mentionné·e·s"
+ disableFederation: "Défédérer"
_postForm:
replyPlaceholder: "Répondre à cette note ..."
quotePlaceholder: "Citez cette note ..."
@@ -1716,10 +1868,12 @@ _profile:
metadataDescription: "Vous pouvez afficher jusqu'à quatre informations supplémentaires dans votre profil."
metadataLabel: "Étiquette"
metadataContent: "Contenu"
- changeAvatar: "Changer l'image de profil"
+ changeAvatar: "Changer l'avatar"
changeBanner: "Changer de bannière"
+ avatarDecorationMax: "Vous pouvez mettre au plus {max} décorations d'avatar."
_exportOrImport:
allNotes: "Toutes les notes"
+ clips: "Clip"
followingList: "Abonnements"
muteList: "Comptes masqués"
blockingList: "Comptes bloqués"
@@ -1828,6 +1982,7 @@ _notification:
yourFollowRequestAccepted: "Votre demande d’abonnement a été accepté"
pollEnded: "Les résultats du sondage sont disponibles"
unreadAntennaNote: "Antenne {name}"
+ roleAssigned: "Rôle attribué"
emptyPushNotificationMessage: "Les notifications push ont été mises à jour"
achievementEarned: "Accomplissement"
testNotification: "Tester la notification"
@@ -1845,6 +2000,7 @@ _notification:
pollEnded: "Sondages se cloturant"
receiveFollowRequest: "Demande d'abonnement reçue"
followRequestAccepted: "Demande d'abonnement acceptée"
+ roleAssigned: "Rôle reçu"
achievementEarned: "Accomplissement"
app: "Notifications provenant des apps"
_actions:
@@ -1878,6 +2034,9 @@ _deck:
channel: "Canal"
mentions: "Mentions"
direct: "Direct"
+_drivecleaner:
+ orderBySizeDesc: "Taille descendante"
+ orderByCreatedAtAsc: "Date d'ajout ascendante"
_webhookSettings:
name: "Nom"
active: "Activé"
@@ -1915,6 +2074,8 @@ _moderationLogTypes:
createAvatarDecoration: "Décoration d'avatar créée"
updateAvatarDecoration: "Décoration d'avatar mise à jour"
deleteAvatarDecoration: "Décoration d'avatar supprimée"
+ unsetUserAvatar: "Supprimer l'avatar de l'utilisateur·rice"
+ unsetUserBanner: "Supprimer la bannière de l'utilisateur·rice"
_fileViewer:
title: "Détails du fichier"
type: "Type du fichier"
@@ -1964,3 +2125,19 @@ _externalResourceInstaller:
_themeInstallFailed:
title: "Échec d'installation du thème"
description: "Il y a eu un problème lors de l'installation du thème. Veuillez réessayer. Pour plus de détails sur l'erreur, veuillez consulter la console JavaScript."
+_dataSaver:
+ _media:
+ title: "Chargement des médias"
+ description: "Empêche le chargement automatique des images et des vidéos. Appuyez sur les images et les vidéos cachées pour les charger."
+ _avatar:
+ title: "Animation d'avatars"
+ description: "Arrête l'animation d'avatars. Comme les images animées peuvent être plus volumineuses que les images normales, cela permet de réduire davantage le trafic de données."
+ _urlPreview:
+ title: "Vignettes d'aperçu des URL"
+ description: "Les vignettes d'aperçu des URL ne seront plus chargées."
+ _code:
+ title: "Mise en évidence du code"
+ description: "Si la notation de mise en évidence du code est utilisée, par exemple dans la MFM, elle ne sera pas chargée tant qu'elle n'aura pas été tapée. La mise en évidence du code nécessite le chargement du fichier de définition de chaque langue à mettre en évidence, mais comme ces fichiers ne sont plus chargés automatiquement, on peut s'attendre à une réduction du trafic de données."
+_reversi:
+ total: "Total"
+
diff --git a/locales/generateDTS.js b/locales/generateDTS.js
index 7af773f3b..49807144e 100644
--- a/locales/generateDTS.js
+++ b/locales/generateDTS.js
@@ -6,68 +6,225 @@ import ts from 'typescript';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
+const parameterRegExp = /\{(\w+)\}/g;
+
+function createMemberType(item) {
+ if (typeof item !== 'string') {
+ return ts.factory.createTypeLiteralNode(createMembers(item));
+ }
+ const parameters = Array.from(
+ item.matchAll(parameterRegExp),
+ ([, parameter]) => parameter,
+ );
+ return parameters.length
+ ? ts.factory.createTypeReferenceNode(
+ ts.factory.createIdentifier('ParameterizedString'),
+ [
+ ts.factory.createUnionTypeNode(
+ parameters.map((parameter) =>
+ ts.factory.createStringLiteral(parameter),
+ ),
+ ),
+ ],
+ )
+ : ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword);
+}
function createMembers(record) {
- return Object.entries(record)
- .map(([k, v]) => ts.factory.createPropertySignature(
+ return Object.entries(record).map(([k, v]) => {
+ const node = ts.factory.createPropertySignature(
undefined,
ts.factory.createStringLiteral(k),
undefined,
- typeof v === 'string'
- ? ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword)
- : ts.factory.createTypeLiteralNode(createMembers(v)),
- ));
+ createMemberType(v),
+ );
+ if (typeof v === 'string') {
+ ts.addSyntheticLeadingComment(
+ node,
+ ts.SyntaxKind.MultiLineCommentTrivia,
+ `*
+ * ${v.replace(/\n/g, '\n * ')}
+ `,
+ true,
+ );
+ }
+ return node;
+ });
}
export default function generateDTS() {
const locale = yaml.load(fs.readFileSync(`${__dirname}/ja-JP.yml`, 'utf-8'));
const members = createMembers(locale);
const elements = [
+ ts.factory.createVariableStatement(
+ [ts.factory.createToken(ts.SyntaxKind.DeclareKeyword)],
+ ts.factory.createVariableDeclarationList(
+ [
+ ts.factory.createVariableDeclaration(
+ ts.factory.createIdentifier('kParameters'),
+ undefined,
+ ts.factory.createTypeOperatorNode(
+ ts.SyntaxKind.UniqueKeyword,
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.SymbolKeyword),
+ ),
+ undefined,
+ ),
+ ],
+ ts.NodeFlags.Const,
+ ),
+ ),
+ ts.factory.createInterfaceDeclaration(
+ [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
+ ts.factory.createIdentifier('ParameterizedString'),
+ [
+ ts.factory.createTypeParameterDeclaration(
+ undefined,
+ ts.factory.createIdentifier('T'),
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
+ ),
+ ],
+ undefined,
+ [
+ ts.factory.createPropertySignature(
+ undefined,
+ ts.factory.createComputedPropertyName(
+ ts.factory.createIdentifier('kParameters'),
+ ),
+ undefined,
+ ts.factory.createTypeReferenceNode(
+ ts.factory.createIdentifier('T'),
+ undefined,
+ ),
+ ),
+ ],
+ ),
+ ts.factory.createInterfaceDeclaration(
+ [ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
+ ts.factory.createIdentifier('ILocale'),
+ undefined,
+ undefined,
+ [
+ ts.factory.createIndexSignature(
+ undefined,
+ [
+ ts.factory.createParameterDeclaration(
+ undefined,
+ undefined,
+ ts.factory.createIdentifier('_'),
+ undefined,
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
+ undefined,
+ ),
+ ],
+ ts.factory.createUnionTypeNode([
+ ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
+ ts.factory.createTypeReferenceNode(
+ ts.factory.createIdentifier('ParameterizedString'),
+ ),
+ ts.factory.createTypeReferenceNode(
+ ts.factory.createIdentifier('ILocale'),
+ undefined,
+ ),
+ ]),
+ ),
+ ],
+ ),
ts.factory.createInterfaceDeclaration(
[ts.factory.createToken(ts.SyntaxKind.ExportKeyword)],
ts.factory.createIdentifier('Locale'),
undefined,
- undefined,
+ [
+ ts.factory.createHeritageClause(ts.SyntaxKind.ExtendsKeyword, [
+ ts.factory.createExpressionWithTypeArguments(
+ ts.factory.createIdentifier('ILocale'),
+ undefined,
+ ),
+ ]),
+ ],
members,
),
ts.factory.createVariableStatement(
[ts.factory.createToken(ts.SyntaxKind.DeclareKeyword)],
ts.factory.createVariableDeclarationList(
- [ts.factory.createVariableDeclaration(
- ts.factory.createIdentifier('locales'),
- undefined,
- ts.factory.createTypeLiteralNode([ts.factory.createIndexSignature(
+ [
+ ts.factory.createVariableDeclaration(
+ ts.factory.createIdentifier('locales'),
undefined,
- [ts.factory.createParameterDeclaration(
- undefined,
- undefined,
- ts.factory.createIdentifier('lang'),
- undefined,
- ts.factory.createKeywordTypeNode(ts.SyntaxKind.StringKeyword),
- undefined,
- )],
- ts.factory.createTypeReferenceNode(
- ts.factory.createIdentifier('Locale'),
- undefined,
- ),
- )]),
- undefined,
- )],
- ts.NodeFlags.Const | ts.NodeFlags.Ambient | ts.NodeFlags.ContextFlags,
+ ts.factory.createTypeLiteralNode([
+ ts.factory.createIndexSignature(
+ undefined,
+ [
+ ts.factory.createParameterDeclaration(
+ undefined,
+ undefined,
+ ts.factory.createIdentifier('lang'),
+ undefined,
+ ts.factory.createKeywordTypeNode(
+ ts.SyntaxKind.StringKeyword,
+ ),
+ undefined,
+ ),
+ ],
+ ts.factory.createTypeReferenceNode(
+ ts.factory.createIdentifier('Locale'),
+ undefined,
+ ),
+ ),
+ ]),
+ undefined,
+ ),
+ ],
+ ts.NodeFlags.Const,
),
),
+ ts.factory.createFunctionDeclaration(
+ [ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)],
+ undefined,
+ ts.factory.createIdentifier('build'),
+ undefined,
+ [],
+ ts.factory.createTypeReferenceNode(
+ ts.factory.createIdentifier('Locale'),
+ undefined,
+ ),
+ undefined,
+ ),
ts.factory.createExportDefault(ts.factory.createIdentifier('locales')),
];
- const printed = ts.createPrinter({
- newLine: ts.NewLineKind.LineFeed,
- }).printList(
- ts.ListFormat.MultiLine,
- ts.factory.createNodeArray(elements),
- ts.createSourceFile('index.d.ts', '', ts.ScriptTarget.ESNext, true, ts.ScriptKind.TS),
+ ts.addSyntheticLeadingComment(
+ elements[0],
+ ts.SyntaxKind.MultiLineCommentTrivia,
+ ' eslint-disable ',
+ true,
);
+ ts.addSyntheticLeadingComment(
+ elements[0],
+ ts.SyntaxKind.SingleLineCommentTrivia,
+ ' This file is generated by locales/generateDTS.js',
+ true,
+ );
+ ts.addSyntheticLeadingComment(
+ elements[0],
+ ts.SyntaxKind.SingleLineCommentTrivia,
+ ' Do not edit this file directly.',
+ true,
+ );
+ const printed = ts
+ .createPrinter({
+ newLine: ts.NewLineKind.LineFeed,
+ })
+ .printList(
+ ts.ListFormat.MultiLine,
+ ts.factory.createNodeArray(elements),
+ ts.createSourceFile(
+ 'index.d.ts',
+ '',
+ ts.ScriptTarget.ESNext,
+ true,
+ ts.ScriptKind.TS,
+ ),
+ );
- fs.writeFileSync(`${__dirname}/index.d.ts`, `/* eslint-disable */
-// This file is generated by locales/generateDTS.js
-// Do not edit this file directly.
-${printed}`, 'utf-8');
+ fs.writeFileSync(`${__dirname}/index.d.ts`, printed, 'utf-8');
}
diff --git a/locales/hr-HR.yml b/locales/hr-HR.yml
index 9cfebdd01..881aa8464 100644
--- a/locales/hr-HR.yml
+++ b/locales/hr-HR.yml
@@ -3,3 +3,4 @@ _lang_: "japanski"
ok: "OK"
gotIt: "Razumijem"
cancel: "otkazati"
+
diff --git a/locales/ht-HT.yml b/locales/ht-HT.yml
index e3595c79b..1698c9f28 100644
--- a/locales/ht-HT.yml
+++ b/locales/ht-HT.yml
@@ -16,3 +16,4 @@ _2fa:
renewTOTPCancel: "Sispann"
_widgets:
profile: "pwofil"
+
diff --git a/locales/hu-HU.yml b/locales/hu-HU.yml
index 023a91494..2f7006484 100644
--- a/locales/hu-HU.yml
+++ b/locales/hu-HU.yml
@@ -102,3 +102,4 @@ _deck:
_columns:
notifications: "Értesítések"
tl: "Idővonal"
+
diff --git a/locales/id-ID.yml b/locales/id-ID.yml
index 041c55cc2..514a2866c 100644
--- a/locales/id-ID.yml
+++ b/locales/id-ID.yml
@@ -81,7 +81,7 @@ exportRequested: "Kamu telah meminta ekspor. Ini akan memakan waktu sesaat. Sete
importRequested: "Kamu telah meminta impor. Ini akan memakan waktu sesaat."
lists: "Daftar"
noLists: "Kamu tidak memiliki daftar apapun"
-note: "Catat"
+note: "Catatan"
notes: "Catatan"
following: "Ikuti"
followers: "Pengikut"
@@ -121,10 +121,16 @@ sensitive: "Konten sensitif"
add: "Tambahkan"
reaction: "Reaksi"
reactions: "Reaksi"
-reactionSetting: "Reaksi untuk dimunculkan di bilah reaksi"
+emojiPicker: "Emoji Picker"
+pinnedEmojisForReactionSettingDescription: "Atur sematan emoji pada reaksi"
+pinnedEmojisSettingDescription: "Atur sematan emoji pada masukan emoji"
+emojiPickerDisplay: "Tampilan Emoji Picker"
+overwriteFromPinnedEmojisForReaction: "Timpa dari pengaturan reaksi"
+overwriteFromPinnedEmojis: "Timpa dari pengaturan umum"
reactionSettingDescription2: "Geser untuk memindah urutan emoji, klik untuk menghapus, tekan \"+\" untuk menambahkan"
rememberNoteVisibility: "Ingat pengaturan visibilitas catatan"
attachCancel: "Hapus lampiran"
+deleteFile: "Berkas dihapus"
markAsSensitive: "Tandai sebagai konten sensitif"
unmarkAsSensitive: "Hapus tanda konten sensitif"
enterFileName: "Masukkan nama berkas"
@@ -261,6 +267,7 @@ removed: "Telah dihapus"
removeAreYouSure: "Apakah kamu yakin ingin menghapus \"{x}\"?"
deleteAreYouSure: "Apakah kamu yakin ingin menghapus \"{x}\"?"
resetAreYouSure: "Yakin mau atur ulang?"
+areYouSure: "Apakah kamu yakin?"
saved: "Telah disimpan"
messaging: "Pesan"
upload: "Unggah"
@@ -311,6 +318,7 @@ folderName: "Nama folder"
createFolder: "Buat folder"
renameFolder: "Ubah nama folder"
deleteFolder: "Hapus folder"
+folder: "Folder"
addFile: "Tambahkan berkas"
emptyDrive: "Drive kosong"
emptyFolder: "Folder kosong"
@@ -372,6 +380,11 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Nyalakan hCaptcha"
hcaptchaSiteKey: "Site Key"
hcaptchaSecretKey: "Secret Key"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "Nyalakan mCaptcha"
+mcaptchaSiteKey: "Site key"
+mcaptchaSecretKey: "Secret Key"
+mcaptchaInstanceUrl: "URL instansi mCaptcha"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Nyalakan reCAPTCHA"
recaptchaSiteKey: "Site key"
@@ -437,7 +450,6 @@ share: "Bagikan"
notFound: "Tidak dapat ditemukan"
notFoundDescription: "Tidak ada halaman sesuai dengan URL yang ditentukan."
uploadFolder: "Lokasi unggah folder bawaan"
-cacheClear: "Bersihkan tembolok"
markAsReadAllNotifications: "Tandai semua notifikasi telah dibaca"
markAsReadAllUnreadNotes: "Tandai semua catatan telah dibaca"
markAsReadAllTalkMessages: "Tandai semua pesan telah dibaca"
@@ -544,6 +556,8 @@ showInPage: "Tampilkan di halaman"
popout: "Pop-out"
volume: "Volume"
masterVolume: "Master volume"
+notUseSound: "Tidak ada keluaran suara"
+useSoundOnlyWhenActive: "Hanya keluarkan suara jika Misskey sedang aktif"
details: "Selengkapnya"
chooseEmoji: "Pilih emoji"
unableToProcess: "Operasi tersebut tidak dapat diselesaikan."
@@ -564,6 +578,10 @@ output: "Keluaran"
script: "Script"
disablePagesScript: "Nonaktifkan script pada halaman"
updateRemoteUser: "Perbaharui informasi pengguna instansi luar"
+unsetUserAvatar: "Hapus avatar"
+unsetUserAvatarConfirm: "Apakah kamu yakin ingin menghapus avatar?"
+unsetUserBanner: "Hapus banner"
+unsetUserBannerConfirm: "Apakah kamu yakin ingin menghapus banner?"
deleteAllFiles: "Hapus semua berkas"
deleteAllFilesConfirm: "Apakah kamu yakin ingin menghapus semua berkas?"
removeAllFollowing: "Batalkan mengikuti semua pengguna"
@@ -614,6 +632,7 @@ medium: "Sedang"
small: "Kecil"
generateAccessToken: "Buat token akses"
permission: "Izin"
+adminPermission: "Wewenang Izin Admin"
enableAll: "Aktifkan semua"
disableAll: "Nonaktifkan semua"
tokenRequested: "Berikan ijin akses ke akun"
@@ -635,6 +654,7 @@ smtpSecure: "Gunakan SSL/TLS implisit untuk koneksi SMTP"
smtpSecureInfo: "Matikan ini ketika menggunakan STARTTLS"
testEmail: "Tes pengiriman surel"
wordMute: "Bisukan kata"
+hardWordMute: "Pembisuan kata keras"
regexpError: "Kesalahan ekspresi reguler"
regexpErrorDescription: "Galat terjadi pada baris {line} ekspresi reguler dari {tab} kata yang dibisukan:"
instanceMute: "Bisukan instansi"
@@ -656,6 +676,7 @@ useGlobalSettingDesc: "Jika dinyalakan, setelan notifikasi akun kamu akan diguna
other: "Lainnya"
regenerateLoginToken: "Perbarui token login"
regenerateLoginTokenDescription: "Perbarui token yang digunakan secara internal saat login. Normalnya aksi ini tidak diperlukan. Jika diperbarui, semua perangkat akan dilogout."
+theKeywordWhenSearchingForCustomEmoji: "Kata kunci ini digunakan untuk mencari emoji kustom yang dicari."
setMultipleBySeparatingWithSpace: "Kamu dapat menyetel banyak dengan memisahkannya menggunakan spasi."
fileIdOrUrl: "File-ID atau URL"
behavior: "Perilaku"
@@ -868,8 +889,8 @@ makeReactionsPublicDescription: "Pengaturan ini akan membuat daftar dari semua r
classic: "Klasik"
muteThread: "Bisukan thread"
unmuteThread: "Suarakan thread"
-ffVisibility: "Visibilitas Mengikuti/Pengikut"
-ffVisibilityDescription: "Mengatur siapa yang dapat melihat pengikutmu dan yang kamu ikuti."
+followingVisibility: "Visibilitas mengikuti"
+followersVisibility: "Visibilitas pengikut"
continueThread: "Lihat lanjutan thread"
deleteAccountConfirm: "Akun akan dihapus. Apakah kamu yakin?"
incorrectPassword: "Kata sandi salah."
@@ -979,6 +1000,7 @@ assign: "Tetapkan\n"
unassign: "Batalkan penetapan"
color: "Warna"
manageCustomEmojis: "Kelola Emoji Kustom"
+manageAvatarDecorations: "Kelola dekorasi avatar"
youCannotCreateAnymore: "Kamu melewati batas pembuatan."
cannotPerformTemporary: "Sementara Tidak Tersedia"
cannotPerformTemporaryDescription: "Aksi ini tidak dapat dilakukan sementara karena melewati batas eksekusi. Mohon tunggu sejenak dan coba lagi."
@@ -1019,6 +1041,10 @@ resetPasswordConfirm: "Yakin untuk mereset kata sandimu?"
sensitiveWords: "Kata sensitif"
sensitiveWordsDescription: "Visibilitas dari semua catatan mengandung kata yang telah diatur akan dijadikan \"Beranda\" secara otomatis. Kamu dapat mendaftarkan kata tersebut lebih dari satu dengan menuliskannya di baris baru."
sensitiveWordsDescription2: "Menggunakan spasi akan membuat ekspresi AND dan kata kunci disekitarnya dengan garis miring akan mengubahnya menjadi ekspresi reguler."
+prohibitedWords: "Kata yang dilarang"
+prohibitedWordsDescription2: "Menggunakan spasi akan membuat ekspresi AND dan kata kunci disekitarnya dengan garis miring akan mengubahnya menjadi ekspresi reguler."
+hiddenTags: "Tagar tersembunyi"
+hiddenTagsDescription: "Pilih tanda yang mana akan tidak diperlihatkan dalam daftar tren.\nTanda lebih dari satu dapat didaftarkan dengan tiap baris."
notesSearchNotAvailable: "Pencarian catatan tidak tersedia."
license: "Lisensi"
unfavoriteConfirm: "Yakin ingin menghapusnya dari favorit?"
@@ -1031,9 +1057,12 @@ enableChartsForRemoteUser: "Buat bagan data pengguna instansi luar"
enableChartsForFederatedInstances: "Buat bagan data peladen instansi luar"
showClipButtonInNoteFooter: "Tambahkan \"Klip\" ke menu aksi catatan"
reactionsDisplaySize: "Ukuran tampilan reaksi"
+limitWidthOfReaction: "Batasi lebar maksimum reaksi dan tampilkan dalam ukuran terbatasi."
noteIdOrUrl: "ID catatan atau URL"
video: "Video"
videos: "Video"
+audio: "Suara"
+audioFiles: "Berkas Suara"
dataSaver: "Penghemat data"
accountMigration: "Pemindahan akun"
accountMoved: "Pengguna ini telah berpindah ke akun baru:"
@@ -1132,14 +1161,59 @@ mutualFollow: "Saling mengikuti"
fileAttachedOnly: "Hanya catatan dengan berkas"
showRepliesToOthersInTimeline: "Tampilkan balasan ke pengguna lain dalam lini masa"
hideRepliesToOthersInTimeline: "Sembunyikan balasan ke orang lain dari lini masa"
+showRepliesToOthersInTimelineAll: "Tampilkan balasan ke lainnya dari semua orang yang kamu ikuti di lini masa"
+hideRepliesToOthersInTimelineAll: "Sembuyikan balasan ke lainnya dari semua orang yang kamu ikuti di lini masa"
+confirmShowRepliesAll: "Operasi ini tidak dapat diubah. Apakah kamu yakin untuk menampilkan balasan ke lainnya dari semua orang yang kamu ikuti di lini masa?"
+confirmHideRepliesAll: "Operasi ini tidak dapat diubah. Apakah kamu yakin untuk menyembunyikan balasan ke lainnya dari semua orang yang kamu ikuti di lini masa?"
externalServices: "Layanan eksternal"
+sourceCode: "Sumber kode"
impressum: "Impressum"
impressumUrl: "Tautan Impressum"
impressumDescription: "Pada beberapa negara seperti Jerman, inklusi dari informasi kontak operator (sebuah Impressum) diperlukan secara legal untuk situs web komersil."
privacyPolicy: "Kebijakan Privasi"
privacyPolicyUrl: "Tautan Kebijakan Privasi"
tosAndPrivacyPolicy: "Syarat dan Ketentuan serta Kebijakan Privasi"
+avatarDecorations: "Dekorasi avatar"
+attach: "Lampirkan"
+detach: "Hapus"
+detachAll: "Lepas Semua"
+angle: "Sudut"
flip: "Balik"
+showAvatarDecorations: "Tampilkan dekorasi avatar"
+releaseToRefresh: "Lepaskan untuk memuat ulang"
+refreshing: "Sedang memuat ulang..."
+pullDownToRefresh: "Tarik ke bawah untuk memuat ulang"
+disableStreamingTimeline: "Nonaktifkan pembaharuan lini masa real-time"
+useGroupedNotifications: "Tampilkan notifikasi secara dikelompokkan"
+signupPendingError: "Terdapat masalah ketika memverifikasi alamat surel. Tautan kemungkinan telah kedaluwarsa."
+cwNotationRequired: "Jika \"Sembunyikan konten\" diaktifkan, deskripsi harus disediakan."
+doReaction: "Tambahkan reaksi"
+code: "Kode"
+reloadRequiredToApplySettings: "Muat ulang diperlukan untuk menerapkan pengaturan."
+remainingN: "Sisa : {n}"
+overwriteContentConfirm: "Apakah kamu yakin untuk menimpa konten saat ini?"
+seasonalScreenEffect: "Efek layar musiman"
+decorate: "Dekor"
+addMfmFunction: "Tambahkan dekorasi"
+enableQuickAddMfmFunction: "Tampilkan pemilih MFM tingkat lanjut"
+bubbleGame: "Bubble Game"
+sfx: "Efek Suara"
+soundWillBePlayed: "Suara yang akan dimainkan"
+showReplay: "Lihat tayangan ulang"
+replay: "Tayangan ulang"
+replaying: "Menayangkan Ulang"
+ranking: "Peringkat"
+lastNDays: "{n} hari terakhir"
+backToTitle: "Ke Judul"
+hemisphere: "Letak kamu tinggal"
+withSensitive: "Lampirkan catatan dengan berkas sensitif"
+userSaysSomethingSensitive: "Postingan oleh {name} mengandung konten sensitif"
+enableHorizontalSwipe: "Geser untuk mengganti tab"
+surrender: "Batalkan"
+_bubbleGame:
+ howToPlay: "Cara bermain"
+ _howToPlay:
+ section1: "Atur posisi dan jatuhkan obyek ke dalam kotak."
_announcement:
forExistingUsers: "Hanya pengguna yang telah ada"
forExistingUsersDescription: "Pengumuman ini akan dimunculkan ke pengguna yang sudah ada dari titik waktu publikasi jika dinyalakan. Apabila dimatikan, mereka yang baru mendaftar setelah publikasi ini akan juga melihatnya."
@@ -1149,6 +1223,10 @@ _announcement:
tooManyActiveAnnouncementDescription: "Terlalu banyak pengumuman dapat memperburuk pengalaman pengguna. Mohon pertimbangkan untuk mengarsipkan pengumuman yang sudah usang/tidak relevan."
readConfirmTitle: "Tandai telah dibaca?"
readConfirmText: "Aksi ini akan menandai konten dari \"{title}\" telah dibaca."
+ shouldNotBeUsedToPresentPermanentInfo: "Karena dapat berdampak pada pengalaman pengguna untuk pengguna baru, sangat direkomendasikan untuk menggunakan notifikasi secara mengalir daripada tetap."
+ dialogAnnouncementUxWarn: "Memiliki dua atau lebih gaya dialog notifikasi secara bersamaan dapat berdampak signifikan pada pengalaman pengguna, mohon untuk menggunakannya dengan hati-hati."
+ silence: "Tiada notifikasi"
+ silenceDescription: "Apabila diaktifkan, notifikasi dari pengumuman ini akan dilewatkan dan pengguna tidak perlu membacanya."
_initialAccountSetting:
accountCreated: "Akun kamu telah sukses dibuat!"
letsStartAccountSetup: "Untuk pemula, ayo atur profilmu dulu."
@@ -1161,8 +1239,44 @@ _initialAccountSetting:
pushNotificationDescription: "Menyalakan notifikasi dorong akan membuatmu menerima notifikasi dari {name} secara langsung ke perangkatmu."
initialAccountSettingCompleted: "Pengaturan profil selesai!"
haveFun: "Selamat menikmati, {name}!"
+ youCanContinueTutorial: "Kamu dapat menjutkan ke tutorial dalam bagaimana menggunakan {name} (Misskey) atau kamu dapat keluar dari pemasangan ini dan langsung menggunakannya segera."
+ startTutorial: "Mulai Tutorial"
skipAreYouSure: "Yakin melewati atur profil?"
laterAreYouSure: "Yakin banget untuk atur profil nanti?"
+_initialTutorial:
+ launchTutorial: "Lihat Tutorial"
+ title: "Tutorial"
+ wellDone: "Kerja bagus!"
+ skipAreYouSure: "Berhenti dari Tutorial?"
+ _landing:
+ title: "Selamat datang di Tutorial"
+ description: "Di sini kamu dapat mempelajari dasar-dasar dari penggunaan Misskey dan fitur-fiturnya."
+ _note:
+ title: "Apa itu Catatan?"
+ description: "Postingan di Misskey disebut sebagai 'Catatan'. Catatan ditampilkan secara kronologis pada lini masa dan dimutakhirkan secara real-time."
+ reply: "Klik pada tombol ini untuk membalas ke sebuah pesan. Bisa juga untuk membalas ke sebuah balasan dan melanjutkannya seperti percakapan selayaknya utas."
+ renote: "Kamu dapat membagikan catatan ke lini masa milikmu. Kamu juga dapat mengutipnya dengan komentarmu."
+ reaction: "Kamu dapat menambahkan reaksi ke Catatan. Detil lebih lanjut akan dijelaskan di halaman berikutnya."
+ _reaction:
+ title: "Apa itu Reaksi?"
+ _timeline:
+ title: "Konsep Lini Masa"
+ _postNote:
+ title: "Pengaturan posting Catatan"
+ _visibility:
+ public: "Perlihatkan catatan ke semua pengguna."
+ home: "Hanya publik ke lini masa Beranda. Pengguna yang mengunjungi profilmu melalui pengikut dan renote dapat melihatnya."
+ followers: "Perlihatkan ke pengikut saja. Hanya pengikut yang dapat melihat postinganmu dan tidak dapat direnote oleh siapapun."
+ direct: "Hanya perlihatkan ke pengguna spesifik dan penerima akan diberi tahu. Dapat juga digunakan sebagai alternatif dari pesan langsung."
+ _cw:
+ title: "Peringatan Konten (CW)"
+ _exampleNote:
+ cw: "Peringatan: Bikin Lapar!"
+ note: "Baru aja makan donat berlapis coklat 🍩😋"
+ _howToMakeAttachmentsSensitive:
+ title: "Bagaimana menandai lampiran sebagai sensitif?"
+ _done:
+ title: "Kamu telah menyelesaikan tutorial! 🎉"
_serverRules:
description: "Daftar peraturan akan ditampilkan sebelum pendaftaran. Mengatur ringkasan dari Syarat dan Ketentuan sangat direkomendasikan."
_serverSettings:
@@ -1474,6 +1588,7 @@ _role:
inviteLimitCycle: "Interval Penerbitan Kode Undangan"
inviteExpirationTime: "Interval kedaluwarsa undangan"
canManageCustomEmojis: "Dapat mengelola Emoji kustom"
+ canManageAvatarDecorations: "Kelola dekorasi avatar"
driveCapacity: "Kapasitas Drive"
alwaysMarkNsfw: "Selalu tandai berkas sebagai NSFW"
pinMax: "Jumlah maksimal catatan yang disematkan"
@@ -1708,6 +1823,14 @@ _sfx:
notification: "Notifikasi"
antenna: "Penerimaan Antenna"
channel: "Notifikasi Kanal"
+ reaction: "Ketika memilih reaksi"
+_soundSettings:
+ driveFile: "Menggunakan berkas audio dalam Drive"
+ driveFileWarn: "Pilih berkas audio dari Drive"
+ driveFileTypeWarn: "Berkas ini tidak didukung"
+ driveFileTypeWarnDescription: "Pilih berkas audio"
+ driveFileDurationWarn: "Audio ini terlalu panjang"
+ driveFileDurationWarnDescription: "Audio panjang dapat mengganggu penggunaan Misskey. Masih ingin melanjutkan?"
_ago:
future: "Masa depan"
justNow: "Baru saja"
@@ -1719,6 +1842,14 @@ _ago:
monthsAgo: "{n} bulan lalu"
yearsAgo: "{n} tahun lalu"
invalid: "Tidak ada sama sekali disini"
+_timeIn:
+ seconds: "dalam {n} detik"
+ minutes: "dalam {n} menit"
+ hours: "dalam {n} jam"
+ days: "dalam {n} hari"
+ weeks: "dalam {n} minggu"
+ months: "dalam {n} bulan"
+ years: "dalam {n} tahun"
_time:
second: "detik"
minute: "menit"
@@ -1790,6 +1921,55 @@ _permissions:
"write:flash": "Sunting Play"
"read:flash-likes": "Lihat daftar Play yang disukai"
"write:flash-likes": "Sunting daftar Play yang disukai"
+ "read:admin:abuse-user-reports": "Lihat laporan pengguna"
+ "write:admin:delete-account": "Hapus akun pengguna"
+ "write:admin:delete-all-files-of-a-user": "Hapus semua berkas dari seorang pengguna"
+ "read:admin:index-stats": "Lihat statistik indeks basis data"
+ "read:admin:table-stats": "Lihat statistik tabel basis data"
+ "read:admin:user-ips": "Lihat alamat IP pengguna"
+ "read:admin:meta": "Lihat metadata instansi"
+ "write:admin:reset-password": "Atur ulang kata sandi pengguna"
+ "write:admin:resolve-abuse-user-report": "Selesaikan laporan pengguna"
+ "write:admin:send-email": "Mengirim surel"
+ "read:admin:server-info": "Lihat informasi peladen"
+ "read:admin:show-moderation-log": "Lihat log moderasi"
+ "read:admin:show-user": "Lihat informasi pengguna privat"
+ "read:admin:show-users": "Lihat informasi pengguna privat"
+ "write:admin:suspend-user": "Tangguhkan pengguna"
+ "write:admin:unset-user-avatar": "Hapus avatar pengguna"
+ "write:admin:unset-user-banner": "Hapus banner pengguna"
+ "write:admin:unsuspend-user": "Batalkan penangguhan pengguna"
+ "write:admin:meta": "Kelola metadata instansi"
+ "write:admin:user-note": "Kelola moderasi catatan"
+ "write:admin:roles": "Kelola peran"
+ "read:admin:roles": "Lihat peran"
+ "write:admin:relays": "Kelola relay"
+ "read:admin:relays": "Lihat relay"
+ "write:admin:invite-codes": "Kelola kode undangan"
+ "read:admin:invite-codes": "Lihat kode undangan"
+ "write:admin:announcements": "Kelola pengumuman"
+ "read:admin:announcements": "Lihat Pengumuman"
+ "write:admin:avatar-decorations": "Kelola dekorasi avatar"
+ "read:admin:avatar-decorations": "Lihat dekorasi avatar"
+ "write:admin:federation": "Kelola data federasi"
+ "write:admin:account": "Kelola akun pengguna"
+ "read:admin:account": "Lihat akun pengguna"
+ "write:admin:emoji": "Kelola emoji"
+ "read:admin:emoji": "Lihat emoji"
+ "write:admin:queue": "Kelola antrian kerja"
+ "read:admin:queue": "Lihat informasi antrian kerja"
+ "write:admin:promo": "Kelola catatan promosi"
+ "write:admin:drive": "Kelola drive pengguna"
+ "read:admin:drive": "Kelola informasi drive pengguna"
+ "read:admin:stream": "Gunakan API WebSocket untuk Admin"
+ "write:admin:ad": "Kelola iklan"
+ "read:admin:ad": "Lihat iklan"
+ "write:invite-codes": "Membuat kode undangan"
+ "read:invite-codes": "Mendapatkan kode undangan"
+ "write:clip-favorite": "Kelola klip yang difavoritkan"
+ "read:clip-favorite": "Lihat klip yang difavoritkan"
+ "read:federation": "Mendapatkan data federasi"
+ "write:report-abuse": "Melaporkan pelanggaran"
_auth:
shareAccessTitle: "Mendapatkan ijin akses aplikasi"
shareAccess: "Apakah kamu ingin mengijinkan \"{name}\" untuk mengakses akun ini?"
@@ -1844,6 +2024,7 @@ _widgets:
_userList:
chooseList: "Pilih daftar"
clicker: "Pengeklik"
+ birthdayFollowings: "Pengguna yang merayakan hari ulang tahunnya hari ini"
_cw:
hide: "Sembunyikan"
show: "Lihat konten"
@@ -1906,9 +2087,11 @@ _profile:
changeAvatar: "Ubah avatar"
changeBanner: "Ubah header"
verifiedLinkDescription: "Dengan memasukkan URL yang mengandung tautan ke profil kamu di sini, ikon verifikasi kepemilikan dapat ditampilkan di sebelah kolom ini."
+ avatarDecorationMax: "Dapat ditambahkan hingga {max} dekorasi."
_exportOrImport:
allNotes: "Semua catatan"
favoritedNotes: "Catatan favorit"
+ clips: "Klip"
followingList: "Ikuti"
muteList: "Bisukan"
blockingList: "Blokir"
@@ -2027,12 +2210,16 @@ _notification:
pollEnded: "Hasil Kuesioner telah keluar"
newNote: "Catatan baru"
unreadAntennaNote: "Antena {name}"
+ roleAssigned: "Peran Diberikan"
emptyPushNotificationMessage: "Pembaruan notifikasi dorong"
achievementEarned: "Pencapaian didapatkan"
testNotification: "Tes notifikasi"
checkNotificationBehavior: "Cek tampilan notifikasi"
sendTestNotification: "Kirim tes notifikasi"
notificationWillBeDisplayedLikeThis: "Notifikasi akan terlihat seperti ini"
+ reactedBySomeUsers: "{n} orang memberikan reaksi"
+ renotedBySomeUsers: "{n} orang telah merenote"
+ followedBySomeUsers: "{n} orang telah mengikuti"
_types:
all: "Semua"
note: "Catatan baru"
@@ -2045,6 +2232,7 @@ _notification:
pollEnded: "Jajak pendapat berakhir"
receiveFollowRequest: "Permintaan mengikuti diterima"
followRequestAccepted: "Permintaan mengikuti disetujui"
+ roleAssigned: "Peran Diberikan"
achievementEarned: "Pencapaian didapatkan"
app: "Notifikasi dari aplikasi tertaut"
_actions:
@@ -2136,6 +2324,11 @@ _moderationLogTypes:
createAd: "Iklan telah dibuat"
deleteAd: "Iklan telah dihapus"
updateAd: "Iklan telah diperbaharui"
+ createAvatarDecoration: "Buat dekorasi avatar"
+ updateAvatarDecoration: "Perbarui dekorasi avatar"
+ deleteAvatarDecoration: "Hapus dekorasi avatar"
+ unsetUserAvatar: "Hapus avatar pengguna"
+ unsetUserBanner: "Hapus banner pengguna"
_fileViewer:
title: "Rincian berkas"
type: "Jenis berkas"
@@ -2144,3 +2337,95 @@ _fileViewer:
uploadedAt: "Diunggah pada"
attachedNotes: "Catatan yang dilampirkan"
thisPageCanBeSeenFromTheAuthor: "Halaman ini hanya dapat dilihat oleh pengguna yang mengunggah bekas ini."
+_externalResourceInstaller:
+ title: "Pasang dari situs eksternal"
+ checkVendorBeforeInstall: "Pastikan sumber dari sumber daya ini terpercaya sebelum melakukan pemasangan."
+ _plugin:
+ title: "Apakah kamu ingin memasang plugin ini?"
+ metaTitle: "Informasi plugin"
+ _theme:
+ title: "Apakah kamu ingin memasang tema ini?"
+ metaTitle: "Informasi tema"
+ _meta:
+ base: "Skema warna dasar"
+ _vendorInfo:
+ title: "Informasi sumber"
+ endpoint: "Referensi Endpoint"
+ hashVerify: "Verifikasi hash"
+ _errors:
+ _invalidParams:
+ title: "Parameter tidak valid"
+ description: "Tidak cukup informasi untuk memuat data dari situs eksternal. Mohon konfirmasi kembali URL yang dimasukkan."
+ _resourceTypeNotSupported:
+ title: "Sumber daya eksternal ini tidak didukung"
+ description: "Tipe sumber daya eksternal ini tidak didukung. Mohon kontak administrator dari situs tersebut."
+ _failedToFetch:
+ title: "Gagal memuat data"
+ fetchErrorDescription: "Kesalahan terjadi ketika menghubungkan dengan situs eksternal. Jika percobaan kembali tidak dapat memperbaiki masalah ini, mohon hubungi administrator dari situs tersebut."
+ parseErrorDescription: "Kesalahan terjadi dalam memproses data yang dimuat dari situs eksternal. Mohon hubungi administrator dari situs tersebut."
+ _hashUnmatched:
+ title: "Verifikasi data gagal"
+ description: "Kesalahan terjadi dalam memverifikasi integritas data yang diambil. Sebagai pencegahan keamanan, pemasangan tidak dapat dilanjutkan. Mohon hubungi administrator dari situs tersebut."
+ _pluginParseFailed:
+ title: "Kesalahan AiScript"
+ description: "Data yang diminta telah diambil dengan sukses, namun kesalahan terjadi ketika AiScript melakukan parsing. Mohon hubungi pembuat plugin. Detil kesalahan dapat dilihat pada konsol Javascript."
+ _pluginInstallFailed:
+ title: "Pemasangan plugin gagal"
+ description: "Kesalahan terjadi ketika pemasangan plugin. Mohon coba lagi. Detil kesalahan dapat dilihat pada konsol Javascript."
+ _themeParseFailed:
+ title: "Parsing tema gagal"
+ description: "Data yang diminta telah diambil dengan sukses, namun kesalahan terjadi ketika tema melakukan parsing. Mohon hubungi pembuat tema. Detil kesalahan dapat dilihat pada konsol Javascript."
+ _themeInstallFailed:
+ title: "Pemasangan tema gagal"
+ description: "Kesalahan terjadi ketika pemasangan tema. Mohon coba lagi. Detil kesalahan dapat dilihat pada konsol Javascript."
+_dataSaver:
+ _media:
+ title: "Memuat media"
+ description: "Mencegah gambar/video dimuat secara otomatis. Menyembunyikan gambar/video dan akan dimuat ketika diketuk."
+ _avatar:
+ title: "Gambar avatar"
+ description: "Hentikan animasi gambar avatar. Gambar animasi dapat berukuran lebih besar dari gambar biasa, berpotensi pada pengurangan lalu lintas data lebih jauh."
+ _urlPreview:
+ title: "Gambar kecil URL pratinjau"
+ description: "Gambar kecil URL pratinjau tidak akan dimuat lagi."
+ _code:
+ title: "Penyorotan kode"
+ description: "Jika notasi penyorotan kode digunakan di MFM, dll. Fungsi tersebut tidak akan dimuat apabila tidak diketuk. Penyorotan sintaks membutuhkan pengunduhan berkas definisi penyorotan untuk setiap bahasa pemrograman. Oleh sebab itu, menonaktifkan pemuatan otomatis dari berkas ini dilakukan untuk mengurangi jumlah komunikasi data."
+_hemisphere:
+ N: "Bumi belahan utara"
+ S: "Bumi belahan selatan"
+ caption: "Digunakan dalam beberapa pengaturan klien untuk menentukan musim."
+_reversi:
+ reversi: "Reversi"
+ gameSettings: "Pengaturan permainan"
+ chooseBoard: "Pilih papan"
+ blackOrWhite: "Hitam/Putih"
+ blackIs: "{name} bermain sebagai Hitam"
+ rules: "Aturan"
+ thisGameIsStartedSoon: "Permainan akan segera dimulai"
+ waitingForOther: "Menunggu langkah giliran dari lawan"
+ waitingForMe: "Menungguh langkah giliran dari kamu"
+ waitingBoth: "Bersiap"
+ ready: "Siap"
+ cancelReady: "Belum siap"
+ opponentTurn: "Giliran lawan"
+ myTurn: "Giliran kamu"
+ turnOf: "Giliran {name}"
+ pastTurnOf: "Giliran {name}"
+ surrender: "Menyerah"
+ surrendered: "Telah menyerah"
+ timeout: "Waktu habis"
+ drawn: "Seri"
+ won: "{name} menang"
+ black: "Hitam"
+ white: "Putih"
+ total: "Jumlah"
+ turnCount: "Langkah ke {count}"
+ myGames: "Rondeku"
+ allGames: "Semua ronde"
+ ended: "Selesai"
+ playing: "Sedang bermain"
+ isLlotheo: "Pemain dengan batu yang sedikit menang (Llotheo)"
+ loopedMap: "Peta melingkar"
+ canPutEverywhere: "Keping dapat ditaruh dimana saja"
+
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 39fbb5779..80d6334e2 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -1,2491 +1,10028 @@
/* eslint-disable */
// This file is generated by locales/generateDTS.js
// Do not edit this file directly.
-export interface Locale {
+declare const kParameters: unique symbol;
+export interface ParameterizedString {
+ [kParameters]: T;
+}
+export interface ILocale {
+ [_: string]: string | ParameterizedString | ILocale;
+}
+export interface Locale extends ILocale {
+ /**
+ * 日本語
+ */
"_lang_": string;
+ /**
+ * ノートでつながるネットワーク
+ */
"headlineMisskey": string;
+ /**
+ * ようこそ!Misskeyは、オープンソースの分散型マイクロブログサービスです。
+ * 「ノート」を作成して、いま起こっていることを共有したり、あなたについて皆に発信しよう📡
+ * 「リアクション」機能で、皆のノートに素早く反応を追加することもできます👍
+ * 新しい世界を探検しよう🚀
+ */
"introMisskey": string;
- "poweredByMisskeyDescription": string;
- "monthAndDay": string;
+ /**
+ * {name}は、オープンソースのプラットフォームMisskeyのサーバーのひとつです。
+ */
+ "poweredByMisskeyDescription": ParameterizedString<"name">;
+ /**
+ * {month}月 {day}日
+ */
+ "monthAndDay": ParameterizedString<"month" | "day">;
+ /**
+ * 検索
+ */
"search": string;
+ /**
+ * 通知
+ */
"notifications": string;
+ /**
+ * ユーザー名
+ */
"username": string;
+ /**
+ * パスワード
+ */
"password": string;
+ /**
+ * パスワードを忘れた
+ */
"forgotPassword": string;
+ /**
+ * 連合に照会中
+ */
"fetchingAsApObject": string;
+ /**
+ * OK
+ */
"ok": string;
+ /**
+ * わかった
+ */
"gotIt": string;
+ /**
+ * キャンセル
+ */
"cancel": string;
+ /**
+ * やめておく
+ */
"noThankYou": string;
+ /**
+ * ユーザー名を入力
+ */
"enterUsername": string;
- "renotedBy": string;
+ /**
+ * {user}がリノート
+ */
+ "renotedBy": ParameterizedString<"user">;
+ /**
+ * ノートはありません
+ */
"noNotes": string;
+ /**
+ * 通知はありません
+ */
"noNotifications": string;
+ /**
+ * サーバー
+ */
"instance": string;
+ /**
+ * 設定
+ */
"settings": string;
+ /**
+ * 通知の設定
+ */
"notificationSettings": string;
+ /**
+ * 基本設定
+ */
"basicSettings": string;
+ /**
+ * その他の設定
+ */
"otherSettings": string;
+ /**
+ * ウィンドウで開く
+ */
"openInWindow": string;
+ /**
+ * プロフィール
+ */
"profile": string;
+ /**
+ * タイムライン
+ */
"timeline": string;
+ /**
+ * 自己紹介はありません
+ */
"noAccountDescription": string;
+ /**
+ * ログイン
+ */
"login": string;
+ /**
+ * ログイン中
+ */
"loggingIn": string;
+ /**
+ * ログアウト
+ */
"logout": string;
+ /**
+ * 新規登録
+ */
"signup": string;
+ /**
+ * アップロード中
+ */
"uploading": string;
+ /**
+ * 保存
+ */
"save": string;
+ /**
+ * ユーザー
+ */
"users": string;
+ /**
+ * ユーザーを追加
+ */
"addUser": string;
+ /**
+ * お気に入り
+ */
"favorite": string;
+ /**
+ * お気に入り
+ */
"favorites": string;
+ /**
+ * お気に入り解除
+ */
"unfavorite": string;
+ /**
+ * お気に入りに登録しました。
+ */
"favorited": string;
+ /**
+ * 既にお気に入りに登録されています。
+ */
"alreadyFavorited": string;
+ /**
+ * お気に入りに登録できませんでした。
+ */
"cantFavorite": string;
+ /**
+ * ピン留め
+ */
"pin": string;
+ /**
+ * ピン留め解除
+ */
"unpin": string;
+ /**
+ * 内容をコピー
+ */
"copyContent": string;
+ /**
+ * リンクをコピー
+ */
"copyLink": string;
+ /**
+ * リノートのリンクをコピー
+ */
"copyLinkRenote": string;
+ /**
+ * 削除
+ */
"delete": string;
+ /**
+ * 削除して編集
+ */
"deleteAndEdit": string;
+ /**
+ * このノートを削除してもう一度編集しますか?このノートへのリアクション、リノート、返信も全て削除されます。
+ */
"deleteAndEditConfirm": string;
+ /**
+ * リストに追加
+ */
"addToList": string;
+ /**
+ * アンテナに追加
+ */
"addToAntenna": string;
+ /**
+ * メッセージを送信
+ */
"sendMessage": string;
+ /**
+ * RSSをコピー
+ */
"copyRSS": string;
+ /**
+ * ユーザー名をコピー
+ */
"copyUsername": string;
+ /**
+ * ユーザーIDをコピー
+ */
"copyUserId": string;
+ /**
+ * ノートIDをコピー
+ */
"copyNoteId": string;
+ /**
+ * ファイルIDをコピー
+ */
"copyFileId": string;
+ /**
+ * フォルダーIDをコピー
+ */
"copyFolderId": string;
+ /**
+ * プロフィールURLをコピー
+ */
"copyProfileUrl": string;
+ /**
+ * ユーザーを検索
+ */
"searchUser": string;
+ /**
+ * 返信
+ */
"reply": string;
+ /**
+ * もっと見る
+ */
"loadMore": string;
+ /**
+ * もっと見る
+ */
"showMore": string;
+ /**
+ * 閉じる
+ */
"showLess": string;
+ /**
+ * フォローされました
+ */
"youGotNewFollower": string;
+ /**
+ * フォローリクエストされました
+ */
"receiveFollowRequest": string;
+ /**
+ * フォローが承認されました
+ */
"followRequestAccepted": string;
+ /**
+ * メンション
+ */
"mention": string;
+ /**
+ * あなた宛て
+ */
"mentions": string;
+ /**
+ * ダイレクト投稿
+ */
"directNotes": string;
+ /**
+ * インポートとエクスポート
+ */
"importAndExport": string;
+ /**
+ * インポート
+ */
"import": string;
+ /**
+ * エクスポート
+ */
"export": string;
+ /**
+ * ファイル
+ */
"files": string;
+ /**
+ * ダウンロード
+ */
"download": string;
- "driveFileDeleteConfirm": string;
- "unfollowConfirm": string;
+ /**
+ * ファイル「{name}」を削除しますか?このファイルを使用した一部のコンテンツも削除されます。
+ */
+ "driveFileDeleteConfirm": ParameterizedString<"name">;
+ /**
+ * {name}のフォローを解除しますか?
+ */
+ "unfollowConfirm": ParameterizedString<"name">;
+ /**
+ * エクスポートをリクエストしました。これには時間がかかる場合があります。エクスポートが終わると、「ドライブ」に追加されます。
+ */
"exportRequested": string;
+ /**
+ * インポートをリクエストしました。これには時間がかかる場合があります。
+ */
"importRequested": string;
+ /**
+ * リスト
+ */
"lists": string;
+ /**
+ * リストはありません
+ */
"noLists": string;
+ /**
+ * ノート
+ */
"note": string;
+ /**
+ * ノート
+ */
"notes": string;
+ /**
+ * フォロー
+ */
"following": string;
+ /**
+ * フォロワー
+ */
"followers": string;
+ /**
+ * フォローされています
+ */
"followsYou": string;
+ /**
+ * リスト作成
+ */
"createList": string;
+ /**
+ * リストの管理
+ */
"manageLists": string;
+ /**
+ * エラー
+ */
"error": string;
+ /**
+ * 問題が発生しました
+ */
"somethingHappened": string;
+ /**
+ * 再試行
+ */
"retry": string;
+ /**
+ * ページの読み込みに失敗しました。
+ */
"pageLoadError": string;
+ /**
+ * これは通常、ネットワークまたはブラウザキャッシュが原因です。キャッシュをクリアするか、しばらく待ってから再度試してください。
+ */
"pageLoadErrorDescription": string;
+ /**
+ * サーバーの応答がありません。しばらく待ってから再度試してください。
+ */
"serverIsDead": string;
+ /**
+ * このページを表示するためには、リロードして新しいバージョンのクライアントをご利用ください。
+ */
"youShouldUpgradeClient": string;
+ /**
+ * リスト名を入力
+ */
"enterListName": string;
+ /**
+ * プライバシー
+ */
"privacy": string;
+ /**
+ * フォローを承認制にする
+ */
"makeFollowManuallyApprove": string;
+ /**
+ * デフォルトの公開範囲
+ */
"defaultNoteVisibility": string;
+ /**
+ * フォロー
+ */
"follow": string;
+ /**
+ * フォロー申請
+ */
"followRequest": string;
+ /**
+ * フォロー申請
+ */
"followRequests": string;
+ /**
+ * フォロー解除
+ */
"unfollow": string;
+ /**
+ * フォロー許可待ち
+ */
"followRequestPending": string;
+ /**
+ * 絵文字を入力
+ */
"enterEmoji": string;
+ /**
+ * リノート
+ */
"renote": string;
+ /**
+ * リノート解除
+ */
"unrenote": string;
+ /**
+ * リノートしました。
+ */
"renoted": string;
+ /**
+ * この投稿はリノートできません。
+ */
"cantRenote": string;
+ /**
+ * リノートをリノートすることはできません。
+ */
"cantReRenote": string;
+ /**
+ * 引用
+ */
"quote": string;
+ /**
+ * チャンネル内リノート
+ */
"inChannelRenote": string;
+ /**
+ * チャンネル内引用
+ */
"inChannelQuote": string;
+ /**
+ * ピン留めされたノート
+ */
"pinnedNote": string;
+ /**
+ * ピン留め
+ */
"pinned": string;
+ /**
+ * あなた
+ */
"you": string;
+ /**
+ * クリックして表示
+ */
"clickToShow": string;
+ /**
+ * センシティブ
+ */
"sensitive": string;
+ /**
+ * 追加
+ */
"add": string;
+ /**
+ * リアクション
+ */
"reaction": string;
+ /**
+ * リアクション
+ */
"reactions": string;
- "reactionSetting": string;
+ /**
+ * 絵文字ピッカー
+ */
+ "emojiPicker": string;
+ /**
+ * リアクション時にピン留め表示する絵文字を設定できます
+ */
+ "pinnedEmojisForReactionSettingDescription": string;
+ /**
+ * 絵文字入力時にピン留め表示する絵文字を設定できます
+ */
+ "pinnedEmojisSettingDescription": string;
+ /**
+ * ピッカーの表示
+ */
+ "emojiPickerDisplay": string;
+ /**
+ * リアクション設定から上書きする
+ */
+ "overwriteFromPinnedEmojisForReaction": string;
+ /**
+ * 全般設定から上書きする
+ */
+ "overwriteFromPinnedEmojis": string;
+ /**
+ * ドラッグして並び替え、クリックして削除、+を押して追加します。
+ */
"reactionSettingDescription2": string;
+ /**
+ * 公開範囲を記憶する
+ */
"rememberNoteVisibility": string;
+ /**
+ * 添付取り消し
+ */
"attachCancel": string;
+ /**
+ * ファイルを削除
+ */
+ "deleteFile": string;
+ /**
+ * センシティブとして設定
+ */
"markAsSensitive": string;
+ /**
+ * センシティブを解除する
+ */
"unmarkAsSensitive": string;
+ /**
+ * ファイル名を入力
+ */
"enterFileName": string;
+ /**
+ * ミュート
+ */
"mute": string;
+ /**
+ * ミュート解除
+ */
"unmute": string;
+ /**
+ * リノートをミュート
+ */
"renoteMute": string;
+ /**
+ * リノートのミュートを解除
+ */
"renoteUnmute": string;
+ /**
+ * ブロック
+ */
"block": string;
+ /**
+ * ブロック解除
+ */
"unblock": string;
+ /**
+ * 凍結
+ */
"suspend": string;
+ /**
+ * 解凍
+ */
"unsuspend": string;
+ /**
+ * ブロックしますか?
+ */
"blockConfirm": string;
+ /**
+ * ブロック解除しますか?
+ */
"unblockConfirm": string;
+ /**
+ * 凍結しますか?
+ */
"suspendConfirm": string;
+ /**
+ * 解凍しますか?
+ */
"unsuspendConfirm": string;
+ /**
+ * リストを選択
+ */
"selectList": string;
+ /**
+ * リストを編集
+ */
"editList": string;
+ /**
+ * チャンネルを選択
+ */
"selectChannel": string;
+ /**
+ * アンテナを選択
+ */
"selectAntenna": string;
+ /**
+ * アンテナを編集
+ */
"editAntenna": string;
+ /**
+ * ウィジェットを選択
+ */
"selectWidget": string;
+ /**
+ * ウィジェットを編集
+ */
"editWidgets": string;
+ /**
+ * 編集を終了
+ */
"editWidgetsExit": string;
+ /**
+ * カスタム絵文字
+ */
"customEmojis": string;
+ /**
+ * 絵文字
+ */
"emoji": string;
+ /**
+ * 絵文字
+ */
"emojis": string;
+ /**
+ * 絵文字名
+ */
"emojiName": string;
+ /**
+ * 絵文字画像URL
+ */
"emojiUrl": string;
+ /**
+ * 絵文字を追加
+ */
"addEmoji": string;
+ /**
+ * おすすめ設定
+ */
"settingGuide": string;
+ /**
+ * リモートのファイルをキャッシュする
+ */
"cacheRemoteFiles": string;
+ /**
+ * この設定を有効にすると、リモートファイルをこのサーバーのストレージにキャッシュするようになります。画像の表示が高速になりますが、サーバーのストレージを多く消費します。リモートユーザーがどれほどキャッシュを保持するかは、ロールによるドライブ容量制限によって決定されます。この制限を超えた場合、古いファイルからキャッシュが削除されリンクになります。この設定が無効の場合、リモートのファイルを最初からリンクとして保持しますが、画像のサムネイル生成やユーザーのプライバシー保護のために、default.ymlでproxyRemoteFilesをtrueにすることをお勧めします。
+ */
"cacheRemoteFilesDescription": string;
+ /**
+ * ファイル管理の🗑️ボタンで全てのキャッシュを削除できます。
+ */
"youCanCleanRemoteFilesCache": string;
+ /**
+ * リモートのセンシティブなファイルをキャッシュする
+ */
"cacheRemoteSensitiveFiles": string;
+ /**
+ * この設定を無効にすると、リモートのセンシティブなファイルはキャッシュせず直リンクするようになります。
+ */
"cacheRemoteSensitiveFilesDescription": string;
+ /**
+ * Botとして設定
+ */
"flagAsBot": string;
+ /**
+ * このアカウントがプログラムによって運用される場合は、このフラグをオンにします。オンにすると、反応の連鎖を防ぐためのフラグとして他の開発者に役立ったり、Misskeyのシステム上での扱いがBotに合ったものになります。
+ */
"flagAsBotDescription": string;
+ /**
+ * にゃああああああああああああああ!!!!!!!!!!!!
+ */
"flagAsCat": string;
+ /**
+ * にゃにゃにゃ??
+ */
"flagAsCatDescription": string;
+ /**
+ * タイムラインにノートへの返信を表示する
+ */
"flagShowTimelineReplies": string;
+ /**
+ * オンにすると、タイムラインにユーザーのノート以外にもそのユーザーの他のノートへの返信を表示します。
+ */
"flagShowTimelineRepliesDescription": string;
+ /**
+ * フォロー中ユーザーからのフォロリクを自動承認
+ */
"autoAcceptFollowed": string;
+ /**
+ * アカウントを追加
+ */
"addAccount": string;
+ /**
+ * アカウントリストの情報を更新
+ */
"reloadAccountsList": string;
+ /**
+ * ログインに失敗しました
+ */
"loginFailed": string;
+ /**
+ * リモートで表示
+ */
"showOnRemote": string;
+ /**
+ * 全般
+ */
"general": string;
+ /**
+ * 壁紙
+ */
"wallpaper": string;
+ /**
+ * 壁紙を設定
+ */
"setWallpaper": string;
+ /**
+ * 壁紙を削除
+ */
"removeWallpaper": string;
- "searchWith": string;
+ /**
+ * 検索: {q}
+ */
+ "searchWith": ParameterizedString<"q">;
+ /**
+ * リストがありません
+ */
"youHaveNoLists": string;
- "followConfirm": string;
+ /**
+ * {name}をフォローしますか?
+ */
+ "followConfirm": ParameterizedString<"name">;
+ /**
+ * プロキシアカウント
+ */
"proxyAccount": string;
+ /**
+ * プロキシアカウントは、特定の条件下でユーザーのリモートフォローを代行するアカウントです。例えば、ユーザーがリモートユーザーをリストに入れたとき、リストに入れられたユーザーを誰もフォローしていないとアクティビティがサーバーに配達されないため、代わりにプロキシアカウントがフォローするようにします。
+ */
"proxyAccountDescription": string;
+ /**
+ * ホスト
+ */
"host": string;
+ /**
+ * ユーザーを選択
+ */
"selectUser": string;
+ /**
+ * 宛先
+ */
"recipient": string;
+ /**
+ * 注釈
+ */
"annotation": string;
+ /**
+ * 連合
+ */
"federation": string;
+ /**
+ * サーバー
+ */
"instances": string;
+ /**
+ * 初観測
+ */
"registeredAt": string;
+ /**
+ * 直近のリクエスト受信
+ */
"latestRequestReceivedAt": string;
+ /**
+ * 直近のステータス
+ */
"latestStatus": string;
+ /**
+ * ストレージ使用量
+ */
"storageUsage": string;
+ /**
+ * チャート
+ */
"charts": string;
+ /**
+ * 1時間ごと
+ */
"perHour": string;
+ /**
+ * 1日ごと
+ */
"perDay": string;
+ /**
+ * アクティビティの配送を停止
+ */
"stopActivityDelivery": string;
+ /**
+ * このサーバーをブロック
+ */
"blockThisInstance": string;
+ /**
+ * サーバーをサイレンス
+ */
"silenceThisInstance": string;
+ /**
+ * このサーバーのメディアを全てセンシティブとして設定
+ */
+ "sensitiveMediaThisInstance": string;
+ /**
+ * 操作
+ */
"operations": string;
+ /**
+ * ソフトウェア
+ */
"software": string;
+ /**
+ * バージョン
+ */
"version": string;
+ /**
+ * メタデータ
+ */
"metadata": string;
- "withNFiles": string;
+ /**
+ * {n}つのファイル
+ */
+ "withNFiles": ParameterizedString<"n">;
+ /**
+ * モニター
+ */
"monitor": string;
+ /**
+ * ジョブキュー
+ */
"jobQueue": string;
+ /**
+ * CPUとメモリ
+ */
"cpuAndMemory": string;
+ /**
+ * ネットワーク
+ */
"network": string;
+ /**
+ * ディスク
+ */
"disk": string;
+ /**
+ * サーバー情報
+ */
"instanceInfo": string;
+ /**
+ * 統計
+ */
"statistics": string;
+ /**
+ * キューをクリア
+ */
"clearQueue": string;
+ /**
+ * キューをクリアしますか?
+ */
"clearQueueConfirmTitle": string;
+ /**
+ * 未配達の投稿は配送されなくなります。通常この操作を行う必要はありません。
+ */
"clearQueueConfirmText": string;
+ /**
+ * キャッシュをクリア
+ */
"clearCachedFiles": string;
+ /**
+ * キャッシュされたリモートファイルをすべて削除しますか?
+ */
"clearCachedFilesConfirm": string;
+ /**
+ * ブロックしたサーバー
+ */
"blockedInstances": string;
+ /**
+ * ブロックしたいサーバーのホストを改行で区切って設定します。ブロックされたサーバーは、このインスタンスとやり取りできなくなります。
+ */
"blockedInstancesDescription": string;
+ /**
+ * サイレンスしたサーバー
+ */
"silencedInstances": string;
+ /**
+ * サイレンスしたいサーバーのホストを改行で区切って設定します。サイレンスされたサーバーに所属するアカウントはすべて「サイレンス」として扱われ、フォローがすべてリクエストになり、フォロワーでないローカルアカウントにはメンションできなくなります。ブロックしたインスタンスには影響しません。
+ */
"silencedInstancesDescription": string;
+ /**
+ * センシティブなメディアを含むサーバー
+ */
+ "sensitiveMediaInstances": string;
+ /**
+ * センシティブなメディアを含むサーバーのホストを改行で区切って設定します。このサーバーからのメディアは全てセンシティブとして扱われます。
+ */
+ "sensitiveMediaInstancesDescription": string;
+ /**
+ * ミュートとブロック
+ */
"muteAndBlock": string;
+ /**
+ * ミュートしたユーザー
+ */
"mutedUsers": string;
+ /**
+ * ブロックしたユーザー
+ */
"blockedUsers": string;
+ /**
+ * ユーザーはいません
+ */
"noUsers": string;
+ /**
+ * プロフィールを編集
+ */
"editProfile": string;
+ /**
+ * このノートを削除しますか?
+ */
"noteDeleteConfirm": string;
+ /**
+ * これ以上ピン留めできません
+ */
"pinLimitExceeded": string;
+ /**
+ * Misskeyのインストールが完了しました!管理者アカウントを作成しましょう。
+ */
"intro": string;
+ /**
+ * 完了
+ */
"done": string;
+ /**
+ * 処理中
+ */
"processing": string;
+ /**
+ * プレビュー
+ */
"preview": string;
+ /**
+ * デフォルト
+ */
"default": string;
- "defaultValueIs": string;
+ /**
+ * デフォルト: {value}
+ */
+ "defaultValueIs": ParameterizedString<"value">;
+ /**
+ * 絵文字はありません
+ */
"noCustomEmojis": string;
+ /**
+ * ジョブはありません
+ */
"noJobs": string;
+ /**
+ * 連合中
+ */
"federating": string;
+ /**
+ * ブロック中
+ */
"blocked": string;
+ /**
+ * 配信停止
+ */
"suspended": string;
+ /**
+ * 全て
+ */
"all": string;
+ /**
+ * 購読中
+ */
"subscribing": string;
+ /**
+ * 配信中
+ */
"publishing": string;
+ /**
+ * 応答なし
+ */
"notResponding": string;
+ /**
+ * サーバーのフォロー
+ */
"instanceFollowing": string;
+ /**
+ * サーバーのフォロワー
+ */
"instanceFollowers": string;
+ /**
+ * サーバーのユーザー
+ */
"instanceUsers": string;
+ /**
+ * パスワードを変更
+ */
"changePassword": string;
+ /**
+ * セキュリティ
+ */
"security": string;
+ /**
+ * 入力が一致しません。
+ */
"retypedNotMatch": string;
+ /**
+ * 現在のパスワード
+ */
"currentPassword": string;
+ /**
+ * 新しいパスワード
+ */
"newPassword": string;
+ /**
+ * 新しいパスワード(再入力)
+ */
"newPasswordRetype": string;
+ /**
+ * ファイルを添付
+ */
"attachFile": string;
+ /**
+ * もっと!
+ */
"more": string;
+ /**
+ * ハイライト
+ */
"featured": string;
+ /**
+ * ユーザー名かユーザーID
+ */
"usernameOrUserId": string;
+ /**
+ * ユーザーが見つかりません
+ */
"noSuchUser": string;
+ /**
+ * 照会
+ */
"lookup": string;
+ /**
+ * お知らせ
+ */
"announcements": string;
+ /**
+ * 画像URL
+ */
"imageUrl": string;
+ /**
+ * 表示順
+ */
+ "displayOrder": string;
+ /**
+ * 削除
+ */
"remove": string;
+ /**
+ * 削除しました
+ */
"removed": string;
- "removeAreYouSure": string;
- "deleteAreYouSure": string;
+ /**
+ * 「{x}」を削除しますか?
+ */
+ "removeAreYouSure": ParameterizedString<"x">;
+ /**
+ * 「{x}」を削除しますか?
+ */
+ "deleteAreYouSure": ParameterizedString<"x">;
+ /**
+ * リセットしますか?
+ */
"resetAreYouSure": string;
+ /**
+ * よろしいですか?
+ */
+ "areYouSure": string;
+ /**
+ * 保存しました
+ */
"saved": string;
+ /**
+ * チャット
+ */
"messaging": string;
+ /**
+ * アップロード
+ */
"upload": string;
+ /**
+ * オリジナル画像を保持
+ */
"keepOriginalUploading": string;
+ /**
+ * 画像をアップロードする時にオリジナル版を保持します。オフにするとアップロード時にブラウザでWeb公開用画像を生成します。
+ */
"keepOriginalUploadingDescription": string;
+ /**
+ * ドライブから
+ */
"fromDrive": string;
+ /**
+ * URLから
+ */
"fromUrl": string;
+ /**
+ * URLアップロード
+ */
"uploadFromUrl": string;
+ /**
+ * アップロードしたいファイルのURL
+ */
"uploadFromUrlDescription": string;
+ /**
+ * アップロードをリクエストしました
+ */
"uploadFromUrlRequested": string;
+ /**
+ * アップロードが完了するまで時間がかかる場合があります。
+ */
"uploadFromUrlMayTakeTime": string;
+ /**
+ * みつける
+ */
"explore": string;
+ /**
+ * 既読
+ */
"messageRead": string;
+ /**
+ * これより過去の履歴はありません
+ */
"noMoreHistory": string;
+ /**
+ * チャットを開始
+ */
"startMessaging": string;
- "nUsersRead": string;
- "agreeTo": string;
+ /**
+ * {n}人が読みました
+ */
+ "nUsersRead": ParameterizedString<"n">;
+ /**
+ * {0}に同意
+ */
+ "agreeTo": ParameterizedString<"0">;
+ /**
+ * 同意する
+ */
"agree": string;
+ /**
+ * 下記に同意する
+ */
"agreeBelow": string;
+ /**
+ * 基本的な注意事項
+ */
"basicNotesBeforeCreateAccount": string;
+ /**
+ * 利用規約
+ */
"termsOfService": string;
+ /**
+ * 始める
+ */
"start": string;
+ /**
+ * ホーム
+ */
"home": string;
+ /**
+ * リモートユーザーのため、情報が不完全です。
+ */
"remoteUserCaution": string;
+ /**
+ * アクティビティ
+ */
"activity": string;
+ /**
+ * 画像
+ */
"images": string;
+ /**
+ * 画像
+ */
"image": string;
+ /**
+ * 誕生日
+ */
"birthday": string;
- "yearsOld": string;
+ /**
+ * {age}歳
+ */
+ "yearsOld": ParameterizedString<"age">;
+ /**
+ * 登録日
+ */
"registeredDate": string;
+ /**
+ * 場所
+ */
"location": string;
+ /**
+ * テーマ
+ */
"theme": string;
+ /**
+ * ライトモードで使うテーマ
+ */
"themeForLightMode": string;
+ /**
+ * ダークモードで使うテーマ
+ */
"themeForDarkMode": string;
+ /**
+ * ライト
+ */
"light": string;
+ /**
+ * ダーク
+ */
"dark": string;
+ /**
+ * 明るいテーマ
+ */
"lightThemes": string;
+ /**
+ * 暗いテーマ
+ */
"darkThemes": string;
+ /**
+ * デバイスのダークモードと同期する
+ */
"syncDeviceDarkMode": string;
+ /**
+ * ドライブ
+ */
"drive": string;
+ /**
+ * ファイル名
+ */
"fileName": string;
+ /**
+ * ファイルを選択
+ */
"selectFile": string;
+ /**
+ * ファイルを選択
+ */
"selectFiles": string;
+ /**
+ * フォルダーを選択
+ */
"selectFolder": string;
+ /**
+ * フォルダーを選択
+ */
"selectFolders": string;
+ /**
+ * ファイル名を変更
+ */
"renameFile": string;
+ /**
+ * フォルダー名
+ */
"folderName": string;
+ /**
+ * フォルダーを作成
+ */
"createFolder": string;
+ /**
+ * フォルダー名を変更
+ */
"renameFolder": string;
+ /**
+ * フォルダーを削除
+ */
"deleteFolder": string;
+ /**
+ * フォルダー
+ */
+ "folder": string;
+ /**
+ * ファイルを追加
+ */
"addFile": string;
+ /**
+ * ドライブは空です
+ */
"emptyDrive": string;
+ /**
+ * フォルダーは空です
+ */
"emptyFolder": string;
+ /**
+ * 削除できません
+ */
"unableToDelete": string;
+ /**
+ * 新しいファイル名を入力してください
+ */
"inputNewFileName": string;
+ /**
+ * 新しいキャプションを入力してください
+ */
"inputNewDescription": string;
+ /**
+ * 新しいフォルダ名を入力してください
+ */
"inputNewFolderName": string;
+ /**
+ * 移動先のフォルダーは、移動するフォルダーのサブフォルダーです。
+ */
"circularReferenceFolder": string;
+ /**
+ * このフォルダは空でないため、削除できません。
+ */
"hasChildFilesOrFolders": string;
+ /**
+ * URLをコピー
+ */
"copyUrl": string;
+ /**
+ * 名前を変更
+ */
"rename": string;
+ /**
+ * アイコン
+ */
"avatar": string;
+ /**
+ * バナー
+ */
"banner": string;
+ /**
+ * センシティブなメディアの表示
+ */
"displayOfSensitiveMedia": string;
+ /**
+ * サーバーとの接続が失われたとき
+ */
"whenServerDisconnected": string;
+ /**
+ * サーバーから切断されました
+ */
"disconnectedFromServer": string;
+ /**
+ * リロード
+ */
"reload": string;
+ /**
+ * なにもしない
+ */
"doNothing": string;
+ /**
+ * リロードしますか?
+ */
"reloadConfirm": string;
+ /**
+ * ウォッチ
+ */
"watch": string;
+ /**
+ * ウォッチ解除
+ */
"unwatch": string;
+ /**
+ * 許可
+ */
"accept": string;
+ /**
+ * 拒否
+ */
"reject": string;
+ /**
+ * 通常
+ */
"normal": string;
+ /**
+ * サーバー名
+ */
"instanceName": string;
+ /**
+ * サーバーの紹介
+ */
"instanceDescription": string;
+ /**
+ * 管理者の名前
+ */
"maintainerName": string;
+ /**
+ * 管理者のメールアドレス
+ */
"maintainerEmail": string;
+ /**
+ * 利用規約URL
+ */
"tosUrl": string;
+ /**
+ * 今年
+ */
"thisYear": string;
+ /**
+ * 今月
+ */
"thisMonth": string;
+ /**
+ * 今日
+ */
"today": string;
- "dayX": string;
- "monthX": string;
- "yearX": string;
+ /**
+ * {day}日
+ */
+ "dayX": ParameterizedString<"day">;
+ /**
+ * {month}月
+ */
+ "monthX": ParameterizedString<"month">;
+ /**
+ * {year}年
+ */
+ "yearX": ParameterizedString<"year">;
+ /**
+ * ページ
+ */
"pages": string;
+ /**
+ * 連携
+ */
"integration": string;
+ /**
+ * 接続する
+ */
"connectService": string;
+ /**
+ * 切断する
+ */
"disconnectService": string;
+ /**
+ * ローカルタイムラインを有効にする
+ */
"enableLocalTimeline": string;
+ /**
+ * グローバルタイムラインを有効にする
+ */
"enableGlobalTimeline": string;
+ /**
+ * これらのタイムラインを無効化しても、利便性のため管理者およびモデレーターは引き続き利用することができます。
+ */
"disablingTimelinesInfo": string;
+ /**
+ * 登録
+ */
"registration": string;
+ /**
+ * 誰でも新規登録できるようにする
+ */
"enableRegistration": string;
+ /**
+ * 招待
+ */
"invite": string;
+ /**
+ * ローカルユーザーひとりあたりのドライブ容量
+ */
"driveCapacityPerLocalAccount": string;
+ /**
+ * リモートユーザーひとりあたりのドライブ容量
+ */
"driveCapacityPerRemoteAccount": string;
+ /**
+ * メガバイト単位
+ */
"inMb": string;
+ /**
+ * バナー画像のURL
+ */
"bannerUrl": string;
+ /**
+ * 背景画像のURL
+ */
"backgroundImageUrl": string;
+ /**
+ * 基本情報
+ */
"basicInfo": string;
+ /**
+ * ピン留めユーザー
+ */
"pinnedUsers": string;
+ /**
+ * 「みつける」ページなどにピン留めしたいユーザーを改行で区切って記述します。
+ */
"pinnedUsersDescription": string;
+ /**
+ * ピン留めページ
+ */
"pinnedPages": string;
+ /**
+ * サーバーのトップページにピン留めしたいページのパスを改行で区切って記述します。
+ */
"pinnedPagesDescription": string;
+ /**
+ * ピン留めするクリップのID
+ */
"pinnedClipId": string;
+ /**
+ * ピン留めされたノート
+ */
"pinnedNotes": string;
+ /**
+ * Misskey Gamesのピン留めチャンネル
+ */
+ "featuredGameChannels": string;
+ /**
+ * Misskey Gamesにピン留めしたいチャンネルを改行で区切って記述します。
+ */
+ "featuredGameChannelsDescription": string;
+ /**
+ * hCaptcha
+ */
"hcaptcha": string;
+ /**
+ * hCaptchaを有効にする
+ */
"enableHcaptcha": string;
+ /**
+ * サイトキー
+ */
"hcaptchaSiteKey": string;
+ /**
+ * シークレットキー
+ */
"hcaptchaSecretKey": string;
+ /**
+ * mCaptcha
+ */
+ "mcaptcha": string;
+ /**
+ * mCaptchaを有効にする
+ */
+ "enableMcaptcha": string;
+ /**
+ * サイトキー
+ */
+ "mcaptchaSiteKey": string;
+ /**
+ * シークレットキー
+ */
+ "mcaptchaSecretKey": string;
+ /**
+ * mCaptchaのインスタンスのURL
+ */
+ "mcaptchaInstanceUrl": string;
+ /**
+ * reCAPTCHA
+ */
"recaptcha": string;
+ /**
+ * reCAPTCHAを有効にする
+ */
"enableRecaptcha": string;
+ /**
+ * サイトキー
+ */
"recaptchaSiteKey": string;
+ /**
+ * シークレットキー
+ */
"recaptchaSecretKey": string;
+ /**
+ * Turnstile
+ */
"turnstile": string;
+ /**
+ * Turnstileを有効にする
+ */
"enableTurnstile": string;
+ /**
+ * サイトキー
+ */
"turnstileSiteKey": string;
+ /**
+ * シークレットキー
+ */
"turnstileSecretKey": string;
+ /**
+ * 複数のCaptchaを使用すると干渉を起こす可能性があります。他のCaptchaを無効にしますか?キャンセルして複数のCaptchaを有効化したままにすることも可能です。
+ */
"avoidMultiCaptchaConfirm": string;
+ /**
+ * アンテナ
+ */
"antennas": string;
+ /**
+ * アンテナの管理
+ */
"manageAntennas": string;
+ /**
+ * 名前
+ */
"name": string;
+ /**
+ * 受信ソース
+ */
"antennaSource": string;
+ /**
+ * 受信キーワード
+ */
"antennaKeywords": string;
+ /**
+ * 除外キーワード
+ */
"antennaExcludeKeywords": string;
+ /**
+ * スペースで区切るとAND指定になり、改行で区切るとOR指定になります
+ */
"antennaKeywordsDescription": string;
+ /**
+ * 新しいノートを通知する
+ */
"notifyAntenna": string;
+ /**
+ * ファイルが添付されたノートのみ
+ */
"withFileAntenna": string;
+ /**
+ * ブラウザへのプッシュ通知を有効にする
+ */
"enableServiceworker": string;
+ /**
+ * ユーザー名を改行で区切って指定します
+ */
"antennaUsersDescription": string;
+ /**
+ * 大文字小文字を区別する
+ */
"caseSensitive": string;
+ /**
+ * 返信を含む
+ */
"withReplies": string;
+ /**
+ * 次のアカウントに接続されています
+ */
"connectedTo": string;
+ /**
+ * 投稿と返信
+ */
"notesAndReplies": string;
+ /**
+ * ファイル付き
+ */
"withFiles": string;
+ /**
+ * サイレンス
+ */
"silence": string;
+ /**
+ * サイレンスしますか?
+ */
"silenceConfirm": string;
+ /**
+ * サイレンス解除
+ */
"unsilence": string;
+ /**
+ * サイレンス解除しますか?
+ */
"unsilenceConfirm": string;
+ /**
+ * 人気のユーザー
+ */
"popularUsers": string;
+ /**
+ * 最近投稿したユーザー
+ */
"recentlyUpdatedUsers": string;
+ /**
+ * 最近登録したユーザー
+ */
"recentlyRegisteredUsers": string;
+ /**
+ * 最近発見されたユーザー
+ */
"recentlyDiscoveredUsers": string;
- "exploreUsersCount": string;
+ /**
+ * {count}のユーザーがいます
+ */
+ "exploreUsersCount": ParameterizedString<"count">;
+ /**
+ * Fediverseを探索
+ */
"exploreFediverse": string;
+ /**
+ * 人気のタグ
+ */
"popularTags": string;
+ /**
+ * リスト
+ */
"userList": string;
+ /**
+ * 情報
+ */
"about": string;
+ /**
+ * Misskeyについて
+ */
"aboutMisskey": string;
+ /**
+ * 管理者
+ */
"administrator": string;
+ /**
+ * 確認コード
+ */
"token": string;
+ /**
+ * 二要素認証
+ */
"2fa": string;
+ /**
+ * 二要素認証のセットアップ
+ */
"setupOf2fa": string;
+ /**
+ * 認証アプリ
+ */
"totp": string;
+ /**
+ * 認証アプリを使ってワンタイムパスワードを入力
+ */
"totpDescription": string;
+ /**
+ * モデレーター
+ */
"moderator": string;
+ /**
+ * モデレーション
+ */
"moderation": string;
+ /**
+ * モデレーションノート
+ */
"moderationNote": string;
+ /**
+ * モデレーションノートを追加する
+ */
"addModerationNote": string;
+ /**
+ * モデログ
+ */
"moderationLogs": string;
- "nUsersMentioned": string;
+ /**
+ * {n}人が投稿
+ */
+ "nUsersMentioned": ParameterizedString<"n">;
+ /**
+ * セキュリティキー・パスキー
+ */
"securityKeyAndPasskey": string;
+ /**
+ * セキュリティキー
+ */
"securityKey": string;
+ /**
+ * 最後の使用
+ */
"lastUsed": string;
- "lastUsedAt": string;
+ /**
+ * 最後の使用: {t}
+ */
+ "lastUsedAt": ParameterizedString<"t">;
+ /**
+ * 登録を解除
+ */
"unregister": string;
+ /**
+ * パスワードレスログイン
+ */
"passwordLessLogin": string;
+ /**
+ * パスワードを使用せず、セキュリティキーやパスキーなどのみでログインします
+ */
"passwordLessLoginDescription": string;
+ /**
+ * パスワードをリセット
+ */
"resetPassword": string;
- "newPasswordIs": string;
+ /**
+ * 新しいパスワードは「{password}」です
+ */
+ "newPasswordIs": ParameterizedString<"password">;
+ /**
+ * UIのアニメーションを減らす
+ */
"reduceUiAnimation": string;
+ /**
+ * 共有
+ */
"share": string;
+ /**
+ * 見つかりません
+ */
"notFound": string;
+ /**
+ * 指定されたURLに該当するページはありませんでした。
+ */
"notFoundDescription": string;
+ /**
+ * 既定アップロード先
+ */
"uploadFolder": string;
- "cacheClear": string;
+ /**
+ * すべての通知を既読にする
+ */
"markAsReadAllNotifications": string;
+ /**
+ * すべての投稿を既読にする
+ */
"markAsReadAllUnreadNotes": string;
+ /**
+ * すべてのチャットを既読にする
+ */
"markAsReadAllTalkMessages": string;
+ /**
+ * ヘルプ
+ */
"help": string;
+ /**
+ * ここにメッセージを入力
+ */
"inputMessageHere": string;
+ /**
+ * 閉じる
+ */
"close": string;
+ /**
+ * 招待
+ */
"invites": string;
+ /**
+ * メンバー
+ */
"members": string;
+ /**
+ * 譲渡
+ */
"transfer": string;
+ /**
+ * タイトル
+ */
"title": string;
+ /**
+ * テキスト
+ */
"text": string;
+ /**
+ * 有効にする
+ */
"enable": string;
+ /**
+ * 次
+ */
"next": string;
+ /**
+ * 再入力
+ */
"retype": string;
- "noteOf": string;
+ /**
+ * {user}のノート
+ */
+ "noteOf": ParameterizedString<"user">;
+ /**
+ * 引用付き
+ */
"quoteAttached": string;
+ /**
+ * 引用として添付しますか?
+ */
"quoteQuestion": string;
+ /**
+ * まだチャットはありません
+ */
"noMessagesYet": string;
+ /**
+ * 新しいメッセージがあります
+ */
"newMessageExists": string;
+ /**
+ * メッセージに添付できるファイルはひとつです
+ */
"onlyOneFileCanBeAttached": string;
+ /**
+ * 続行する前に、サインアップまたはサインインが必要です
+ */
"signinRequired": string;
+ /**
+ * 招待
+ */
"invitations": string;
+ /**
+ * 招待コード
+ */
"invitationCode": string;
+ /**
+ * 確認しています
+ */
"checking": string;
+ /**
+ * 利用できます
+ */
"available": string;
+ /**
+ * 利用できません
+ */
"unavailable": string;
+ /**
+ * a~z、A~Z、0~9、_が使えます
+ */
"usernameInvalidFormat": string;
+ /**
+ * 短すぎます
+ */
"tooShort": string;
+ /**
+ * 長すぎます
+ */
"tooLong": string;
+ /**
+ * 弱いパスワード
+ */
"weakPassword": string;
+ /**
+ * 普通のパスワード
+ */
"normalPassword": string;
+ /**
+ * 強いパスワード
+ */
"strongPassword": string;
+ /**
+ * 一致しました
+ */
"passwordMatched": string;
+ /**
+ * 一致していません
+ */
"passwordNotMatched": string;
- "signinWith": string;
+ /**
+ * {x}でログイン
+ */
+ "signinWith": ParameterizedString<"x">;
+ /**
+ * ログインできませんでした。ユーザー名とパスワードを確認してください。
+ */
"signinFailed": string;
+ /**
+ * もしくは
+ */
"or": string;
+ /**
+ * 言語
+ */
"language": string;
+ /**
+ * UIの表示言語
+ */
"uiLanguage": string;
- "aboutX": string;
+ /**
+ * {x}について
+ */
+ "aboutX": ParameterizedString<"x">;
+ /**
+ * 絵文字のスタイル
+ */
"emojiStyle": string;
+ /**
+ * ネイティブ
+ */
"native": string;
+ /**
+ * メニューをドロワーで表示しない
+ */
"disableDrawer": string;
+ /**
+ * ノートのアクションをホバー時のみ表示する
+ */
"showNoteActionsOnlyHover": string;
+ /**
+ * ノートの返信数を表示する
+ */
+ "showRepliesCount": string;
+ /**
+ * ノートのリノート数を表示する
+ */
+ "showRenotesCount": string;
+ /**
+ * ノートのリアクション数を表示する
+ */
+ "showReactionsCount": string;
+ /**
+ * 履歴はありません
+ */
"noHistory": string;
+ /**
+ * ログイン履歴
+ */
"signinHistory": string;
+ /**
+ * 高度なMFMを有効にする
+ */
"enableAdvancedMfm": string;
+ /**
+ * 動きのあるMFMを有効にする
+ */
"enableAnimatedMfm": string;
+ /**
+ * やっています
+ */
"doing": string;
+ /**
+ * カテゴリ
+ */
"category": string;
+ /**
+ * タグ
+ */
"tags": string;
+ /**
+ * このドキュメントのソース
+ */
"docSource": string;
+ /**
+ * アカウントを作成
+ */
"createAccount": string;
+ /**
+ * 既存のアカウント
+ */
"existingAccount": string;
+ /**
+ * 再生成
+ */
"regenerate": string;
+ /**
+ * フォントサイズ
+ */
"fontSize": string;
+ /**
+ * 画像が1枚のみのメディアリストの高さ
+ */
"mediaListWithOneImageAppearance": string;
- "limitTo": string;
+ /**
+ * {x}を上限に
+ */
+ "limitTo": ParameterizedString<"x">;
+ /**
+ * フォロー申請はありません
+ */
"noFollowRequests": string;
+ /**
+ * 画像を新しいタブで開く
+ */
"openImageInNewTab": string;
+ /**
+ * ダッシュボード
+ */
"dashboard": string;
+ /**
+ * ローカル
+ */
"local": string;
+ /**
+ * リモート
+ */
"remote": string;
+ /**
+ * 合計
+ */
"total": string;
+ /**
+ * 前週比
+ */
"weekOverWeekChanges": string;
+ /**
+ * 前日比
+ */
"dayOverDayChanges": string;
+ /**
+ * アピアランス
+ */
"appearance": string;
+ /**
+ * クライアント設定
+ */
"clientSettings": string;
+ /**
+ * アカウント設定
+ */
"accountSettings": string;
+ /**
+ * プロモーション
+ */
"promotion": string;
+ /**
+ * プロモート
+ */
"promote": string;
+ /**
+ * 日数
+ */
"numberOfDays": string;
+ /**
+ * このノートを非表示
+ */
"hideThisNote": string;
+ /**
+ * タイムラインにおすすめのノートを表示する
+ */
"showFeaturedNotesInTimeline": string;
+ /**
+ * オブジェクトストレージ
+ */
"objectStorage": string;
+ /**
+ * オブジェクトストレージを使用
+ */
"useObjectStorage": string;
+ /**
+ * Base URL
+ */
"objectStorageBaseUrl": string;
+ /**
+ * 参照に使用するURL。CDNやProxyを使用している場合はそのURL、S3: 'https://.s3.amazonaws.com'、GCS等: 'https://storage.googleapis.com/'。
+ */
"objectStorageBaseUrlDesc": string;
+ /**
+ * Bucket
+ */
"objectStorageBucket": string;
+ /**
+ * 使用サービスのbucket名を指定してください。
+ */
"objectStorageBucketDesc": string;
+ /**
+ * Prefix
+ */
"objectStoragePrefix": string;
+ /**
+ * このprefixのディレクトリ下に格納されます。
+ */
"objectStoragePrefixDesc": string;
+ /**
+ * Endpoint
+ */
"objectStorageEndpoint": string;
+ /**
+ * S3の場合は空、それ以外の場合は各サービスのendpointを指定してください。''または':'のように指定します。
+ */
"objectStorageEndpointDesc": string;
+ /**
+ * Region
+ */
"objectStorageRegion": string;
+ /**
+ * 'xx-east-1'のようなregionを指定してください。使用サービスにregionの概念がない場合は'us-east-1'にしてください。AWS設定ファイルまたは環境変数を参照する場合は空にしてください。
+ */
"objectStorageRegionDesc": string;
+ /**
+ * SSLを使用する
+ */
"objectStorageUseSSL": string;
+ /**
+ * API接続にhttpsを使用しない場合はオフにしてください
+ */
"objectStorageUseSSLDesc": string;
+ /**
+ * Proxyを利用する
+ */
"objectStorageUseProxy": string;
+ /**
+ * API接続にproxyを利用しない場合はオフにしてください
+ */
"objectStorageUseProxyDesc": string;
+ /**
+ * アップロード時に'public-read'を設定する
+ */
"objectStorageSetPublicRead": string;
+ /**
+ * s3ForcePathStyleを有効にすると、バケット名をURLのホスト名ではなくパスの一部として指定することを強制します。セルフホストされたMinioなどの使用時に有効にする必要がある場合があります。
+ */
"s3ForcePathStyleDesc": string;
+ /**
+ * サーバーログ
+ */
"serverLogs": string;
+ /**
+ * 全て削除
+ */
"deleteAll": string;
+ /**
+ * タイムライン上部に投稿フォームを表示する
+ */
"showFixedPostForm": string;
+ /**
+ * タイムライン上部に投稿フォームを表示する(チャンネル)
+ */
"showFixedPostFormInChannel": string;
+ /**
+ * フォローする際、デフォルトで返信をTLに含むようにする
+ */
"withRepliesByDefaultForNewlyFollowed": string;
+ /**
+ * 新しいノートがあります
+ */
"newNoteRecived": string;
+ /**
+ * サウンド
+ */
"sounds": string;
+ /**
+ * サウンド
+ */
"sound": string;
+ /**
+ * 聴く
+ */
"listen": string;
+ /**
+ * なし
+ */
"none": string;
+ /**
+ * ページで表示
+ */
"showInPage": string;
+ /**
+ * ポップアウト
+ */
"popout": string;
+ /**
+ * 音量
+ */
"volume": string;
+ /**
+ * マスター音量
+ */
"masterVolume": string;
+ /**
+ * サウンドを出力しない
+ */
+ "notUseSound": string;
+ /**
+ * Misskeyがアクティブな時のみサウンドを出力する
+ */
+ "useSoundOnlyWhenActive": string;
+ /**
+ * 詳細
+ */
"details": string;
+ /**
+ * 絵文字を選択
+ */
"chooseEmoji": string;
+ /**
+ * 操作を完了できません
+ */
"unableToProcess": string;
+ /**
+ * 最近使用
+ */
"recentUsed": string;
+ /**
+ * インストール
+ */
"install": string;
+ /**
+ * アンインストール
+ */
"uninstall": string;
+ /**
+ * インストールされたアプリ
+ */
"installedApps": string;
+ /**
+ * ありません
+ */
"nothing": string;
+ /**
+ * インストール日時
+ */
"installedDate": string;
+ /**
+ * 最終使用日時
+ */
"lastUsedDate": string;
+ /**
+ * 状態
+ */
"state": string;
+ /**
+ * ソート
+ */
"sort": string;
+ /**
+ * 昇順
+ */
"ascendingOrder": string;
+ /**
+ * 降順
+ */
"descendingOrder": string;
+ /**
+ * スクラッチパッド
+ */
"scratchpad": string;
+ /**
+ * スクラッチパッドは、AiScriptの実験環境を提供します。Misskeyと対話するコードの記述、実行、結果の確認ができます。
+ */
"scratchpadDescription": string;
+ /**
+ * 出力
+ */
"output": string;
+ /**
+ * スクリプト
+ */
"script": string;
+ /**
+ * Pagesのスクリプトを無効にする
+ */
"disablePagesScript": string;
+ /**
+ * リモートユーザー情報の更新
+ */
"updateRemoteUser": string;
+ /**
+ * アイコンを解除
+ */
"unsetUserAvatar": string;
+ /**
+ * アイコンを解除しますか?
+ */
"unsetUserAvatarConfirm": string;
+ /**
+ * バナーを解除
+ */
"unsetUserBanner": string;
+ /**
+ * バナーを解除しますか?
+ */
"unsetUserBannerConfirm": string;
+ /**
+ * すべてのファイルを削除
+ */
"deleteAllFiles": string;
+ /**
+ * すべてのファイルを削除しますか?
+ */
"deleteAllFilesConfirm": string;
+ /**
+ * フォローを全解除
+ */
"removeAllFollowing": string;
- "removeAllFollowingDescription": string;
+ /**
+ * {host}からのフォローをすべて解除します。そのサーバーがもう存在しなくなった場合などに実行してください。
+ */
+ "removeAllFollowingDescription": ParameterizedString<"host">;
+ /**
+ * このユーザーは凍結されています。
+ */
"userSuspended": string;
+ /**
+ * このユーザーは制限されています。
+ */
+ "userLimited": string;
+ /**
+ * このユーザーはサイレンスされています。
+ */
"userSilenced": string;
+ /**
+ * アカウントが凍結されています
+ */
"yourAccountSuspendedTitle": string;
+ /**
+ * このアカウントは、サーバーの利用規約に違反したなどの理由により、凍結されています。詳細については管理者までお問い合わせください。新しいアカウントを作らないでください。
+ */
"yourAccountSuspendedDescription": string;
+ /**
+ * トークンが無効です
+ */
"tokenRevoked": string;
+ /**
+ * ログイントークンが失効しています。ログインし直してください。
+ */
"tokenRevokedDescription": string;
+ /**
+ * アカウントは削除されています
+ */
"accountDeleted": string;
+ /**
+ * このアカウントは削除されています。
+ */
"accountDeletedDescription": string;
+ /**
+ * メニュー
+ */
"menu": string;
+ /**
+ * 分割線
+ */
"divider": string;
+ /**
+ * 項目を追加
+ */
"addItem": string;
+ /**
+ * 並び替え
+ */
"rearrange": string;
+ /**
+ * リレー
+ */
"relays": string;
+ /**
+ * リレーの追加
+ */
"addRelay": string;
+ /**
+ * inboxのURL
+ */
"inboxUrl": string;
+ /**
+ * 追加済みのリレー
+ */
"addedRelays": string;
+ /**
+ * プッシュ通知を行うには有効にする必要があります。
+ */
"serviceworkerInfo": string;
+ /**
+ * 削除された投稿
+ */
"deletedNote": string;
+ /**
+ * 非公開の投稿
+ */
"invisibleNote": string;
+ /**
+ * 自動でもっと見る
+ */
"enableInfiniteScroll": string;
+ /**
+ * 公開範囲
+ */
"visibility": string;
+ /**
+ * アンケート
+ */
"poll": string;
+ /**
+ * 内容を隠す
+ */
"useCw": string;
+ /**
+ * プレイヤーを開く
+ */
"enablePlayer": string;
+ /**
+ * プレイヤーを閉じる
+ */
"disablePlayer": string;
+ /**
+ * ポストを展開する
+ */
"expandTweet": string;
+ /**
+ * テーマエディター
+ */
"themeEditor": string;
+ /**
+ * 説明
+ */
"description": string;
+ /**
+ * キャプションを付ける
+ */
"describeFile": string;
+ /**
+ * キャプションを入力
+ */
"enterFileDescription": string;
+ /**
+ * 作者
+ */
"author": string;
+ /**
+ * 未保存の変更があります。破棄しますか?
+ */
"leaveConfirm": string;
+ /**
+ * 管理
+ */
"manage": string;
+ /**
+ * プラグイン
+ */
"plugins": string;
+ /**
+ * 設定のバックアップ
+ */
"preferencesBackups": string;
+ /**
+ * デッキ
+ */
"deck": string;
+ /**
+ * デッキ解除
+ */
"undeck": string;
+ /**
+ * モーダルにぼかし効果を使用
+ */
"useBlurEffectForModal": string;
+ /**
+ * フル機能リアクションピッカーを使用
+ */
"useFullReactionPicker": string;
+ /**
+ * 幅
+ */
"width": string;
+ /**
+ * 高さ
+ */
"height": string;
+ /**
+ * 大
+ */
"large": string;
+ /**
+ * 中
+ */
"medium": string;
+ /**
+ * 小
+ */
"small": string;
+ /**
+ * アクセストークンの発行
+ */
"generateAccessToken": string;
+ /**
+ * 権限
+ */
"permission": string;
+ /**
+ * 管理者権限
+ */
+ "adminPermission": string;
+ /**
+ * 全て有効にする
+ */
"enableAll": string;
+ /**
+ * 全て無効にする
+ */
"disableAll": string;
+ /**
+ * アカウントへのアクセス許可
+ */
"tokenRequested": string;
+ /**
+ * このプラグインはここで設定した権限を行使できるようになります。
+ */
"pluginTokenRequestedDescription": string;
+ /**
+ * 通知の種類
+ */
"notificationType": string;
+ /**
+ * 編集
+ */
"edit": string;
+ /**
+ * メールサーバー
+ */
"emailServer": string;
+ /**
+ * メール配信機能を有効化する
+ */
"enableEmail": string;
+ /**
+ * メールアドレスの確認やパスワードリセットの際に使います
+ */
"emailConfigInfo": string;
+ /**
+ * メール
+ */
"email": string;
+ /**
+ * メールアドレス
+ */
"emailAddress": string;
+ /**
+ * SMTP サーバーの設定
+ */
"smtpConfig": string;
+ /**
+ * ホスト
+ */
"smtpHost": string;
+ /**
+ * ポート
+ */
"smtpPort": string;
+ /**
+ * ユーザー名
+ */
"smtpUser": string;
+ /**
+ * パスワード
+ */
"smtpPass": string;
+ /**
+ * ユーザー名とパスワードを空欄にすることで、SMTP認証を無効化出来ます
+ */
"emptyToDisableSmtpAuth": string;
+ /**
+ * SMTP 接続に暗黙的なSSL/TLSを使用する
+ */
"smtpSecure": string;
+ /**
+ * STARTTLS使用時はオフにします。
+ */
"smtpSecureInfo": string;
+ /**
+ * 配信テスト
+ */
"testEmail": string;
+ /**
+ * ワードミュート
+ */
"wordMute": string;
+ /**
+ * 正規表現エラー
+ */
"regexpError": string;
- "regexpErrorDescription": string;
+ /**
+ * {tab}ワードミュートの{line}行目の正規表現にエラーが発生しました:
+ */
+ "regexpErrorDescription": ParameterizedString<"tab" | "line">;
+ /**
+ * サーバーミュート
+ */
"instanceMute": string;
- "userSaysSomething": string;
+ /**
+ * {name}が何かを言いました
+ */
+ "userSaysSomething": ParameterizedString<"name">;
+ /**
+ * アクティブにする
+ */
"makeActive": string;
+ /**
+ * 表示
+ */
"display": string;
+ /**
+ * コピー
+ */
"copy": string;
+ /**
+ * メトリクス
+ */
"metrics": string;
+ /**
+ * 概要
+ */
"overview": string;
+ /**
+ * ログ
+ */
"logs": string;
+ /**
+ * 遅延
+ */
"delayed": string;
+ /**
+ * データベース
+ */
"database": string;
+ /**
+ * チャンネル
+ */
"channel": string;
+ /**
+ * 作成
+ */
"create": string;
+ /**
+ * 通知設定
+ */
"notificationSetting": string;
+ /**
+ * 表示する通知の種別を選択してください。
+ */
"notificationSettingDesc": string;
+ /**
+ * グローバル設定を使う
+ */
"useGlobalSetting": string;
+ /**
+ * オンにすると、アカウントの通知設定が使用されます。オフにすると、個別に設定できるようになります。
+ */
"useGlobalSettingDesc": string;
+ /**
+ * その他
+ */
"other": string;
+ /**
+ * ログイントークンを再生成
+ */
"regenerateLoginToken": string;
+ /**
+ * ログインに使用される内部トークンを再生成します。通常この操作を行う必要はありません。再生成すると、全てのデバイスでログアウトされます。
+ */
"regenerateLoginTokenDescription": string;
+ /**
+ * カスタム絵文字を検索する時のキーワードになります。
+ */
+ "theKeywordWhenSearchingForCustomEmoji": string;
+ /**
+ * スペースで区切って複数設定できます。
+ */
"setMultipleBySeparatingWithSpace": string;
+ /**
+ * ファイルIDまたはURL
+ */
"fileIdOrUrl": string;
+ /**
+ * 動作
+ */
"behavior": string;
+ /**
+ * サンプル
+ */
"sample": string;
+ /**
+ * 通報
+ */
"abuseReports": string;
+ /**
+ * 通報
+ */
"reportAbuse": string;
+ /**
+ * リノートを通報
+ */
"reportAbuseRenote": string;
- "reportAbuseOf": string;
+ /**
+ * {name}を通報する
+ */
+ "reportAbuseOf": ParameterizedString<"name">;
+ /**
+ * 通報理由の詳細を記入してください。対象のノートがある場合はそのURLも記入してください。
+ */
"fillAbuseReportDescription": string;
+ /**
+ * 内容が送信されました。ご報告ありがとうございました。
+ */
"abuseReported": string;
+ /**
+ * 通報者
+ */
"reporter": string;
+ /**
+ * 通報先
+ */
"reporteeOrigin": string;
+ /**
+ * 通報元
+ */
"reporterOrigin": string;
+ /**
+ * リモートサーバーに通報を転送する
+ */
"forwardReport": string;
+ /**
+ * リモートサーバーからはあなたの情報は見れず、匿名のシステムアカウントとして表示されます。
+ */
"forwardReportIsAnonymous": string;
+ /**
+ * 送信
+ */
"send": string;
+ /**
+ * 対応済みにする
+ */
"abuseMarkAsResolved": string;
+ /**
+ * 新しいタブで開く
+ */
"openInNewTab": string;
+ /**
+ * サイドビューで開く
+ */
"openInSideView": string;
+ /**
+ * デフォルトのナビゲーション
+ */
"defaultNavigationBehaviour": string;
+ /**
+ * これらの設定を編集するとアカウントが破損する可能性があります。
+ */
"editTheseSettingsMayBreakAccount": string;
+ /**
+ * ノートのサーバー情報
+ */
"instanceTicker": string;
- "waitingFor": string;
+ /**
+ * {x}を待っています
+ */
+ "waitingFor": ParameterizedString<"x">;
+ /**
+ * ランダム
+ */
"random": string;
+ /**
+ * システム
+ */
"system": string;
+ /**
+ * UI切り替え
+ */
"switchUi": string;
+ /**
+ * デスクトップ
+ */
"desktop": string;
+ /**
+ * クリップ
+ */
"clip": string;
+ /**
+ * 新規作成
+ */
"createNew": string;
+ /**
+ * 任意
+ */
"optional": string;
+ /**
+ * 新しいクリップを作成
+ */
"createNewClip": string;
+ /**
+ * クリップ解除
+ */
"unclip": string;
- "confirmToUnclipAlreadyClippedNote": string;
+ /**
+ * このノートはすでにクリップ「{name}」に含まれています。ノートをこのクリップから除外しますか?
+ */
+ "confirmToUnclipAlreadyClippedNote": ParameterizedString<"name">;
+ /**
+ * パブリック
+ */
"public": string;
+ /**
+ * 非公開
+ */
"private": string;
- "i18nInfo": string;
+ /**
+ * Misskeyは有志によって様々な言語に翻訳されています。{link}で翻訳に協力できます。
+ */
+ "i18nInfo": ParameterizedString<"link">;
+ /**
+ * アクセストークンの管理
+ */
"manageAccessTokens": string;
+ /**
+ * アカウント情報
+ */
"accountInfo": string;
+ /**
+ * ノートの数
+ */
"notesCount": string;
+ /**
+ * 返信した数
+ */
"repliesCount": string;
+ /**
+ * リノートした数
+ */
"renotesCount": string;
+ /**
+ * 返信された数
+ */
"repliedCount": string;
+ /**
+ * リノートされた数
+ */
"renotedCount": string;
+ /**
+ * フォロー数
+ */
"followingCount": string;
+ /**
+ * フォロワー数
+ */
"followersCount": string;
+ /**
+ * リアクションした数
+ */
"sentReactionsCount": string;
+ /**
+ * リアクションされた数
+ */
"receivedReactionsCount": string;
+ /**
+ * アンケートに投票した数
+ */
"pollVotesCount": string;
+ /**
+ * アンケートに投票された数
+ */
"pollVotedCount": string;
+ /**
+ * はい
+ */
"yes": string;
+ /**
+ * いいえ
+ */
"no": string;
+ /**
+ * ドライブのファイル数
+ */
"driveFilesCount": string;
+ /**
+ * ドライブ使用量
+ */
"driveUsage": string;
+ /**
+ * クローラーによるインデックスを拒否
+ */
"noCrawle": string;
+ /**
+ * 外部の検索エンジンにあなたのユーザーページ、ノート、Pagesなどのコンテンツを登録(インデックス)しないよう要求します。
+ */
"noCrawleDescription": string;
+ /**
+ * フォローを承認制にしても、ノートの公開範囲を「フォロワー」にしない限り、誰でもあなたのノートを見ることができます。
+ */
"lockedAccountInfo": string;
+ /**
+ * デフォルトでメディアをセンシティブ設定にする
+ */
"alwaysMarkSensitive": string;
+ /**
+ * 添付画像のサムネイルをオリジナル画質にする
+ */
"loadRawImages": string;
+ /**
+ * アニメーション画像を再生しない
+ */
"disableShowingAnimatedImages": string;
+ /**
+ * メディアがセンシティブであることを分かりやすく表示
+ */
"highlightSensitiveMedia": string;
+ /**
+ * 確認のメールを送信しました。メールに記載されたリンクにアクセスして、設定を完了してください。
+ */
"verificationEmailSent": string;
+ /**
+ * 未設定
+ */
"notSet": string;
+ /**
+ * メールアドレスが確認されました
+ */
"emailVerified": string;
+ /**
+ * お気に入りノートの数
+ */
"noteFavoritesCount": string;
+ /**
+ * Pageにいいねした数
+ */
"pageLikesCount": string;
+ /**
+ * Pageにいいねされた数
+ */
"pageLikedCount": string;
+ /**
+ * 連絡先
+ */
"contact": string;
+ /**
+ * システムのデフォルトのフォントを使う
+ */
"useSystemFont": string;
+ /**
+ * クリップ
+ */
"clips": string;
+ /**
+ * 実験的機能
+ */
"experimentalFeatures": string;
+ /**
+ * 実験的
+ */
"experimental": string;
+ /**
+ * これは実験的な機能です。仕様が変更されたり、正常に動作しなかったりする可能性があります。
+ */
"thisIsExperimentalFeature": string;
+ /**
+ * 開発者
+ */
"developer": string;
+ /**
+ * アカウントを見つけやすくする
+ */
"makeExplorable": string;
+ /**
+ * オフにすると、「みつける」にアカウントが載らなくなります。
+ */
"makeExplorableDescription": string;
+ /**
+ * タイムラインのノートを離して表示
+ */
"showGapBetweenNotesInTimeline": string;
+ /**
+ * 複製
+ */
"duplicate": string;
+ /**
+ * 左
+ */
"left": string;
+ /**
+ * 中央
+ */
"center": string;
+ /**
+ * 広い
+ */
"wide": string;
+ /**
+ * 狭い
+ */
"narrow": string;
+ /**
+ * 設定はページリロード後に反映されます。今すぐリロードしますか?
+ */
"reloadToApplySetting": string;
+ /**
+ * 反映には再起動が必要です。
+ */
"needReloadToApply": string;
+ /**
+ * タイトルバーを表示する
+ */
"showTitlebar": string;
+ /**
+ * キャッシュをクリア
+ */
"clearCache": string;
- "onlineUsersCount": string;
- "nUsers": string;
- "nNotes": string;
+ /**
+ * {n}人がオンライン
+ */
+ "onlineUsersCount": ParameterizedString<"n">;
+ /**
+ * {n}ユーザー
+ */
+ "nUsers": ParameterizedString<"n">;
+ /**
+ * {n}ノート
+ */
+ "nNotes": ParameterizedString<"n">;
+ /**
+ * エラーリポートを送信
+ */
"sendErrorReports": string;
+ /**
+ * オンにすると、問題が発生したときにエラーの詳細情報がMisskeyに共有され、ソフトウェアの品質向上に役立てることができます。エラー情報には、OSのバージョン、ブラウザの種類、行動履歴などが含まれます。
+ */
"sendErrorReportsDescription": string;
+ /**
+ * マイテーマ
+ */
"myTheme": string;
+ /**
+ * 背景
+ */
"backgroundColor": string;
+ /**
+ * アクセント
+ */
"accentColor": string;
+ /**
+ * 文字
+ */
"textColor": string;
+ /**
+ * 名前を付けて保存
+ */
"saveAs": string;
+ /**
+ * 高度
+ */
"advanced": string;
+ /**
+ * 高度な設定
+ */
"advancedSettings": string;
+ /**
+ * 値
+ */
"value": string;
+ /**
+ * 作成日時
+ */
"createdAt": string;
+ /**
+ * 更新日時
+ */
"updatedAt": string;
+ /**
+ * 保存しますか?
+ */
"saveConfirm": string;
+ /**
+ * 削除しますか?
+ */
"deleteConfirm": string;
+ /**
+ * 有効な値ではありません。
+ */
"invalidValue": string;
+ /**
+ * レジストリ
+ */
"registry": string;
+ /**
+ * アカウントを閉鎖する
+ */
"closeAccount": string;
+ /**
+ * 現在のバージョン
+ */
"currentVersion": string;
+ /**
+ * 最新のバージョン
+ */
"latestVersion": string;
+ /**
+ * お使いのクライアントは最新です。
+ */
"youAreRunningUpToDateClient": string;
+ /**
+ * 新しいバージョンのクライアントが利用可能です。
+ */
"newVersionOfClientAvailable": string;
+ /**
+ * 使用量
+ */
"usageAmount": string;
+ /**
+ * 容量
+ */
"capacity": string;
+ /**
+ * 使用中
+ */
"inUse": string;
+ /**
+ * コードを編集
+ */
"editCode": string;
+ /**
+ * 適用
+ */
"apply": string;
+ /**
+ * サーバーからのお知らせを受け取る
+ */
"receiveAnnouncementFromInstance": string;
+ /**
+ * メール通知
+ */
"emailNotification": string;
+ /**
+ * 公開
+ */
"publish": string;
+ /**
+ * チャンネル内検索
+ */
"inChannelSearch": string;
+ /**
+ * 右クリックでリアクションピッカーを開く
+ */
"useReactionPickerForContextMenu": string;
- "typingUsers": string;
+ /**
+ * {users}が入力中
+ */
+ "typingUsers": ParameterizedString<"users">;
+ /**
+ * 特定の日付にジャンプ
+ */
"jumpToSpecifiedDate": string;
+ /**
+ * 過去のタイムラインを表示しています
+ */
"showingPastTimeline": string;
+ /**
+ * クリア
+ */
"clear": string;
+ /**
+ * 全て既読にする
+ */
"markAllAsRead": string;
+ /**
+ * 戻る
+ */
"goBack": string;
+ /**
+ * いいね解除しますか?
+ */
"unlikeConfirm": string;
+ /**
+ * フルビュー
+ */
"fullView": string;
+ /**
+ * フルビュー解除
+ */
"quitFullView": string;
+ /**
+ * 説明を追加
+ */
"addDescription": string;
+ /**
+ * 個々のノートのメニューから「ピン留め」を選択することで、ここにノートを表示しておくことができます。
+ */
"userPagePinTip": string;
+ /**
+ * 宛先に含まれていないメンションがあります
+ */
"notSpecifiedMentionWarning": string;
+ /**
+ * 情報
+ */
"info": string;
+ /**
+ * ユーザー情報
+ */
"userInfo": string;
+ /**
+ * 不明
+ */
"unknown": string;
+ /**
+ * オンライン状態
+ */
"onlineStatus": string;
+ /**
+ * オンライン状態を隠す
+ */
"hideOnlineStatus": string;
+ /**
+ * オンライン状態を隠すと、検索などの一部機能において利便性が低下することがあります。
+ */
"hideOnlineStatusDescription": string;
+ /**
+ * オンライン
+ */
"online": string;
+ /**
+ * アクティブ
+ */
"active": string;
+ /**
+ * オフライン
+ */
"offline": string;
+ /**
+ * 非推奨
+ */
"notRecommended": string;
+ /**
+ * Botプロテクション
+ */
"botProtection": string;
+ /**
+ * サーバーブロック・サイレンス
+ */
"instanceBlocking": string;
+ /**
+ * アカウントを選択
+ */
"selectAccount": string;
+ /**
+ * アカウントを切り替え
+ */
"switchAccount": string;
+ /**
+ * 有効
+ */
"enabled": string;
+ /**
+ * 無効
+ */
"disabled": string;
+ /**
+ * クイックアクション
+ */
"quickAction": string;
+ /**
+ * ユーザー
+ */
"user": string;
+ /**
+ * 管理
+ */
"administration": string;
+ /**
+ * アカウント
+ */
"accounts": string;
+ /**
+ * 切り替え
+ */
"switch": string;
+ /**
+ * 管理者情報が設定されていません。
+ */
"noMaintainerInformationWarning": string;
+ /**
+ * Botプロテクションが設定されていません。
+ */
"noBotProtectionWarning": string;
+ /**
+ * 設定する
+ */
"configure": string;
+ /**
+ * ギャラリーへ投稿
+ */
"postToGallery": string;
+ /**
+ * このハッシュタグで投稿
+ */
"postToHashtag": string;
+ /**
+ * ギャラリー
+ */
"gallery": string;
+ /**
+ * 最近の投稿
+ */
"recentPosts": string;
+ /**
+ * 人気の投稿
+ */
"popularPosts": string;
+ /**
+ * ノートで共有
+ */
"shareWithNote": string;
+ /**
+ * 広告
+ */
"ads": string;
+ /**
+ * 期限
+ */
"expiration": string;
+ /**
+ * 開始期間
+ */
"startingperiod": string;
+ /**
+ * メモ
+ */
"memo": string;
+ /**
+ * 優先度
+ */
"priority": string;
+ /**
+ * 高
+ */
"high": string;
+ /**
+ * 中
+ */
"middle": string;
+ /**
+ * 低
+ */
"low": string;
+ /**
+ * メールアドレスの設定がされていません。
+ */
"emailNotConfiguredWarning": string;
+ /**
+ * 比率
+ */
"ratio": string;
+ /**
+ * 本文をプレビュー
+ */
"previewNoteText": string;
+ /**
+ * カスタムCSS
+ */
"customCss": string;
+ /**
+ * この設定は必ず知識のある方が行ってください。不適切な設定を行うとクライアントが正常に使用できなくなる恐れがあります。
+ */
"customCssWarn": string;
+ /**
+ * グローバル
+ */
"global": string;
+ /**
+ * アイコンを四角形で表示
+ */
"squareAvatars": string;
+ /**
+ * 送信
+ */
"sent": string;
+ /**
+ * 受信
+ */
"received": string;
+ /**
+ * 検索結果
+ */
"searchResult": string;
+ /**
+ * ハッシュタグ
+ */
"hashtags": string;
+ /**
+ * トラブルシューティング
+ */
"troubleshooting": string;
+ /**
+ * UIにぼかし効果を使用
+ */
"useBlurEffect": string;
+ /**
+ * 詳しく
+ */
"learnMore": string;
+ /**
+ * Misskeyが更新されました!
+ */
"misskeyUpdated": string;
+ /**
+ * 更新情報を見る
+ */
"whatIsNew": string;
+ /**
+ * 翻訳
+ */
"translate": string;
- "translatedFrom": string;
+ /**
+ * {x}から翻訳
+ */
+ "translatedFrom": ParameterizedString<"x">;
+ /**
+ * アカウントの削除が進行中です
+ */
"accountDeletionInProgress": string;
+ /**
+ * サーバー上であなたのアカウントを一意に識別するための名前。アルファベット(a~z, A~Z)、数字(0~9)、およびアンダーバー(_)が使用できます。ユーザー名は後から変更することは出来ません。
+ */
"usernameInfo": string;
+ /**
+ * 藍モード
+ */
"aiChanMode": string;
+ /**
+ * 開発者モード
+ */
"devMode": string;
+ /**
+ * CWを維持する
+ */
"keepCw": string;
+ /**
+ * Pub/Subのアカウント
+ */
"pubSub": string;
+ /**
+ * 直近の通信
+ */
"lastCommunication": string;
+ /**
+ * 解決済み
+ */
"resolved": string;
+ /**
+ * 未解決
+ */
"unresolved": string;
+ /**
+ * フォロワーを解除
+ */
"breakFollow": string;
+ /**
+ * フォロワー解除しますか?
+ */
"breakFollowConfirm": string;
+ /**
+ * オンになっています
+ */
"itsOn": string;
+ /**
+ * オフになっています
+ */
"itsOff": string;
+ /**
+ * オン
+ */
"on": string;
+ /**
+ * オフ
+ */
"off": string;
+ /**
+ * アカウント登録にメールアドレスを必須にする
+ */
"emailRequiredForSignup": string;
+ /**
+ * 未読
+ */
"unread": string;
+ /**
+ * フィルタ
+ */
"filter": string;
+ /**
+ * コントロールパネル
+ */
"controlPanel": string;
+ /**
+ * アカウントを管理
+ */
"manageAccounts": string;
+ /**
+ * リアクション一覧を公開する
+ */
"makeReactionsPublic": string;
+ /**
+ * あなたがしたリアクション一覧を誰でも見れるようにします。
+ */
"makeReactionsPublicDescription": string;
+ /**
+ * クラシック
+ */
"classic": string;
+ /**
+ * スレッドをミュート
+ */
"muteThread": string;
+ /**
+ * スレッドのミュートを解除
+ */
"unmuteThread": string;
- "ffVisibility": string;
- "ffVisibilityDescription": string;
+ /**
+ * フォローの公開範囲
+ */
+ "followingVisibility": string;
+ /**
+ * フォロワーの公開範囲
+ */
+ "followersVisibility": string;
+ /**
+ * さらにスレッドを見る
+ */
"continueThread": string;
+ /**
+ * アカウントが削除されます。よろしいですか?
+ */
"deleteAccountConfirm": string;
+ /**
+ * パスワードが間違っています。
+ */
"incorrectPassword": string;
- "voteConfirm": string;
+ /**
+ * 「{choice}」に投票しますか?
+ */
+ "voteConfirm": ParameterizedString<"choice">;
+ /**
+ * 隠す
+ */
"hide": string;
+ /**
+ * モバイルデバイスのときドロワーで表示
+ */
"useDrawerReactionPickerForMobile": string;
- "welcomeBackWithName": string;
- "clickToFinishEmailVerification": string;
+ /**
+ * おかえりなさい、{name}さん
+ */
+ "welcomeBackWithName": ParameterizedString<"name">;
+ /**
+ * [{ok}]を押して、メールアドレスの確認を完了してください。
+ */
+ "clickToFinishEmailVerification": ParameterizedString<"ok">;
+ /**
+ * デバイスタイプ
+ */
"overridedDeviceKind": string;
+ /**
+ * スマートフォン
+ */
"smartphone": string;
+ /**
+ * タブレット
+ */
"tablet": string;
+ /**
+ * 自動
+ */
"auto": string;
+ /**
+ * テーマカラー
+ */
"themeColor": string;
+ /**
+ * サイズ
+ */
"size": string;
+ /**
+ * 列の数
+ */
"numberOfColumn": string;
+ /**
+ * 検索
+ */
"searchByGoogle": string;
+ /**
+ * サーバーデフォルトのライトテーマ
+ */
"instanceDefaultLightTheme": string;
+ /**
+ * サーバーデフォルトのダークテーマ
+ */
"instanceDefaultDarkTheme": string;
+ /**
+ * オブジェクト形式のテーマコードを記入します。
+ */
"instanceDefaultThemeDescription": string;
+ /**
+ * ミュートする期限
+ */
"mutePeriod": string;
+ /**
+ * 期限
+ */
"period": string;
+ /**
+ * 無期限
+ */
"indefinitely": string;
+ /**
+ * 10分
+ */
"tenMinutes": string;
+ /**
+ * 1時間
+ */
"oneHour": string;
+ /**
+ * 1日
+ */
"oneDay": string;
+ /**
+ * 1週間
+ */
"oneWeek": string;
+ /**
+ * 1ヶ月
+ */
"oneMonth": string;
+ /**
+ * 反映されるまで時間がかかる場合があります。
+ */
"reflectMayTakeTime": string;
+ /**
+ * アカウント情報の取得に失敗しました
+ */
"failedToFetchAccountInformation": string;
+ /**
+ * レート制限を超えました
+ */
"rateLimitExceeded": string;
+ /**
+ * 画像のクロップ
+ */
"cropImage": string;
+ /**
+ * 画像をクロップしますか?
+ */
"cropImageAsk": string;
+ /**
+ * クロップする
+ */
"cropYes": string;
+ /**
+ * そのまま使う
+ */
"cropNo": string;
+ /**
+ * ファイル
+ */
"file": string;
- "recentNHours": string;
- "recentNDays": string;
+ /**
+ * 直近{n}時間
+ */
+ "recentNHours": ParameterizedString<"n">;
+ /**
+ * 直近{n}日
+ */
+ "recentNDays": ParameterizedString<"n">;
+ /**
+ * メールサーバーの設定がされていません。
+ */
"noEmailServerWarning": string;
+ /**
+ * 未対応の通報があります。
+ */
"thereIsUnresolvedAbuseReportWarning": string;
+ /**
+ * 推奨
+ */
"recommended": string;
+ /**
+ * チェック
+ */
"check": string;
+ /**
+ * このユーザーのドライブ容量上限を変更
+ */
"driveCapOverrideLabel": string;
+ /**
+ * 0以下を指定すると解除されます。
+ */
"driveCapOverrideCaption": string;
+ /**
+ * 閲覧するには管理者アカウントでログインしている必要があります。
+ */
"requireAdminForView": string;
+ /**
+ * システムにより自動で作成・管理されているアカウントです。
+ */
"isSystemAccount": string;
- "typeToConfirm": string;
+ /**
+ * この操作を行うには {x} と入力してください
+ */
+ "typeToConfirm": ParameterizedString<"x">;
+ /**
+ * アカウント削除
+ */
"deleteAccount": string;
+ /**
+ * ドキュメント
+ */
"document": string;
+ /**
+ * ページキャッシュ数
+ */
"numberOfPageCache": string;
+ /**
+ * 多くすると利便性が向上しますが、負荷とメモリ使用量が増えます。
+ */
"numberOfPageCacheDescription": string;
+ /**
+ * ログアウトしますか?
+ */
"logoutConfirm": string;
+ /**
+ * 最終利用日時
+ */
"lastActiveDate": string;
+ /**
+ * ステータスバー
+ */
"statusbar": string;
+ /**
+ * 選択してください
+ */
"pleaseSelect": string;
+ /**
+ * 反転
+ */
"reverse": string;
+ /**
+ * 色付き
+ */
"colored": string;
+ /**
+ * 更新間隔
+ */
"refreshInterval": string;
+ /**
+ * ラベル
+ */
"label": string;
+ /**
+ * タイプ
+ */
"type": string;
+ /**
+ * 速度
+ */
"speed": string;
+ /**
+ * 遅い
+ */
"slow": string;
+ /**
+ * 速い
+ */
"fast": string;
+ /**
+ * センシティブなメディアの検出
+ */
"sensitiveMediaDetection": string;
+ /**
+ * ローカルのみ
+ */
"localOnly": string;
+ /**
+ * リモートのみ
+ */
"remoteOnly": string;
+ /**
+ * アップロード失敗
+ */
"failedToUpload": string;
+ /**
+ * 不適切な内容を含む可能性があると判定されたためアップロードできません。
+ */
"cannotUploadBecauseInappropriate": string;
+ /**
+ * ドライブの空き容量が無いためアップロードできません。
+ */
"cannotUploadBecauseNoFreeSpace": string;
+ /**
+ * ファイルサイズの制限を超えているためアップロードできません。
+ */
"cannotUploadBecauseExceedsFileSizeLimit": string;
+ /**
+ * ベータ
+ */
"beta": string;
+ /**
+ * 自動センシティブ判定
+ */
"enableAutoSensitive": string;
+ /**
+ * 利用可能な場合は、機械学習を利用して自動でメディアにセンシティブフラグを設定します。この機能をオフにしても、サーバーによっては自動で設定されることがあります。
+ */
"enableAutoSensitiveDescription": string;
+ /**
+ * ユーザーのメールアドレスのバリデーションを、捨てアドかどうかや実際に通信可能かどうかなどを判定しより積極的に行います。オフにすると単に文字列として正しいかどうかのみチェックされます。
+ */
"activeEmailValidationDescription": string;
+ /**
+ * ナビゲーションバー
+ */
"navbar": string;
+ /**
+ * シャッフル
+ */
"shuffle": string;
+ /**
+ * アカウント
+ */
"account": string;
+ /**
+ * 移動
+ */
"move": string;
+ /**
+ * プッシュ通知
+ */
"pushNotification": string;
+ /**
+ * プッシュ通知を有効化
+ */
"subscribePushNotification": string;
+ /**
+ * プッシュ通知を停止する
+ */
"unsubscribePushNotification": string;
+ /**
+ * プッシュ通知は有効です
+ */
"pushNotificationAlreadySubscribed": string;
+ /**
+ * ブラウザかサーバーがプッシュ通知に非対応
+ */
"pushNotificationNotSupported": string;
+ /**
+ * 通知が既読になったらプッシュ通知を削除する
+ */
"sendPushNotificationReadMessage": string;
+ /**
+ * 端末の電池消費量が増加する可能性があります。
+ */
"sendPushNotificationReadMessageCaption": string;
+ /**
+ * 最大化
+ */
"windowMaximize": string;
+ /**
+ * 最小化
+ */
"windowMinimize": string;
+ /**
+ * 元に戻す
+ */
"windowRestore": string;
+ /**
+ * キャプション
+ */
"caption": string;
+ /**
+ * Botアカウントでログイン中
+ */
"loggedInAsBot": string;
+ /**
+ * ツール
+ */
"tools": string;
+ /**
+ * 読み込めません
+ */
"cannotLoad": string;
+ /**
+ * プロフィール表示回数
+ */
"numberOfProfileView": string;
+ /**
+ * いいね!
+ */
"like": string;
+ /**
+ * いいねを解除
+ */
"unlike": string;
+ /**
+ * いいね数
+ */
"numberOfLikes": string;
+ /**
+ * 表示
+ */
"show": string;
+ /**
+ * 今後表示しない
+ */
"neverShow": string;
+ /**
+ * また後で
+ */
"remindMeLater": string;
+ /**
+ * Misskeyを気に入っていただけましたか?
+ */
"didYouLikeMisskey": string;
- "pleaseDonate": string;
+ /**
+ * Misskeyは{host}が使用している無料のソフトウェアです。これからも開発を続けられるように、ぜひ寄付をお願いします!
+ */
+ "pleaseDonate": ParameterizedString<"host">;
+ /**
+ * 対応するソースコードは{anchor}から利用可能です。
+ */
+ "correspondingSourceIsAvailable": ParameterizedString<"anchor">;
+ /**
+ * ロール
+ */
"roles": string;
+ /**
+ * ロール
+ */
"role": string;
+ /**
+ * ロールはありません
+ */
"noRole": string;
+ /**
+ * 一般ユーザー
+ */
"normalUser": string;
+ /**
+ * 未定義
+ */
"undefined": string;
+ /**
+ * アサイン
+ */
"assign": string;
+ /**
+ * アサインを解除
+ */
"unassign": string;
+ /**
+ * 色
+ */
"color": string;
+ /**
+ * カスタム絵文字の管理
+ */
"manageCustomEmojis": string;
+ /**
+ * アバターデコレーションの管理
+ */
"manageAvatarDecorations": string;
+ /**
+ * これ以上作成することはできません。
+ */
"youCannotCreateAnymore": string;
+ /**
+ * 一時的に利用できません
+ */
"cannotPerformTemporary": string;
+ /**
+ * 操作回数が制限を超過するため一時的に利用できません。しばらく時間を置いてから再度お試しください。
+ */
"cannotPerformTemporaryDescription": string;
+ /**
+ * パラメータエラー
+ */
"invalidParamError": string;
+ /**
+ * リクエストパラメータに問題があります。通常これはバグですが、入力した文字数が多すぎる等の可能性もあります。
+ */
"invalidParamErrorDescription": string;
+ /**
+ * 操作が拒否されました
+ */
"permissionDeniedError": string;
+ /**
+ * このアカウントにはこの操作を行うための権限がありません。
+ */
"permissionDeniedErrorDescription": string;
+ /**
+ * プリセット
+ */
"preset": string;
+ /**
+ * プリセットから選択
+ */
"selectFromPresets": string;
+ /**
+ * 実績
+ */
"achievements": string;
+ /**
+ * サーバーの応答が無効です
+ */
"gotInvalidResponseError": string;
+ /**
+ * サーバーがダウンまたはメンテナンスしている可能性があります。しばらくしてから再度お試しください。
+ */
"gotInvalidResponseErrorDescription": string;
+ /**
+ * この投稿は迷惑になる可能性があります。
+ */
"thisPostMayBeAnnoying": string;
+ /**
+ * ホームに投稿
+ */
"thisPostMayBeAnnoyingHome": string;
+ /**
+ * やめる
+ */
"thisPostMayBeAnnoyingCancel": string;
+ /**
+ * このまま投稿
+ */
"thisPostMayBeAnnoyingIgnore": string;
+ /**
+ * 見たことのあるリノートを省略して表示
+ */
"collapseRenotes": string;
+ /**
+ * サーバー内部エラー
+ */
"internalServerError": string;
+ /**
+ * サーバー内部で予期しないエラーが発生しました。
+ */
"internalServerErrorDescription": string;
+ /**
+ * エラー情報をコピー
+ */
"copyErrorInfo": string;
+ /**
+ * このサーバーに登録する
+ */
"joinThisServer": string;
+ /**
+ * 他のサーバーを探す
+ */
"exploreOtherServers": string;
+ /**
+ * タイムラインを見てみる
+ */
"letsLookAtTimeline": string;
+ /**
+ * 連合なしにしますか?
+ */
"disableFederationConfirm": string;
+ /**
+ * 連合なしにしても投稿は非公開になりません。ほとんどの場合、連合なしにする必要はありません。
+ */
"disableFederationConfirmWarn": string;
+ /**
+ * 連合なしにする
+ */
"disableFederationOk": string;
+ /**
+ * 現在このサーバーは招待制です。招待コードをお持ちの方のみ登録できます。
+ */
"invitationRequiredToRegister": string;
+ /**
+ * このサーバーではメール配信はサポートされていません
+ */
"emailNotSupported": string;
+ /**
+ * チャンネルに投稿
+ */
"postToTheChannel": string;
+ /**
+ * 後から変更できません。
+ */
"cannotBeChangedLater": string;
+ /**
+ * リアクションの受け入れ
+ */
"reactionAcceptance": string;
+ /**
+ * いいねのみ
+ */
"likeOnly": string;
+ /**
+ * 全て (リモートはいいねのみ)
+ */
"likeOnlyForRemote": string;
+ /**
+ * 非センシティブのみ
+ */
"nonSensitiveOnly": string;
+ /**
+ * 非センシティブのみ (リモートはいいねのみ)
+ */
"nonSensitiveOnlyForLocalLikeOnlyForRemote": string;
+ /**
+ * 自分に割り当てられたロール
+ */
"rolesAssignedToMe": string;
+ /**
+ * パスワードリセットしますか?
+ */
"resetPasswordConfirm": string;
+ /**
+ * センシティブワード
+ */
"sensitiveWords": string;
+ /**
+ * 設定したワードが含まれるノートの公開範囲をホームにします。改行で区切って複数設定できます。
+ */
"sensitiveWordsDescription": string;
+ /**
+ * スペースで区切るとAND指定になり、キーワードをスラッシュで囲むと正規表現になります。
+ */
"sensitiveWordsDescription2": string;
+ /**
+ * 禁止ワード
+ */
+ "prohibitedWords": string;
+ /**
+ * 設定したワードが含まれるノートを投稿しようとした際、エラーとなるようにします。改行で区切って複数設定できます。
+ */
+ "prohibitedWordsDescription": string;
+ /**
+ * スペースで区切るとAND指定になり、キーワードをスラッシュで囲むと正規表現になります。
+ */
+ "prohibitedWordsDescription2": string;
+ /**
+ * 非表示ハッシュタグ
+ */
+ "hiddenTags": string;
+ /**
+ * 設定したタグをトレンドに表示させないようにします。改行で区切って複数設定できます。
+ */
+ "hiddenTagsDescription": string;
+ /**
+ * ノート検索は利用できません。
+ */
"notesSearchNotAvailable": string;
+ /**
+ * ライセンス
+ */
"license": string;
+ /**
+ * リクエスト
+ */
+ "request": string;
+ /**
+ * お気に入り解除しますか?
+ */
"unfavoriteConfirm": string;
+ /**
+ * 自分のクリップ
+ */
"myClips": string;
+ /**
+ * ドライブクリーナー
+ */
"drivecleaner": string;
+ /**
+ * すべてのキューを今すぐ再試行
+ */
"retryAllQueuesNow": string;
+ /**
+ * 今すぐ再試行しますか?
+ */
"retryAllQueuesConfirmTitle": string;
+ /**
+ * 一時的にサーバーの負荷が増大することがあります。
+ */
"retryAllQueuesConfirmText": string;
+ /**
+ * リモートユーザーのチャートを生成
+ */
"enableChartsForRemoteUser": string;
+ /**
+ * リモートサーバーのチャートを生成
+ */
"enableChartsForFederatedInstances": string;
+ /**
+ * ノートのアクションにクリップを追加
+ */
"showClipButtonInNoteFooter": string;
+ /**
+ * リアクションの表示サイズ
+ */
"reactionsDisplaySize": string;
+ /**
+ * リアクションの最大横幅を制限し、縮小して表示する
+ */
+ "limitWidthOfReaction": string;
+ /**
+ * ノートIDまたはURL
+ */
"noteIdOrUrl": string;
+ /**
+ * 動画
+ */
"video": string;
+ /**
+ * 動画
+ */
"videos": string;
+ /**
+ * 音声
+ */
+ "audio": string;
+ /**
+ * 音声
+ */
+ "audioFiles": string;
+ /**
+ * データセーバー
+ */
"dataSaver": string;
+ /**
+ * アカウントの移行
+ */
"accountMigration": string;
+ /**
+ * このユーザーは新しいアカウントに移行しました:
+ */
"accountMoved": string;
+ /**
+ * このアカウントは移行されています
+ */
"accountMovedShort": string;
+ /**
+ * この操作はできません
+ */
"operationForbidden": string;
+ /**
+ * 常に広告を表示する
+ */
"forceShowAds": string;
+ /**
+ * メモを追加
+ */
"addMemo": string;
+ /**
+ * メモを編集
+ */
"editMemo": string;
+ /**
+ * リアクション一覧
+ */
"reactionsList": string;
+ /**
+ * リノート一覧
+ */
"renotesList": string;
+ /**
+ * 通知の表示
+ */
"notificationDisplay": string;
+ /**
+ * 左上
+ */
"leftTop": string;
+ /**
+ * 右上
+ */
"rightTop": string;
+ /**
+ * 左下
+ */
"leftBottom": string;
+ /**
+ * 右下
+ */
"rightBottom": string;
+ /**
+ * スタック方向
+ */
"stackAxis": string;
+ /**
+ * 縦
+ */
"vertical": string;
+ /**
+ * 横
+ */
"horizontal": string;
+ /**
+ * 位置
+ */
"position": string;
+ /**
+ * サーバールール
+ */
"serverRules": string;
+ /**
+ * このサーバーに登録するには、以下の内容を確認し同意する必要があります。
+ */
"pleaseConfirmBelowBeforeSignup": string;
+ /**
+ * 続けるには、全ての「同意する」にチェックが入っている必要があります。
+ */
"pleaseAgreeAllToContinue": string;
+ /**
+ * 続ける
+ */
"continue": string;
+ /**
+ * 予約ユーザー名
+ */
"preservedUsernames": string;
+ /**
+ * 予約するユーザー名を改行で列挙します。ここで指定されたユーザー名はアカウント作成時に使えなくなりますが、管理者によるアカウント作成時はこの制限を受けません。また、既に存在するアカウントも影響を受けません。
+ */
"preservedUsernamesDescription": string;
+ /**
+ * このファイルからノートを作成
+ */
"createNoteFromTheFile": string;
+ /**
+ * アーカイブ
+ */
"archive": string;
- "channelArchiveConfirmTitle": string;
+ /**
+ * {name}をアーカイブしますか?
+ */
+ "channelArchiveConfirmTitle": ParameterizedString<"name">;
+ /**
+ * アーカイブすると、チャンネル一覧や検索結果に表示されなくなり、新たな書き込みもできなくなります。
+ */
"channelArchiveConfirmDescription": string;
+ /**
+ * このチャンネルはアーカイブされています。
+ */
"thisChannelArchived": string;
+ /**
+ * ノートの表示
+ */
"displayOfNote": string;
+ /**
+ * 初期設定
+ */
"initialAccountSetting": string;
+ /**
+ * フォロー中
+ */
"youFollowing": string;
+ /**
+ * 生成AIによる学習を拒否
+ */
"preventAiLearning": string;
+ /**
+ * 外部の文章生成AIや画像生成AIに対して、投稿したノートや画像などのコンテンツを学習の対象にしないように要求します。これはnoaiフラグをHTMLレスポンスに含めることによって実現されますが、この要求に従うかはそのAI次第であるため、学習を完全に防止するものではありません。
+ */
"preventAiLearningDescription": string;
+ /**
+ * オプション
+ */
"options": string;
+ /**
+ * ユーザー指定
+ */
"specifyUser": string;
+ /**
+ * プレビューできません
+ */
"failedToPreviewUrl": string;
+ /**
+ * 更新
+ */
"update": string;
+ /**
+ * リアクションとして使えるロール
+ */
"rolesThatCanBeUsedThisEmojiAsReaction": string;
+ /**
+ * ロールの指定が一つもない場合、誰でもリアクションとして使えます。
+ */
"rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription": string;
+ /**
+ * ロールは公開ロールである必要があります。
+ */
"rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn": string;
+ /**
+ * リアクションとして使えないロール
+ */
+ "rolesThatCanNotBeUsedThisEmojiAsReaction": string;
+ /**
+ * リアクションを取り消しますか?
+ */
"cancelReactionConfirm": string;
+ /**
+ * リアクションを変更しますか?
+ */
"changeReactionConfirm": string;
+ /**
+ * あとで
+ */
"later": string;
+ /**
+ * Misskeyへ
+ */
"goToMisskey": string;
+ /**
+ * 絵文字の追加辞書
+ */
"additionalEmojiDictionary": string;
+ /**
+ * インストール済み
+ */
"installed": string;
+ /**
+ * ブランディング
+ */
"branding": string;
+ /**
+ * ダイアログを閉じるまでの待機時間
+ */
+ "dialogCloseDuration": string;
+ /**
+ * サーバーのマシン情報を公開する
+ */
"enableServerMachineStats": string;
+ /**
+ * ユーザーごとのIdenticon生成を有効にする
+ */
"enableIdenticonGeneration": string;
+ /**
+ * オフにするとパフォーマンスが向上します。
+ */
"turnOffToImprovePerformance": string;
+ /**
+ * 招待コードを作成
+ */
"createInviteCode": string;
+ /**
+ * オプションを指定して作成
+ */
"createWithOptions": string;
+ /**
+ * 作成数
+ */
"createCount": string;
+ /**
+ * 招待コードを作成しました
+ */
"inviteCodeCreated": string;
+ /**
+ * 作成できる招待コードの数が上限に達しています。
+ */
"inviteLimitExceeded": string;
- "createLimitRemaining": string;
- "inviteLimitResetCycle": string;
+ /**
+ * 作成できる招待コード: 残り {limit} 個
+ */
+ "createLimitRemaining": ParameterizedString<"limit">;
+ /**
+ * {time}で最大 {limit} 個の招待コードを作成できます。
+ */
+ "inviteLimitResetCycle": ParameterizedString<"time" | "limit">;
+ /**
+ * 有効期限
+ */
"expirationDate": string;
+ /**
+ * 有効期限を設けない
+ */
"noExpirationDate": string;
+ /**
+ * 招待コードが使用された日時
+ */
"inviteCodeUsedAt": string;
+ /**
+ * 招待コードを使用したユーザー
+ */
"registeredUserUsingInviteCode": string;
+ /**
+ * メール認証待ち
+ */
"waitingForMailAuth": string;
+ /**
+ * 招待コードを作成したユーザー
+ */
"inviteCodeCreator": string;
+ /**
+ * 使用日時
+ */
"usedAt": string;
+ /**
+ * 未使用
+ */
"unused": string;
+ /**
+ * 使用済み
+ */
"used": string;
+ /**
+ * 期限切れ
+ */
"expired": string;
+ /**
+ * 同意しますか?
+ */
"doYouAgree": string;
+ /**
+ * 重要ですので必ずお読みください。
+ */
"beSureToReadThisAsItIsImportant": string;
- "iHaveReadXCarefullyAndAgree": string;
+ /**
+ * 「{x}」の内容をよく読み、同意します。
+ */
+ "iHaveReadXCarefullyAndAgree": ParameterizedString<"x">;
+ /**
+ * ダイアログ
+ */
"dialog": string;
+ /**
+ * アイコン
+ */
"icon": string;
+ /**
+ * あなたへ
+ */
"forYou": string;
+ /**
+ * 現在のお知らせ
+ */
"currentAnnouncements": string;
+ /**
+ * 過去のお知らせ
+ */
"pastAnnouncements": string;
+ /**
+ * 未読のお知らせがあります。
+ */
"youHaveUnreadAnnouncements": string;
+ /**
+ * ブラウザまたはデバイスの指示に従って、セキュリティキーまたはパスキーを使用してください。
+ */
"useSecurityKey": string;
+ /**
+ * 返信
+ */
"replies": string;
+ /**
+ * リノート
+ */
"renotes": string;
+ /**
+ * 返信を見る
+ */
"loadReplies": string;
+ /**
+ * 会話を見る
+ */
"loadConversation": string;
+ /**
+ * ピン留めされたリスト
+ */
"pinnedList": string;
+ /**
+ * デバイスの画面を常にオンにする
+ */
"keepScreenOn": string;
+ /**
+ * このリンク先の所有者であることが確認されました
+ */
"verifiedLink": string;
+ /**
+ * 投稿を通知
+ */
"notifyNotes": string;
+ /**
+ * 投稿の通知を解除
+ */
"unnotifyNotes": string;
+ /**
+ * 認証
+ */
"authentication": string;
+ /**
+ * 続けるには認証を行ってください
+ */
"authenticationRequiredToContinue": string;
+ /**
+ * 日時
+ */
"dateAndTime": string;
+ /**
+ * リノートを表示
+ */
"showRenotes": string;
+ /**
+ * 編集済み
+ */
"edited": string;
+ /**
+ * 通知の受信設定
+ */
"notificationRecieveConfig": string;
+ /**
+ * 相互フォロー
+ */
"mutualFollow": string;
+ /**
+ * フォロー中またはフォロワー
+ */
+ "followingOrFollower": string;
+ /**
+ * ファイル付きのみ
+ */
"fileAttachedOnly": string;
+ /**
+ * TLに他の人への返信を含める
+ */
"showRepliesToOthersInTimeline": string;
+ /**
+ * TLに他の人への返信を含めない
+ */
"hideRepliesToOthersInTimeline": string;
+ /**
+ * TLに現在フォロー中の人全員の返信を含めるようにする
+ */
"showRepliesToOthersInTimelineAll": string;
+ /**
+ * TLに現在フォロー中の人全員の返信を含めないようにする
+ */
"hideRepliesToOthersInTimelineAll": string;
+ /**
+ * この操作は元に戻せません。本当にTLに現在フォロー中の人全員の返信を含めるようにしますか?
+ */
"confirmShowRepliesAll": string;
+ /**
+ * この操作は元に戻せません。本当にTLに現在フォロー中の人全員の返信を含めないようにしますか?
+ */
"confirmHideRepliesAll": string;
+ /**
+ * 外部サービス
+ */
"externalServices": string;
+ /**
+ * ソースコード
+ */
+ "sourceCode": string;
+ /**
+ * ソースコードはまだ提供されていません。この問題の修正について管理者に問い合わせてください。
+ */
+ "sourceCodeIsNotYetProvided": string;
+ /**
+ * リポジトリURL
+ */
+ "repositoryUrl": string;
+ /**
+ * ソースコードが公開されているリポジトリがある場合、そのURLを記入します。Misskeyを現状のまま(ソースコードにいかなる変更も加えずに)使用している場合は https://github.com/misskey-dev/misskey と記入します。
+ */
+ "repositoryUrlDescription": string;
+ /**
+ * フィードバック
+ */
+ "feedback": string;
+ /**
+ * フィードバックURL
+ */
+ "feedbackUrl": string;
+ /**
+ * お問い合わせ
+ */
+ "support": string;
+ /**
+ * {name}を支援
+ */
+ "supportThisInstance": ParameterizedString<"name">;
+ /**
+ * 運営者情報
+ */
"impressum": string;
+ /**
+ * 運営者情報URL
+ */
"impressumUrl": string;
+ /**
+ * ドイツなどの一部の国と地域では表示が義務付けられています(Impressum)。
+ */
"impressumDescription": string;
+ /**
+ * プライバシーポリシー
+ */
"privacyPolicy": string;
+ /**
+ * プライバシーポリシーURL
+ */
"privacyPolicyUrl": string;
+ /**
+ * 利用規約・プライバシーポリシー
+ */
"tosAndPrivacyPolicy": string;
+ /**
+ * アイコンデコレーション
+ */
"avatarDecorations": string;
+ /**
+ * 付ける
+ */
"attach": string;
+ /**
+ * 外す
+ */
"detach": string;
+ /**
+ * 全て外す
+ */
+ "detachAll": string;
+ /**
+ * 角度
+ */
"angle": string;
+ /**
+ * 反転
+ */
"flip": string;
+ /**
+ * アイコンのデコレーションを表示
+ */
"showAvatarDecorations": string;
+ /**
+ * 離してリロード
+ */
"releaseToRefresh": string;
+ /**
+ * リロード中
+ */
"refreshing": string;
+ /**
+ * 引っ張ってリロード
+ */
"pullDownToRefresh": string;
+ /**
+ * タイムラインのリアルタイム更新を無効にする
+ */
"disableStreamingTimeline": string;
+ /**
+ * 通知をグルーピングして表示する
+ */
"useGroupedNotifications": string;
+ /**
+ * メールアドレスの確認中に問題が発生しました。リンクの有効期限が切れている可能性があります。
+ */
"signupPendingError": string;
+ /**
+ * 「内容を隠す」がオンの場合は注釈の記述が必要です。
+ */
"cwNotationRequired": string;
+ /**
+ * リアクションする
+ */
"doReaction": string;
+ /**
+ * サムネイルの表示を制限するURL
+ */
+ "urlPreviewDenyList": string;
+ /**
+ * スペースで区切るとAND指定になり、改行で区切るとOR指定になります。スラッシュで囲むと正規表現になります。一致した場合、サムネイルがぼかされて表示されます。
+ */
+ "urlPreviewDenyListDescription": string;
+ /**
+ * コード
+ */
+ "code": string;
+ /**
+ * 設定の反映にはリロードが必要です。
+ */
+ "reloadRequiredToApplySettings": string;
+ /**
+ * 残り: {n}
+ */
+ "remainingN": ParameterizedString<"n">;
+ /**
+ * 現在の内容に上書きされますがよろしいですか?
+ */
+ "overwriteContentConfirm": string;
+ /**
+ * 季節に応じた画面の演出
+ */
+ "seasonalScreenEffect": string;
+ /**
+ * デコる
+ */
+ "decorate": string;
+ /**
+ * 装飾を追加
+ */
+ "addMfmFunction": string;
+ /**
+ * 高度なMFMのピッカーを表示する
+ */
+ "enableQuickAddMfmFunction": string;
+ /**
+ * バブルゲーム
+ */
+ "bubbleGame": string;
+ /**
+ * 効果音
+ */
+ "sfx": string;
+ /**
+ * サウンドが再生されます
+ */
+ "soundWillBePlayed": string;
+ /**
+ * リプレイを見る
+ */
+ "showReplay": string;
+ /**
+ * リプレイ
+ */
+ "replay": string;
+ /**
+ * リプレイ中
+ */
+ "replaying": string;
+ /**
+ * リプレイを終了
+ */
+ "endReplay": string;
+ /**
+ * リプレイデータをコピー
+ */
+ "copyReplayData": string;
+ /**
+ * ランキング
+ */
+ "ranking": string;
+ /**
+ * 直近{n}日
+ */
+ "lastNDays": ParameterizedString<"n">;
+ /**
+ * タイトルへ
+ */
+ "backToTitle": string;
+ /**
+ * お住まいの地域
+ */
+ "hemisphere": string;
+ /**
+ * センシティブなファイルを含むノートを表示
+ */
+ "withSensitive": string;
+ /**
+ * {name}のセンシティブなファイルを含む投稿
+ */
+ "userSaysSomethingSensitive": ParameterizedString<"name">;
+ /**
+ * スワイプしてタブを切り替える
+ */
+ "enableHorizontalSwipe": string;
+ /**
+ * 読み込み中
+ */
+ "loading": string;
+ /**
+ * やめる
+ */
+ "surrender": string;
+ /**
+ * リトライ
+ */
+ "gameRetry": string;
+ /**
+ * 通報の種類
+ */
+ "abuseReportCategory": string;
+ /**
+ * カテゴリを選択
+ */
+ "selectCategory": string;
+ /**
+ * 通報完了
+ */
+ "reportComplete": string;
+ /**
+ * このユーザーをブロックする
+ */
+ "blockThisUser": string;
+ /**
+ * このユーザーをミュートする
+ */
+ "muteThisUser": string;
+ "_bubbleGame": {
+ /**
+ * 遊び方
+ */
+ "howToPlay": string;
+ /**
+ * ホールド
+ */
+ "hold": string;
+ "_score": {
+ /**
+ * スコア
+ */
+ "score": string;
+ /**
+ * 稼いだ金額
+ */
+ "scoreYen": string;
+ /**
+ * ハイスコア
+ */
+ "highScore": string;
+ /**
+ * 最大チェーン数
+ */
+ "maxChain": string;
+ /**
+ * {yen}円
+ */
+ "yen": ParameterizedString<"yen">;
+ /**
+ * {qty}個分
+ */
+ "estimatedQty": ParameterizedString<"qty">;
+ /**
+ * おにぎり {onigiriQtyWithUnit}
+ */
+ "scoreSweets": ParameterizedString<"onigiriQtyWithUnit">;
+ };
+ "_howToPlay": {
+ /**
+ * 位置を調整してハコにモノを落とします。
+ */
+ "section1": string;
+ /**
+ * 同じ種類のモノがくっつくと別のモノに変化して、スコアが得られます。
+ */
+ "section2": string;
+ /**
+ * モノがハコからあふれるとゲームオーバーです。ハコからあふれないようにしつつモノを融合させてハイスコアを目指そう!
+ */
+ "section3": string;
+ };
+ };
+ "_abuseReportMsgs": {
+ /**
+ * 申し訳ございません。権利侵害の通報は権利者ご本人からのみ受け付けております。
+ */
+ "rightsAbuseCantAccept": string;
+ };
+ "_abuseReportCategory": {
+ /**
+ * センシティブなコンテンツを含む投稿
+ */
+ "nsfw": string;
+ /**
+ * スパム
+ */
+ "spam": string;
+ /**
+ * 暴力もしくは攻撃的な投稿
+ */
+ "explicit": string;
+ /**
+ * フィッシングもしくは詐欺行為
+ */
+ "phishing": string;
+ /**
+ * 本人もしくは他人の個人情報の漏えい
+ */
+ "personalInfoLeak": string;
+ /**
+ * 自殺もしくは自害など生命に関わる問題
+ */
+ "selfHarm": string;
+ /**
+ * 重大な規約違反
+ */
+ "criticalBreach": string;
+ /**
+ * その他の規約違反
+ */
+ "otherBreach": string;
+ /**
+ * 権利侵害もしくはなりすまし(本人)
+ */
+ "violationRights": string;
+ /**
+ * 権利侵害(他人)
+ */
+ "violationRightsOther": string;
+ /**
+ * この人が気に入らない
+ */
+ "notLike": string;
+ /**
+ * その他
+ */
+ "other": string;
+ };
"_announcement": {
+ /**
+ * 既存ユーザーのみ
+ */
"forExistingUsers": string;
+ /**
+ * 有効にすると、このお知らせ作成時点で存在するユーザーにのみお知らせが表示されます。無効にすると、このお知らせ作成後にアカウントを作成したユーザーにもお知らせが表示されます。
+ */
"forExistingUsersDescription": string;
+ /**
+ * 既読にするのに確認が必要
+ */
"needConfirmationToRead": string;
+ /**
+ * 有効にすると、このお知らせを既読にする際に確認ダイアログが表示されます。また、一括既読操作の対象になりません。
+ */
"needConfirmationToReadDescription": string;
+ /**
+ * お知らせを終了
+ */
"end": string;
+ /**
+ * アクティブなお知らせが多いため、UXが低下する可能性があります。終了したお知らせはアーカイブすることを検討してください。
+ */
"tooManyActiveAnnouncementDescription": string;
+ /**
+ * 既読にしますか?
+ */
"readConfirmTitle": string;
- "readConfirmText": string;
+ /**
+ * 「{title}」の内容を読み、既読にします。
+ */
+ "readConfirmText": ParameterizedString<"title">;
+ /**
+ * 特に新規ユーザーのUXを損ねる可能性が高いため、常時掲示するための情報ではなく、即時性が求められる情報の掲示のためにお知らせを使用することを推奨します。
+ */
"shouldNotBeUsedToPresentPermanentInfo": string;
+ /**
+ * ダイアログ形式のお知らせが同時に2つ以上ある場合、UXに悪影響を及ぼす可能性が非常に高いため、使用は慎重に行うことを推奨します。
+ */
"dialogAnnouncementUxWarn": string;
+ /**
+ * 非通知
+ */
"silence": string;
+ /**
+ * オンにすると、このお知らせは通知されず、既読にする必要もなくなります。
+ */
"silenceDescription": string;
};
"_initialAccountSetting": {
+ /**
+ * アカウントの作成が完了しました!
+ */
"accountCreated": string;
+ /**
+ * さっそくアカウントの初期設定を行いましょう。
+ */
"letsStartAccountSetup": string;
+ /**
+ * まずはあなたのプロフィールを設定しましょう。
+ */
"letsFillYourProfile": string;
+ /**
+ * プロフィール設定
+ */
"profileSetting": string;
+ /**
+ * プライバシー設定
+ */
"privacySetting": string;
+ /**
+ * これらの設定は後から変更できます。
+ */
"theseSettingsCanEditLater": string;
+ /**
+ * この他にも様々な設定を「設定」ページから行えます。ぜひ後で確認してみてください。
+ */
"youCanEditMoreSettingsInSettingsPageLater": string;
+ /**
+ * タイムラインを構築するため、気になるユーザーをフォローしてみましょう。
+ */
"followUsers": string;
- "pushNotificationDescription": string;
+ /**
+ * プッシュ通知を有効にすると{name}の通知をお使いのデバイスで受け取ることができます。
+ */
+ "pushNotificationDescription": ParameterizedString<"name">;
+ /**
+ * 初期設定が完了しました!
+ */
"initialAccountSettingCompleted": string;
- "haveFun": string;
- "youCanContinueTutorial": string;
+ /**
+ * {name}をお楽しみください!
+ */
+ "haveFun": ParameterizedString<"name">;
+ /**
+ * このまま{name}(Misskey)の使い方についてのチュートリアルに進むこともできますが、ここで中断してすぐに使い始めることもできます。
+ */
+ "youCanContinueTutorial": ParameterizedString<"name">;
+ /**
+ * チュートリアルを開始
+ */
"startTutorial": string;
+ /**
+ * 初期設定をスキップしますか?
+ */
"skipAreYouSure": string;
+ /**
+ * 初期設定をあとでやり直しますか?
+ */
"laterAreYouSure": string;
};
"_initialTutorial": {
+ /**
+ * チュートリアルを見る
+ */
"launchTutorial": string;
+ /**
+ * チュートリアル
+ */
"title": string;
+ /**
+ * よくできました
+ */
"wellDone": string;
+ /**
+ * チュートリアルを終了しますか?
+ */
"skipAreYouSure": string;
"_landing": {
+ /**
+ * チュートリアルへようこそ
+ */
"title": string;
+ /**
+ * ここでは、Misskeyの基本的な使い方や機能を確認できます。
+ */
"description": string;
};
"_note": {
+ /**
+ * ノートって何?
+ */
"title": string;
+ /**
+ * Misskeyでの投稿は「ノート」と呼びます。ノートはタイムラインに時系列で並んでいて、リアルタイムで更新されていきます。
+ */
"description": string;
+ /**
+ * 返信することができます。返信に対しての返信も可能で、スレッドのように会話を続けることもできます。
+ */
"reply": string;
+ /**
+ * そのノートを自分のタイムラインに流して共有することができます。テキストを追加して引用することも可能です。
+ */
"renote": string;
+ /**
+ * リアクションをつけることができます。詳しくは次のページで解説します。
+ */
"reaction": string;
+ /**
+ * ノートの詳細を表示したり、リンクをコピーしたりなどの様々な操作が行えます。
+ */
"menu": string;
};
"_reaction": {
+ /**
+ * リアクションって何?
+ */
"title": string;
+ /**
+ * ノートには「リアクション」をつけることができます。「いいね」では伝わらないニュアンスも、リアクションで簡単・気軽に表現できます。
+ */
"description": string;
+ /**
+ * リアクションは、ノートの「+」ボタンをクリックするとつけられます。試しにこのサンプルのノートにリアクションをつけてみてください!
+ */
"letsTryReacting": string;
+ /**
+ * リアクションをつけると先に進めるようになります。
+ */
"reactToContinue": string;
+ /**
+ * あなたのノートが誰かにリアクションされると、リアルタイムで通知を受け取ります。
+ */
"reactNotification": string;
+ /**
+ * 「ー」ボタンを押すとリアクションを取り消すことができます。
+ */
"reactDone": string;
};
"_timeline": {
+ /**
+ * タイムラインのしくみ
+ */
"title": string;
+ /**
+ * Misskeyには、使い方に応じて複数のタイムラインが用意されています(サーバーによってはいずれかが無効になっていることがあります)。
+ */
"description1": string;
+ /**
+ * あなたがフォローしているアカウントの投稿を見られます。
+ */
"home": string;
+ /**
+ * このサーバーにいるユーザー全員の投稿を見られます。
+ */
"local": string;
+ /**
+ * ホームタイムラインとローカルタイムラインの投稿が両方表示されます。
+ */
"social": string;
+ /**
+ * 接続している他のすべてのサーバーからの投稿を見られます。
+ */
"global": string;
+ /**
+ * それぞれのタイムラインは、画面上部でいつでも切り替えられます。
+ */
"description2": string;
- "description3": string;
+ /**
+ * その他にも、リストタイムラインやチャンネルタイムラインなどがあります。詳しくは{link}をご覧ください。
+ */
+ "description3": ParameterizedString<"link">;
};
"_postNote": {
+ /**
+ * ノートの投稿設定
+ */
"title": string;
+ /**
+ * Misskeyにノートを投稿する際には、様々なオプションの設定が可能です。投稿フォームはこのようになっています。
+ */
"description1": string;
"_visibility": {
+ /**
+ * ノートを表示できる相手を制限できます。
+ */
"description": string;
+ /**
+ * すべてのユーザーに公開。
+ */
"public": string;
+ /**
+ * ホームタイムラインのみに公開。フォロワー・プロフィールを見に来た人・リノートから、他のユーザーも見ることができます。
+ */
"home": string;
+ /**
+ * フォロワーにのみ公開。本人以外がリノートすることはできず、またフォロワー以外は閲覧できません。
+ */
"followers": string;
+ /**
+ * 指定したユーザーにのみ公開され、また相手に通知が入ります。ダイレクトメッセージのかわりにお使いいただけます。
+ */
"direct": string;
+ /**
+ * 機密情報は送信する際は注意してください。
+ */
"doNotSendConfidencialOnDirect1": string;
+ /**
+ * 送信先のサーバーの管理者は投稿内容を見ることが可能なので、信頼できないサーバーのユーザーにダイレクト投稿を送信する場合は、機密情報の扱いに注意が必要です。
+ */
"doNotSendConfidencialOnDirect2": string;
+ /**
+ * 他のサーバーに投稿を連合しません。上記の公開範囲に関わらず、他のサーバーのユーザーは、この設定がついたノートを直接閲覧することができなくなります。
+ */
"localOnly": string;
};
"_cw": {
+ /**
+ * 内容を隠す(CW)
+ */
"title": string;
+ /**
+ * 本文のかわりに「注釈」に書いた内容が表示されます。「もっと見る」を押すと本文が表示されます。
+ */
"description": string;
"_exampleNote": {
+ /**
+ * 飯テロ注意
+ */
"cw": string;
+ /**
+ * チョコのかかったドーナツを食べました🍩😋
+ */
"note": string;
};
+ /**
+ * サーバーのガイドラインにより必要とされるノートに指定したり、ネタバレ投稿やセンシティブな文章を自主規制したりするときに使います。
+ */
"useCases": string;
};
};
"_howToMakeAttachmentsSensitive": {
+ /**
+ * 添付ファイルをセンシティブにするには?
+ */
"title": string;
+ /**
+ * サーバーのガイドラインにより必要とされる際や、そのまま見れる状態にしておくべきではない添付ファイルには、「センシティブ」設定を付けます。
+ */
"description": string;
+ /**
+ * 試しに、このフォームに添付された画像をセンシティブにしてみてください!
+ */
"tryThisFile": string;
"_exampleNote": {
+ /**
+ * 納豆のフタ開けるのミスったわね…
+ */
"note": string;
};
+ /**
+ * 添付ファイルをセンシティブにする際は、そのファイルをクリックしてメニューを開き、「センシティブとして設定」をクリックします。
+ */
"method": string;
+ /**
+ * ファイルを添付する際は、サーバーのガイドラインに従ってセンシティブを適切に設定してください。
+ */
"sensitiveSucceeded": string;
+ /**
+ * 画像をセンシティブに設定すると先に進めるようになります。
+ */
"doItToContinue": string;
};
"_done": {
+ /**
+ * チュートリアルは終了です🎉
+ */
"title": string;
- "description": string;
+ /**
+ * ここで紹介した機能はほんの一部にすぎません。Misskeyの使い方をより詳しく知るには、{link}をご覧ください。
+ */
+ "description": ParameterizedString<"link">;
};
};
"_timelineDescription": {
+ /**
+ * ホームタイムラインでは、あなたがフォローしているアカウントの投稿を見られます。
+ */
"home": string;
+ /**
+ * ローカルタイムラインでは、このサーバーにいるユーザー全員の投稿を見られます。
+ */
"local": string;
+ /**
+ * ソーシャルタイムラインには、ホームタイムラインとローカルタイムラインの投稿が両方表示されます。
+ */
"social": string;
+ /**
+ * グローバルタイムラインでは、接続している他のすべてのサーバーからの投稿を見られます。
+ */
"global": string;
};
"_serverRules": {
+ /**
+ * 新規登録前に表示する、サーバーの簡潔なルールを設定します。内容は利用規約の要約とすることを推奨します。
+ */
"description": string;
};
"_serverSettings": {
+ /**
+ * アイコン画像のURL
+ */
"iconUrl": string;
- "appIconDescription": string;
+ /**
+ * {host}がアプリとして表示される際のアイコンを指定します。
+ */
+ "appIconDescription": ParameterizedString<"host">;
+ /**
+ * 例: PWAや、スマートフォンのホーム画面にブックマークとして追加された時など
+ */
"appIconUsageExample": string;
+ /**
+ * 円形もしくは角丸にクロップされる場合があるため、塗り潰された余白のある背景を持つことが推奨されます。
+ */
"appIconStyleRecommendation": string;
- "appIconResolutionMustBe": string;
+ /**
+ * 解像度は必ず{resolution}である必要があります。
+ */
+ "appIconResolutionMustBe": ParameterizedString<"resolution">;
+ /**
+ * manifest.jsonのオーバーライド
+ */
"manifestJsonOverride": string;
+ /**
+ * 略称
+ */
"shortName": string;
+ /**
+ * サーバーの正式名称が長い場合に、代わりに表示することのできる略称や通称。
+ */
"shortNameDescription": string;
+ /**
+ * 有効にすると、各種タイムラインを取得する際のパフォーマンスが大幅に向上し、データベースへの負荷を軽減することが可能です。ただし、Redisのメモリ使用量は増加します。サーバーのメモリ容量が少ない場合、または動作が不安定な場合は無効にすることができます。
+ */
"fanoutTimelineDescription": string;
+ /**
+ * データベースへのフォールバック
+ */
"fanoutTimelineDbFallback": string;
+ /**
+ * 有効にすると、タイムラインがキャッシュされていない場合にDBへ追加で問い合わせを行うフォールバック処理を行います。無効にすると、フォールバック処理を行わないことでさらにサーバーの負荷を軽減することができますが、タイムラインが取得できる範囲に制限が生じます。
+ */
"fanoutTimelineDbFallbackDescription": string;
};
"_accountMigration": {
+ /**
+ * 別のアカウントからこのアカウントに移行
+ */
"moveFrom": string;
+ /**
+ * 別のアカウントへエイリアスを作成
+ */
"moveFromSub": string;
- "moveFromLabel": string;
+ /**
+ * 移行元のアカウント #{n}
+ */
+ "moveFromLabel": ParameterizedString<"n">;
+ /**
+ * 別のアカウントからこのアカウントに移行したい場合、ここでエイリアスを作成しておく必要があります。
+ * 移行元のアカウントをこのように入力してください: @username@server.example.com
+ * 削除するには、入力欄を空にして保存します(非推奨)。
+ */
"moveFromDescription": string;
+ /**
+ * このアカウントを新しいアカウントへ移行
+ */
"moveTo": string;
+ /**
+ * 移行先のアカウント:
+ */
"moveToLabel": string;
+ /**
+ * アカウントを移行すると、取り消すことはできません。
+ */
"moveCannotBeUndone": string;
+ /**
+ * 新しいアカウントへ移行します。
+ * ・フォロワーが新しいアカウントを自動でフォローします
+ * ・このアカウントからのフォローは全て解除されます
+ * ・このアカウントではノートの作成などができなくなります
+ *
+ * フォロワーの移行は自動ですが、フォローの移行は手動で行う必要があります。移行前にこのアカウントでフォローエクスポートし、移行後すぐに移行先アカウントでインポートを行なってください。
+ * リスト・ミュート・ブロックについても同様ですので、手動で移行する必要があります。
+ *
+ * (この説明はこのサーバー(Misskey v13.12.0以降)の仕様です。Mastodonなどの他のActivityPubソフトウェアでは挙動が異なる場合があります。)
+ */
"moveAccountDescription": string;
+ /**
+ * アカウントの移行には、まずは移行先のアカウントでこのアカウントに対しエイリアスを作成します。
+ * エイリアス作成後、移行先のアカウントを次のように入力してください: @username@server.example.com
+ */
"moveAccountHowTo": string;
+ /**
+ * 移行する
+ */
"startMigration": string;
- "migrationConfirm": string;
+ /**
+ * 本当にこのアカウントを {account} に移行しますか?一度移行すると取り消せず、二度とこのアカウントを元の状態で使用できなくなります。
+ */
+ "migrationConfirm": ParameterizedString<"account">;
+ /**
+ *
+ * アカウントは移行されています。
+ * 移行を取り消すことはできません。
+ */
"movedAndCannotBeUndone": string;
+ /**
+ * このアカウントからのフォロー解除は移行操作から24時間後に実行されます。
+ * このアカウントのフォロー・フォロワー数は0になっています。フォロワーの解除はされないため、あなたのフォロワーはこのアカウントのフォロワー向け投稿を引き続き閲覧できます。
+ */
"postMigrationNote": string;
+ /**
+ * 移行先のアカウント:
+ */
"movedTo": string;
};
"_achievements": {
+ /**
+ * 獲得日時
+ */
"earnedAt": string;
"_types": {
"_notes1": {
+ /**
+ * just setting up my msky
+ */
"title": string;
+ /**
+ * 初めてノートを投稿した
+ */
"description": string;
+ /**
+ * 良いMisskeyライフを!
+ */
"flavor": string;
};
"_notes10": {
+ /**
+ * いくつかのノート
+ */
"title": string;
+ /**
+ * ノートを10回投稿した
+ */
"description": string;
};
"_notes100": {
+ /**
+ * たくさんのノート
+ */
"title": string;
+ /**
+ * ノートを100回投稿した
+ */
"description": string;
};
"_notes500": {
+ /**
+ * ノートまみれ
+ */
"title": string;
+ /**
+ * ノートを500回投稿した
+ */
"description": string;
};
"_notes1000": {
+ /**
+ * ノートの山
+ */
"title": string;
+ /**
+ * ノートを1,000回投稿した
+ */
"description": string;
};
"_notes5000": {
+ /**
+ * 湧き出るノート
+ */
"title": string;
+ /**
+ * ノートを5,000回投稿した
+ */
"description": string;
};
"_notes10000": {
+ /**
+ * スーパーノート
+ */
"title": string;
+ /**
+ * ノートを10,000回投稿した
+ */
"description": string;
};
"_notes20000": {
+ /**
+ * ニードモアノート
+ */
"title": string;
+ /**
+ * ノートを20,000回投稿した
+ */
"description": string;
};
"_notes30000": {
+ /**
+ * ノートノートノート
+ */
"title": string;
+ /**
+ * ノートを30,000回投稿した
+ */
"description": string;
};
"_notes40000": {
+ /**
+ * ノート工場
+ */
"title": string;
+ /**
+ * ノートを40,000回投稿した
+ */
"description": string;
};
"_notes50000": {
+ /**
+ * ノートの惑星
+ */
"title": string;
+ /**
+ * ノートを50,000回投稿した
+ */
"description": string;
};
"_notes60000": {
+ /**
+ * ノートクエーサー
+ */
"title": string;
+ /**
+ * ノートを60,000回投稿した
+ */
"description": string;
};
"_notes70000": {
+ /**
+ * ブラックノートホール
+ */
"title": string;
+ /**
+ * ノートを70,000回投稿した
+ */
"description": string;
};
"_notes80000": {
+ /**
+ * ノートギャラクシー
+ */
"title": string;
+ /**
+ * ノートを80,000回投稿した
+ */
"description": string;
};
"_notes90000": {
+ /**
+ * ノートバース
+ */
"title": string;
+ /**
+ * ノートを90,000回投稿した
+ */
"description": string;
};
"_notes100000": {
+ /**
+ * ALL YOUR NOTE ARE BELONG TO US
+ */
"title": string;
+ /**
+ * ノートを100,000回投稿した
+ */
"description": string;
+ /**
+ * そんなに書くことある?
+ */
"flavor": string;
};
"_login3": {
+ /**
+ * ビギナーⅠ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が3日
+ */
"description": string;
+ /**
+ * 今日からね僕は ミスキストってことで
+ */
"flavor": string;
};
"_login7": {
+ /**
+ * ビギナーⅡ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が7日
+ */
"description": string;
+ /**
+ * 慣れてきましたか?
+ */
"flavor": string;
};
"_login15": {
+ /**
+ * ビギナーⅢ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が15日
+ */
"description": string;
};
"_login30": {
+ /**
+ * ミスキストⅠ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が30日
+ */
"description": string;
};
"_login60": {
+ /**
+ * ミスキストⅡ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が60日
+ */
"description": string;
};
"_login100": {
+ /**
+ * ミスキストⅢ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が100日
+ */
"description": string;
+ /**
+ * そのユーザー、ミスキストにつき
+ */
"flavor": string;
};
"_login200": {
+ /**
+ * 常連Ⅰ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が200日
+ */
"description": string;
};
"_login300": {
+ /**
+ * 常連Ⅱ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が300日
+ */
"description": string;
};
"_login400": {
+ /**
+ * 常連Ⅲ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が400日
+ */
"description": string;
};
"_login500": {
+ /**
+ * ベテランⅠ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が500日
+ */
"description": string;
+ /**
+ * 諸君、私はノートが好きだ
+ */
"flavor": string;
};
"_login600": {
+ /**
+ * ベテランⅡ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が600日
+ */
"description": string;
};
"_login700": {
+ /**
+ * ベテランⅢ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が700日
+ */
"description": string;
};
"_login800": {
+ /**
+ * ノートマスターⅠ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が800日
+ */
"description": string;
};
"_login900": {
+ /**
+ * ノートマスターⅡ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が900日
+ */
"description": string;
};
"_login1000": {
+ /**
+ * ノートマスターⅢ
+ */
"title": string;
+ /**
+ * 通算ログイン日数が1,000日
+ */
"description": string;
+ /**
+ * Misskeyを使ってくれてありがとう!
+ */
"flavor": string;
};
"_noteClipped1": {
+ /**
+ * クリップせずにはいられないな
+ */
"title": string;
+ /**
+ * 初めてノートをクリップした
+ */
"description": string;
};
"_noteFavorited1": {
+ /**
+ * 星をみるひと
+ */
"title": string;
+ /**
+ * 初めてノートをお気に入りに登録した
+ */
"description": string;
};
"_myNoteFavorited1": {
+ /**
+ * 星が欲しい
+ */
"title": string;
+ /**
+ * 自分のノートが他の人からお気に入りに登録された
+ */
"description": string;
};
"_profileFilled": {
+ /**
+ * 準備万端
+ */
"title": string;
+ /**
+ * プロフィール設定を行った
+ */
"description": string;
};
"_markedAsCat": {
+ /**
+ * 吾輩は猫である
+ */
"title": string;
+ /**
+ * アカウントをCatとして設定した
+ */
"description": string;
+ /**
+ * 名前はまだない。
+ */
"flavor": string;
};
"_following1": {
+ /**
+ * はじめてのフォロー
+ */
"title": string;
+ /**
+ * 初めてフォローした
+ */
"description": string;
};
"_following10": {
+ /**
+ * ついてく、ついてく
+ */
"title": string;
+ /**
+ * フォローが10人を超した
+ */
"description": string;
};
"_following50": {
+ /**
+ * 友達たくさん
+ */
"title": string;
+ /**
+ * フォローが50人を超した
+ */
"description": string;
};
"_following100": {
+ /**
+ * 友達100人
+ */
"title": string;
+ /**
+ * フォローが100人を超した
+ */
"description": string;
};
"_following300": {
+ /**
+ * 友達過多
+ */
"title": string;
+ /**
+ * フォローが300人を超した
+ */
"description": string;
};
"_followers1": {
+ /**
+ * はじめてのフォロワー
+ */
"title": string;
+ /**
+ * 初めてフォローされた
+ */
"description": string;
};
"_followers10": {
+ /**
+ * フォローミー!
+ */
"title": string;
+ /**
+ * フォロワーが10人を超した
+ */
"description": string;
};
"_followers50": {
+ /**
+ * ぞろぞろ
+ */
"title": string;
+ /**
+ * フォロワーが50人を超した
+ */
"description": string;
};
"_followers100": {
+ /**
+ * 人気者
+ */
"title": string;
+ /**
+ * フォロワーが100人を超した
+ */
"description": string;
};
"_followers300": {
+ /**
+ * 一列でお並びください
+ */
"title": string;
+ /**
+ * フォロワーが300人を超した
+ */
"description": string;
};
"_followers500": {
+ /**
+ * 基地局
+ */
"title": string;
+ /**
+ * フォロワーが500人を超した
+ */
"description": string;
};
"_followers1000": {
+ /**
+ * インフルエンサー
+ */
"title": string;
+ /**
+ * フォロワーが1,000人を超した
+ */
"description": string;
};
"_collectAchievements30": {
+ /**
+ * 実績コレクター
+ */
"title": string;
+ /**
+ * 実績を30個以上獲得した
+ */
"description": string;
};
"_viewAchievements3min": {
+ /**
+ * 実績好き
+ */
"title": string;
+ /**
+ * 実績一覧を3分以上眺め続けた
+ */
"description": string;
};
"_iLoveMisskey": {
+ /**
+ * I Love Misskey
+ */
"title": string;
+ /**
+ * "I ❤ #Misskey"を投稿した
+ */
"description": string;
+ /**
+ * Misskeyを使ってくださりありがとうございます! by 開発チーム
+ */
"flavor": string;
};
"_foundTreasure": {
+ /**
+ * 宝探し
+ */
"title": string;
+ /**
+ * 隠されたお宝を発見した
+ */
"description": string;
};
"_client30min": {
+ /**
+ * ひとやすみ
+ */
"title": string;
+ /**
+ * クライアントを起動してから30分以上経過した
+ */
"description": string;
};
"_client60min": {
+ /**
+ * Misskeyの見すぎ
+ */
"title": string;
+ /**
+ * クライアントを起動してから60分以上経過した
+ */
"description": string;
};
"_noteDeletedWithin1min": {
+ /**
+ * いまのなし
+ */
"title": string;
+ /**
+ * 投稿してから1分以内にその投稿を削除した
+ */
"description": string;
};
"_postedAtLateNight": {
+ /**
+ * 夜行性
+ */
"title": string;
+ /**
+ * 深夜にノートを投稿した
+ */
"description": string;
+ /**
+ * そろそろ寝よう。
+ */
"flavor": string;
};
"_postedAt0min0sec": {
+ /**
+ * 時報
+ */
"title": string;
+ /**
+ * 0分0秒にノートを投稿した
+ */
"description": string;
+ /**
+ * ポッ ポッ ポッ ピーン
+ */
"flavor": string;
};
"_selfQuote": {
+ /**
+ * 自己言及
+ */
"title": string;
+ /**
+ * 自分のノートを引用した
+ */
"description": string;
};
"_htl20npm": {
+ /**
+ * 流れるTL
+ */
"title": string;
+ /**
+ * ホームタイムラインの流速が20npmを越す
+ */
"description": string;
};
"_viewInstanceChart": {
+ /**
+ * アナリスト
+ */
"title": string;
+ /**
+ * サーバーのチャートを表示した
+ */
"description": string;
};
"_outputHelloWorldOnScratchpad": {
+ /**
+ * Hello, world!
+ */
"title": string;
+ /**
+ * スクラッチパッドで hello world を出力した
+ */
"description": string;
};
"_open3windows": {
+ /**
+ * マルチウィンドウ
+ */
"title": string;
+ /**
+ * ウィンドウを3つ以上開いた状態にした
+ */
"description": string;
};
"_driveFolderCircularReference": {
+ /**
+ * 循環参照
+ */
"title": string;
+ /**
+ * ドライブのフォルダを再帰的な入れ子にしようとした
+ */
"description": string;
};
"_reactWithoutRead": {
+ /**
+ * ちゃんと読んだ?
+ */
"title": string;
+ /**
+ * 100文字以上のテキストを含むノートに投稿されてから3秒以内にリアクションした
+ */
"description": string;
};
"_clickedClickHere": {
+ /**
+ * ここをクリック
+ */
"title": string;
+ /**
+ * ここをクリックした
+ */
"description": string;
};
"_justPlainLucky": {
+ /**
+ * 単なるラッキー
+ */
"title": string;
+ /**
+ * 10秒ごとに0.005%の確率で獲得
+ */
"description": string;
};
"_setNameToSyuilo": {
+ /**
+ * 神様コンプレックス
+ */
"title": string;
+ /**
+ * 名前を syuilo に設定した
+ */
"description": string;
};
"_passedSinceAccountCreated1": {
+ /**
+ * 一周年
+ */
"title": string;
+ /**
+ * アカウント作成から1年経過した
+ */
"description": string;
};
"_passedSinceAccountCreated2": {
+ /**
+ * 二周年
+ */
"title": string;
+ /**
+ * アカウント作成から2年経過した
+ */
"description": string;
};
"_passedSinceAccountCreated3": {
+ /**
+ * 三周年
+ */
"title": string;
+ /**
+ * アカウント作成から3年経過した
+ */
"description": string;
};
"_loggedInOnBirthday": {
+ /**
+ * ハッピーバースデー
+ */
"title": string;
+ /**
+ * 誕生日にログインした
+ */
"description": string;
};
"_loggedInOnNewYearsDay": {
+ /**
+ * あけましておめでとうございます
+ */
"title": string;
+ /**
+ * 元日にログインした
+ */
"description": string;
+ /**
+ * 今年も弊サーバーをよろしくお願いします
+ */
"flavor": string;
};
"_cookieClicked": {
+ /**
+ * クッキーをクリックするゲーム
+ */
"title": string;
+ /**
+ * クッキーをクリックした
+ */
"description": string;
+ /**
+ * ソフト間違ってない?
+ */
"flavor": string;
};
"_brainDiver": {
+ /**
+ * Brain Diver
+ */
"title": string;
+ /**
+ * Brain Diverへのリンクを投稿した
+ */
"description": string;
+ /**
+ * Misskey-Misskey La-Tu-Ma
+ */
"flavor": string;
};
"_smashTestNotificationButton": {
+ /**
+ * テスト過剰
+ */
"title": string;
+ /**
+ * 通知のテストをごく短時間のうちに連続して行った
+ */
"description": string;
};
"_tutorialCompleted": {
+ /**
+ * Misskey初心者講座 修了証
+ */
"title": string;
+ /**
+ * チュートリアルを完了した
+ */
"description": string;
};
+ "_bubbleGameExplodingHead": {
+ /**
+ * 🤯
+ */
+ "title": string;
+ /**
+ * バブルゲームで最も大きいモノを出した
+ */
+ "description": string;
+ };
+ "_bubbleGameDoubleExplodingHead": {
+ /**
+ * ダブル🤯
+ */
+ "title": string;
+ /**
+ * バブルゲームで最も大きいモノを2つ同時に出した
+ */
+ "description": string;
+ /**
+ * これくらいの おべんとばこに 🤯 🤯 ちょっとつめて
+ */
+ "flavor": string;
+ };
};
};
"_role": {
+ /**
+ * ロールの作成
+ */
"new": string;
+ /**
+ * ロールの編集
+ */
"edit": string;
+ /**
+ * ロール名
+ */
"name": string;
+ /**
+ * ロールの説明
+ */
"description": string;
+ /**
+ * ロールの権限
+ */
"permission": string;
+ /**
+ * モデレーターは基本的なモデレーションに関する操作を行えます。
+ * 管理者はサーバーの全ての設定を変更できます。
+ */
"descriptionOfPermission": string;
+ /**
+ * アサイン
+ */
"assignTarget": string;
+ /**
+ * マニュアルは誰がこのロールに含まれるかを手動で管理します。
+ * コンディショナルは条件を設定し、それに合致するユーザーが自動で含まれるようになります。
+ */
"descriptionOfAssignTarget": string;
+ /**
+ * マニュアル
+ */
"manual": string;
+ /**
+ * マニュアルロール
+ */
+ "manualRoles": string;
+ /**
+ * コンディショナル
+ */
"conditional": string;
+ /**
+ * コンディショナルロール
+ */
+ "conditionalRoles": string;
+ /**
+ * 条件
+ */
"condition": string;
+ /**
+ * これはコンディショナルロールです。
+ */
"isConditionalRole": string;
+ /**
+ * 公開ロール
+ */
"isPublic": string;
+ /**
+ * ユーザーのプロフィールでこのロールが表示されます。
+ */
"descriptionOfIsPublic": string;
+ /**
+ * オプション
+ */
"options": string;
+ /**
+ * ポリシー
+ */
"policies": string;
+ /**
+ * ベースロール
+ */
"baseRole": string;
+ /**
+ * ベースロールの値を使用
+ */
"useBaseValue": string;
+ /**
+ * アサインするロールを選択
+ */
"chooseRoleToAssign": string;
+ /**
+ * アイコン画像のURL
+ */
"iconUrl": string;
+ /**
+ * バッジとして表示
+ */
"asBadge": string;
+ /**
+ * オンにすると、ユーザー名の横にロールのアイコンが表示されます。
+ */
"descriptionOfAsBadge": string;
+ /**
+ * ユーザーを見つけやすくする
+ */
"isExplorable": string;
+ /**
+ * オンにすると、「みつける」でメンバー一覧が公開されるほか、ロールのタイムラインが利用可能になります。
+ */
"descriptionOfIsExplorable": string;
+ /**
+ * 表示順
+ */
"displayOrder": string;
+ /**
+ * 数値が大きいほどUI上で先頭に表示されます。
+ */
"descriptionOfDisplayOrder": string;
+ /**
+ * モデレーターのメンバー編集を許可
+ */
"canEditMembersByModerator": string;
+ /**
+ * オンにすると、管理者に加えてモデレーターもこのロールへユーザーをアサイン/アサイン解除できるようになります。オフにすると管理者のみが行えます。
+ */
"descriptionOfCanEditMembersByModerator": string;
+ /**
+ * 優先度
+ */
"priority": string;
"_priority": {
+ /**
+ * 低
+ */
"low": string;
+ /**
+ * 中
+ */
"middle": string;
+ /**
+ * 高
+ */
"high": string;
};
"_options": {
+ /**
+ * グローバルタイムラインの閲覧
+ */
"gtlAvailable": string;
+ /**
+ * ローカルタイムラインの閲覧
+ */
"ltlAvailable": string;
+ /**
+ * パブリック投稿の許可
+ */
"canPublicNote": string;
+ /**
+ * メンション、リプライ、引用の許可
+ */
+ "canInitiateConversation": string;
+ /**
+ * コンテンツの作成
+ */
+ "canCreateContent": string;
+ /**
+ * コンテンツの編集
+ */
+ "canUpdateContent": string;
+ /**
+ * コンテンツの削除
+ */
+ "canDeleteContent": string;
+ /**
+ * 完全なアカウントの削除
+ */
+ "canPurgeAccount": string;
+ /**
+ * アイコンの変更
+ */
+ "canUpdateAvatar": string;
+ /**
+ * バナーの変更
+ */
+ "canUpdateBanner": string;
+ /**
+ * ノート内の最大メンション数
+ */
+ "mentionMax": string;
+ /**
+ * サーバー招待コードの発行
+ */
"canInvite": string;
+ /**
+ * 招待コードの作成可能数
+ */
"inviteLimit": string;
+ /**
+ * 招待コードの発行間隔
+ */
"inviteLimitCycle": string;
+ /**
+ * 招待コードの有効期限
+ */
"inviteExpirationTime": string;
+ /**
+ * カスタム絵文字の管理
+ */
"canManageCustomEmojis": string;
+ /**
+ * アバターデコレーションの管理
+ */
"canManageAvatarDecorations": string;
+ /**
+ * ドライブ容量
+ */
"driveCapacity": string;
+ /**
+ * ファイルにNSFWを常に付与
+ */
"alwaysMarkNsfw": string;
+ /**
+ * AIによるNSFW検出を無視
+ */
+ "skipNsfwDetection": string;
+ /**
+ * ノートのピン留めの最大数
+ */
"pinMax": string;
+ /**
+ * アンテナの作成可能数
+ */
"antennaMax": string;
+ /**
+ * アンテナに保持する最大ノート数
+ */
+ "antennaNotesMax": string;
+ /**
+ * ワードミュートの最大文字数
+ */
"wordMuteMax": string;
+ /**
+ * Webhookの作成可能数
+ */
"webhookMax": string;
+ /**
+ * クリップの作成可能数
+ */
"clipMax": string;
+ /**
+ * クリップ内のノートの最大数
+ */
"noteEachClipsMax": string;
+ /**
+ * ユーザーリストの作成可能数
+ */
"userListMax": string;
+ /**
+ * ユーザーリスト内のユーザーの最大数
+ */
"userEachUserListsMax": string;
+ /**
+ * レートリミット
+ */
"rateLimitFactor": string;
+ /**
+ * 小さいほど制限が緩和され、大きいほど制限が強化されます。
+ */
"descriptionOfRateLimitFactor": string;
+ /**
+ * 広告の非表示
+ */
"canHideAds": string;
+ /**
+ * ノート検索の利用
+ */
"canSearchNotes": string;
+ /**
+ * 翻訳機能の利用
+ */
"canUseTranslator": string;
+ /**
+ * サウンド設定でドライブのファイルを利用
+ */
+ "canUseDriveFileInSoundSettings": string;
+ /**
+ * アイコンデコレーションの最大取付個数
+ */
+ "avatarDecorationLimit": string;
};
"_condition": {
+ /**
+ * マニュアルロールにアサイン済み
+ */
+ "roleAssignedTo": string;
+ /**
+ * ローカルユーザー
+ */
"isLocal": string;
+ /**
+ * リモートユーザー
+ */
"isRemote": string;
+ /**
+ * アカウント作成から~以内
+ */
"createdLessThan": string;
+ /**
+ * アカウント作成から~経過
+ */
"createdMoreThan": string;
+ /**
+ * フォロワー数が~以下
+ */
"followersLessThanOrEq": string;
+ /**
+ * フォロワー数が~以上
+ */
"followersMoreThanOrEq": string;
+ /**
+ * フォロー数が~以下
+ */
"followingLessThanOrEq": string;
+ /**
+ * フォロー数が~以上
+ */
"followingMoreThanOrEq": string;
+ /**
+ * 投稿数が~以下
+ */
"notesLessThanOrEq": string;
+ /**
+ * 投稿数が~以上
+ */
"notesMoreThanOrEq": string;
+ /**
+ * ~かつ~
+ */
"and": string;
+ /**
+ * ~または~
+ */
"or": string;
+ /**
+ * ~ではない
+ */
"not": string;
};
};
"_sensitiveMediaDetection": {
+ /**
+ * 機械学習を使って自動でセンシティブなメディアを検出し、モデレーションに役立てることができます。サーバーの負荷が少し増えます。
+ */
"description": string;
+ /**
+ * 検出感度
+ */
"sensitivity": string;
+ /**
+ * 感度を低くすると、誤検知(偽陽性)が減ります。感度を高くすると、検知漏れ(偽陰性)が減ります。
+ */
"sensitivityDescription": string;
+ /**
+ * センシティブフラグを設定する
+ */
"setSensitiveFlagAutomatically": string;
+ /**
+ * この設定をオフにしても内部的に判定結果は保持されます。
+ */
"setSensitiveFlagAutomaticallyDescription": string;
+ /**
+ * 動画の解析を有効化
+ */
"analyzeVideos": string;
+ /**
+ * 静止画に加えて動画も解析するようにします。サーバーの負荷が少し増えます。
+ */
"analyzeVideosDescription": string;
};
"_emailUnavailable": {
+ /**
+ * 既に使用されています
+ */
"used": string;
+ /**
+ * 形式が正しくありません
+ */
"format": string;
+ /**
+ * 恒久的に使用可能なアドレスではありません
+ */
"disposable": string;
+ /**
+ * 正しいメールサーバーではありません
+ */
"mx": string;
+ /**
+ * メールサーバーが応答しません
+ */
"smtp": string;
+ /**
+ * このメールアドレスでは登録できません
+ */
+ "banned": string;
};
"_ffVisibility": {
+ /**
+ * 公開
+ */
"public": string;
+ /**
+ * フォロワーだけに公開
+ */
"followers": string;
+ /**
+ * 非公開
+ */
"private": string;
};
"_signup": {
+ /**
+ * ほとんど完了です
+ */
"almostThere": string;
+ /**
+ * あなたが使っているメールアドレスを入力してください。メールアドレスが公開されることはありません。
+ */
"emailAddressInfo": string;
- "emailSent": string;
+ /**
+ * 入力されたメールアドレス({email})宛に確認のメールが送信されました。メールに記載されたリンクにアクセスすると、アカウントの作成が完了します。メールに記載されているリンクの有効期限は30分です。
+ */
+ "emailSent": ParameterizedString<"email">;
};
"_accountDelete": {
+ /**
+ * アカウントの削除
+ */
"accountDelete": string;
+ /**
+ * アカウントの削除は負荷のかかる処理であるため、作成したコンテンツの数やアップロードしたファイルの数が多いと完了までに時間がかかることがあります。
+ */
"mayTakeTime": string;
+ /**
+ * アカウントの削除が完了する際は、登録してあったメールアドレス宛に通知を送信します。
+ */
"sendEmail": string;
+ /**
+ * アカウント削除をリクエスト
+ */
"requestAccountDelete": string;
+ /**
+ * 削除処理が開始されました。
+ */
"started": string;
+ /**
+ * 削除が進行中
+ */
"inProgress": string;
};
"_ad": {
+ /**
+ * 戻る
+ */
"back": string;
+ /**
+ * この広告の表示頻度を下げる
+ */
"reduceFrequencyOfThisAd": string;
+ /**
+ * 表示しない
+ */
"hide": string;
+ /**
+ * 曜日はサーバーのタイムゾーンを元に指定されます。
+ */
"timezoneinfo": string;
+ /**
+ * 広告配信設定
+ */
"adsSettings": string;
+ /**
+ * リアルタイム更新中に広告を配信する間隔(ノートの個数)
+ */
"notesPerOneAd": string;
+ /**
+ * 0でリアルタイム更新時の広告配信を無効
+ */
"setZeroToDisable": string;
+ /**
+ * 広告の配信間隔が極めて短いため、ユーザー体験が著しく損われる可能性があります。
+ */
"adsTooClose": string;
};
"_forgotPassword": {
+ /**
+ * アカウントに登録したメールアドレスを入力してください。そのアドレス宛てに、パスワードリセット用のリンクが送信されます。
+ */
"enterEmail": string;
+ /**
+ * メールアドレスを登録していない場合は、管理者までお問い合わせください。
+ */
"ifNoEmail": string;
+ /**
+ * このサーバーではメールがサポートされていないため、パスワードリセットを行う場合は管理者までお問い合わせください。
+ */
"contactAdmin": string;
};
"_gallery": {
+ /**
+ * 自分の投稿
+ */
"my": string;
+ /**
+ * いいねした投稿
+ */
"liked": string;
+ /**
+ * いいね!
+ */
"like": string;
+ /**
+ * いいね解除
+ */
"unlike": string;
};
"_email": {
"_follow": {
+ /**
+ * フォローされました
+ */
"title": string;
};
"_receiveFollowRequest": {
+ /**
+ * フォローリクエストを受け取りました
+ */
"title": string;
};
};
"_plugin": {
+ /**
+ * プラグインのインストール
+ */
"install": string;
+ /**
+ * 信頼できないプラグインはインストールしないでください。
+ */
"installWarn": string;
+ /**
+ * プラグインの管理
+ */
"manage": string;
+ /**
+ * ソースを表示
+ */
"viewSource": string;
+ /**
+ * ログを表示
+ */
+ "viewLog": string;
};
"_preferencesBackups": {
+ /**
+ * 作成したバックアップ
+ */
"list": string;
+ /**
+ * 新規保存
+ */
"saveNew": string;
+ /**
+ * ファイルを読み込み
+ */
"loadFile": string;
+ /**
+ * このデバイスに適用
+ */
"apply": string;
+ /**
+ * 上書き保存
+ */
"save": string;
+ /**
+ * バックアップ名を入力
+ */
"inputName": string;
+ /**
+ * 保存できません
+ */
"cannotSave": string;
- "nameAlreadyExists": string;
- "applyConfirm": string;
- "saveConfirm": string;
- "deleteConfirm": string;
- "renameConfirm": string;
+ /**
+ * バックアップ名「{name}」は既に存在します。違う名前を指定してください。
+ */
+ "nameAlreadyExists": ParameterizedString<"name">;
+ /**
+ * バックアップ「{name}」を現在のデバイスに適用しますか?現在のデバイス設定は失われます。
+ */
+ "applyConfirm": ParameterizedString<"name">;
+ /**
+ * {name}に上書き保存しますか?
+ */
+ "saveConfirm": ParameterizedString<"name">;
+ /**
+ * {name}を削除しますか?
+ */
+ "deleteConfirm": ParameterizedString<"name">;
+ /**
+ * 「{old}」を「{new}」に変更しますか?
+ */
+ "renameConfirm": ParameterizedString<"old" | "new">;
+ /**
+ * バックアップはありません。「新規保存」で現在のクライアント設定をサーバーに保存できます。
+ */
"noBackups": string;
- "createdAt": string;
- "updatedAt": string;
+ /**
+ * 作成日時: {date} {time}
+ */
+ "createdAt": ParameterizedString<"date" | "time">;
+ /**
+ * 更新日時: {date} {time}
+ */
+ "updatedAt": ParameterizedString<"date" | "time">;
+ /**
+ * 読み込みできません
+ */
"cannotLoad": string;
+ /**
+ * ファイル形式が違います。
+ */
"invalidFile": string;
};
"_registry": {
+ /**
+ * スコープ
+ */
"scope": string;
+ /**
+ * キー
+ */
"key": string;
+ /**
+ * キー
+ */
"keys": string;
+ /**
+ * ドメイン
+ */
"domain": string;
+ /**
+ * キーを作成
+ */
"createKey": string;
};
"_aboutMisskey": {
+ /**
+ * Misskeyはsyuiloによって2014年から開発されている、オープンソースのソフトウェアです。
+ */
"about": string;
+ /**
+ * コントリビューター
+ */
"contributors": string;
+ /**
+ * 全てのコントリビューター
+ */
"allContributors": string;
+ /**
+ * ソースコード
+ */
"source": string;
+ /**
+ * オリジナル
+ */
+ "original": string;
+ /**
+ * {name}はオリジナルのMisskeyを改変したバージョンを使用しています。
+ */
+ "thisIsModifiedVersion": ParameterizedString<"name">;
+ /**
+ * Misskeyを翻訳
+ */
"translation": string;
+ /**
+ * Misskeyに寄付
+ */
"donate": string;
+ /**
+ * 他にも多くの方が支援してくれています。ありがとうございます🥰
+ */
"morePatrons": string;
+ /**
+ * 支援者
+ */
"patrons": string;
+ /**
+ * プロジェクトメンバー
+ */
"projectMembers": string;
};
"_displayOfSensitiveMedia": {
+ /**
+ * センシティブ設定されたメディアを隠す
+ */
"respect": string;
+ /**
+ * センシティブ設定されたメディアを隠さない
+ */
"ignore": string;
+ /**
+ * 常にメディアを隠す
+ */
"force": string;
};
"_instanceTicker": {
+ /**
+ * 表示しない
+ */
"none": string;
+ /**
+ * リモートユーザーに表示
+ */
"remote": string;
+ /**
+ * 常に表示
+ */
"always": string;
};
"_serverDisconnectedBehavior": {
+ /**
+ * 自動でリロード
+ */
"reload": string;
+ /**
+ * ダイアログで警告
+ */
"dialog": string;
+ /**
+ * 控えめに警告
+ */
"quiet": string;
};
"_channel": {
+ /**
+ * チャンネルを作成
+ */
"create": string;
+ /**
+ * チャンネルを編集
+ */
"edit": string;
+ /**
+ * バナーを設定
+ */
"setBanner": string;
+ /**
+ * バナーを削除
+ */
"removeBanner": string;
+ /**
+ * トレンド
+ */
"featured": string;
+ /**
+ * 管理中
+ */
"owned": string;
+ /**
+ * フォロー中
+ */
"following": string;
- "usersCount": string;
- "notesCount": string;
+ /**
+ * {n}人が参加中
+ */
+ "usersCount": ParameterizedString<"n">;
+ /**
+ * {n}投稿があります
+ */
+ "notesCount": ParameterizedString<"n">;
+ /**
+ * 名前と説明
+ */
"nameAndDescription": string;
+ /**
+ * 名前のみ
+ */
"nameOnly": string;
+ /**
+ * チャンネル外へのリノートと引用リノートを許可する
+ */
"allowRenoteToExternal": string;
};
"_menuDisplay": {
+ /**
+ * 横
+ */
"sideFull": string;
+ /**
+ * 横(アイコン)
+ */
"sideIcon": string;
+ /**
+ * 上部
+ */
"top": string;
+ /**
+ * 隠す
+ */
"hide": string;
};
"_wordMute": {
+ /**
+ * ミュートするワード
+ */
"muteWords": string;
+ /**
+ * スペースで区切るとAND指定になり、改行で区切るとOR指定になります。
+ */
"muteWordsDescription": string;
+ /**
+ * キーワードをスラッシュで囲むと正規表現になります。
+ */
"muteWordsDescription2": string;
+ /**
+ * ミュートされた単語を含むノートを非表示にする
+ */
+ "hideMutedNotes": string;
};
"_instanceMute": {
+ /**
+ * ミュートしたサーバーのユーザーへの返信を含めて、設定したサーバーの全てのノートとRenoteをミュートします。
+ */
"instanceMuteDescription": string;
+ /**
+ * 改行で区切って設定します
+ */
"instanceMuteDescription2": string;
+ /**
+ * 設定したサーバーのノートを隠します。
+ */
"title": string;
+ /**
+ * ミュートするサーバー
+ */
"heading": string;
};
"_theme": {
+ /**
+ * テーマを探す
+ */
"explore": string;
+ /**
+ * テーマのインストール
+ */
"install": string;
+ /**
+ * テーマの管理
+ */
"manage": string;
+ /**
+ * テーマコード
+ */
"code": string;
+ /**
+ * 説明
+ */
"description": string;
- "installed": string;
+ /**
+ * {name}をインストールしました
+ */
+ "installed": ParameterizedString<"name">;
+ /**
+ * インストールされたテーマ
+ */
"installedThemes": string;
+ /**
+ * 標準のテーマ
+ */
"builtinThemes": string;
+ /**
+ * そのテーマは既にインストールされています
+ */
"alreadyInstalled": string;
+ /**
+ * テーマの形式が間違っています
+ */
"invalid": string;
+ /**
+ * テーマを作る
+ */
"make": string;
+ /**
+ * ベース
+ */
"base": string;
+ /**
+ * 定数を追加
+ */
"addConstant": string;
+ /**
+ * 定数
+ */
"constant": string;
+ /**
+ * デフォルト値
+ */
"defaultValue": string;
+ /**
+ * 色
+ */
"color": string;
+ /**
+ * プロパティを参照
+ */
"refProp": string;
+ /**
+ * 定数を参照
+ */
"refConst": string;
+ /**
+ * キー
+ */
"key": string;
+ /**
+ * 関数
+ */
"func": string;
+ /**
+ * 関数の種類
+ */
"funcKind": string;
+ /**
+ * 引数
+ */
"argument": string;
+ /**
+ * 元にするプロパティの名前
+ */
"basedProp": string;
+ /**
+ * 不透明度
+ */
"alpha": string;
+ /**
+ * 暗さ
+ */
"darken": string;
+ /**
+ * 明るさ
+ */
"lighten": string;
+ /**
+ * 定数名を入力してください
+ */
"inputConstantName": string;
+ /**
+ * ここにテーマコードを貼り付けて、エディターにインポートできます
+ */
"importInfo": string;
- "deleteConstantConfirm": string;
+ /**
+ * 定数 {const} を削除しても良いですか?
+ */
+ "deleteConstantConfirm": ParameterizedString<"const">;
"keys": {
+ /**
+ * アクセント
+ */
"accent": string;
+ /**
+ * 背景
+ */
"bg": string;
+ /**
+ * 文字
+ */
"fg": string;
+ /**
+ * フォーカス
+ */
"focus": string;
+ /**
+ * インジケーター
+ */
"indicator": string;
+ /**
+ * パネル
+ */
"panel": string;
+ /**
+ * 影
+ */
"shadow": string;
+ /**
+ * ヘッダー
+ */
"header": string;
+ /**
+ * サイドバーの背景
+ */
"navBg": string;
+ /**
+ * サイドバーの文字
+ */
"navFg": string;
+ /**
+ * サイドバー文字(ホバー)
+ */
"navHoverFg": string;
+ /**
+ * サイドバー文字(アクティブ)
+ */
"navActive": string;
+ /**
+ * サイドバーのインジケーター
+ */
"navIndicator": string;
+ /**
+ * リンク
+ */
"link": string;
+ /**
+ * ハッシュタグ
+ */
"hashtag": string;
+ /**
+ * メンション
+ */
"mention": string;
+ /**
+ * あなた宛てメンション
+ */
"mentionMe": string;
+ /**
+ * Renote
+ */
"renote": string;
+ /**
+ * モーダルの背景
+ */
"modalBg": string;
+ /**
+ * 分割線
+ */
"divider": string;
+ /**
+ * スクロールバーの取っ手
+ */
"scrollbarHandle": string;
+ /**
+ * スクロールバーの取っ手(ホバー)
+ */
"scrollbarHandleHover": string;
+ /**
+ * 日付ラベルの文字
+ */
"dateLabelFg": string;
+ /**
+ * 情報の背景
+ */
"infoBg": string;
+ /**
+ * 情報の文字
+ */
"infoFg": string;
+ /**
+ * 警告の背景
+ */
"infoWarnBg": string;
+ /**
+ * 警告の文字
+ */
"infoWarnFg": string;
+ /**
+ * 通知トーストの背景
+ */
"toastBg": string;
+ /**
+ * 通知トーストの文字
+ */
"toastFg": string;
+ /**
+ * ボタンの背景
+ */
"buttonBg": string;
+ /**
+ * ボタンの背景 (ホバー)
+ */
"buttonHoverBg": string;
+ /**
+ * 入力ボックスの縁取り
+ */
"inputBorder": string;
+ /**
+ * リスト項目の背景 (ホバー)
+ */
"listItemHoverBg": string;
+ /**
+ * ドライブフォルダーの背景
+ */
"driveFolderBg": string;
+ /**
+ * 壁紙のオーバーレイ
+ */
"wallpaperOverlay": string;
+ /**
+ * バッジ
+ */
"badge": string;
+ /**
+ * チャットの背景
+ */
"messageBg": string;
+ /**
+ * アクセント (暗め)
+ */
"accentDarken": string;
+ /**
+ * アクセント (明るめ)
+ */
"accentLighten": string;
+ /**
+ * 強調された文字
+ */
"fgHighlighted": string;
};
};
"_sfx": {
+ /**
+ * ノート
+ */
"note": string;
+ /**
+ * ノート(自分)
+ */
"noteMy": string;
+ /**
+ * 通知
+ */
"notification": string;
+ /**
+ * アンテナ受信
+ */
"antenna": string;
+ /**
+ * チャンネル通知
+ */
"channel": string;
+ /**
+ * リアクション選択時
+ */
+ "reaction": string;
+ };
+ "_soundSettings": {
+ /**
+ * ドライブの音声を使用
+ */
+ "driveFile": string;
+ /**
+ * ドライブのファイルを選択してください
+ */
+ "driveFileWarn": string;
+ /**
+ * このファイルは対応していません
+ */
+ "driveFileTypeWarn": string;
+ /**
+ * 音声ファイルを選択してください
+ */
+ "driveFileTypeWarnDescription": string;
+ /**
+ * 音声が長すぎます
+ */
+ "driveFileDurationWarn": string;
+ /**
+ * 長い音声を使用するとMisskeyの使用に支障をきたす可能性があります。それでも続行しますか?
+ */
+ "driveFileDurationWarnDescription": string;
};
"_ago": {
+ /**
+ * 未来
+ */
"future": string;
+ /**
+ * たった今
+ */
"justNow": string;
- "secondsAgo": string;
- "minutesAgo": string;
- "hoursAgo": string;
- "daysAgo": string;
- "weeksAgo": string;
- "monthsAgo": string;
- "yearsAgo": string;
+ /**
+ * {n}秒前
+ */
+ "secondsAgo": ParameterizedString<"n">;
+ /**
+ * {n}分前
+ */
+ "minutesAgo": ParameterizedString<"n">;
+ /**
+ * {n}時間前
+ */
+ "hoursAgo": ParameterizedString<"n">;
+ /**
+ * {n}日前
+ */
+ "daysAgo": ParameterizedString<"n">;
+ /**
+ * {n}週間前
+ */
+ "weeksAgo": ParameterizedString<"n">;
+ /**
+ * {n}ヶ月前
+ */
+ "monthsAgo": ParameterizedString<"n">;
+ /**
+ * {n}年前
+ */
+ "yearsAgo": ParameterizedString<"n">;
+ /**
+ * 日時の解析に失敗
+ */
"invalid": string;
};
"_timeIn": {
- "seconds": string;
- "minutes": string;
- "hours": string;
- "days": string;
- "weeks": string;
- "months": string;
- "years": string;
+ /**
+ * {n}秒後
+ */
+ "seconds": ParameterizedString<"n">;
+ /**
+ * {n}分後
+ */
+ "minutes": ParameterizedString<"n">;
+ /**
+ * {n}時間後
+ */
+ "hours": ParameterizedString<"n">;
+ /**
+ * {n}日後
+ */
+ "days": ParameterizedString<"n">;
+ /**
+ * {n}週間後
+ */
+ "weeks": ParameterizedString<"n">;
+ /**
+ * {n}ヶ月後
+ */
+ "months": ParameterizedString<"n">;
+ /**
+ * {n}年後
+ */
+ "years": ParameterizedString<"n">;
};
"_time": {
+ /**
+ * 秒
+ */
"second": string;
+ /**
+ * 分
+ */
"minute": string;
+ /**
+ * 時間
+ */
"hour": string;
+ /**
+ * 日
+ */
"day": string;
};
"_2fa": {
+ /**
+ * 既に設定は完了しています。
+ */
"alreadyRegistered": string;
+ /**
+ * 認証アプリの設定を開始
+ */
"registerTOTP": string;
- "step1": string;
+ /**
+ * まず、{a}や{b}などの認証アプリをお使いのデバイスにインストールします。
+ */
+ "step1": ParameterizedString<"a" | "b">;
+ /**
+ * 次に、表示されているQRコードをアプリでスキャンします。
+ */
"step2": string;
+ /**
+ * QRコードをクリックすると、お使いの端末にインストールされている認証アプリやキーリングに登録できます。
+ */
"step2Click": string;
+ /**
+ * デスクトップアプリを使用する場合は次のURIを入力します
+ */
"step2Uri": string;
+ /**
+ * 確認コードを入力
+ */
"step3Title": string;
+ /**
+ * アプリに表示されている確認コード(トークン)を入力します。
+ */
"step3": string;
+ /**
+ * 設定が完了しました
+ */
"setupCompleted": string;
+ /**
+ * これからログインするときも、同じように確認コードを入力します。
+ */
"step4": string;
+ /**
+ * お使いのブラウザはセキュリティキーに対応していません。
+ */
"securityKeyNotSupported": string;
+ /**
+ * セキュリティキー・パスキーを登録するには、まず認証アプリの設定を行なってください。
+ */
"registerTOTPBeforeKey": string;
+ /**
+ * FIDO2をサポートするハードウェアセキュリティキー、端末の生体認証やPINロック、パスキーといった、WebAuthn由来の鍵を登録します。
+ */
"securityKeyInfo": string;
+ /**
+ * セキュリティキー・パスキーを登録する
+ */
"registerSecurityKey": string;
+ /**
+ * キーの名前を入力
+ */
"securityKeyName": string;
+ /**
+ * ブラウザの指示に従い、セキュリティキーやパスキーを登録してください
+ */
"tapSecurityKey": string;
+ /**
+ * セキュリティキーを削除
+ */
"removeKey": string;
- "removeKeyConfirm": string;
+ /**
+ * {name}を削除しますか?
+ */
+ "removeKeyConfirm": ParameterizedString<"name">;
+ /**
+ * セキュリティキーが登録されている場合、認証アプリの設定は解除できません。
+ */
"whyTOTPOnlyRenew": string;
+ /**
+ * 認証アプリを再設定
+ */
"renewTOTP": string;
+ /**
+ * 今までの認証アプリの確認コードおよびバックアップコードは使用できなくなります
+ */
"renewTOTPConfirm": string;
+ /**
+ * 再設定する
+ */
"renewTOTPOk": string;
+ /**
+ * やめておく
+ */
"renewTOTPCancel": string;
+ /**
+ * このウィザードを閉じる前に、以下のバックアップコードを確認してください。
+ */
"checkBackupCodesBeforeCloseThisWizard": string;
+ /**
+ * バックアップコード
+ */
"backupCodes": string;
+ /**
+ * 認証アプリが使用できなくなった場合、以下のバックアップコードを使ってアカウントにアクセスできます。これらのコードは必ず安全な場所に保管してください。各コードは一回だけ使用できます。
+ */
"backupCodesDescription": string;
+ /**
+ * バックアップコードが使用されました。認証アプリが使えなくなっている場合、なるべく早く認証アプリを再設定してください。
+ */
"backupCodeUsedWarning": string;
+ /**
+ * バックアップコードが全て使用されました。認証アプリを利用できない場合、これ以上アカウントにアクセスできなくなります。認証アプリを再登録してください。
+ */
"backupCodesExhaustedWarning": string;
};
"_permissions": {
+ /**
+ * アカウントの情報を見る
+ */
"read:account": string;
+ /**
+ * アカウントの情報を変更する
+ */
"write:account": string;
+ /**
+ * ブロックを見る
+ */
"read:blocks": string;
+ /**
+ * ブロックを操作する
+ */
"write:blocks": string;
+ /**
+ * ドライブを見る
+ */
"read:drive": string;
+ /**
+ * ドライブを操作する
+ */
"write:drive": string;
+ /**
+ * お気に入りを見る
+ */
"read:favorites": string;
+ /**
+ * お気に入りを操作する
+ */
"write:favorites": string;
+ /**
+ * フォローの情報を見る
+ */
"read:following": string;
+ /**
+ * フォロー・フォロー解除する
+ */
"write:following": string;
+ /**
+ * チャットを見る
+ */
"read:messaging": string;
+ /**
+ * チャットを操作する
+ */
"write:messaging": string;
+ /**
+ * ミュートを見る
+ */
"read:mutes": string;
+ /**
+ * ミュートを操作する
+ */
"write:mutes": string;
+ /**
+ * ノートを作成・削除する
+ */
"write:notes": string;
+ /**
+ * 通知を見る
+ */
"read:notifications": string;
+ /**
+ * 通知を操作する
+ */
"write:notifications": string;
+ /**
+ * リアクションを見る
+ */
"read:reactions": string;
+ /**
+ * リアクションを操作する
+ */
"write:reactions": string;
+ /**
+ * 投票する
+ */
"write:votes": string;
+ /**
+ * ページを見る
+ */
"read:pages": string;
+ /**
+ * ページを操作する
+ */
"write:pages": string;
+ /**
+ * ページのいいねを見る
+ */
"read:page-likes": string;
+ /**
+ * ページのいいねを操作する
+ */
"write:page-likes": string;
+ /**
+ * ユーザーグループを見る
+ */
"read:user-groups": string;
+ /**
+ * ユーザーグループを操作する
+ */
"write:user-groups": string;
+ /**
+ * チャンネルを見る
+ */
"read:channels": string;
+ /**
+ * チャンネルを操作する
+ */
"write:channels": string;
+ /**
+ * ギャラリーを見る
+ */
"read:gallery": string;
+ /**
+ * ギャラリーを操作する
+ */
"write:gallery": string;
+ /**
+ * ギャラリーのいいねを見る
+ */
"read:gallery-likes": string;
+ /**
+ * ギャラリーのいいねを操作する
+ */
"write:gallery-likes": string;
+ /**
+ * Playを見る
+ */
"read:flash": string;
+ /**
+ * Playを操作する
+ */
"write:flash": string;
+ /**
+ * Playのいいねを見る
+ */
"read:flash-likes": string;
+ /**
+ * Playのいいねを操作する
+ */
"write:flash-likes": string;
+ /**
+ * ユーザーからの通報を見る
+ */
+ "read:admin:abuse-user-reports": string;
+ /**
+ * リゾルバーを見る
+ */
+ "read:admin:abuse-report-resolvers": string;
+ /**
+ * リゾルバーを編集する
+ */
+ "write:admin:abuse-report-resolvers": string;
+ /**
+ * ユーザーアカウントを削除する
+ */
+ "write:admin:delete-account": string;
+ /**
+ * ユーザーのすべてのファイルを削除する
+ */
+ "write:admin:delete-all-files-of-a-user": string;
+ /**
+ * データベースインデックスに関する情報を見る
+ */
+ "read:admin:index-stats": string;
+ /**
+ * データベーステーブルに関する情報を見る
+ */
+ "read:admin:table-stats": string;
+ /**
+ * ユーザーのIPアドレスを見る
+ */
+ "read:admin:user-ips": string;
+ /**
+ * インスタンスのメタデータを見る
+ */
+ "read:admin:meta": string;
+ /**
+ * ユーザーのパスワードをリセットする
+ */
+ "write:admin:reset-password": string;
+ /**
+ * ユーザーからの通報を解決する
+ */
+ "write:admin:resolve-abuse-user-report": string;
+ /**
+ * メールを送る
+ */
+ "write:admin:send-email": string;
+ /**
+ * サーバーの情報を見る
+ */
+ "read:admin:server-info": string;
+ /**
+ * モデレーションログを見る
+ */
+ "read:admin:show-moderation-log": string;
+ /**
+ * ユーザーのプライベートな情報を見る
+ */
+ "read:admin:show-user": string;
+ /**
+ * ユーザーのプライベートな情報を見る
+ */
+ "read:admin:show-users": string;
+ /**
+ * ユーザーを凍結する
+ */
+ "write:admin:suspend-user": string;
+ /**
+ * ユーザーのアバターを削除する
+ */
+ "write:admin:unset-user-avatar": string;
+ /**
+ * ユーザーのバーナーを削除する
+ */
+ "write:admin:unset-user-banner": string;
+ /**
+ * ユーザーの凍結を解除する
+ */
+ "write:admin:unsuspend-user": string;
+ /**
+ * インスタンスのメタデータを操作する
+ */
+ "write:admin:meta": string;
+ /**
+ * モデレーションノートを操作する
+ */
+ "write:admin:user-note": string;
+ /**
+ * ロールを操作する
+ */
+ "write:admin:roles": string;
+ /**
+ * ロールを見る
+ */
+ "read:admin:roles": string;
+ /**
+ * リレーを操作する
+ */
+ "write:admin:relays": string;
+ /**
+ * リレーを見る
+ */
+ "read:admin:relays": string;
+ /**
+ * 招待コードを操作する
+ */
+ "write:admin:invite-codes": string;
+ /**
+ * 招待コードを見る
+ */
+ "read:admin:invite-codes": string;
+ /**
+ * お知らせを操作する
+ */
+ "write:admin:announcements": string;
+ /**
+ * お知らせを見る
+ */
+ "read:admin:announcements": string;
+ /**
+ * アバターデコレーションを操作する
+ */
+ "write:admin:avatar-decorations": string;
+ /**
+ * アバターデコレーションを見る
+ */
+ "read:admin:avatar-decorations": string;
+ /**
+ * 連合に関する情報を操作する
+ */
+ "write:admin:federation": string;
+ /**
+ * ユーザーアカウントを操作する
+ */
+ "write:admin:account": string;
+ /**
+ * ユーザーに関する情報を見る
+ */
+ "read:admin:account": string;
+ /**
+ * 絵文字を操作する
+ */
+ "write:admin:emoji": string;
+ /**
+ * 絵文字を見る
+ */
+ "read:admin:emoji": string;
+ /**
+ * ジョブキューを操作する
+ */
+ "write:admin:queue": string;
+ /**
+ * ジョブキューに関する情報を見る
+ */
+ "read:admin:queue": string;
+ /**
+ * プロモーションノートを操作する
+ */
+ "write:admin:promo": string;
+ /**
+ * ユーザーのドライブを操作する
+ */
+ "write:admin:drive": string;
+ /**
+ * ユーザーのドライブの関する情報を見る
+ */
+ "read:admin:drive": string;
+ /**
+ * 管理者用のWebsocket APIを使う
+ */
+ "read:admin:stream": string;
+ /**
+ * 広告を操作する
+ */
+ "write:admin:ad": string;
+ /**
+ * 広告を見る
+ */
+ "read:admin:ad": string;
+ /**
+ * 招待コードを作成する
+ */
+ "write:invite-codes": string;
+ /**
+ * 招待コードを取得する
+ */
+ "read:invite-codes": string;
+ /**
+ * クリップのいいねを操作する
+ */
+ "write:clip-favorite": string;
+ /**
+ * クリップのいいねを見る
+ */
+ "read:clip-favorite": string;
+ /**
+ * 連合に関する情報を取得する
+ */
+ "read:federation": string;
+ /**
+ * 違反を報告する
+ */
+ "write:report-abuse": string;
};
"_auth": {
+ /**
+ * アプリへのアクセス許可
+ */
"shareAccessTitle": string;
- "shareAccess": string;
+ /**
+ * 「{name}」がアカウントにアクセスすることを許可しますか?
+ */
+ "shareAccess": ParameterizedString<"name">;
+ /**
+ * アカウントへのアクセスを許可しますか?
+ */
"shareAccessAsk": string;
- "permission": string;
+ /**
+ * {name}は次の権限を要求しています
+ */
+ "permission": ParameterizedString<"name">;
+ /**
+ * このアプリは次の権限を要求しています
+ */
"permissionAsk": string;
+ /**
+ * アプリケーションに戻ってやっていってください
+ */
"pleaseGoBack": string;
+ /**
+ * アプリケーションに戻っています
+ */
"callback": string;
+ /**
+ * アクセスを拒否しました
+ */
"denied": string;
+ /**
+ * アプリケーションにアクセス許可を与えるには、ログインが必要です。
+ */
"pleaseLogin": string;
};
"_antennaSources": {
+ /**
+ * 全てのノート
+ */
"all": string;
+ /**
+ * フォローしているユーザーのノート
+ */
"homeTimeline": string;
+ /**
+ * 指定した一人または複数のユーザーのノート
+ */
"users": string;
+ /**
+ * 指定したリストのユーザーのノート
+ */
"userList": string;
+ /**
+ * 指定した一人または複数のユーザーを除いた全てのノート
+ */
"userBlacklist": string;
};
"_weekday": {
+ /**
+ * 日曜日
+ */
"sunday": string;
+ /**
+ * 月曜日
+ */
"monday": string;
+ /**
+ * 火曜日
+ */
"tuesday": string;
+ /**
+ * 水曜日
+ */
"wednesday": string;
+ /**
+ * 木曜日
+ */
"thursday": string;
+ /**
+ * 金曜日
+ */
"friday": string;
+ /**
+ * 土曜日
+ */
"saturday": string;
};
"_widgets": {
+ /**
+ * プロフィール
+ */
"profile": string;
+ /**
+ * サーバー情報
+ */
"instanceInfo": string;
+ /**
+ * 付箋
+ */
"memo": string;
+ /**
+ * 通知
+ */
"notifications": string;
+ /**
+ * タイムライン
+ */
"timeline": string;
+ /**
+ * カレンダー
+ */
"calendar": string;
+ /**
+ * トレンド
+ */
"trends": string;
+ /**
+ * 時計
+ */
"clock": string;
+ /**
+ * RSSリーダー
+ */
"rss": string;
+ /**
+ * RSSティッカー
+ */
"rssTicker": string;
+ /**
+ * アクティビティ
+ */
"activity": string;
+ /**
+ * フォト
+ */
"photos": string;
+ /**
+ * デジタル時計
+ */
"digitalClock": string;
+ /**
+ * UNIX時計
+ */
"unixClock": string;
+ /**
+ * 連合
+ */
"federation": string;
+ /**
+ * サーバークラウド
+ */
"instanceCloud": string;
+ /**
+ * 投稿フォーム
+ */
"postForm": string;
+ /**
+ * スライドショー
+ */
"slideshow": string;
+ /**
+ * ボタン
+ */
"button": string;
+ /**
+ * オンラインユーザー
+ */
"onlineUsers": string;
+ /**
+ * ジョブキュー
+ */
"jobQueue": string;
+ /**
+ * サーバーメトリクス
+ */
"serverMetric": string;
+ /**
+ * AiScriptコンソール
+ */
"aiscript": string;
+ /**
+ * AiScript App
+ */
"aiscriptApp": string;
+ /**
+ * 藍
+ */
"aichan": string;
+ /**
+ * ユーザーリスト
+ */
"userList": string;
"_userList": {
+ /**
+ * リストを選択
+ */
"chooseList": string;
};
+ /**
+ * クリッカー
+ */
"clicker": string;
+ /**
+ * 今日誕生日のユーザー
+ */
+ "birthdayFollowings": string;
};
"_cw": {
+ /**
+ * 隠す
+ */
"hide": string;
+ /**
+ * もっと見る
+ */
"show": string;
- "chars": string;
- "files": string;
+ /**
+ * {count}文字
+ */
+ "chars": ParameterizedString<"count">;
+ /**
+ * {count}ファイル
+ */
+ "files": ParameterizedString<"count">;
};
"_poll": {
+ /**
+ * 選択肢は最低2つ必要です
+ */
"noOnlyOneChoice": string;
- "choiceN": string;
+ /**
+ * 選択肢{n}
+ */
+ "choiceN": ParameterizedString<"n">;
+ /**
+ * これ以上追加できません
+ */
"noMore": string;
+ /**
+ * 複数回答可
+ */
"canMultipleVote": string;
+ /**
+ * 期限
+ */
"expiration": string;
+ /**
+ * 無期限
+ */
"infinite": string;
+ /**
+ * 日時指定
+ */
"at": string;
+ /**
+ * 経過指定
+ */
"after": string;
+ /**
+ * 期日
+ */
"deadlineDate": string;
+ /**
+ * 時間
+ */
"deadlineTime": string;
+ /**
+ * 期間
+ */
"duration": string;
- "votesCount": string;
- "totalVotes": string;
+ /**
+ * {n}票
+ */
+ "votesCount": ParameterizedString<"n">;
+ /**
+ * 計{n}票
+ */
+ "totalVotes": ParameterizedString<"n">;
+ /**
+ * 投票する
+ */
"vote": string;
+ /**
+ * 結果を見る
+ */
"showResult": string;
+ /**
+ * 投票済み
+ */
"voted": string;
+ /**
+ * 終了済み
+ */
"closed": string;
- "remainingDays": string;
- "remainingHours": string;
- "remainingMinutes": string;
- "remainingSeconds": string;
+ /**
+ * 終了まであと{d}日{h}時間
+ */
+ "remainingDays": ParameterizedString<"d" | "h">;
+ /**
+ * 終了まであと{h}時間{m}分
+ */
+ "remainingHours": ParameterizedString<"h" | "m">;
+ /**
+ * 終了まであと{m}分{s}秒
+ */
+ "remainingMinutes": ParameterizedString<"m" | "s">;
+ /**
+ * 終了まであと{s}秒
+ */
+ "remainingSeconds": ParameterizedString<"s">;
};
"_visibility": {
+ /**
+ * パブリック
+ */
"public": string;
+ /**
+ * 全てのユーザーに公開
+ */
"publicDescription": string;
+ /**
+ * ホーム
+ */
"home": string;
+ /**
+ * ホームタイムラインのみに公開
+ */
"homeDescription": string;
+ /**
+ * フォロワー
+ */
"followers": string;
+ /**
+ * 自分のフォロワーのみに公開
+ */
"followersDescription": string;
+ /**
+ * ダイレクト
+ */
"specified": string;
+ /**
+ * 指定したユーザーのみに公開
+ */
"specifiedDescription": string;
+ /**
+ * 連合なし
+ */
"disableFederation": string;
+ /**
+ * 他サーバーへの配信を行いません
+ */
"disableFederationDescription": string;
};
"_postForm": {
+ /**
+ * このノートに返信...
+ */
"replyPlaceholder": string;
+ /**
+ * このノートを引用...
+ */
"quotePlaceholder": string;
+ /**
+ * チャンネルに投稿...
+ */
"channelPlaceholder": string;
"_placeholders": {
+ /**
+ * いまどうしてる?
+ */
"a": string;
+ /**
+ * 何かありましたか?
+ */
"b": string;
+ /**
+ * 何をお考えですか?
+ */
"c": string;
+ /**
+ * 言いたいことは?
+ */
"d": string;
+ /**
+ * ここに書いてください
+ */
"e": string;
+ /**
+ * あなたが書くのを待っています...
+ */
"f": string;
};
+ /**
+ * [NSFWガイドライン]({nsfwGuideUrl})を必ずお読みになってからご利用ください。
+ */
+ "guidelineInfo": ParameterizedString<"nsfwGuideUrl">;
};
"_profile": {
+ /**
+ * 名前
+ */
"name": string;
+ /**
+ * ユーザー名
+ */
"username": string;
+ /**
+ * 自己紹介
+ */
"description": string;
+ /**
+ * ハッシュタグを含めることができます。
+ */
"youCanIncludeHashtags": string;
+ /**
+ * 追加情報
+ */
"metadata": string;
+ /**
+ * 追加情報を編集
+ */
"metadataEdit": string;
+ /**
+ * プロフィールに表として追加情報を表示することができます。
+ */
"metadataDescription": string;
+ /**
+ * ラベル
+ */
"metadataLabel": string;
+ /**
+ * 内容
+ */
"metadataContent": string;
+ /**
+ * アイコン画像を変更
+ */
"changeAvatar": string;
+ /**
+ * バナー画像を変更
+ */
"changeBanner": string;
+ /**
+ * 内容にURLを設定すると、リンク先のWebサイトに自分のプロフィールへのリンクが含まれている場合に所有者確認済みアイコンを表示させることができます。
+ */
"verifiedLinkDescription": string;
+ /**
+ * 最大{max}つまでデコレーションを付けられます。
+ */
+ "avatarDecorationMax": ParameterizedString<"max">;
};
"_exportOrImport": {
+ /**
+ * 全てのノート
+ */
"allNotes": string;
+ /**
+ * お気に入りにしたノート
+ */
"favoritedNotes": string;
+ /**
+ * クリップ
+ */
+ "clips": string;
+ /**
+ * フォロー
+ */
"followingList": string;
+ /**
+ * ミュート
+ */
"muteList": string;
+ /**
+ * ブロック
+ */
"blockingList": string;
+ /**
+ * リスト
+ */
"userLists": string;
+ /**
+ * ミュートしているユーザーを除外
+ */
"excludeMutingUsers": string;
+ /**
+ * 使われていないアカウントを除外
+ */
"excludeInactiveUsers": string;
+ /**
+ * インポートした人による返信をTLに含むようにする
+ */
"withReplies": string;
};
"_charts": {
+ /**
+ * 連合
+ */
"federation": string;
+ /**
+ * リクエスト
+ */
"apRequest": string;
+ /**
+ * ユーザーの増減
+ */
"usersIncDec": string;
+ /**
+ * ユーザーの合計
+ */
"usersTotal": string;
+ /**
+ * アクティブユーザー数
+ */
"activeUsers": string;
+ /**
+ * ノートの増減
+ */
"notesIncDec": string;
+ /**
+ * ローカルのノートの増減
+ */
"localNotesIncDec": string;
+ /**
+ * リモートのノートの増減
+ */
"remoteNotesIncDec": string;
+ /**
+ * ノートの合計
+ */
"notesTotal": string;
+ /**
+ * ファイルの増減
+ */
"filesIncDec": string;
+ /**
+ * ファイルの合計
+ */
"filesTotal": string;
+ /**
+ * ストレージ使用量の増減
+ */
"storageUsageIncDec": string;
+ /**
+ * ストレージ使用量の合計
+ */
"storageUsageTotal": string;
};
"_instanceCharts": {
+ /**
+ * リクエスト
+ */
"requests": string;
+ /**
+ * ユーザーの増減
+ */
"users": string;
+ /**
+ * ユーザーの累積
+ */
"usersTotal": string;
+ /**
+ * ノートの増減
+ */
"notes": string;
+ /**
+ * ノートの累積
+ */
"notesTotal": string;
+ /**
+ * フォロー/フォロワーの増減
+ */
"ff": string;
+ /**
+ * フォロー/フォロワーの累積
+ */
"ffTotal": string;
+ /**
+ * キャッシュサイズの増減
+ */
"cacheSize": string;
+ /**
+ * キャッシュサイズの累積
+ */
"cacheSizeTotal": string;
+ /**
+ * ファイル数の増減
+ */
"files": string;
+ /**
+ * ファイル数の累積
+ */
"filesTotal": string;
};
"_timelines": {
+ /**
+ * ホーム
+ */
"home": string;
+ /**
+ * ローカル
+ */
"local": string;
+ /**
+ * メディア
+ */
+ "media": string;
+ /**
+ * ソーシャル
+ */
"social": string;
+ /**
+ * グローバル
+ */
"global": string;
};
"_play": {
+ /**
+ * Playの作成
+ */
"new": string;
+ /**
+ * Playの編集
+ */
"edit": string;
+ /**
+ * Playを作成しました
+ */
"created": string;
+ /**
+ * Playを更新しました
+ */
"updated": string;
+ /**
+ * Playを削除しました
+ */
"deleted": string;
+ /**
+ * Play設定
+ */
"pageSetting": string;
+ /**
+ * このPlayを編集
+ */
"editThisPage": string;
+ /**
+ * ソースを表示
+ */
"viewSource": string;
+ /**
+ * 自分のPlay
+ */
"my": string;
+ /**
+ * いいねしたPlay
+ */
"liked": string;
+ /**
+ * 人気
+ */
"featured": string;
+ /**
+ * タイトル
+ */
"title": string;
+ /**
+ * スクリプト
+ */
"script": string;
+ /**
+ * 説明
+ */
"summary": string;
+ /**
+ * 非公開に設定するとプロフィールに表示されなくなりますが、URLを知っている人は引き続きアクセスできます。
+ */
+ "visibilityDescription": string;
};
"_pages": {
+ /**
+ * ページの作成
+ */
"newPage": string;
+ /**
+ * ページの編集
+ */
"editPage": string;
+ /**
+ * ソースを表示中
+ */
"readPage": string;
+ /**
+ * ページを作成しました
+ */
"created": string;
+ /**
+ * ページを更新しました
+ */
"updated": string;
+ /**
+ * ページを削除しました
+ */
"deleted": string;
+ /**
+ * ページ設定
+ */
"pageSetting": string;
+ /**
+ * 指定されたページURLは既に存在しています
+ */
"nameAlreadyExists": string;
+ /**
+ * 不正なページURLです
+ */
"invalidNameTitle": string;
+ /**
+ * 空白でないか確認してください
+ */
"invalidNameText": string;
+ /**
+ * このページを編集
+ */
"editThisPage": string;
+ /**
+ * ソースを表示
+ */
"viewSource": string;
+ /**
+ * ページを見る
+ */
"viewPage": string;
+ /**
+ * いいね
+ */
"like": string;
+ /**
+ * いいね解除
+ */
"unlike": string;
+ /**
+ * 自分のページ
+ */
"my": string;
+ /**
+ * いいねしたページ
+ */
"liked": string;
+ /**
+ * 人気
+ */
"featured": string;
+ /**
+ * インスペクター
+ */
"inspector": string;
+ /**
+ * コンテンツ
+ */
"contents": string;
+ /**
+ * ページブロック
+ */
"content": string;
+ /**
+ * 変数
+ */
"variables": string;
+ /**
+ * タイトル
+ */
"title": string;
+ /**
+ * ページURL
+ */
"url": string;
+ /**
+ * ページの要約
+ */
"summary": string;
+ /**
+ * 中央寄せ
+ */
"alignCenter": string;
+ /**
+ * ピン留めされているときにタイトルを非表示
+ */
"hideTitleWhenPinned": string;
+ /**
+ * フォント
+ */
"font": string;
+ /**
+ * セリフ
+ */
"fontSerif": string;
+ /**
+ * サンセリフ
+ */
"fontSansSerif": string;
+ /**
+ * アイキャッチ画像を設定
+ */
"eyeCatchingImageSet": string;
+ /**
+ * アイキャッチ画像を削除
+ */
"eyeCatchingImageRemove": string;
+ /**
+ * ブロックを追加
+ */
"chooseBlock": string;
+ /**
+ * 種類を選択
+ */
"selectType": string;
+ /**
+ * コンテンツ
+ */
"contentBlocks": string;
+ /**
+ * 入力
+ */
"inputBlocks": string;
+ /**
+ * 特殊
+ */
"specialBlocks": string;
"blocks": {
+ /**
+ * テキスト
+ */
"text": string;
+ /**
+ * テキストエリア
+ */
"textarea": string;
+ /**
+ * セクション
+ */
"section": string;
+ /**
+ * 画像
+ */
"image": string;
+ /**
+ * ボタン
+ */
"button": string;
+ /**
+ * ノート埋め込み
+ */
"note": string;
"_note": {
+ /**
+ * ノートID
+ */
"id": string;
+ /**
+ * ノートURLをペーストして設定することもできます。
+ */
"idDescription": string;
+ /**
+ * 詳細な表示
+ */
"detailed": string;
};
};
};
"_relayStatus": {
+ /**
+ * 承認待ち
+ */
"requesting": string;
+ /**
+ * 承認済み
+ */
"accepted": string;
+ /**
+ * 拒否済み
+ */
"rejected": string;
};
"_notification": {
+ /**
+ * ファイルがアップロードされました
+ */
"fileUploaded": string;
- "youGotMention": string;
- "youGotReply": string;
- "youGotQuote": string;
- "youRenoted": string;
+ /**
+ * {name}からのメンション
+ */
+ "youGotMention": ParameterizedString<"name">;
+ /**
+ * {name}からのリプライ
+ */
+ "youGotReply": ParameterizedString<"name">;
+ /**
+ * {name}による引用
+ */
+ "youGotQuote": ParameterizedString<"name">;
+ /**
+ * {name}がRenoteしました
+ */
+ "youRenoted": ParameterizedString<"name">;
+ /**
+ * フォローされました
+ */
"youWereFollowed": string;
+ /**
+ * フォローリクエストが来ました
+ */
"youReceivedFollowRequest": string;
+ /**
+ * フォローリクエストが承認されました
+ */
"yourFollowRequestAccepted": string;
+ /**
+ * アンケートの結果が出ました
+ */
"pollEnded": string;
+ /**
+ * 新しい投稿
+ */
"newNote": string;
- "unreadAntennaNote": string;
+ /**
+ * アンテナ {name}
+ */
+ "unreadAntennaNote": ParameterizedString<"name">;
+ /**
+ * ロールが付与されました
+ */
+ "roleAssigned": string;
+ /**
+ * プッシュ通知の更新をしました
+ */
"emptyPushNotificationMessage": string;
+ /**
+ * 実績を獲得
+ */
"achievementEarned": string;
+ /**
+ * 通知テスト
+ */
"testNotification": string;
+ /**
+ * 通知の表示を確かめる
+ */
"checkNotificationBehavior": string;
+ /**
+ * テスト通知を送信する
+ */
"sendTestNotification": string;
+ /**
+ * 通知はこのように表示されます
+ */
"notificationWillBeDisplayedLikeThis": string;
- "reactedBySomeUsers": string;
- "renotedBySomeUsers": string;
- "followedBySomeUsers": string;
+ /**
+ * {n}人がリアクションしました
+ */
+ "reactedBySomeUsers": ParameterizedString<"n">;
+ /**
+ * {n}人がいいねしました
+ */
+ "likedBySomeUsers": ParameterizedString<"n">;
+ /**
+ * {n}人がリノートしました
+ */
+ "renotedBySomeUsers": ParameterizedString<"n">;
+ /**
+ * {n}人にフォローされました
+ */
+ "followedBySomeUsers": ParameterizedString<"n">;
+ /**
+ * 通知の履歴をリセットする
+ */
+ "flushNotification": string;
"_types": {
+ /**
+ * すべて
+ */
"all": string;
+ /**
+ * ユーザーの新規投稿
+ */
"note": string;
+ /**
+ * フォロー
+ */
"follow": string;
+ /**
+ * メンション
+ */
"mention": string;
+ /**
+ * リプライ
+ */
"reply": string;
+ /**
+ * Renote
+ */
"renote": string;
+ /**
+ * 引用
+ */
"quote": string;
+ /**
+ * リアクション
+ */
"reaction": string;
+ /**
+ * アンケートが終了
+ */
"pollEnded": string;
+ /**
+ * フォロー申請を受け取った
+ */
"receiveFollowRequest": string;
+ /**
+ * フォローが受理された
+ */
"followRequestAccepted": string;
+ /**
+ * ロールが付与された
+ */
+ "roleAssigned": string;
+ /**
+ * 実績の獲得
+ */
"achievementEarned": string;
+ /**
+ * 連携アプリからの通知
+ */
"app": string;
};
"_actions": {
+ /**
+ * フォローバック
+ */
"followBack": string;
+ /**
+ * 返信
+ */
"reply": string;
+ /**
+ * Renote
+ */
"renote": string;
};
};
"_deck": {
+ /**
+ * 常にメインカラムを表示
+ */
"alwaysShowMainColumn": string;
+ /**
+ * カラムの寄せ
+ */
"columnAlign": string;
+ /**
+ * カラムを追加
+ */
"addColumn": string;
+ /**
+ * カラムの設定
+ */
"configureColumn": string;
+ /**
+ * 左に移動
+ */
"swapLeft": string;
+ /**
+ * 右に移動
+ */
"swapRight": string;
+ /**
+ * 上に移動
+ */
"swapUp": string;
+ /**
+ * 下に移動
+ */
"swapDown": string;
+ /**
+ * 左にスタック
+ */
"stackLeft": string;
+ /**
+ * 右に出す
+ */
"popRight": string;
+ /**
+ * プロファイル
+ */
"profile": string;
+ /**
+ * 新規プロファイル
+ */
"newProfile": string;
+ /**
+ * プロファイルを削除
+ */
"deleteProfile": string;
+ /**
+ * カラムを組み合わせて自分だけのインターフェイスを作りましょう!
+ */
"introduction": string;
+ /**
+ * 画面の右にある + を押して、いつでもカラムを追加できます。
+ */
"introduction2": string;
+ /**
+ * カラムのメニューから、「ウィジェットの編集」を選択してウィジェットを追加してください
+ */
"widgetsIntroduction": string;
+ /**
+ * 非ルートページは簡易UIで表示
+ */
"useSimpleUiForNonRootPages": string;
+ /**
+ * 「幅を自動調整」が有効の場合、これが幅の最小値となります
+ */
"usedAsMinWidthWhenFlexible": string;
+ /**
+ * 幅を自動調整
+ */
"flexible": string;
"_columns": {
+ /**
+ * メイン
+ */
"main": string;
+ /**
+ * ウィジェット
+ */
"widgets": string;
+ /**
+ * 通知
+ */
"notifications": string;
+ /**
+ * タイムライン
+ */
"tl": string;
+ /**
+ * アンテナ
+ */
"antenna": string;
+ /**
+ * リスト
+ */
"list": string;
+ /**
+ * チャンネル
+ */
"channel": string;
+ /**
+ * あなた宛て
+ */
"mentions": string;
+ /**
+ * ダイレクト
+ */
"direct": string;
+ /**
+ * ロールタイムライン
+ */
"roleTimeline": string;
};
};
"_dialog": {
- "charactersExceeded": string;
- "charactersBelow": string;
+ /**
+ * 最大文字数を超えています! 現在 {current} / 制限 {max}
+ */
+ "charactersExceeded": ParameterizedString<"current" | "max">;
+ /**
+ * 最小文字数を下回っています! 現在 {current} / 制限 {min}
+ */
+ "charactersBelow": ParameterizedString<"current" | "min">;
};
"_disabledTimeline": {
+ /**
+ * 無効化されたタイムライン
+ */
"title": string;
+ /**
+ * 現在のロールでは、このタイムラインを使用することはできません。
+ */
"description": string;
};
"_drivecleaner": {
+ /**
+ * サイズが大きい順
+ */
"orderBySizeDesc": string;
+ /**
+ * 追加日が古い順
+ */
"orderByCreatedAtAsc": string;
};
"_webhookSettings": {
+ /**
+ * Webhookを作成
+ */
"createWebhook": string;
+ /**
+ * 名前
+ */
"name": string;
+ /**
+ * シークレット
+ */
"secret": string;
+ /**
+ * Webhookを実行するタイミング
+ */
"events": string;
+ /**
+ * 有効
+ */
"active": string;
"_events": {
+ /**
+ * フォローしたとき
+ */
"follow": string;
+ /**
+ * フォローされたとき
+ */
"followed": string;
+ /**
+ * ノートを投稿したとき
+ */
"note": string;
+ /**
+ * 返信されたとき
+ */
"reply": string;
+ /**
+ * Renoteされたとき
+ */
"renote": string;
+ /**
+ * リアクションがあったとき
+ */
"reaction": string;
+ /**
+ * メンションされたとき
+ */
"mention": string;
};
};
+ "_abuse": {
+ "_resolver": {
+ /**
+ * 一時間
+ */
+ "1hour": string;
+ /**
+ * 半日
+ */
+ "12hours": string;
+ /**
+ * 一日
+ */
+ "1day": string;
+ /**
+ * 一週間
+ */
+ "1week": string;
+ /**
+ * 一ヶ月
+ */
+ "1month": string;
+ /**
+ * 三ヶ月
+ */
+ "3months": string;
+ /**
+ * 六ヶ月
+ */
+ "6months": string;
+ /**
+ * 一年
+ */
+ "1year": string;
+ /**
+ * 無期限
+ */
+ "indefinitely": string;
+ /**
+ * この条件の有効期限
+ */
+ "expiresAt": string;
+ /**
+ * 通報先のパターン
+ */
+ "targetUserPattern": string;
+ /**
+ * 通報元のパターン
+ */
+ "reporterPattern": string;
+ /**
+ * 通報内容のパターン
+ */
+ "reportContentPattern": string;
+ };
+ /**
+ * 一覧
+ */
+ "list": string;
+ /**
+ * リソルバー
+ */
+ "resolver": string;
+ };
"_moderationLogTypes": {
+ /**
+ * ロールを作成
+ */
"createRole": string;
+ /**
+ * ロールを削除
+ */
"deleteRole": string;
+ /**
+ * ロールを更新
+ */
"updateRole": string;
+ /**
+ * ロールへアサイン
+ */
"assignRole": string;
+ /**
+ * ロールのアサイン解除
+ */
"unassignRole": string;
+ /**
+ * 凍結
+ */
"suspend": string;
+ /**
+ * 凍結解除
+ */
"unsuspend": string;
+ /**
+ * カスタム絵文字追加
+ */
"addCustomEmoji": string;
+ /**
+ * カスタム絵文字更新
+ */
"updateCustomEmoji": string;
+ /**
+ * カスタム絵文字削除
+ */
"deleteCustomEmoji": string;
+ /**
+ * サーバー設定更新
+ */
"updateServerSettings": string;
+ /**
+ * ユーザーのモデレーションノート更新
+ */
"updateUserNote": string;
+ /**
+ * ファイルを削除
+ */
"deleteDriveFile": string;
+ /**
+ * ノートを削除
+ */
"deleteNote": string;
+ /**
+ * 全体のお知らせを作成
+ */
"createGlobalAnnouncement": string;
+ /**
+ * ユーザーへお知らせを作成
+ */
"createUserAnnouncement": string;
+ /**
+ * 全体のお知らせを更新
+ */
"updateGlobalAnnouncement": string;
+ /**
+ * ユーザーのお知らせを更新
+ */
"updateUserAnnouncement": string;
+ /**
+ * 全体のお知らせを削除
+ */
"deleteGlobalAnnouncement": string;
+ /**
+ * ユーザーのお知らせを削除
+ */
"deleteUserAnnouncement": string;
+ /**
+ * パスワードをリセット
+ */
"resetPassword": string;
+ /**
+ * リモートサーバーを停止
+ */
"suspendRemoteInstance": string;
+ /**
+ * リモートサーバーを再開
+ */
"unsuspendRemoteInstance": string;
+ /**
+ * リモートサーバーのモデレーションノート更新
+ */
+ "updateRemoteInstanceNote": string;
+ /**
+ * ファイルをセンシティブ付与
+ */
"markSensitiveDriveFile": string;
+ /**
+ * ファイルをセンシティブ解除
+ */
"unmarkSensitiveDriveFile": string;
+ /**
+ * 通報を解決
+ */
"resolveAbuseReport": string;
+ /**
+ * 招待コードを作成
+ */
"createInvitation": string;
+ /**
+ * 広告を作成
+ */
"createAd": string;
+ /**
+ * 広告を削除
+ */
"deleteAd": string;
+ /**
+ * 広告を更新
+ */
"updateAd": string;
+ /**
+ * アイコンデコレーションを作成
+ */
"createAvatarDecoration": string;
+ /**
+ * アイコンデコレーションを更新
+ */
"updateAvatarDecoration": string;
+ /**
+ * アイコンデコレーションを削除
+ */
"deleteAvatarDecoration": string;
+ /**
+ * ユーザーのアイコンを解除
+ */
"unsetUserAvatar": string;
+ /**
+ * ユーザーのバナーを解除
+ */
"unsetUserBanner": string;
};
"_fileViewer": {
+ /**
+ * ファイルの詳細
+ */
"title": string;
+ /**
+ * ファイルタイプ
+ */
"type": string;
+ /**
+ * ファイルサイズ
+ */
"size": string;
+ /**
+ * URL
+ */
"url": string;
+ /**
+ * 追加日
+ */
"uploadedAt": string;
+ /**
+ * 添付されているノート
+ */
"attachedNotes": string;
+ /**
+ * このページは、このファイルをアップロードしたユーザーしか閲覧できません。
+ */
"thisPageCanBeSeenFromTheAuthor": string;
};
"_externalResourceInstaller": {
+ /**
+ * 外部サイトからインストール
+ */
"title": string;
+ /**
+ * 配布元が信頼できるかを確認した上でインストールしてください。
+ */
"checkVendorBeforeInstall": string;
"_plugin": {
+ /**
+ * このプラグインをインストールしますか?
+ */
"title": string;
+ /**
+ * プラグイン情報
+ */
"metaTitle": string;
};
"_theme": {
+ /**
+ * このテーマをインストールしますか?
+ */
"title": string;
+ /**
+ * テーマ情報
+ */
"metaTitle": string;
};
"_meta": {
+ /**
+ * 基本のカラースキーム
+ */
"base": string;
};
"_vendorInfo": {
+ /**
+ * 配布元情報
+ */
"title": string;
+ /**
+ * 参照したエンドポイント
+ */
"endpoint": string;
+ /**
+ * ファイル整合性の確認
+ */
"hashVerify": string;
};
"_errors": {
"_invalidParams": {
+ /**
+ * パラメータが不足しています
+ */
"title": string;
+ /**
+ * 外部サイトからデータを取得するために必要な情報が不足しています。URLをお確かめください。
+ */
"description": string;
};
"_resourceTypeNotSupported": {
+ /**
+ * この外部リソースには対応していません
+ */
"title": string;
+ /**
+ * この外部サイトから取得したリソースの種別には対応していません。サイト管理者にお問い合わせください。
+ */
"description": string;
};
"_failedToFetch": {
+ /**
+ * データの取得に失敗しました
+ */
"title": string;
+ /**
+ * 外部サイトとの通信に失敗しました。もう一度試しても改善しない場合、サイト管理者にお問い合わせください。
+ */
"fetchErrorDescription": string;
+ /**
+ * 外部サイトから取得したデータが読み取れませんでした。サイト管理者にお問い合わせください。
+ */
"parseErrorDescription": string;
};
"_hashUnmatched": {
+ /**
+ * 正しいデータが取得できませんでした
+ */
"title": string;
+ /**
+ * 提供されたデータの整合性の確認に失敗しました。セキュリティ上、インストールは続行できません。サイト管理者にお問い合わせください。
+ */
"description": string;
};
"_pluginParseFailed": {
+ /**
+ * AiScript エラー
+ */
"title": string;
+ /**
+ * データは取得できたものの、AiScriptの解析時にエラーがあったため読み込めませんでした。プラグインの作者にお問い合わせください。エラーの詳細はJavascriptコンソールをご確認ください。
+ */
"description": string;
};
"_pluginInstallFailed": {
+ /**
+ * プラグインのインストールに失敗しました
+ */
"title": string;
+ /**
+ * プラグインのインストール中に問題が発生しました。もう一度お試しください。エラーの詳細はJavascriptコンソールをご覧ください。
+ */
"description": string;
};
"_themeParseFailed": {
+ /**
+ * テーマ解析エラー
+ */
"title": string;
+ /**
+ * データは取得できたものの、テーマファイルの解析時にエラーがあったため読み込めませんでした。テーマの作者にお問い合わせください。エラーの詳細はJavascriptコンソールをご確認ください。
+ */
"description": string;
};
"_themeInstallFailed": {
+ /**
+ * テーマのインストールに失敗しました
+ */
"title": string;
+ /**
+ * テーマのインストール中に問題が発生しました。もう一度お試しください。エラーの詳細はJavascriptコンソールをご覧ください。
+ */
"description": string;
};
};
};
+ "_dataSaver": {
+ "_media": {
+ /**
+ * メディアの読み込み
+ */
+ "title": string;
+ /**
+ * 画像・動画が自動で読み込まれるのを防止します。隠れている画像・動画はタップすると読み込まれます。
+ */
+ "description": string;
+ };
+ "_avatar": {
+ /**
+ * アイコン画像
+ */
+ "title": string;
+ /**
+ * アイコン画像のアニメーションが停止します。アニメーション画像は通常の画像よりファイルサイズが大きいことがあるので、データ通信量をさらに削減できます。
+ */
+ "description": string;
+ };
+ "_urlPreview": {
+ /**
+ * URLプレビューのサムネイル
+ */
+ "title": string;
+ /**
+ * URLプレビューのサムネイル画像が読み込まれなくなります。
+ */
+ "description": string;
+ };
+ "_code": {
+ /**
+ * コードハイライト
+ */
+ "title": string;
+ /**
+ * MFMなどでコードハイライト記法が使われている場合、タップするまで読み込まれなくなります。コードハイライトではハイライトする言語ごとにその定義ファイルを読み込む必要がありますが、それらが自動で読み込まれなくなるため、通信量の削減が見込めます。
+ */
+ "description": string;
+ };
+ };
+ "_hemisphere": {
+ /**
+ * 北半球
+ */
+ "N": string;
+ /**
+ * 南半球
+ */
+ "S": string;
+ /**
+ * 一部のクライアント設定で、季節を判定するために使用します。
+ */
+ "caption": string;
+ };
+ "_reversi": {
+ /**
+ * リバーシ
+ */
+ "reversi": string;
+ /**
+ * 対局の設定
+ */
+ "gameSettings": string;
+ /**
+ * ボードを選択
+ */
+ "chooseBoard": string;
+ /**
+ * 先行/後攻
+ */
+ "blackOrWhite": string;
+ /**
+ * {name}が黒(先行)
+ */
+ "blackIs": ParameterizedString<"name">;
+ /**
+ * ルール
+ */
+ "rules": string;
+ /**
+ * 対局はまもなく開始されます
+ */
+ "thisGameIsStartedSoon": string;
+ /**
+ * 相手の準備が完了するのを待っています
+ */
+ "waitingForOther": string;
+ /**
+ * あなたの準備が完了するのを待っています
+ */
+ "waitingForMe": string;
+ /**
+ * 準備してください
+ */
+ "waitingBoth": string;
+ /**
+ * 準備完了
+ */
+ "ready": string;
+ /**
+ * 準備を再開
+ */
+ "cancelReady": string;
+ /**
+ * 相手のターンです
+ */
+ "opponentTurn": string;
+ /**
+ * あなたのターンです
+ */
+ "myTurn": string;
+ /**
+ * {name}のターンです
+ */
+ "turnOf": ParameterizedString<"name">;
+ /**
+ * {name}のターン
+ */
+ "pastTurnOf": ParameterizedString<"name">;
+ /**
+ * 投了
+ */
+ "surrender": string;
+ /**
+ * 投了により
+ */
+ "surrendered": string;
+ /**
+ * 時間切れ
+ */
+ "timeout": string;
+ /**
+ * 引き分け
+ */
+ "drawn": string;
+ /**
+ * {name}の勝ち
+ */
+ "won": ParameterizedString<"name">;
+ /**
+ * 黒
+ */
+ "black": string;
+ /**
+ * 白
+ */
+ "white": string;
+ /**
+ * 合計
+ */
+ "total": string;
+ /**
+ * {count}ターン目
+ */
+ "turnCount": ParameterizedString<"count">;
+ /**
+ * 自分の対局
+ */
+ "myGames": string;
+ /**
+ * みんなの対局
+ */
+ "allGames": string;
+ /**
+ * 終了
+ */
+ "ended": string;
+ /**
+ * 対局中
+ */
+ "playing": string;
+ /**
+ * 石の少ない方が勝ち(ロセオ)
+ */
+ "isLlotheo": string;
+ /**
+ * ループマップ
+ */
+ "loopedMap": string;
+ /**
+ * どこでも置けるモード
+ */
+ "canPutEverywhere": string;
+ /**
+ * 1ターンの時間制限
+ */
+ "timeLimitForEachTurn": string;
+ /**
+ * フリーマッチ
+ */
+ "freeMatch": string;
+ /**
+ * 対戦相手を探しています
+ */
+ "lookingForPlayer": string;
+ /**
+ * 対局がキャンセルされました
+ */
+ "gameCanceled": string;
+ /**
+ * 開始時に対局をタイムラインに投稿
+ */
+ "shareToTlTheGameWhenStart": string;
+ /**
+ * 対局を開始しました! #MisskeyReversi
+ */
+ "iStartedAGame": string;
+ /**
+ * 相手が設定を変更しました
+ */
+ "opponentHasSettingsChanged": string;
+ /**
+ * 変則許可 (完全フリー)
+ */
+ "allowIrregularRules": string;
+ /**
+ * 変則なし
+ */
+ "disallowIrregularRules": string;
+ /**
+ * 盤面に行・列番号を表示
+ */
+ "showBoardLabels": string;
+ /**
+ * 石をアイコンにする
+ */
+ "useAvatarAsStone": string;
+ };
+ "_offlineScreen": {
+ /**
+ * オフライン - サーバーに接続できません
+ */
+ "title": string;
+ /**
+ * サーバーに接続できません
+ */
+ "header": string;
+ };
}
declare const locales: {
[lang: string]: Locale;
};
+export function build(): Locale;
export default locales;
diff --git a/locales/index.js b/locales/index.js
index 67a406d98..650e55233 100644
--- a/locales/index.js
+++ b/locales/index.js
@@ -51,33 +51,37 @@ const primaries = {
// 何故か文字列にバックスペース文字が混入することがあり、YAMLが壊れるので取り除く
const clean = (text) => text.replace(new RegExp(String.fromCodePoint(0x08), 'g'), '');
-const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, import.meta.url), 'utf-8'))) || {}, a), {});
+export function build() {
+ const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, import.meta.url), 'utf-8'))) || {}, a), {});
-// 空文字列が入ることがあり、フォールバックが動作しなくなるのでプロパティごと消す
-const removeEmpty = (obj) => {
- for (const [k, v] of Object.entries(obj)) {
- if (v === '') {
- delete obj[k];
- } else if (typeof v === 'object') {
- removeEmpty(v);
+ // 空文字列が入ることがあり、フォールバックが動作しなくなるのでプロパティごと消す
+ const removeEmpty = (obj) => {
+ for (const [k, v] of Object.entries(obj)) {
+ if (v === '') {
+ delete obj[k];
+ } else if (typeof v === 'object') {
+ removeEmpty(v);
+ }
}
- }
- return obj;
-};
-removeEmpty(locales);
+ return obj;
+ };
+ removeEmpty(locales);
-export default Object.entries(locales)
- .reduce((a, [k ,v]) => (a[k] = (() => {
- const [lang] = k.split('-');
- switch (k) {
- case 'ja-JP': return v;
- case 'ja-KS':
- case 'en-US': return merge(locales['ja-JP'], v);
- default: return merge(
- locales['ja-JP'],
- locales['en-US'],
- locales[`${lang}-${primaries[lang]}`] ?? {},
- v
- );
- }
- })(), a), {});
+ return Object.entries(locales)
+ .reduce((a, [k, v]) => (a[k] = (() => {
+ const [lang] = k.split('-');
+ switch (k) {
+ case 'ja-JP': return v;
+ case 'ja-KS':
+ case 'en-US': return merge(locales['ja-JP'], v);
+ default: return merge(
+ locales['ja-JP'],
+ locales['en-US'],
+ locales[`${lang}-${primaries[lang]}`] ?? {},
+ v
+ );
+ }
+ })(), a), {});
+}
+
+export default build();
diff --git a/locales/it-IT.yml b/locales/it-IT.yml
index dd0abf228..480d11b6b 100644
--- a/locales/it-IT.yml
+++ b/locales/it-IT.yml
@@ -15,7 +15,7 @@ gotIt: "ok!"
cancel: "Annulla"
noThankYou: "No grazie"
enterUsername: "Inserisci un nome utente"
-renotedBy: "Rinotato da {user}"
+renotedBy: "Rinotata da {user}"
noNotes: "Nessuna nota!"
noNotifications: "Nessuna notifica"
instance: "Istanza"
@@ -102,12 +102,12 @@ defaultNoteVisibility: "Privacy predefinita delle note"
follow: "Segui"
followRequest: "Richiesta di follow"
followRequests: "Richieste di follow"
-unfollow: "Non seguire"
+unfollow: "Smetti di seguire"
followRequestPending: "Richiesta in approvazione"
enterEmoji: "Inserisci emoji"
renote: "Rinota"
unrenote: "Elimina la Rinota"
-renoted: "Rinotato!"
+renoted: "Rinotata!"
cantRenote: "È impossibile rinotare questa nota."
cantReRenote: "È impossibile rinotare una Rinota."
quote: "Citazione"
@@ -121,10 +121,16 @@ sensitive: "Allegato esplicito"
add: "Aggiungi"
reaction: "Reazioni"
reactions: "Reazioni"
-reactionSetting: "Reazioni visualizzate sul pannello"
+emojiPicker: "Selettore emoji"
+pinnedEmojisForReactionSettingDescription: "Scegli quale sia l'emoji in cima, quando reagisci"
+pinnedEmojisSettingDescription: "Scegli quale sia l'emoji in cima, quando reagisci"
+emojiPickerDisplay: "Visualizza selettore"
+overwriteFromPinnedEmojisForReaction: "Sovrascrivi con le impostazioni reazioni"
+overwriteFromPinnedEmojis: "Sovrascrivi con le impostazioni globali"
reactionSettingDescription2: "Trascina per riorganizzare, clicca per cancellare, usa il pulsante \"+\" per aggiungere."
rememberNoteVisibility: "Ricordare le impostazioni di visibilità delle note"
attachCancel: "Rimuovi allegato"
+deleteFile: "File da Drive eliminato"
markAsSensitive: "Segna come esplicito"
unmarkAsSensitive: "Non segnare come esplicito "
enterFileName: "Nome del file"
@@ -261,6 +267,7 @@ removed: "Eliminato con successo"
removeAreYouSure: "Vuoi davvero eliminare \"{x}\"?"
deleteAreYouSure: "Vuoi davvero eliminare \"{x}\"?"
resetAreYouSure: "Ripristinare?"
+areYouSure: "Confermi?"
saved: "Salvato"
messaging: "Messaggi"
upload: "Carica"
@@ -311,6 +318,7 @@ folderName: "Nome della cartella"
createFolder: "Nuova cartella"
renameFolder: "Rinomina cartella"
deleteFolder: "Elimina cartella"
+folder: "Cartella"
addFile: "Allega"
emptyDrive: "Il Drive è vuoto"
emptyFolder: "La cartella è vuota"
@@ -372,6 +380,11 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Abilita hCaptcha"
hcaptchaSiteKey: "Chiave del sito"
hcaptchaSecretKey: "Chiave segreta"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "Abilita hCaptcha"
+mcaptchaSiteKey: "Chiave del sito"
+mcaptchaSecretKey: "Chiave segreta"
+mcaptchaInstanceUrl: "URL della istanza mCaptcha"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Abilita reCAPTCHA"
recaptchaSiteKey: "Chiave del sito"
@@ -422,7 +435,7 @@ moderation: "moderazione"
moderationNote: "Promemoria di moderazione"
addModerationNote: "Aggiungi promemoria di moderazione"
moderationLogs: "Cronologia di moderazione"
-nUsersMentioned: "{n} profili menzionati"
+nUsersMentioned: "{n} profili ne parlano"
securityKeyAndPasskey: "Chiave di sicurezza e accesso"
securityKey: "Chiave di sicurezza"
lastUsed: "Ultima attività"
@@ -437,7 +450,6 @@ share: "Condividi"
notFound: "Non trovato"
notFoundDescription: "Nessuna pagina corrisponde all'URL indicata."
uploadFolder: "Destinazione caricamento predefinita"
-cacheClear: "Svuota cache"
markAsReadAllNotifications: "Segna tutte le notifiche come lette"
markAsReadAllUnreadNotes: "Segna tutte le note come lette"
markAsReadAllTalkMessages: "Segna tutte le chat come lette"
@@ -544,6 +556,8 @@ showInPage: "Visualizza in pagina"
popout: "Finestra pop-out"
volume: "Volume"
masterVolume: "Volume principale"
+notUseSound: "Non emettere suoni"
+useSoundOnlyWhenActive: "Emetti suoni solo quando Misskey è in attività"
details: "Dettagli"
chooseEmoji: "Scegli emoji"
unableToProcess: "Impossibile compiere l'operazione"
@@ -564,6 +578,10 @@ output: "Uscita"
script: "Script"
disablePagesScript: "Disabilita AiScript nelle pagine"
updateRemoteUser: "Aggiorna le informazioni dal profilo remoto"
+unsetUserAvatar: "Rimozione foto profilo"
+unsetUserAvatarConfirm: "Vuoi davvero rimuovere la foto profilo?"
+unsetUserBanner: "Rimuovi intestazione profilo"
+unsetUserBannerConfirm: "Vuoi davvero rimuovere l'intestazione dal profilo?"
deleteAllFiles: "Elimina tutti i file"
deleteAllFilesConfirm: "Vuoi davvero eliminare tutti i file?"
removeAllFollowing: "Annulla tutti i follow"
@@ -614,6 +632,7 @@ medium: "Medio"
small: "Piccolo"
generateAccessToken: "Genera token di accesso"
permission: "Autorizzazioni "
+adminPermission: "Privilegi amministrativi"
enableAll: "Abilita tutto"
disableAll: "Disabilita tutto"
tokenRequested: "Autorizza accesso al profilo"
@@ -635,10 +654,11 @@ smtpSecure: "Usare SSL/TLS implicito per le connessioni SMTP"
smtpSecureInfo: "Disabilitare quando è attivo STARTTLS."
testEmail: "Verifica il funzionamento"
wordMute: "Filtri parole"
+hardWordMute: "Filtro parole forte"
regexpError: "errore regex"
regexpErrorDescription: "Si è verificato un errore nell'espressione regolare alla riga {line} della parola muta {tab}:"
instanceMute: "Silenzia l'istanza"
-userSaysSomething: "{name} ha detto qualcosa"
+userSaysSomething: "{name} ha parlato"
makeActive: "Attiva"
display: "Visualizza"
copy: "Copia"
@@ -656,6 +676,7 @@ useGlobalSettingDesc: "Quando attiva, verranno utilizzate le impostazioni notifi
other: "Ulteriori"
regenerateLoginToken: "Genera di nuovo un token di connessione"
regenerateLoginTokenDescription: "Genera un nuovo token di autenticazione. Solitamente questa operazione non è necessaria: quando si genera un nuovo token, tutti i dispositivi vanno disconnessi."
+theKeywordWhenSearchingForCustomEmoji: "Questa sarà la parola chiave durante la ricerca di emoji personalizzate"
setMultipleBySeparatingWithSpace: "È possibile creare multiple voci separate da spazi."
fileIdOrUrl: "ID o URL del file"
behavior: "Comportamento"
@@ -741,7 +762,7 @@ reloadToApplySetting: "Le tue preferenze verranno impostate dopo il ricaricament
needReloadToApply: "È necessario riavviare per rendere effettive le modifiche."
showTitlebar: "Visualizza la barra del titolo"
clearCache: "Svuota la cache"
-onlineUsersCount: "{n} persone online"
+onlineUsersCount: "{n} persone attive adesso"
nUsers: "{n} profili"
nNotes: "{n}Note"
sendErrorReports: "Invia segnalazioni di errori"
@@ -814,7 +835,7 @@ configure: "Imposta"
postToGallery: "Pubblicare nella galleria"
postToHashtag: "Pubblica a questo hashtag"
gallery: "Galleria"
-recentPosts: "Le più recenti"
+recentPosts: "Pubblicazioni recenti"
popularPosts: "Le più visualizzate"
shareWithNote: "Condividere in nota"
ads: "Banner"
@@ -852,7 +873,7 @@ pubSub: "Publish/Subscribe del profilo"
lastCommunication: "La comunicazione più recente"
resolved: "Risolto"
unresolved: "Non risolto"
-breakFollow: "Non farti più seguire"
+breakFollow: "Impedire di seguirmi"
breakFollowConfirm: "Vuoi davvero che questo profilo smetta di seguirti?"
itsOn: "Abilitato"
itsOff: "Disabilitato"
@@ -868,8 +889,8 @@ makeReactionsPublicDescription: "La lista delle reazioni che avete fatto è a di
classic: "Classico"
muteThread: "Silenzia conversazione"
unmuteThread: "Riattiva la conversazione"
-ffVisibility: "Visibilità delle connessioni"
-ffVisibilityDescription: "Puoi scegliere a chi mostrare le tue relazioni con altri profili nel fediverso."
+followingVisibility: "Visibilità dei profili seguiti"
+followersVisibility: "Visibilità dei profili che ti seguono"
continueThread: "Altre conversazioni"
deleteAccountConfirm: "Così verrà eliminato il profilo. Vuoi procedere?"
incorrectPassword: "La password è errata."
@@ -970,6 +991,7 @@ neverShow: "Non mostrare più"
remindMeLater: "Rimanda"
didYouLikeMisskey: "Ti piace Misskey?"
pleaseDonate: "Misskey è il software libero utilizzato su {host}. Offrendo una donazione è più facile continuare a svilupparlo!"
+correspondingSourceIsAvailable: ""
roles: "Ruoli"
role: "Ruolo"
noRole: "Ruolo non trovato"
@@ -1020,6 +1042,11 @@ resetPasswordConfirm: "Vuoi davvero ripristinare la password?"
sensitiveWords: "Parole esplicite"
sensitiveWordsDescription: "Imposta automaticamente \"Home\" alla visibilità delle Note che contengono una qualsiasi parola tra queste configurate. Puoi separarle per riga."
sensitiveWordsDescription2: "Gli spazi creano la relazione \"E\" tra parole (questo E quello). Racchiudere una parola nelle slash \"/\" la trasforma in Espressione Regolare."
+prohibitedWords: "Parole proibite"
+prohibitedWordsDescription: "Verrà impedito di pubblicare Note che abbiano le parole indicate. Puoi impostare più parole, separatamente, su ogni riga."
+prohibitedWordsDescription2: "Gli spazi creano la relazione \"E\" tra parole (questo E quello). Racchiudere una parola nelle slash \"/\" la trasforma in Espressione Regolare."
+hiddenTags: "Hashtag nascosti"
+hiddenTagsDescription: "Impedire la visualizzazione del tag impostato nei trend. Puoi impostare più valori, uno per riga."
notesSearchNotAvailable: "Non è possibile cercare tra le Note."
license: "Licenza"
unfavoriteConfirm: "Vuoi davvero rimuovere la preferenza?"
@@ -1032,9 +1059,12 @@ enableChartsForRemoteUser: "Abilita i grafici per i profili remoti"
enableChartsForFederatedInstances: "Abilita i grafici per le istanze federate"
showClipButtonInNoteFooter: "Aggiungi il bottone Clip tra le azioni delle Note"
reactionsDisplaySize: "Grandezza delle reazioni"
+limitWidthOfReaction: "Limita la larghezza delle reazioni e ridimensionale"
noteIdOrUrl: "ID della Nota o URL"
video: "Video"
videos: "Video"
+audio: "Audio"
+audioFiles: "Audio"
dataSaver: "Risparmia dati"
accountMigration: "Migrazione del profilo"
accountMoved: "Questo profilo ha migrato altrove:"
@@ -1114,7 +1144,7 @@ currentAnnouncements: "Annunci attuali"
pastAnnouncements: "Annunci precedenti"
youHaveUnreadAnnouncements: "Ci sono Annunci non letti"
useSecurityKey: "Per utilizzare la chiave di sicurezza o la passkey, segui le indicazioni del dispositivo"
-replies: "Rispondi"
+replies: "Risposte"
renotes: "Rinota"
loadReplies: "Leggi le risposte"
loadConversation: "Leggi la conversazione"
@@ -1138,6 +1168,13 @@ hideRepliesToOthersInTimelineAll: "Nascondi le risposte dei tuoi follow nella TL
confirmShowRepliesAll: "Questa è una attività irreversibile. Vuoi davvero includere tutte le risposte dei following in TL?"
confirmHideRepliesAll: "Questa è una attività irreversibile. Vuoi davvero escludere tutte le risposte dei following in TL?"
externalServices: "Servizi esterni"
+sourceCode: "Codice sorgente"
+sourceCodeIsNotYetProvided: ""
+repositoryUrl: "URL della repository"
+repositoryUrlDescription: "Se esiste un repository il cui il codice sorgente è disponibile pubblicamente, inserisci il suo URL. Se stai utilizzando Misskey così com'è (senza alcuna modifica al codice sorgente), inserisci https://github.com/misskey-dev/misskey."
+repositoryUrlOrTarballRequired: "Se non disponi di un repository pubblico, dovrai fornire un file tarball (tar). Vedere .config/example.yml per i dettagli."
+feedback: "Feedback"
+feedbackUrl: "URL di feedback"
impressum: "Dichiarazione di proprietà"
impressumUrl: "URL della dichiarazione di proprietà"
impressumDescription: "La dichiarazione di proprietà, è obbligatoria in alcuni paesi come la Germania (Impressum)."
@@ -1147,6 +1184,7 @@ tosAndPrivacyPolicy: "Condizioni d'uso e informativa privacy"
avatarDecorations: "Decorazioni foto profilo"
attach: "Applica"
detach: "Rimuovi"
+detachAll: "Togli tutto"
angle: "Angolo"
flip: "Inverti"
showAvatarDecorations: "Mostra decorazione della foto profilo"
@@ -1158,6 +1196,34 @@ useGroupedNotifications: "Mostra le notifiche raggruppate"
signupPendingError: "Si è verificato un problema durante la verifica del tuo indirizzo email. Potrebbe essere scaduto il collegamento temporaneo."
cwNotationRequired: "Devi indicare perché il contenuto è indicato come esplicito."
doReaction: "Reagisci"
+code: "Codice"
+reloadRequiredToApplySettings: "Per applicare le impostazioni, occorre ricaricare."
+remainingN: "Rimangono: {n}"
+overwriteContentConfirm: "Vuoi davvero sostituire l'attuale contenuto?"
+seasonalScreenEffect: "Schermate in base alla stagione"
+decorate: "Decora"
+addMfmFunction: "Aggiungi decorazioni"
+enableQuickAddMfmFunction: "Attiva il selettore di funzioni MFM"
+bubbleGame: "Bubble Game"
+sfx: "Effetti sonori"
+soundWillBePlayed: "Con musica ed effetti sonori"
+showReplay: "Vedi i replay"
+replay: "Replay"
+replaying: "Replay in corso"
+ranking: "Classifica"
+lastNDays: "Ultimi {n} giorni"
+backToTitle: "Torna al titolo"
+hemisphere: "Geolocalizzazione"
+withSensitive: "Mostra le Note con allegati espliciti"
+userSaysSomethingSensitive: "Note da {name} con allegati espliciti"
+enableHorizontalSwipe: "Trascina per invertire i tab"
+surrender: "Annulla"
+_bubbleGame:
+ howToPlay: "Come giocare"
+ _howToPlay:
+ section1: "Scegli la posizione e rilascia l'oggetto nel contenitore."
+ section2: "Se due oggetti dello stesso tipo si toccano, si trasformano in un oggetto diverso, aumentando il punteggio."
+ section3: "Se gli oggetti escono dal limite superiore del contenitore, il gioco finisce. Cerca di ottenere un punteggio elevato fondendo gli oggetti, evitando che escano dal contenitore!"
_announcement:
forExistingUsers: "Solo ai profili attuali"
forExistingUsersDescription: "L'annuncio sarà visibile solo ai profili esistenti in questo momento. Se disabilitato, sarà visibile anche ai profili che verranno creati dopo la pubblicazione di questo annuncio."
@@ -1266,6 +1332,8 @@ _serverSettings:
shortName: "Abbreviazione"
shortNameDescription: "Un'abbreviazione o un nome comune che può essere visualizzato al posto del nome ufficiale lungo del server."
fanoutTimelineDescription: "Attivando questa funzionalità migliori notevolmente la capacità delle Timeline di collezionare Note, riducendo il carico sul database. Tuttavia, aumenterà l'impiego di memoria RAM per Redis. Disattiva se il tuo server ha poca RAM o la funzionalità è irregolare."
+ fanoutTimelineDbFallback: "Elaborazione dati alternativa"
+ fanoutTimelineDbFallbackDescription: "Attivando l'elaborazione alternativa, verrà interrogato ulteriormente il database se la timeline non è nella cache. \nDisattivando, si può ridurre ulteriormente il carico del server, evitando l'elaborazione alternativa, ma limitando l'intervallo recuperabile delle timeline."
_accountMigration:
moveFrom: "Migra un altro profilo dentro a questo"
moveFromSub: "Crea un alias verso un altro profilo remoto"
@@ -1526,6 +1594,13 @@ _achievements:
_tutorialCompleted:
title: "Attestato di partecipazione al corso per principianti di Misskey"
description: "Ha completato il tutorial"
+ _bubbleGameExplodingHead:
+ title: "🤯"
+ description: "Estrai l'oggetto più grande dal Bubble Game"
+ _bubbleGameDoubleExplodingHead:
+ title: "Doppio 🤯"
+ description: "Due oggetti più grossi contemporaneamente nel Bubble Game"
+ flavor: "Ha le dimensioni di una bento-box 🤯 🤯"
_role:
new: "Nuovo ruolo"
edit: "Modifica ruolo"
@@ -1536,7 +1611,9 @@ _role:
assignTarget: "Modalità di assegnazione del ruolo"
descriptionOfAssignTarget: "Manuale: per assegnare manualmente questo ruolo ai profili.\nCondizionale: per assegnare o rimuovere automaticamente questo ruolo ai profili, a precise condizioni."
manual: "Manuale"
+ manualRoles: "Ruoli assegnati manualmente"
conditional: "Condizionale"
+ conditionalRoles: "Ruoli condizionati"
condition: "Condizioni"
isConditionalRole: "Questo è un ruolo condizionato"
isPublic: "Ruolo pubblico"
@@ -1585,6 +1662,7 @@ _role:
canHideAds: "Nascondere i banner"
canSearchNotes: "Ricercare nelle Note"
canUseTranslator: "Tradurre le Note"
+ avatarDecorationLimit: "Numero massimo di decorazioni foto profilo installabili"
_condition:
isLocal: "Profilo locale"
isRemote: "Profilo remoto"
@@ -1613,6 +1691,7 @@ _emailUnavailable:
disposable: "Indirizzo email non utilizzabile"
mx: "Server email non corretto"
smtp: "Il server email non risponde"
+ banned: "Non puoi registrarti con questo indirizzo email"
_ffVisibility:
public: "Pubblica"
followers: "Mostra solo ai follower"
@@ -1660,7 +1739,7 @@ _preferencesBackups:
list: "Elenco di impostazioni salvate in precedenza"
saveNew: "Nuovo salvataggio"
loadFile: "Carica da file"
- apply: "Applicabile a questo dispositivo"
+ apply: "Applica a questo dispositivo"
save: "Sovrascrivi il backup"
inputName: "Inserire il nome del backup."
cannotSave: "Impossibile salvare."
@@ -1685,6 +1764,8 @@ _aboutMisskey:
contributors: "Principali sostenitori"
allContributors: "Tutti i sostenitori"
source: "Codice sorgente"
+ original: "Originale"
+ thisIsModifiedVersion: "{name} sta usando una versione modificata diversa da Misskey originale."
translation: "Tradurre Misskey"
donate: "Sostieni Misskey"
morePatrons: "Apprezziamo sinceramente il supporto di tante altre persone. Grazie mille! 🥰"
@@ -1806,6 +1887,14 @@ _sfx:
notification: "Notifiche"
antenna: "Ricezione dell'antenna"
channel: "Notifiche di canale"
+ reaction: "Quando seleziono una reazione"
+_soundSettings:
+ driveFile: "Suoni del Drive"
+ driveFileWarn: "Seleziona file dal dispositivo"
+ driveFileTypeWarn: "Formato file non supportato"
+ driveFileTypeWarnDescription: "Per favore, scegli un file di tipo audio"
+ driveFileDurationWarn: "La durata dell'audio è troppo lunga"
+ driveFileDurationWarnDescription: "Scegliere un audio lungo potrebbe interferire con l'uso di Misskey. Vuoi continuare lo stesso?"
_ago:
future: "Futuro"
justNow: "Adesso"
@@ -1817,6 +1906,14 @@ _ago:
monthsAgo: "{n} mesi fa"
yearsAgo: "{n} anni fa"
invalid: "Niente da visualizzare"
+_timeIn:
+ seconds: "Dopo {n} secondi"
+ minutes: "Dopo {n} minuti"
+ hours: "Dopo {n} ore"
+ days: "Dopo {n} giorni"
+ weeks: "Dopo {n} settimane"
+ months: "Dopo {n} mesi"
+ years: "Dopo {n} anni"
_time:
second: "s"
minute: "min"
@@ -1861,7 +1958,7 @@ _permissions:
"read:favorites": "Visualizza i tuoi preferiti"
"write:favorites": "Gestisci i tuoi preferiti"
"read:following": "Vedi le informazioni di follow"
- "write:following": "Seguire / Non seguire altri profili"
+ "write:following": "Following di altri profili"
"read:messaging": "Visualizzare la chat"
"write:messaging": "Gestire la chat"
"read:mutes": "Vedi i profili silenziati"
@@ -1888,6 +1985,55 @@ _permissions:
"write:flash": "Modifica Play"
"read:flash-likes": "Visualizza lista di Play piaciuti"
"write:flash-likes": "Modifica lista di Play piaciuti"
+ "read:admin:abuse-user-reports": "Mostra i report dai profili utente"
+ "write:admin:delete-account": "Elimina l'account utente"
+ "write:admin:delete-all-files-of-a-user": "Elimina i file dell'account utente"
+ "read:admin:index-stats": "Visualizza informazioni sugli indici del database"
+ "read:admin:table-stats": "Visualizza informazioni sulle tabelle del database"
+ "read:admin:user-ips": "Visualizza indirizzi IP degli account"
+ "read:admin:meta": "Visualizza i metadati dell'istanza"
+ "write:admin:reset-password": "Ripristina la password dell'account utente"
+ "write:admin:resolve-abuse-user-report": "Risolvere le segnalazioni dagli account utente"
+ "write:admin:send-email": "Spedire email"
+ "read:admin:server-info": "Vedere le informazioni sul server"
+ "read:admin:show-moderation-log": "Vedere lo storico di moderazione"
+ "read:admin:show-user": "Vedere le informazioni private degli account utente"
+ "read:admin:show-users": "Vedere le informazioni private degli account utente"
+ "write:admin:suspend-user": "Sospendere i profili"
+ "write:admin:unset-user-avatar": "Rimuovere la foto profilo dai profili"
+ "write:admin:unset-user-banner": "Rimuovere l'immagine testata dai profili"
+ "write:admin:unsuspend-user": "Togliere la sospensione ai profili"
+ "write:admin:meta": "Modificare i metadati dell'istanza"
+ "write:admin:user-note": "Scrivere annotazioni di moderazione"
+ "write:admin:roles": "Gestire i ruoli"
+ "read:admin:roles": "Vedere i ruoli"
+ "write:admin:relays": "Gestire i Relay"
+ "read:admin:relays": "Vedere i Relay"
+ "write:admin:invite-codes": "Gestire codici di invito"
+ "read:admin:invite-codes": "Vedere codici di invito"
+ "write:admin:announcements": "Gestire gli annunci"
+ "read:admin:announcements": "Leggere gli annunci"
+ "write:admin:avatar-decorations": "Gestire le decorazioni"
+ "read:admin:avatar-decorations": "Vedere le decorazioni"
+ "write:admin:federation": "Gestire la federazione"
+ "write:admin:account": "Vedere la federazione"
+ "read:admin:account": "Vedere le utenze"
+ "write:admin:emoji": "Gestire le emoji personalizzate"
+ "read:admin:emoji": "Vedere le emoji personalizzate"
+ "write:admin:queue": "Gestire la coda di attività"
+ "read:admin:queue": "Vedere la coda di attività"
+ "write:admin:promo": "Gestire le promozioni"
+ "write:admin:drive": "Gestire il Drive degli account"
+ "read:admin:drive": "Vedere il Drive degli account"
+ "read:admin:stream": "Usare le API Websocket"
+ "write:admin:ad": "Gestire i banner pubblicitari"
+ "read:admin:ad": "Vedere i banner pubblicitari"
+ "write:invite-codes": "Creare codici di invito"
+ "read:invite-codes": "Vedere i codici di invito"
+ "write:clip-favorite": "Impostare Clip preferite"
+ "read:clip-favorite": "Vedere Clip preferite"
+ "read:federation": "Vedere la federazione"
+ "write:report-abuse": "Inviare segnalazioni"
_auth:
shareAccessTitle: "Permessi dell'applicazione"
shareAccess: "Vuoi autorizzare {name} ad accedere al tuo profilo?"
@@ -1932,7 +2078,7 @@ _widgets:
postForm: "Finestra di pubblicazione"
slideshow: "Diapositive"
button: "Pulsante"
- onlineUsers: "Persone online"
+ onlineUsers: "Persone attive adesso"
jobQueue: "Coda di lavoro"
serverMetric: "Statistiche server"
aiscript: "Console AiScript"
@@ -1942,6 +2088,7 @@ _widgets:
_userList:
chooseList: "Seleziona una lista"
clicker: "Cliccaggio"
+ birthdayFollowings: "Chi nacque oggi"
_cw:
hide: "Nascondere"
show: "Continua la lettura..."
@@ -2004,9 +2151,11 @@ _profile:
changeAvatar: "Modifica immagine profilo"
changeBanner: "Cambia intestazione"
verifiedLinkDescription: "Puoi verificare il tuo profilo mostrando una icona. Devi inserire la URL alla pagina che contiene un link al tuo profilo."
+ avatarDecorationMax: "Puoi aggiungere fino a {max} decorazioni."
_exportOrImport:
allNotes: "Tutte le note"
favoritedNotes: "Note preferite"
+ clips: "Clip"
followingList: "Follow"
muteList: "Elenco profili silenziati"
blockingList: "Elenco profili bloccati"
@@ -2125,6 +2274,7 @@ _notification:
pollEnded: "Risultati del sondaggio."
newNote: "Nuove Note"
unreadAntennaNote: "Antenna {name}"
+ roleAssigned: "Ruolo assegnato"
emptyPushNotificationMessage: "Le notifiche push sono state aggiornate."
achievementEarned: "Obiettivo raggiunto"
testNotification: "Prova la notifica"
@@ -2146,6 +2296,7 @@ _notification:
pollEnded: "Sondaggio chiuso."
receiveFollowRequest: "Richiesta di follow ricevuta"
followRequestAccepted: "Richiesta di follow accettata"
+ roleAssigned: "Ruolo concesso"
achievementEarned: "Risultato raggiunto"
app: "Notifiche da applicazioni"
_actions:
@@ -2240,6 +2391,8 @@ _moderationLogTypes:
createAvatarDecoration: "Creazione decorazione della foto profilo"
updateAvatarDecoration: "Aggiornamento decorazione foto profilo"
deleteAvatarDecoration: "Eliminazione decorazione della foto profilo"
+ unsetUserAvatar: "Rimossa foto profilo"
+ unsetUserBanner: "Rimossa intestazione profilo"
_fileViewer:
title: "Dettagli del file"
type: "Tipo di file"
@@ -2289,3 +2442,66 @@ _externalResourceInstaller:
_themeInstallFailed:
title: "Impossibile installare la variazione grafica"
description: "Si è verificato un impedimento durante l'installazione della variazione grafica. Per favore riprova e consulta la console di Javascript per ottenere dettagli aggiuntivi."
+_dataSaver:
+ _media:
+ title: "Caricamento dei media"
+ description: "Impedire il caricamento automatico di immagini e video. Devi toccare le immagini o i video nascosti per caricarli."
+ _avatar:
+ title: "Immagine del profilo"
+ description: "Impedire l'animazione per l'immagine del profilo. Le immagini animate possono avere dimensioni file maggiori rispetto a quelle normali, puoi ridurre ulteriormente l'utilizzo dei dati."
+ _urlPreview:
+ title: "Anteprime delle URL"
+ description: "Impedire il caricamento delle anteprime URL."
+ _code:
+ title: "Codice evidenziato"
+ description: "Impedire che il codice sorgente sia automaticamente evidenziato. Evidenziare il codice richiede il caricamento di un file per ogni linguaggio. Puoi evidenziare soltanto il codice che intendi leggere e ridurre il traffico inutilizzato."
+_hemisphere:
+ N: "Emisfero boreale"
+ S: "Emisfero australe"
+ caption: "Utile per alcune impostazioni del client, per determinare la stagione."
+_reversi:
+ reversi: "Reversi"
+ gameSettings: "Impostazioni di gioco"
+ chooseBoard: "Segli la tavola"
+ blackOrWhite: "Neri / Bianchi"
+ blackIs: "{name} muove i Neri"
+ rules: "Regole del gioco"
+ thisGameIsStartedSoon: "Il gioco sta per iniziare"
+ waitingForOther: "Attendere l'avversario"
+ waitingForMe: "Ti stanno aspettando"
+ waitingBoth: "Preparatevi"
+ ready: "Pronti"
+ cancelReady: "Riprendere la preparazione"
+ opponentTurn: "Turno avversario"
+ myTurn: "Tocca a te"
+ turnOf: "Tocca a {name}"
+ pastTurnOf: "Turno di {name}"
+ surrender: "Mi arrendo"
+ surrendered: "Ha ceduto"
+ timeout: "Tempo scaduto"
+ drawn: "Pareggio"
+ won: "Ha vinto {name}"
+ black: "Neri"
+ white: "Bianchi"
+ total: "Totale"
+ turnCount: "Turno N. {count}"
+ myGames: "Le mie sfide"
+ allGames: "Tutte le sfide"
+ ended: "Conclusione"
+ playing: "In gioco"
+ isLlotheo: "Vince chi ha meno pietre (Roseo)"
+ loopedMap: "Mappa ricorsiva"
+ canPutEverywhere: "Modalità che può essere posizionata ovunque"
+ timeLimitForEachTurn: "Tempo limite per turno"
+ freeMatch: "Sfida libera"
+ lookingForPlayer: "Alla ricerca di un avversario"
+ gameCanceled: "Sfida cancellata"
+ shareToTlTheGameWhenStart: "Pubblica l'inizio della partita sulla tua Timeline"
+ iStartedAGame: "Inizia la sfida! #MisskeyReversi"
+ opponentHasSettingsChanged: "L'avversario ha cambiato configurazione"
+ allowIrregularRules: "Regole inconsuete (completamente libere)"
+ disallowIrregularRules: "Impedire le regole inconsuete"
+_offlineScreen:
+ title: "Scollegato. Impossibile connettersi al server"
+ header: "Impossibile connettersi al server"
+
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index c10faa382..02d38f086 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -121,10 +121,16 @@ sensitive: "センシティブ"
add: "追加"
reaction: "リアクション"
reactions: "リアクション"
-reactionSetting: "ピッカーに表示するリアクション"
+emojiPicker: "絵文字ピッカー"
+pinnedEmojisForReactionSettingDescription: "リアクション時にピン留め表示する絵文字を設定できます"
+pinnedEmojisSettingDescription: "絵文字入力時にピン留め表示する絵文字を設定できます"
+emojiPickerDisplay: "ピッカーの表示"
+overwriteFromPinnedEmojisForReaction: "リアクション設定から上書きする"
+overwriteFromPinnedEmojis: "全般設定から上書きする"
reactionSettingDescription2: "ドラッグして並び替え、クリックして削除、+を押して追加します。"
rememberNoteVisibility: "公開範囲を記憶する"
attachCancel: "添付取り消し"
+deleteFile: "ファイルを削除"
markAsSensitive: "センシティブとして設定"
unmarkAsSensitive: "センシティブを解除する"
enterFileName: "ファイル名を入力"
@@ -196,6 +202,7 @@ perDay: "1日ごと"
stopActivityDelivery: "アクティビティの配送を停止"
blockThisInstance: "このサーバーをブロック"
silenceThisInstance: "サーバーをサイレンス"
+sensitiveMediaThisInstance: "このサーバーのメディアを全てセンシティブとして設定"
operations: "操作"
software: "ソフトウェア"
version: "バージョン"
@@ -217,6 +224,8 @@ blockedInstances: "ブロックしたサーバー"
blockedInstancesDescription: "ブロックしたいサーバーのホストを改行で区切って設定します。ブロックされたサーバーは、このインスタンスとやり取りできなくなります。"
silencedInstances: "サイレンスしたサーバー"
silencedInstancesDescription: "サイレンスしたいサーバーのホストを改行で区切って設定します。サイレンスされたサーバーに所属するアカウントはすべて「サイレンス」として扱われ、フォローがすべてリクエストになり、フォロワーでないローカルアカウントにはメンションできなくなります。ブロックしたインスタンスには影響しません。"
+sensitiveMediaInstances: "センシティブなメディアを含むサーバー"
+sensitiveMediaInstancesDescription: "センシティブなメディアを含むサーバーのホストを改行で区切って設定します。このサーバーからのメディアは全てセンシティブとして扱われます。"
muteAndBlock: "ミュートとブロック"
mutedUsers: "ミュートしたユーザー"
blockedUsers: "ブロックしたユーザー"
@@ -256,11 +265,13 @@ noSuchUser: "ユーザーが見つかりません"
lookup: "照会"
announcements: "お知らせ"
imageUrl: "画像URL"
+displayOrder: "表示順"
remove: "削除"
removed: "削除しました"
removeAreYouSure: "「{x}」を削除しますか?"
deleteAreYouSure: "「{x}」を削除しますか?"
resetAreYouSure: "リセットしますか?"
+areYouSure: "よろしいですか?"
saved: "保存しました"
messaging: "チャット"
upload: "アップロード"
@@ -311,6 +322,7 @@ folderName: "フォルダー名"
createFolder: "フォルダーを作成"
renameFolder: "フォルダー名を変更"
deleteFolder: "フォルダーを削除"
+folder: "フォルダー"
addFile: "ファイルを追加"
emptyDrive: "ドライブは空です"
emptyFolder: "フォルダーは空です"
@@ -368,10 +380,17 @@ pinnedPages: "ピン留めページ"
pinnedPagesDescription: "サーバーのトップページにピン留めしたいページのパスを改行で区切って記述します。"
pinnedClipId: "ピン留めするクリップのID"
pinnedNotes: "ピン留めされたノート"
+featuredGameChannels: "Misskey Gamesのピン留めチャンネル"
+featuredGameChannelsDescription: "Misskey Gamesにピン留めしたいチャンネルを改行で区切って記述します。"
hcaptcha: "hCaptcha"
enableHcaptcha: "hCaptchaを有効にする"
hcaptchaSiteKey: "サイトキー"
hcaptchaSecretKey: "シークレットキー"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "mCaptchaを有効にする"
+mcaptchaSiteKey: "サイトキー"
+mcaptchaSecretKey: "シークレットキー"
+mcaptchaInstanceUrl: "mCaptchaのインスタンスのURL"
recaptcha: "reCAPTCHA"
enableRecaptcha: "reCAPTCHAを有効にする"
recaptchaSiteKey: "サイトキー"
@@ -437,7 +456,6 @@ share: "共有"
notFound: "見つかりません"
notFoundDescription: "指定されたURLに該当するページはありませんでした。"
uploadFolder: "既定アップロード先"
-cacheClear: "キャッシュを削除"
markAsReadAllNotifications: "すべての通知を既読にする"
markAsReadAllUnreadNotes: "すべての投稿を既読にする"
markAsReadAllTalkMessages: "すべてのチャットを既読にする"
@@ -482,6 +500,9 @@ emojiStyle: "絵文字のスタイル"
native: "ネイティブ"
disableDrawer: "メニューをドロワーで表示しない"
showNoteActionsOnlyHover: "ノートのアクションをホバー時のみ表示する"
+showRepliesCount: "ノートの返信数を表示する"
+showRenotesCount: "ノートのリノート数を表示する"
+showReactionsCount: "ノートのリアクション数を表示する"
noHistory: "履歴はありません"
signinHistory: "ログイン履歴"
enableAdvancedMfm: "高度なMFMを有効にする"
@@ -544,6 +565,8 @@ showInPage: "ページで表示"
popout: "ポップアウト"
volume: "音量"
masterVolume: "マスター音量"
+notUseSound: "サウンドを出力しない"
+useSoundOnlyWhenActive: "Misskeyがアクティブな時のみサウンドを出力する"
details: "詳細"
chooseEmoji: "絵文字を選択"
unableToProcess: "操作を完了できません"
@@ -573,6 +596,7 @@ deleteAllFilesConfirm: "すべてのファイルを削除しますか?"
removeAllFollowing: "フォローを全解除"
removeAllFollowingDescription: "{host}からのフォローをすべて解除します。そのサーバーがもう存在しなくなった場合などに実行してください。"
userSuspended: "このユーザーは凍結されています。"
+userLimited: "このユーザーは制限されています。"
userSilenced: "このユーザーはサイレンスされています。"
yourAccountSuspendedTitle: "アカウントが凍結されています"
yourAccountSuspendedDescription: "このアカウントは、サーバーの利用規約に違反したなどの理由により、凍結されています。詳細については管理者までお問い合わせください。新しいアカウントを作らないでください。"
@@ -618,6 +642,7 @@ medium: "中"
small: "小"
generateAccessToken: "アクセストークンの発行"
permission: "権限"
+adminPermission: "管理者権限"
enableAll: "全て有効にする"
disableAll: "全て無効にする"
tokenRequested: "アカウントへのアクセス許可"
@@ -660,6 +685,7 @@ useGlobalSettingDesc: "オンにすると、アカウントの通知設定が使
other: "その他"
regenerateLoginToken: "ログイントークンを再生成"
regenerateLoginTokenDescription: "ログインに使用される内部トークンを再生成します。通常この操作を行う必要はありません。再生成すると、全てのデバイスでログアウトされます。"
+theKeywordWhenSearchingForCustomEmoji: "カスタム絵文字を検索する時のキーワードになります。"
setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。"
fileIdOrUrl: "ファイルIDまたはURL"
behavior: "動作"
@@ -872,8 +898,8 @@ makeReactionsPublicDescription: "あなたがしたリアクション一覧を
classic: "クラシック"
muteThread: "スレッドをミュート"
unmuteThread: "スレッドのミュートを解除"
-ffVisibility: "つながりの公開範囲"
-ffVisibilityDescription: "自分のフォロー/フォロワー情報の公開範囲を設定できます。"
+followingVisibility: "フォローの公開範囲"
+followersVisibility: "フォロワーの公開範囲"
continueThread: "さらにスレッドを見る"
deleteAccountConfirm: "アカウントが削除されます。よろしいですか?"
incorrectPassword: "パスワードが間違っています。"
@@ -974,6 +1000,7 @@ neverShow: "今後表示しない"
remindMeLater: "また後で"
didYouLikeMisskey: "Misskeyを気に入っていただけましたか?"
pleaseDonate: "Misskeyは{host}が使用している無料のソフトウェアです。これからも開発を続けられるように、ぜひ寄付をお願いします!"
+correspondingSourceIsAvailable: "対応するソースコードは{anchor}から利用可能です。"
roles: "ロール"
role: "ロール"
noRole: "ロールはありません"
@@ -1024,8 +1051,14 @@ resetPasswordConfirm: "パスワードリセットしますか?"
sensitiveWords: "センシティブワード"
sensitiveWordsDescription: "設定したワードが含まれるノートの公開範囲をホームにします。改行で区切って複数設定できます。"
sensitiveWordsDescription2: "スペースで区切るとAND指定になり、キーワードをスラッシュで囲むと正規表現になります。"
+prohibitedWords: "禁止ワード"
+prohibitedWordsDescription: "設定したワードが含まれるノートを投稿しようとした際、エラーとなるようにします。改行で区切って複数設定できます。"
+prohibitedWordsDescription2: "スペースで区切るとAND指定になり、キーワードをスラッシュで囲むと正規表現になります。"
+hiddenTags: "非表示ハッシュタグ"
+hiddenTagsDescription: "設定したタグをトレンドに表示させないようにします。改行で区切って複数設定できます。"
notesSearchNotAvailable: "ノート検索は利用できません。"
license: "ライセンス"
+request: "リクエスト"
unfavoriteConfirm: "お気に入り解除しますか?"
myClips: "自分のクリップ"
drivecleaner: "ドライブクリーナー"
@@ -1036,9 +1069,12 @@ enableChartsForRemoteUser: "リモートユーザーのチャートを生成"
enableChartsForFederatedInstances: "リモートサーバーのチャートを生成"
showClipButtonInNoteFooter: "ノートのアクションにクリップを追加"
reactionsDisplaySize: "リアクションの表示サイズ"
+limitWidthOfReaction: "リアクションの最大横幅を制限し、縮小して表示する"
noteIdOrUrl: "ノートIDまたはURL"
video: "動画"
videos: "動画"
+audio: "音声"
+audioFiles: "音声"
dataSaver: "データセーバー"
accountMigration: "アカウントの移行"
accountMoved: "このユーザーは新しいアカウントに移行しました:"
@@ -1081,6 +1117,7 @@ update: "更新"
rolesThatCanBeUsedThisEmojiAsReaction: "リアクションとして使えるロール"
rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "ロールの指定が一つもない場合、誰でもリアクションとして使えます。"
rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "ロールは公開ロールである必要があります。"
+rolesThatCanNotBeUsedThisEmojiAsReaction: "リアクションとして使えないロール"
cancelReactionConfirm: "リアクションを取り消しますか?"
changeReactionConfirm: "リアクションを変更しますか?"
later: "あとで"
@@ -1088,6 +1125,7 @@ goToMisskey: "Misskeyへ"
additionalEmojiDictionary: "絵文字の追加辞書"
installed: "インストール済み"
branding: "ブランディング"
+dialogCloseDuration: "ダイアログを閉じるまでの待機時間"
enableServerMachineStats: "サーバーのマシン情報を公開する"
enableIdenticonGeneration: "ユーザーごとのIdenticon生成を有効にする"
turnOffToImprovePerformance: "オフにするとパフォーマンスが向上します。"
@@ -1134,6 +1172,7 @@ showRenotes: "リノートを表示"
edited: "編集済み"
notificationRecieveConfig: "通知の受信設定"
mutualFollow: "相互フォロー"
+followingOrFollower: "フォロー中またはフォロワー"
fileAttachedOnly: "ファイル付きのみ"
showRepliesToOthersInTimeline: "TLに他の人への返信を含める"
hideRepliesToOthersInTimeline: "TLに他の人への返信を含めない"
@@ -1142,6 +1181,14 @@ hideRepliesToOthersInTimelineAll: "TLに現在フォロー中の人全員の返
confirmShowRepliesAll: "この操作は元に戻せません。本当にTLに現在フォロー中の人全員の返信を含めるようにしますか?"
confirmHideRepliesAll: "この操作は元に戻せません。本当にTLに現在フォロー中の人全員の返信を含めないようにしますか?"
externalServices: "外部サービス"
+sourceCode: "ソースコード"
+sourceCodeIsNotYetProvided: "ソースコードはまだ提供されていません。この問題の修正について管理者に問い合わせてください。"
+repositoryUrl: "リポジトリURL"
+repositoryUrlDescription: "ソースコードが公開されているリポジトリがある場合、そのURLを記入します。Misskeyを現状のまま(ソースコードにいかなる変更も加えずに)使用している場合は https://github.com/misskey-dev/misskey と記入します。"
+feedback: "フィードバック"
+feedbackUrl: "フィードバックURL"
+support: "お問い合わせ"
+supportThisInstance: "{name}を支援"
impressum: "運営者情報"
impressumUrl: "運営者情報URL"
impressumDescription: "ドイツなどの一部の国と地域では表示が義務付けられています(Impressum)。"
@@ -1151,6 +1198,7 @@ tosAndPrivacyPolicy: "利用規約・プライバシーポリシー"
avatarDecorations: "アイコンデコレーション"
attach: "付ける"
detach: "外す"
+detachAll: "全て外す"
angle: "角度"
flip: "反転"
showAvatarDecorations: "アイコンのデコレーションを表示"
@@ -1162,6 +1210,72 @@ useGroupedNotifications: "通知をグルーピングして表示する"
signupPendingError: "メールアドレスの確認中に問題が発生しました。リンクの有効期限が切れている可能性があります。"
cwNotationRequired: "「内容を隠す」がオンの場合は注釈の記述が必要です。"
doReaction: "リアクションする"
+urlPreviewDenyList: "サムネイルの表示を制限するURL"
+urlPreviewDenyListDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります。スラッシュで囲むと正規表現になります。一致した場合、サムネイルがぼかされて表示されます。"
+code: "コード"
+reloadRequiredToApplySettings: "設定の反映にはリロードが必要です。"
+remainingN: "残り: {n}"
+overwriteContentConfirm: "現在の内容に上書きされますがよろしいですか?"
+seasonalScreenEffect: "季節に応じた画面の演出"
+decorate: "デコる"
+addMfmFunction: "装飾を追加"
+enableQuickAddMfmFunction: "高度なMFMのピッカーを表示する"
+bubbleGame: "バブルゲーム"
+sfx: "効果音"
+soundWillBePlayed: "サウンドが再生されます"
+showReplay: "リプレイを見る"
+replay: "リプレイ"
+replaying: "リプレイ中"
+endReplay: "リプレイを終了"
+copyReplayData: "リプレイデータをコピー"
+ranking: "ランキング"
+lastNDays: "直近{n}日"
+backToTitle: "タイトルへ"
+hemisphere: "お住まいの地域"
+withSensitive: "センシティブなファイルを含むノートを表示"
+userSaysSomethingSensitive: "{name}のセンシティブなファイルを含む投稿"
+enableHorizontalSwipe: "スワイプしてタブを切り替える"
+loading: "読み込み中"
+surrender: "やめる"
+gameRetry: "リトライ"
+abuseReportCategory: "通報の種類"
+selectCategory: "カテゴリを選択"
+reportComplete: "通報完了"
+blockThisUser: "このユーザーをブロックする"
+muteThisUser: "このユーザーをミュートする"
+
+_bubbleGame:
+ howToPlay: "遊び方"
+ hold: "ホールド"
+ _score:
+ score: "スコア"
+ scoreYen: "稼いだ金額"
+ highScore: "ハイスコア"
+ maxChain: "最大チェーン数"
+ yen: "{yen}円"
+ estimatedQty: "{qty}個分"
+ scoreSweets: "おにぎり {onigiriQtyWithUnit}"
+ _howToPlay:
+ section1: "位置を調整してハコにモノを落とします。"
+ section2: "同じ種類のモノがくっつくと別のモノに変化して、スコアが得られます。"
+ section3: "モノがハコからあふれるとゲームオーバーです。ハコからあふれないようにしつつモノを融合させてハイスコアを目指そう!"
+
+_abuseReportMsgs:
+ rightsAbuseCantAccept: "申し訳ございません。権利侵害の通報は権利者ご本人からのみ受け付けております。"
+
+_abuseReportCategory:
+ nsfw: "センシティブなコンテンツを含む投稿"
+ spam: "スパム"
+ explicit: "暴力もしくは攻撃的な投稿"
+ phishing: "フィッシングもしくは詐欺行為"
+ personalInfoLeak: "本人もしくは他人の個人情報の漏えい"
+ selfHarm: "自殺もしくは自害など生命に関わる問題"
+ criticalBreach: "重大な規約違反"
+ otherBreach: "その他の規約違反"
+ violationRights: "権利侵害もしくはなりすまし(本人)"
+ violationRightsOther: "権利侵害(他人)"
+ notLike: "この人が気に入らない"
+ other: "その他"
_announcement:
forExistingUsers: "既存ユーザーのみ"
@@ -1172,7 +1286,7 @@ _announcement:
tooManyActiveAnnouncementDescription: "アクティブなお知らせが多いため、UXが低下する可能性があります。終了したお知らせはアーカイブすることを検討してください。"
readConfirmTitle: "既読にしますか?"
readConfirmText: "「{title}」の内容を読み、既読にします。"
- shouldNotBeUsedToPresentPermanentInfo: "特に新規ユーザーのUXを損ねる可能性が高いため、ストック情報ではなくフロー情報の掲示にお知らせを使用することを推奨します。"
+ shouldNotBeUsedToPresentPermanentInfo: "特に新規ユーザーのUXを損ねる可能性が高いため、常時掲示するための情報ではなく、即時性が求められる情報の掲示のためにお知らせを使用することを推奨します。"
dialogAnnouncementUxWarn: "ダイアログ形式のお知らせが同時に2つ以上ある場合、UXに悪影響を及ぼす可能性が非常に高いため、使用は慎重に行うことを推奨します。"
silence: "非通知"
silenceDescription: "オンにすると、このお知らせは通知されず、既読にする必要もなくなります。"
@@ -1540,6 +1654,13 @@ _achievements:
_tutorialCompleted:
title: "Misskey初心者講座 修了証"
description: "チュートリアルを完了した"
+ _bubbleGameExplodingHead:
+ title: "🤯"
+ description: "バブルゲームで最も大きいモノを出した"
+ _bubbleGameDoubleExplodingHead:
+ title: "ダブル🤯"
+ description: "バブルゲームで最も大きいモノを2つ同時に出した"
+ flavor: "これくらいの おべんとばこに 🤯 🤯 ちょっとつめて"
_role:
new: "ロールの作成"
@@ -1551,7 +1672,9 @@ _role:
assignTarget: "アサイン"
descriptionOfAssignTarget: "マニュアルは誰がこのロールに含まれるかを手動で管理します。\nコンディショナルは条件を設定し、それに合致するユーザーが自動で含まれるようになります。"
manual: "マニュアル"
+ manualRoles: "マニュアルロール"
conditional: "コンディショナル"
+ conditionalRoles: "コンディショナルロール"
condition: "条件"
isConditionalRole: "これはコンディショナルロールです。"
isPublic: "公開ロール"
@@ -1579,6 +1702,14 @@ _role:
gtlAvailable: "グローバルタイムラインの閲覧"
ltlAvailable: "ローカルタイムラインの閲覧"
canPublicNote: "パブリック投稿の許可"
+ canInitiateConversation: "メンション、リプライ、引用の許可"
+ canCreateContent: "コンテンツの作成"
+ canUpdateContent: "コンテンツの編集"
+ canDeleteContent: "コンテンツの削除"
+ canPurgeAccount: "完全なアカウントの削除"
+ canUpdateAvatar: "アイコンの変更"
+ canUpdateBanner: "バナーの変更"
+ mentionMax: "ノート内の最大メンション数"
canInvite: "サーバー招待コードの発行"
inviteLimit: "招待コードの作成可能数"
inviteLimitCycle: "招待コードの発行間隔"
@@ -1587,8 +1718,10 @@ _role:
canManageAvatarDecorations: "アバターデコレーションの管理"
driveCapacity: "ドライブ容量"
alwaysMarkNsfw: "ファイルにNSFWを常に付与"
+ skipNsfwDetection: "AIによるNSFW検出を無視"
pinMax: "ノートのピン留めの最大数"
antennaMax: "アンテナの作成可能数"
+ antennaNotesMax: "アンテナに保持する最大ノート数"
wordMuteMax: "ワードミュートの最大文字数"
webhookMax: "Webhookの作成可能数"
clipMax: "クリップの作成可能数"
@@ -1600,7 +1733,10 @@ _role:
canHideAds: "広告の非表示"
canSearchNotes: "ノート検索の利用"
canUseTranslator: "翻訳機能の利用"
+ canUseDriveFileInSoundSettings: "サウンド設定でドライブのファイルを利用"
+ avatarDecorationLimit: "アイコンデコレーションの最大取付個数"
_condition:
+ roleAssignedTo: "マニュアルロールにアサイン済み"
isLocal: "ローカルユーザー"
isRemote: "リモートユーザー"
createdLessThan: "アカウント作成から~以内"
@@ -1630,6 +1766,7 @@ _emailUnavailable:
disposable: "恒久的に使用可能なアドレスではありません"
mx: "正しいメールサーバーではありません"
smtp: "メールサーバーが応答しません"
+ banned: "このメールアドレスでは登録できません"
_ffVisibility:
public: "公開"
@@ -1681,6 +1818,7 @@ _plugin:
installWarn: "信頼できないプラグインはインストールしないでください。"
manage: "プラグインの管理"
viewSource: "ソースを表示"
+ viewLog: "ログを表示"
_preferencesBackups:
list: "作成したバックアップ"
@@ -1713,6 +1851,8 @@ _aboutMisskey:
contributors: "コントリビューター"
allContributors: "全てのコントリビューター"
source: "ソースコード"
+ original: "オリジナル"
+ thisIsModifiedVersion: "{name}はオリジナルのMisskeyを改変したバージョンを使用しています。"
translation: "Misskeyを翻訳"
donate: "Misskeyに寄付"
morePatrons: "他にも多くの方が支援してくれています。ありがとうございます🥰"
@@ -1758,6 +1898,7 @@ _wordMute:
muteWords: "ミュートするワード"
muteWordsDescription: "スペースで区切るとAND指定になり、改行で区切るとOR指定になります。"
muteWordsDescription2: "キーワードをスラッシュで囲むと正規表現になります。"
+ hideMutedNotes: "ミュートされた単語を含むノートを非表示にする"
_instanceMute:
instanceMuteDescription: "ミュートしたサーバーのユーザーへの返信を含めて、設定したサーバーの全てのノートとRenoteをミュートします。"
@@ -1844,6 +1985,15 @@ _sfx:
notification: "通知"
antenna: "アンテナ受信"
channel: "チャンネル通知"
+ reaction: "リアクション選択時"
+
+_soundSettings:
+ driveFile: "ドライブの音声を使用"
+ driveFileWarn: "ドライブのファイルを選択してください"
+ driveFileTypeWarn: "このファイルは対応していません"
+ driveFileTypeWarnDescription: "音声ファイルを選択してください"
+ driveFileDurationWarn: "音声が長すぎます"
+ driveFileDurationWarnDescription: "長い音声を使用するとMisskeyの使用に支障をきたす可能性があります。それでも続行しますか?"
_ago:
future: "未来"
@@ -1882,7 +2032,7 @@ _2fa:
step3Title: "確認コードを入力"
step3: "アプリに表示されている確認コード(トークン)を入力します。"
setupCompleted: "設定が完了しました"
- step4: "これからログインするときも、同じようにコードを入力します。"
+ step4: "これからログインするときも、同じように確認コードを入力します。"
securityKeyNotSupported: "お使いのブラウザはセキュリティキーに対応していません。"
registerTOTPBeforeKey: "セキュリティキー・パスキーを登録するには、まず認証アプリの設定を行なってください。"
securityKeyInfo: "FIDO2をサポートするハードウェアセキュリティキー、端末の生体認証やPINロック、パスキーといった、WebAuthn由来の鍵を登録します。"
@@ -1939,6 +2089,57 @@ _permissions:
"write:flash": "Playを操作する"
"read:flash-likes": "Playのいいねを見る"
"write:flash-likes": "Playのいいねを操作する"
+ "read:admin:abuse-user-reports": "ユーザーからの通報を見る"
+ "read:admin:abuse-report-resolvers": "リゾルバーを見る"
+ "write:admin:abuse-report-resolvers": "リゾルバーを編集する"
+ "write:admin:delete-account": "ユーザーアカウントを削除する"
+ "write:admin:delete-all-files-of-a-user": "ユーザーのすべてのファイルを削除する"
+ "read:admin:index-stats": "データベースインデックスに関する情報を見る"
+ "read:admin:table-stats": "データベーステーブルに関する情報を見る"
+ "read:admin:user-ips": "ユーザーのIPアドレスを見る"
+ "read:admin:meta": "インスタンスのメタデータを見る"
+ "write:admin:reset-password": "ユーザーのパスワードをリセットする"
+ "write:admin:resolve-abuse-user-report": "ユーザーからの通報を解決する"
+ "write:admin:send-email": "メールを送る"
+ "read:admin:server-info": "サーバーの情報を見る"
+ "read:admin:show-moderation-log": "モデレーションログを見る"
+ "read:admin:show-user": "ユーザーのプライベートな情報を見る"
+ "read:admin:show-users": "ユーザーのプライベートな情報を見る"
+ "write:admin:suspend-user": "ユーザーを凍結する"
+ "write:admin:unset-user-avatar": "ユーザーのアバターを削除する"
+ "write:admin:unset-user-banner": "ユーザーのバーナーを削除する"
+ "write:admin:unsuspend-user": "ユーザーの凍結を解除する"
+ "write:admin:meta": "インスタンスのメタデータを操作する"
+ "write:admin:user-note": "モデレーションノートを操作する"
+ "write:admin:roles": "ロールを操作する"
+ "read:admin:roles": "ロールを見る"
+ "write:admin:relays": "リレーを操作する"
+ "read:admin:relays": "リレーを見る"
+ "write:admin:invite-codes": "招待コードを操作する"
+ "read:admin:invite-codes": "招待コードを見る"
+ "write:admin:announcements": "お知らせを操作する"
+ "read:admin:announcements": "お知らせを見る"
+ "write:admin:avatar-decorations": "アバターデコレーションを操作する"
+ "read:admin:avatar-decorations": "アバターデコレーションを見る"
+ "write:admin:federation": "連合に関する情報を操作する"
+ "write:admin:account": "ユーザーアカウントを操作する"
+ "read:admin:account": "ユーザーに関する情報を見る"
+ "write:admin:emoji": "絵文字を操作する"
+ "read:admin:emoji": "絵文字を見る"
+ "write:admin:queue": "ジョブキューを操作する"
+ "read:admin:queue": "ジョブキューに関する情報を見る"
+ "write:admin:promo": "プロモーションノートを操作する"
+ "write:admin:drive": "ユーザーのドライブを操作する"
+ "read:admin:drive": "ユーザーのドライブの関する情報を見る"
+ "read:admin:stream": "管理者用のWebsocket APIを使う"
+ "write:admin:ad": "広告を操作する"
+ "read:admin:ad": "広告を見る"
+ "write:invite-codes": "招待コードを作成する"
+ "read:invite-codes": "招待コードを取得する"
+ "write:clip-favorite": "クリップのいいねを操作する"
+ "read:clip-favorite": "クリップのいいねを見る"
+ "read:federation": "連合に関する情報を取得する"
+ "write:report-abuse": "違反を報告する"
_auth:
shareAccessTitle: "アプリへのアクセス許可"
@@ -1997,6 +2198,7 @@ _widgets:
_userList:
chooseList: "リストを選択"
clicker: "クリッカー"
+ birthdayFollowings: "今日誕生日のユーザー"
_cw:
hide: "隠す"
@@ -2050,6 +2252,7 @@ _postForm:
d: "言いたいことは?"
e: "ここに書いてください"
f: "あなたが書くのを待っています..."
+ guidelineInfo: "[NSFWガイドライン]({nsfwGuideUrl})を必ずお読みになってからご利用ください。"
_profile:
name: "名前"
@@ -2064,10 +2267,12 @@ _profile:
changeAvatar: "アイコン画像を変更"
changeBanner: "バナー画像を変更"
verifiedLinkDescription: "内容にURLを設定すると、リンク先のWebサイトに自分のプロフィールへのリンクが含まれている場合に所有者確認済みアイコンを表示させることができます。"
+ avatarDecorationMax: "最大{max}つまでデコレーションを付けられます。"
_exportOrImport:
allNotes: "全てのノート"
favoritedNotes: "お気に入りにしたノート"
+ clips: "クリップ"
followingList: "フォロー"
muteList: "ミュート"
blockingList: "ブロック"
@@ -2107,6 +2312,7 @@ _instanceCharts:
_timelines:
home: "ホーム"
local: "ローカル"
+ media: "メディア"
social: "ソーシャル"
global: "グローバル"
@@ -2125,6 +2331,7 @@ _play:
title: "タイトル"
script: "スクリプト"
summary: "説明"
+ visibilityDescription: "非公開に設定するとプロフィールに表示されなくなりますが、URLを知っている人は引き続きアクセスできます。"
_pages:
newPage: "ページの作成"
@@ -2194,6 +2401,7 @@ _notification:
pollEnded: "アンケートの結果が出ました"
newNote: "新しい投稿"
unreadAntennaNote: "アンテナ {name}"
+ roleAssigned: "ロールが付与されました"
emptyPushNotificationMessage: "プッシュ通知の更新をしました"
achievementEarned: "実績を獲得"
testNotification: "通知テスト"
@@ -2201,8 +2409,10 @@ _notification:
sendTestNotification: "テスト通知を送信する"
notificationWillBeDisplayedLikeThis: "通知はこのように表示されます"
reactedBySomeUsers: "{n}人がリアクションしました"
+ likedBySomeUsers: "{n}人がいいねしました"
renotedBySomeUsers: "{n}人がリノートしました"
followedBySomeUsers: "{n}人にフォローされました"
+ flushNotification: "通知の履歴をリセットする"
_types:
all: "すべて"
@@ -2216,6 +2426,7 @@ _notification:
pollEnded: "アンケートが終了"
receiveFollowRequest: "フォロー申請を受け取った"
followRequestAccepted: "フォローが受理された"
+ roleAssigned: "ロールが付与された"
achievementEarned: "実績の獲得"
app: "連携アプリからの通知"
@@ -2284,6 +2495,24 @@ _webhookSettings:
reaction: "リアクションがあったとき"
mention: "メンションされたとき"
+_abuse:
+ _resolver:
+ 1hour: "一時間"
+ 12hours: "半日"
+ 1day: "一日"
+ 1week: "一週間"
+ 1month: "一ヶ月"
+ 3months: "三ヶ月"
+ 6months: "六ヶ月"
+ 1year: "一年"
+ indefinitely: "無期限"
+ expiresAt: "この条件の有効期限"
+ targetUserPattern: "通報先のパターン"
+ reporterPattern: "通報元のパターン"
+ reportContentPattern: "通報内容のパターン"
+ list: "一覧"
+ resolver: "リソルバー"
+
_moderationLogTypes:
createRole: "ロールを作成"
deleteRole: "ロールを削除"
@@ -2296,7 +2525,7 @@ _moderationLogTypes:
updateCustomEmoji: "カスタム絵文字更新"
deleteCustomEmoji: "カスタム絵文字削除"
updateServerSettings: "サーバー設定更新"
- updateUserNote: "モデレーションノート更新"
+ updateUserNote: "ユーザーのモデレーションノート更新"
deleteDriveFile: "ファイルを削除"
deleteNote: "ノートを削除"
createGlobalAnnouncement: "全体のお知らせを作成"
@@ -2308,6 +2537,7 @@ _moderationLogTypes:
resetPassword: "パスワードをリセット"
suspendRemoteInstance: "リモートサーバーを停止"
unsuspendRemoteInstance: "リモートサーバーを再開"
+ updateRemoteInstanceNote: "リモートサーバーのモデレーションノート更新"
markSensitiveDriveFile: "ファイルをセンシティブ付与"
unmarkSensitiveDriveFile: "ファイルをセンシティブ解除"
resolveAbuseReport: "通報を解決"
@@ -2371,3 +2601,72 @@ _externalResourceInstaller:
_themeInstallFailed:
title: "テーマのインストールに失敗しました"
description: "テーマのインストール中に問題が発生しました。もう一度お試しください。エラーの詳細はJavascriptコンソールをご覧ください。"
+
+_dataSaver:
+ _media:
+ title: "メディアの読み込み"
+ description: "画像・動画が自動で読み込まれるのを防止します。隠れている画像・動画はタップすると読み込まれます。"
+ _avatar:
+ title: "アイコン画像"
+ description: "アイコン画像のアニメーションが停止します。アニメーション画像は通常の画像よりファイルサイズが大きいことがあるので、データ通信量をさらに削減できます。"
+ _urlPreview:
+ title: "URLプレビューのサムネイル"
+ description: "URLプレビューのサムネイル画像が読み込まれなくなります。"
+ _code:
+ title: "コードハイライト"
+ description: "MFMなどでコードハイライト記法が使われている場合、タップするまで読み込まれなくなります。コードハイライトではハイライトする言語ごとにその定義ファイルを読み込む必要がありますが、それらが自動で読み込まれなくなるため、通信量の削減が見込めます。"
+
+_hemisphere:
+ N: "北半球"
+ S: "南半球"
+ caption: "一部のクライアント設定で、季節を判定するために使用します。"
+
+_reversi:
+ reversi: "リバーシ"
+ gameSettings: "対局の設定"
+ chooseBoard: "ボードを選択"
+ blackOrWhite: "先行/後攻"
+ blackIs: "{name}が黒(先行)"
+ rules: "ルール"
+ thisGameIsStartedSoon: "対局はまもなく開始されます"
+ waitingForOther: "相手の準備が完了するのを待っています"
+ waitingForMe: "あなたの準備が完了するのを待っています"
+ waitingBoth: "準備してください"
+ ready: "準備完了"
+ cancelReady: "準備を再開"
+ opponentTurn: "相手のターンです"
+ myTurn: "あなたのターンです"
+ turnOf: "{name}のターンです"
+ pastTurnOf: "{name}のターン"
+ surrender: "投了"
+ surrendered: "投了により"
+ timeout: "時間切れ"
+ drawn: "引き分け"
+ won: "{name}の勝ち"
+ black: "黒"
+ white: "白"
+ total: "合計"
+ turnCount: "{count}ターン目"
+ myGames: "自分の対局"
+ allGames: "みんなの対局"
+ ended: "終了"
+ playing: "対局中"
+ isLlotheo: "石の少ない方が勝ち(ロセオ)"
+ loopedMap: "ループマップ"
+ canPutEverywhere: "どこでも置けるモード"
+ timeLimitForEachTurn: "1ターンの時間制限"
+ freeMatch: "フリーマッチ"
+ lookingForPlayer: "対戦相手を探しています"
+ gameCanceled: "対局がキャンセルされました"
+ shareToTlTheGameWhenStart: "開始時に対局をタイムラインに投稿"
+ iStartedAGame: "対局を開始しました! #MisskeyReversi"
+ opponentHasSettingsChanged: "相手が設定を変更しました"
+ allowIrregularRules: "変則許可 (完全フリー)"
+ disallowIrregularRules: "変則なし"
+ showBoardLabels: "盤面に行・列番号を表示"
+ useAvatarAsStone: "石をアイコンにする"
+
+_offlineScreen:
+ title: "オフライン - サーバーに接続できません"
+ header: "サーバーに接続できません"
+
diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml
index aa68def1d..7ff26c757 100644
--- a/locales/ja-KS.yml
+++ b/locales/ja-KS.yml
@@ -15,7 +15,7 @@ gotIt: "ほい"
cancel: "やめとく"
noThankYou: "やめとく"
enterUsername: "ユーザー名を入れてや"
-renotedBy: "{user}がRenoteしたで"
+renotedBy: "{user}がリノートしたで"
noNotes: "ノートはあらへん"
noNotifications: "通知はあらへん"
instance: "サーバー"
@@ -38,7 +38,7 @@ addUser: "ユーザーを追加や"
favorite: "お気に入り"
favorites: "お気に入り"
unfavorite: "やっぱ気に入らん"
-favorited: "お気に入りに入れたで"
+favorited: "お気に入りに入れたで。"
alreadyFavorited: "もうお気に入りに入れとるがな。"
cantFavorite: "アカン、お気に入りに入れれんかったわ。"
pin: "ピン留めしとく"
@@ -48,9 +48,9 @@ copyLink: "リンクをコピー"
copyLinkRenote: "リノートのリンクをコピーするで?"
delete: "ほかす"
deleteAndEdit: "ほかして直す"
-deleteAndEditConfirm: "このノートをほかしてもっかい直す?このノートへのツッコミ、Renote、返信も全部消えるんやけどそれでもええん?"
+deleteAndEditConfirm: "このノートをほかしてもっかい直す?このノートへのツッコミ、リノート、返信も全部消えるんやけどそれでもええん?"
addToList: "リストに入れたる"
-addToAntenna: "アンテナに追加"
+addToAntenna: "アンテナに入れる"
sendMessage: "メッセージを送る"
copyRSS: "RSSをコピー"
copyUsername: "ユーザー名をコピー"
@@ -59,7 +59,7 @@ copyNoteId: "ノートIDをコピー"
copyFileId: "ファイルIDをコピー"
copyFolderId: "フォルダーIDをコピー"
copyProfileUrl: "プロフィールURLをコピー"
-searchUser: "ユーザーを検索"
+searchUser: "ユーザーを探す"
reply: "返事"
loadMore: "まだまだあるで!"
showMore: "まだまだあるで!"
@@ -68,7 +68,7 @@ youGotNewFollower: "フォローされたで"
receiveFollowRequest: "フォローリクエストされたで"
followRequestAccepted: "フォローが承認されたで"
mention: "メンション"
-mentions: "自分宛て"
+mentions: "あんた宛て"
directNotes: "ダイレクト投稿"
importAndExport: "インポートとエクスポート"
import: "インポート"
@@ -88,7 +88,7 @@ followers: "フォロワー"
followsYou: "フォローされとるで"
createList: "リスト作る"
manageLists: "リストの管理"
-error: "エラー"
+error: "おかしなったで"
somethingHappened: "なんかあかんわ"
retry: "もっぺんやる?"
pageLoadError: "ページが読み込めんかったわ。"
@@ -105,13 +105,13 @@ followRequests: "フォロー申請"
unfollow: "フォローやめる"
followRequestPending: "フォロー許してくれるん待っとる"
enterEmoji: "絵文字を入れてや"
-renote: "Renote"
-unrenote: "Renoteやめる"
-renoted: "Renoteしたで。"
-cantRenote: "この投稿はRenoteできへんらしい。"
-cantReRenote: "Renote自体はRenoteできへんで。"
+renote: "リノート"
+unrenote: "リノートやめる"
+renoted: "リノートしたで。"
+cantRenote: "この投稿はリノートできへんっぽい。"
+cantReRenote: "リノート自体はリノートできへんで。"
quote: "引用"
-inChannelRenote: "チャンネル内Renote"
+inChannelRenote: "チャンネルの中でリノート"
inChannelQuote: "チャンネル内引用"
pinnedNote: "ピン留めされとるノート"
pinned: "ピン留めしとく"
@@ -121,17 +121,23 @@ sensitive: "気いつけて見いや"
add: "増やす"
reaction: "ツッコミ"
reactions: "ツッコミ"
-reactionSetting: "ピッカーに出しとくツッコミ"
+emojiPicker: "絵文字ピッカー"
+pinnedEmojisForReactionSettingDescription: "リアクションしたときにピンで留めてる表示をする絵文字を設定するで"
+pinnedEmojisSettingDescription: "絵文字打ったときにピン留め表示する絵文字設定できるで"
+emojiPickerDisplay: "ピッカーの表示"
+overwriteFromPinnedEmojisForReaction: "リアクション設定から上書きする"
+overwriteFromPinnedEmojis: "全般設定から上書きする"
reactionSettingDescription2: "ドラッグで並び替え、クリックで削除、+を押して追加やで。"
rememberNoteVisibility: "公開範囲覚えといて"
attachCancel: "のっけるのやめる"
+deleteFile: "ファイルをほかす"
markAsSensitive: "ちょっとこれはアカン"
unmarkAsSensitive: "そこまでアカンことないやろ"
enterFileName: "ファイル名を入れてや"
mute: "ミュート"
unmute: "ミュートやめたる"
-renoteMute: "Renoteは見いひん"
-renoteUnmute: "Renoteもやっぱ見るわ"
+renoteMute: "リノートは見いひん"
+renoteUnmute: "リノートもやっぱ見るわ"
block: "ブロック"
unblock: "ブロックやめたる"
suspend: "凍結"
@@ -141,13 +147,13 @@ unblockConfirm: "ブロックやめたるってほんまか?"
suspendConfirm: "凍結してしもうてええか?"
unsuspendConfirm: "解凍するけどええか?"
selectList: "リストを選ぶ"
-editList: "リスト直すで"
+editList: "リストいじる"
selectChannel: "チャンネルを選ぶ"
selectAntenna: "アンテナを選ぶ"
-editAntenna: "アンテナを編集"
+editAntenna: "アンテナいじる"
selectWidget: "ウィジェットを選ぶ"
editWidgets: "ウィジェットをいじる"
-editWidgetsExit: "編集終ったで"
+editWidgetsExit: "いじるのをやめる"
customEmojis: "カスタム絵文字"
emoji: "絵文字"
emojis: "絵文字"
@@ -156,14 +162,14 @@ emojiUrl: "絵文字画像URL"
addEmoji: "絵文字を追加"
settingGuide: "ええ感じの設定"
cacheRemoteFiles: "リモートのファイルをキャッシュする"
-cacheRemoteFilesDescription: "この設定を切っとったら、リモートファイルをキャッシュせんと直リンクするようになるで。サーバーの容量は節約できるけど、サムネイルを作らんなるから通信量が増えるで。"
+cacheRemoteFilesDescription: "この設定を入れとったら、リモートのファイルを端から端までこのサーバーのキャッシュん中突っ込むようになるで。画像映し出すんがめっちゃ速うなるけど、サーバーの容量をやたらと食うようになるで。リモートの人がどんだけ長くキャッシュを持っとくかはドライブ容量の制限で決めとくで。制限を超えたら古いのから順々に消してって、かわりにリンクになるで。この設定を切ったら、リモートのファイルは最初っからリンクとして扱うことにするけど、画像のサムネ作るのとかみんなのプライバシー守るために、default.ymlのproxyRemoteFilesをtrueにしといたほうがええよ。"
youCanCleanRemoteFilesCache: "ファイル管理にある🗑️ボタンでキャッシュ全部ほかすで。"
-cacheRemoteSensitiveFiles: "リモートのセンシティブなファイルをキャッシュする"
-cacheRemoteSensitiveFilesDescription: "この設定を無効にすると、リモートのセンシティブなファイルはキャッシュせず直リンクするようになるで。"
+cacheRemoteSensitiveFiles: "リモートのきわどいファイルをキャッシュに突っ込む"
+cacheRemoteSensitiveFilesDescription: "この設定を切ると、リモートのきわどいファイルはキャッシュせず直でリンクするようになるで。"
flagAsBot: "Botにするで"
flagAsBotDescription: "もしこのアカウントをプログラム使うて運用するんやったら、このフラグをオンにしてや。オンにすれば、反応がバーッて連鎖せんように開発者が使うたり、Misskeyのシステム上での扱いがBotに合ったもんになるからな。"
-flagAsCat: "Catやで"
-flagAsCatDescription: "ワレ、猫ちゃんならこのフラグをつけてみ?"
+flagAsCat: "猫や。かわええな。"
+flagAsCatDescription: "ネコになりたいんならこれつけとき。"
flagShowTimelineReplies: "タイムラインにノートへの返信を表示するで"
flagShowTimelineRepliesDescription: "オンにしたら、タイムラインにユーザーのノートの他にもそのユーザーの他のノートへの返信を表示するで。"
autoAcceptFollowed: "フォローしとるユーザーからのフォローリクエストを勝手に許可しとく"
@@ -214,12 +220,12 @@ clearQueueConfirmText: "未配達の投稿は配送されんなるで。ふつ
clearCachedFiles: "キャッシュをほかす"
clearCachedFilesConfirm: "キャッシュされとるリモートファイルをみんなほかしてええか?"
blockedInstances: "ブロックしたサーバー"
-blockedInstancesDescription: "ブロックしたいサーバーのホストを改行で区切って設定してな。ブロックされてもうたサーバーとはもう金輪際やり取りできひんくなるで。ついでにそのサブドメインもブロックするで。"
+blockedInstancesDescription: "ブロックしたいサーバーのホストを改行で区切って設定してな。ブロックされてもうたサーバーとはもう金輪際やり取りできひんくなるで。"
silencedInstances: "サーバーサイレンスされてんねん"
silencedInstancesDescription: "サイレンスしたいサーバーのホストを改行で区切って設定すんで。サイレンスされたサーバーに所属するアカウントはすべて「サイレンス」として扱われ、フォローがすべてリクエストになり、フォロワーでないローカルアカウントにはメンションできなくなんねん。ブロックしたインスタンスには影響せーへんで。"
muteAndBlock: "ミュートとブロック"
-mutedUsers: "ミュートしたユーザー"
-blockedUsers: "ブロックしたユーザー"
+mutedUsers: "ミュートしとるユーザー"
+blockedUsers: "ブロックしとるユーザー"
noUsers: "ユーザーはおらん"
editProfile: "プロフィールをいじる"
noteDeleteConfirm: "このノートをほかしてええか?"
@@ -246,7 +252,7 @@ changePassword: "パスワードをいじる"
security: "セキュリティ"
retypedNotMatch: "入れたやつ合うてへんわ。"
currentPassword: "今のパスワード"
-newPassword: "次のパスワード"
+newPassword: "今度のパスワード"
newPasswordRetype: "今度のパスワード(もっぺん入れて)"
attachFile: "ファイルのっける"
more: "他のん"
@@ -261,6 +267,7 @@ removed: "ほかしたで!"
removeAreYouSure: "「{x}」はほかしてええか?"
deleteAreYouSure: "「{x}」はほかしてええか?"
resetAreYouSure: "リセットしてええん?"
+areYouSure: "いいん?"
saved: "保存したで!"
messaging: "チャット"
upload: "アップロード"
@@ -311,6 +318,7 @@ folderName: "フォルダー名"
createFolder: "フォルダー作る"
renameFolder: "フォルダー名を変える"
deleteFolder: "フォルダーをほかす"
+folder: "フォルダー"
addFile: "ファイルを追加"
emptyDrive: "ドライブは空っぽや"
emptyFolder: "このフォルダーは空や"
@@ -324,7 +332,7 @@ copyUrl: "URLをコピー"
rename: "名前を変えるで"
avatar: "アイコン"
banner: "バナー"
-displayOfSensitiveMedia: "センシティブなメディアの表示"
+displayOfSensitiveMedia: "きわどいやつの表示"
whenServerDisconnected: "サーバーとの接続が失くなってしもうたとき"
disconnectedFromServer: "サーバーが機嫌悪いねん"
reload: "リロード"
@@ -372,6 +380,11 @@ hcaptcha: "hCaptcha(キャプチャ)"
enableHcaptcha: "hCaptcha(キャプチャ)をつけとく"
hcaptchaSiteKey: "サイトキー"
hcaptchaSecretKey: "シークレットキー"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "hCaptcha(キャプチャ)をつけとく"
+mcaptchaSiteKey: "サイトキー"
+mcaptchaSecretKey: "シークレットキー"
+mcaptchaInstanceUrl: "mCaptchaのインスタンスのURL"
recaptcha: "reCAPTCHA"
enableRecaptcha: "reCAPTCHA(リキャプチャ)を有効にする"
recaptchaSiteKey: "サイトキー"
@@ -412,7 +425,7 @@ userList: "リスト"
about: "情報"
aboutMisskey: "Misskeyってなんや?"
administrator: "管理者"
-token: "トークン"
+token: "確認コード"
2fa: "二要素認証"
setupOf2fa: "二要素認証のセットアップ"
totp: "認証アプリ"
@@ -425,7 +438,7 @@ moderationLogs: "モデログ"
nUsersMentioned: "{n}人が投稿"
securityKeyAndPasskey: "セキュリティキー・パスキー"
securityKey: "セキュリティキー"
-lastUsed: "最後につこうた日"
+lastUsed: "最後に使うた日"
lastUsedAt: "最後に使うたんは: {t}"
unregister: "登録やめる"
passwordLessLogin: "パスワード無くてもログインできるようにする"
@@ -437,7 +450,6 @@ share: "わけわけ"
notFound: "見つからへんね"
notFoundDescription: "言われたURLにはまるページはなかったで。"
uploadFolder: "とりあえずアップロードしたやつ置いとく所"
-cacheClear: "キャッシュをほかす"
markAsReadAllNotifications: "通知はもう全て読んだわっ"
markAsReadAllUnreadNotes: "投稿は全て読んだわっ"
markAsReadAllTalkMessages: "チャットはもうぜんぶ読んだわっ"
@@ -471,7 +483,7 @@ weakPassword: "へぼいパスワード"
normalPassword: "ぼちぼちのパスワード"
strongPassword: "ええ感じのパスワード"
passwordMatched: "よし!一致や!"
-passwordNotMatched: "一致しとらんで?"
+passwordNotMatched: "ちゃうで?"
signinWith: "{x}でログイン"
signinFailed: "ログインできんかったで。もっかいユーザー名とパスワードを確認してみてや。"
or: "それか"
@@ -525,7 +537,7 @@ objectStorageEndpointDesc: "S3のときは空、それ以外は各サービス
objectStorageRegion: "Region"
objectStorageRegionDesc: "'xx-east-1'みたいなregionを指定したってやー。使ってるサービスにregionの概念がないときは、空か'us-east-1'にするんやで。"
objectStorageUseSSL: "SSLを使う"
-objectStorageUseSSLDesc: "API接続にhttpsを使わん場合はオフにするんやで"
+objectStorageUseSSLDesc: "API接続にhttpsを使わんのやったら消しといて"
objectStorageUseProxy: "Proxyを使う"
objectStorageUseProxyDesc: "API接続にproxy使わんのやったら切ってくれへん?"
objectStorageSetPublicRead: "アップロードした時に'public-read'を設定してや"
@@ -536,14 +548,16 @@ showFixedPostForm: "タイムラインの上の方で投稿できるようにや
showFixedPostFormInChannel: "タイムラインの上の方で投稿できるようにするわ(チャンネル)"
withRepliesByDefaultForNewlyFollowed: "フォローする時、デフォルトで返信をタイムラインに含むようにしよか"
newNoteRecived: "新しいノートがあるで"
-sounds: "サウンド"
-sound: "サウンド"
+sounds: "音"
+sound: "音"
listen: "聴く"
none: "なし"
showInPage: "ページで表示"
popout: "ポップアウト"
volume: "やかましさ"
masterVolume: "全体のやかましさ"
+notUseSound: "音出さへん"
+useSoundOnlyWhenActive: "Misskeyがアクティブなときだけ音出す"
details: "もっと"
chooseEmoji: "絵文字を選ぶ"
unableToProcess: "なんか奥の方で詰まってもうた"
@@ -564,6 +578,10 @@ output: "出力"
script: "スクリプト"
disablePagesScript: "Pagesのスクリプトを無効にしてや"
updateRemoteUser: "リモートユーザー情報の更新してくれん?"
+unsetUserAvatar: "アイコン戻す"
+unsetUserAvatarConfirm: "アイコンを元に戻すで?"
+unsetUserBanner: "バナー戻す"
+unsetUserBannerConfirm: "バナー元に戻すで?"
deleteAllFiles: "ファイルを全部ほかす"
deleteAllFilesConfirm: "ホンマにファイル全部ほかすんか?消したもんはもう戻ってこんのやで?"
removeAllFollowing: "フォローを全解除"
@@ -575,7 +593,7 @@ yourAccountSuspendedDescription: "あんたのアカウントは、サーバー
tokenRevoked: "トークンが無効やで"
tokenRevokedDescription: "ログイントークンが失効しとるで。もっかいログインしてもろてもええか?"
accountDeleted: "アカウントは削除されとるで"
-accountDeletedDescription: "このアカウントは削除されとるで。"
+accountDeletedDescription: "このアカウントはもう消えとる。"
menu: "メニュー"
divider: "分割線"
addItem: "項目を追加"
@@ -591,9 +609,9 @@ enableInfiniteScroll: "自動でもっと見る"
visibility: "公開範囲"
poll: "アンケート"
useCw: "内容を隠す"
-enablePlayer: "プレイヤーを開く"
-disablePlayer: "プレイヤーを閉じる"
-expandTweet: "ポストを展開する"
+enablePlayer: "プレイヤー開く"
+disablePlayer: "プレイヤー閉じる"
+expandTweet: "ポスト展開しとく"
themeEditor: "テーマエディター"
description: "説明"
describeFile: "キャプションを付ける"
@@ -606,7 +624,7 @@ preferencesBackups: "設定のバックアップ"
deck: "デッキ"
undeck: "デッキ解除"
useBlurEffectForModal: "モーダルにぼかし効果を使用"
-useFullReactionPicker: "フル機能の突っ込みピッカーを使用"
+useFullReactionPicker: "フルフルのツッコミピッカーを使う"
width: "幅"
height: "高さ"
large: "大"
@@ -614,6 +632,7 @@ medium: "中"
small: "小"
generateAccessToken: "アクセストークンの発行"
permission: "権限"
+adminPermission: "管理者権限"
enableAll: "全部使えるようにする"
disableAll: "全部使えへんようにする"
tokenRequested: "アカウントへのアクセス許してやったらどうや"
@@ -635,6 +654,7 @@ smtpSecure: "SMTP 接続に暗黙的なSSL/TLSを使用する"
smtpSecureInfo: "STARTTLS使っとる時はオフにしてや。"
testEmail: "配信テスト"
wordMute: "ワードミュート"
+hardWordMute: "ハードワードミュート"
regexpError: "正規表現エラー"
regexpErrorDescription: "{tab}ワードミュートの{line}行目の正規表現にエラーが出てきたで:"
instanceMute: "サーバーミュート"
@@ -650,12 +670,13 @@ database: "データベース"
channel: "チャンネル"
create: "作成"
notificationSetting: "通知設定"
-notificationSettingDesc: "表示する通知の種類えらんでや。"
+notificationSettingDesc: "出す通知の種類えらんでや。"
useGlobalSetting: "グローバル設定を使ってや"
useGlobalSettingDesc: "オンにすると、アカウントの通知設定が使われるで。オフにすると、別々に設定できるようになるで。"
other: "その他"
regenerateLoginToken: "ログイントークンを再生成"
regenerateLoginTokenDescription: "ログインに使われる内部トークンをもっかい作るで。いつもならこれをやる必要はないで。もっかい作ると、全部のデバイスでログアウトされるで気ぃつけてなー。"
+theKeywordWhenSearchingForCustomEmoji: "カスタム絵文字を探すときのキーワードになるで。"
setMultipleBySeparatingWithSpace: "スペースで区切って何個でも設定できるで。"
fileIdOrUrl: "ファイルIDかURL"
behavior: "動作"
@@ -687,18 +708,18 @@ clip: "クリップ"
createNew: "新しく作るで"
optional: "任意"
createNewClip: "新しいクリップを作るで"
-unclip: "クリップ解除するで"
-confirmToUnclipAlreadyClippedNote: "このノートはすでにクリップ「{name}」に含まれとるで。ノートをこのクリップから除外しよか?"
+unclip: "クリップやめとく"
+confirmToUnclipAlreadyClippedNote: "このノートはもう「{name}」に含まれとるで。ノート、このクリップから外そか?"
public: "パブリック"
private: "非公開"
-i18nInfo: "Misskeyは有志によっていろんな言語に翻訳されとるで。{link}で翻訳に協力したってやー。"
+i18nInfo: "Misskeyは有志がいろんな言語に訳しとるで。{link}で翻訳に協力したってやー。"
manageAccessTokens: "アクセストークンの管理"
accountInfo: "アカウント情報"
notesCount: "ノートの数やで"
repliesCount: "返信した数やで"
-renotesCount: "Renoteした数やで"
+renotesCount: "リノートした数やで"
repliedCount: "返信された数やで"
-renotedCount: "Renoteされた数やで"
+renotedCount: "リノートされた数やで"
followingCount: "フォロー数やで"
followersCount: "フォロワー数やで"
sentReactionsCount: "ツッコんだ数"
@@ -715,7 +736,7 @@ lockedAccountInfo: "フォローを承認制にしとっても、ノートの公
alwaysMarkSensitive: "デフォルトでメディアを閲覧注意にするで"
loadRawImages: "添付画像のサムネイルをオリジナル画質にするで"
disableShowingAnimatedImages: "アニメーション画像を再生せんとくで"
-highlightSensitiveMedia: "メディアがセンシティブなことをめっっちゃわかりやすく表紙"
+highlightSensitiveMedia: "きわどいことをめっっちゃわかりやすくする"
verificationEmailSent: "無事確認のメールを送れたで。メールに書いてあるリンクにアクセスして、設定を完了してなー。"
notSet: "未設定"
emailVerified: "メールアドレスは確認されたで"
@@ -727,7 +748,7 @@ useSystemFont: "システムのデフォルトのフォントを使うで"
clips: "クリップ"
experimentalFeatures: "おためし機能やで"
experimental: "実験的"
-thisIsExperimentalFeature: "これは実験的な機能やで。仕様が変更になったりちゃんと動かなかったりするかもやで。"
+thisIsExperimentalFeature: "これは実験的な機能やから、仕様が変わったりちゃんと動かんかったりするかもしれん。"
developer: "開発者やで"
makeExplorable: "アカウントを見つけやすくするで"
makeExplorableDescription: "オフにすると、「みつける」にアカウントが載らんくなるで。"
@@ -745,7 +766,7 @@ onlineUsersCount: "{n}人が起きとるで"
nUsers: "{n}ユーザー"
nNotes: "{n}ノート"
sendErrorReports: "エラーリポートを送る"
-sendErrorReportsDescription: "オンにしたら、変なことが起きたときにエラーの詳細がMisskeyに送られて、ソフトウェアの品質向上に使えるようになるで。エラー情報には、OSのバージョン、ブラウザの種類、行動履歴なんかが含まれるで。"
+sendErrorReportsDescription: "オンにしたら、なんか変なことが起きたとき、詳しいのが全部Misskeyに送られて、ソフトウェアをもっと良うするで。エラー情報には、OSのバージョン、ブラウザの種類、行動履歴なんかが含まれるな。"
myTheme: "マイテーマ"
backgroundColor: "背景"
accentColor: "アクセント"
@@ -761,8 +782,8 @@ deleteConfirm: "ホンマにほかすで?"
invalidValue: "有効な値じゃないみたいやで。"
registry: "レジストリ"
closeAccount: "アカウントを閉鎖する"
-currentVersion: "現在のバージョン"
-latestVersion: "最新のバージョン"
+currentVersion: "今のやつ"
+latestVersion: "いっちゃん新しいやつ"
youAreRunningUpToDateClient: "今使ってるクライアントが最新やで!"
newVersionOfClientAvailable: "新しいバージョンのクライアントが使えるで。"
usageAmount: "使用量"
@@ -784,9 +805,9 @@ goBack: "戻る"
unlikeConfirm: "いいね解除するんか?"
fullView: "フルビュー"
quitFullView: "フルビュー解除"
-addDescription: "説明を追加するで"
-userPagePinTip: "個々のノートのメニューから「ピン留め」を選んどくと、ここにノートを表示しておけるで。"
-notSpecifiedMentionWarning: "宛先に含まれてへんメンションがあるで"
+addDescription: "説明を入れるで"
+userPagePinTip: "ノートのメニューから「ピン留め」を選んどいたら、ここにノートを置いとけるで。"
+notSpecifiedMentionWarning: "宛先にないメンションがあるで"
info: "情報"
userInfo: "ユーザー情報やで"
unknown: "不明"
@@ -798,7 +819,7 @@ active: "アクティブ"
offline: "オフライン"
notRecommended: "あんま推奨しやんで"
botProtection: "Botプロテクション"
-instanceBlocking: "サーバーブロック"
+instanceBlocking: "サーバーブロック・サイレンス"
selectAccount: "アカウントを選んでなー"
switchAccount: "アカウントを変えるで"
enabled: "有効"
@@ -858,7 +879,7 @@ itsOn: "オンになっとるよ"
itsOff: "オフになってるで"
on: "オン"
off: "オフ"
-emailRequiredForSignup: "アカウント登録にメールアドレスを必須にするで"
+emailRequiredForSignup: "アカウント作るのにメールアドレスを必須にするで"
unread: "未読"
filter: "フィルタ"
controlPanel: "コントロールパネル"
@@ -868,11 +889,11 @@ makeReactionsPublicDescription: "あんたがしたツッコミ一覧を誰で
classic: "クラシック"
muteThread: "スレッドをミュート"
unmuteThread: "スレッドのミュートを解除"
-ffVisibility: "つながりの公開範囲"
-ffVisibilityDescription: "あんたのフォロー/フォロワー情報の公開範囲を設定できるで。"
+followingVisibility: "フォローの公開範囲"
+followersVisibility: "フォロワーの公開範囲"
continueThread: "さらにスレッドを見るで"
deleteAccountConfirm: "アカウントを消すで?ええんか?"
-incorrectPassword: "パスワードがちゃうで。"
+incorrectPassword: "パスワードがちゃうわ。"
voteConfirm: "「{choice}」に投票するんか?"
hide: "隠す"
useDrawerReactionPickerForMobile: "ケータイとかのときドロワーで表示するで"
@@ -900,8 +921,8 @@ oneMonth: "1ヶ月"
reflectMayTakeTime: "反映されるまで時間がかかることがあるで"
failedToFetchAccountInformation: "アカウントの取得に失敗したみたいや…"
rateLimitExceeded: "レート制限が超えたみたいやで"
-cropImage: "画像のクロップ"
-cropImageAsk: "画像をクロップしてもええか?"
+cropImage: "画像切り取り"
+cropImageAsk: "画像を切り取ってもええか?"
cropYes: "切り抜いたる"
cropNo: "切り抜かへん"
file: "ファイル"
@@ -912,18 +933,18 @@ thereIsUnresolvedAbuseReportWarning: "未対応の通報があるみたいやで
recommended: "推奨"
check: "チェック"
driveCapOverrideLabel: "このユーザーのドライブ容量上限を変更するで"
-driveCapOverrideCaption: "0以下を指定すると解除されるで。"
-requireAdminForView: "これを見るには管理者アカウントでログインしとらなあかんで。"
+driveCapOverrideCaption: "0以下にしたら解除されるで。"
+requireAdminForView: "これ見たいんなら管理者じゃないとアカンわ。"
isSystemAccount: "システムが自動で作成・管理しとるアカウントやで。"
-typeToConfirm: "この操作をやるんなら {x} と入力してなー"
+typeToConfirm: "これやるんなら {x} って入力してなー"
deleteAccount: "アカウント削除するで"
document: "ドキュメント"
numberOfPageCache: "ページ、どんだけキャッシュすんの?"
-numberOfPageCacheDescription: "増やすと使いやすくなる、負荷とメモリ使用量が増えてくで。一長一短やな。"
+numberOfPageCacheDescription: "増やすと使いやすくなるけど、負荷とメモリ使用量が増えてくで。一長一短やな。"
logoutConfirm: "ログアウトしまっか?"
lastActiveDate: "最後に使った日時"
statusbar: "ステータスバー"
-pleaseSelect: "選択したってやー"
+pleaseSelect: "選んだってやー"
reverse: "反転"
colored: "色付き"
refreshInterval: "更新間隔"
@@ -932,28 +953,28 @@ type: "タイプ"
speed: "速度"
slow: "遅い"
fast: "速い"
-sensitiveMediaDetection: "センシティブなメディアの検出"
-localOnly: "ローカルのみ"
-remoteOnly: "リモートのみ"
+sensitiveMediaDetection: "きわどいやつの検出"
+localOnly: "ローカルだけ"
+remoteOnly: "リモートだけ"
failedToUpload: "アップロードに失敗してもうたわ…"
-cannotUploadBecauseInappropriate: "不適切な内容を含むかもしれへんって判定されたからアップロードできへんわ。"
-cannotUploadBecauseNoFreeSpace: "ドライブの空き容量が無いからアップロードできへんわ。"
+cannotUploadBecauseInappropriate: "きわどい内容を含むかもしれへんって言われたからアップロードできへんわ。"
+cannotUploadBecauseNoFreeSpace: "ドライブがもうパンパンやからアップロードできへんわ。"
cannotUploadBecauseExceedsFileSizeLimit: "ファイルが思うたよりも大きいさかいアップロードできへんでこれ。"
beta: "ベータ"
-enableAutoSensitive: "自動NSFW判定"
+enableAutoSensitive: "自動できわどいか判断する"
enableAutoSensitiveDescription: "使える時は、機械学習を使って自動でメディアにNSFWフラグを設定するで。この機能をオフにしても、サーバーによっては自動で設定されることがあるで。"
-activeEmailValidationDescription: "ユーザーのメールアドレスのバリデーションを、捨てアドかどうかや実際に通信可能かどうかとかを判定して積極的に行うで。オフにすると単に文字列として正しいかどうかだけチェックするで。"
+activeEmailValidationDescription: "ユーザーのメアドのバリデーションを、捨てアドかどうかとか、ちゃんと通信できるかとかを見るで。切ったら単に文字列として合っとるかどうかだけ見るわ。"
navbar: "ナビゲーションバー"
shuffle: "シャッフルするで"
account: "アカウント"
-move: "移動するで"
+move: "移すで"
pushNotification: "プッシュ通知"
subscribePushNotification: "プッシュ通知をオンにするで"
unsubscribePushNotification: "プッシュ通知を止めるで"
pushNotificationAlreadySubscribed: "プッシュ通知はオンになってるで"
pushNotificationNotSupported: "ブラウザかサーバーがプッシュ通知に対応してないみたいやで。"
sendPushNotificationReadMessage: "通知やメッセージが既読になったらプッシュ通知を消すで"
-sendPushNotificationReadMessageCaption: "「{emptyPushNotificationMessage}」っていう表示が一瞬表示されるようになるで。端末の電池使用量が増える可能性があるで。"
+sendPushNotificationReadMessageCaption: "あんたの端末の電池使う量が増えるかもしれん。"
windowMaximize: "最大化"
windowMinimize: "最小化"
windowRestore: "元に戻す"
@@ -963,30 +984,31 @@ tools: "ツール"
cannotLoad: "読み込めへんで"
numberOfProfileView: "プロフィール表示回数"
like: "ええやん!"
-unlike: "いいねを解除"
+unlike: "いいねやめる"
numberOfLikes: "いいね数"
show: "表示"
neverShow: "今後表示しない"
remindMeLater: "また後で"
didYouLikeMisskey: "Misskey気に入ってくれた?"
-pleaseDonate: "Misskeyは{host}が使用している無料のソフトウェアやで。これからも開発を続けれるように、寄付したってな~。"
+pleaseDonate: "Misskeyは{host}が使うとる無料のソフトウェアやで。これからも開発を続けれるように、寄付したってな~。"
+correspondingSourceIsAvailable: "{anchor}"
roles: "ロール"
role: "ロール"
noRole: "ロールはありまへん"
normalUser: "一般ユーザー"
undefined: "未定義"
assign: "アサイン"
-unassign: "アサインを解除"
+unassign: "アサインやめる"
color: "色"
manageCustomEmojis: "カスタム絵文字の管理"
manageAvatarDecorations: "アバターを飾るモンの管理"
youCannotCreateAnymore: "これ以上作れなさそうやわ"
-cannotPerformTemporary: "一時的に利用できへんで"
-cannotPerformTemporaryDescription: "操作回数が制限を超えたから一時的に利用できへんくなったで。ちょっと時間置いてからもう一回やってやー。"
+cannotPerformTemporary: "ちょっといまは使えへんで"
+cannotPerformTemporaryDescription: "操作し過ぎてちょっと今は使えへんくしとるで。ちょっと待ってからもっかいやってや。"
invalidParamError: "パラメータがエラー言うとりますわ"
-invalidParamErrorDescription: "リクエストパラメータに問題があんねん。普通はバグやねんけど、もしかすると入力した文字数が多すぎるとかの可能性もあるから確認してや〜"
+invalidParamErrorDescription: "リクエストパラメータが変やわ。だいたいはバグやねんけど、もしかしたら入れた文字が多すぎるとかかもしれんから確認してや〜"
permissionDeniedError: "操作が拒否されてもうた。"
-permissionDeniedErrorDescription: "自分のアカウントにはこの操作を行う権限があらへんねん"
+permissionDeniedErrorDescription: "このアカウントはこれやったらアカンって。"
preset: "プリセット"
selectFromPresets: "プリセットから選ぶ"
achievements: "実績"
@@ -996,15 +1018,15 @@ thisPostMayBeAnnoying: "この投稿は迷惑かもしらんで。"
thisPostMayBeAnnoyingHome: "ホームに投稿"
thisPostMayBeAnnoyingCancel: "やめとく"
thisPostMayBeAnnoyingIgnore: "このまま投稿"
-collapseRenotes: "見たことあるRenoteは飛ばして表示するで"
+collapseRenotes: "見たことあるリノートは飛ばして表示するで"
internalServerError: "サーバー内部エラー"
-internalServerErrorDescription: "サーバー内部でよう分からんエラーやわ"
-copyErrorInfo: "エラー情報をコピー"
+internalServerErrorDescription: "サーバーでなんか変なこと起こっとるわ。"
+copyErrorInfo: "エラー情報をコピるで"
joinThisServer: "このサーバーに登録するわ"
exploreOtherServers: "他のサーバー見てみる"
letsLookAtTimeline: "タイムライン見てみーや"
disableFederationConfirm: "連合なしにしとくか?"
-disableFederationConfirmWarn: "連合なしにしても投稿は非公開にはならへんで。大体の場合は連合なしにする必要はないで。"
+disableFederationConfirmWarn: "連合なしにしても投稿が非公開になるわけちゃうで。大体の場合は連合なしにする必要はないで。"
disableFederationOk: "連合なしにしとく"
invitationRequiredToRegister: "今このサーバー招待制になってもうてんねん。招待コードを持っとるんやったら登録できるで。"
emailNotSupported: "このサーバーはメール配信がサポートされてへんみたいやわ"
@@ -1013,14 +1035,17 @@ cannotBeChangedLater: "後からは変えられへんで。"
reactionAcceptance: "ツッコミの受け入れ"
likeOnly: "いいねだけ"
likeOnlyForRemote: "リモートからはいいねだけな"
-nonSensitiveOnly: "センシティブじゃないやつだけ"
-nonSensitiveOnlyForLocalLikeOnlyForRemote: "センシティブじゃないやつだけ (リモートはいいねだけ)"
+nonSensitiveOnly: "いつ見ても大丈夫なやつだけ"
+nonSensitiveOnlyForLocalLikeOnlyForRemote: "いつ見ても大丈夫なやつだけ (リモートはいいねだけ)"
rolesAssignedToMe: "自分に割り当てられたロール"
resetPasswordConfirm: "パスワード作り直すんでええな?"
sensitiveWords: "けったいな単語"
sensitiveWordsDescription: "設定した単語が入っとるノートの公開範囲をホームにしたるわ。改行で区切ったら複数設定できるで。"
sensitiveWordsDescription2: "スペースで区切るとAND指定、キーワードをスラッシュで囲んだら正規表現や。"
-notesSearchNotAvailable: "ノート検索は使われへんで。"
+prohibitedWordsDescription2: "スペースで区切るとAND指定、キーワードをスラッシュで囲んだら正規表現や。"
+hiddenTags: "見えてへんハッシュタグ"
+hiddenTagsDescription: "設定したタグを最近流行りのとこに見えんようにすんで。複数設定するときは改行で区切ってな。"
+notesSearchNotAvailable: "なんかノート探せへん。"
license: "ライセンス"
unfavoriteConfirm: "ほんまに気に入らんの?"
myClips: "自分のクリップ"
@@ -1031,20 +1056,23 @@ retryAllQueuesConfirmText: "一時的にサーバー重なるかもしれへん
enableChartsForRemoteUser: "リモートユーザーのチャートを作る"
enableChartsForFederatedInstances: "リモートサーバーのチャートを作る"
showClipButtonInNoteFooter: "ノートのアクションにクリップを追加"
-reactionsDisplaySize: "リアクションの表示のでかさ"
+reactionsDisplaySize: "ツッコミの表示のでかさ"
+limitWidthOfReaction: "ツッコミの最大横幅を制限して、ちっさく表示するで"
noteIdOrUrl: "ノートIDかURL"
video: "動画"
videos: "動画"
+audio: "音声"
+audioFiles: "音声"
dataSaver: "データケチケチ"
accountMigration: "アカウントのお引っ越し"
accountMoved: "このユーザーはさらのアカウントに引っ越したで:"
-accountMovedShort: "このアカウントは移行されとるで"
+accountMovedShort: "このアカウントは引っ越し済みや"
operationForbidden: "この操作はできまへん"
-forceShowAds: "常に広告を表示しとく"
+forceShowAds: "いっつも広告を映す"
addMemo: "メモを足す"
editMemo: "メモをいらう"
reactionsList: "ツッコミ一覧"
-renotesList: "Renote一覧"
+renotesList: "リノート一覧"
notificationDisplay: "通知見せる"
leftTop: "左上"
rightTop: "右上"
@@ -1056,7 +1084,7 @@ horizontal: "横"
position: "位置"
serverRules: "サーバールール"
pleaseConfirmBelowBeforeSignup: "このサーバーに登録する前に、下に書いてること確認してな。"
-pleaseAgreeAllToContinue: "続けるんやったら、全ての「せやな」にチェック入れてる必要があるで。"
+pleaseAgreeAllToContinue: "続けるんやったら、全部にチェック入れとかなアカンで。"
continue: "続けるで"
preservedUsernames: "予約ユーザー名"
preservedUsernamesDescription: "予約しとくユーザー名を行ごとに挙げるで。ここで指定されたユーザー名はアカウント作るときに使えへんくなるけど、管理者は例外や。あと、もうあるアカウントも例外やな。"
@@ -1082,29 +1110,29 @@ changeReactionConfirm: "ツッコミを別のに変えるか?"
later: "あとで"
goToMisskey: "Misskeyへ"
additionalEmojiDictionary: "絵文字の追加辞書"
-installed: "インストール済み"
+installed: "インストールしとる"
branding: "ブランディング"
enableServerMachineStats: "サーバーのマシン情報見せびらかすで"
enableIdenticonGeneration: "ユーザーごとのIdenticon生成を有効にする"
turnOffToImprovePerformance: "オフにしたらえらい軽うなるで。"
-createInviteCode: "招待コードを作成"
-createWithOptions: "オプションを指定して作成"
-createCount: "作成数"
+createInviteCode: "招待コード作る"
+createWithOptions: "オプション決めて作る"
+createCount: "作った数"
inviteCodeCreated: "招待コード作ったで"
inviteLimitExceeded: "招待コード作りすぎやで。"
-createLimitRemaining: "作成できる招待コード: 残り {limit} 個やで"
-inviteLimitResetCycle: "{time}で最大 {limit} 個の招待コードを作成できるで。"
+createLimitRemaining: "作れる招待コードは残り {limit} 個や"
+inviteLimitResetCycle: "{time}で最大 {limit} 個の招待コードを作れるで。"
expirationDate: "有効期限"
-noExpirationDate: "有効期限を設けへん"
-inviteCodeUsedAt: "招待コードが使用された日時"
-registeredUserUsingInviteCode: "招待コードを使用したユーザー"
+noExpirationDate: "期限なし"
+inviteCodeUsedAt: "招待コードが使われた時"
+registeredUserUsingInviteCode: "招待コードを使うた人"
waitingForMailAuth: "メール認証待ち"
-inviteCodeCreator: "招待コードを作成したユーザー"
-usedAt: "使用日時"
+inviteCodeCreator: "招待コードを作った人"
+usedAt: "使った時"
unused: "つこてへん"
used: "もうつこてる"
expired: "期限切れ"
-doYouAgree: "同意するんか?"
+doYouAgree: "ええんか?"
beSureToReadThisAsItIsImportant: "重要やから絶対読んでや。"
iHaveReadXCarefullyAndAgree: "「{x}」の内容をよう読んで、同意するで。"
dialog: "ダイアログ"
@@ -1115,119 +1143,204 @@ pastAnnouncements: "過去のお知らせやで"
youHaveUnreadAnnouncements: "あんたまだこのお知らせ読んどらんやろ。"
useSecurityKey: "ブラウザまたはデバイスの言う通りに、セキュリティキーまたはパスキーを使ってや。"
replies: "返事"
-renotes: "Renote"
+renotes: "リノート"
loadReplies: "返信を見るで"
loadConversation: "会話を見るで"
pinnedList: "ピン留めしはったリスト"
keepScreenOn: "デバイスの画面を常にオンにすんで"
-verifiedLink: "このリンク先の所有者であることが確認されたで。"
+verifiedLink: "このリンク先の所有者ってわかったわ。"
notifyNotes: "投稿を通知"
-unnotifyNotes: "投稿の通知を解除すんで"
+unnotifyNotes: "投稿の通知やめる"
authentication: "認証"
-authenticationRequiredToContinue: "続けるには認証をやってや。"
+authenticationRequiredToContinue: "続けるんなら認証してや。"
dateAndTime: "日時"
-showRenotes: "リノートを表示"
-edited: "編集し終わってる"
-notificationRecieveConfig: "通知を受け取るかの設定"
+showRenotes: "リノート出す"
+edited: "いじったやつ"
+notificationRecieveConfig: "通知もらうかの設定"
mutualFollow: "お互いフォローしてんで"
-fileAttachedOnly: "ファイル付きのみ"
-showRepliesToOthersInTimeline: "タイムラインに他の人への返信とかも含めんで"
-hideRepliesToOthersInTimeline: "タイムラインに他の人への返信とかは見ーへんで"
-showRepliesToOthersInTimelineAll: ""
-hideRepliesToOthersInTimelineAll: ""
-confirmShowRepliesAll: ""
-confirmHideRepliesAll: ""
+fileAttachedOnly: "ファイルのっけてあるやつだけ"
+showRepliesToOthersInTimeline: "タイムラインに他の人への返信とかも入れるで"
+hideRepliesToOthersInTimeline: "タイムラインに他の人への返信とかは入れへん"
+showRepliesToOthersInTimelineAll: "タイムラインに今フォローしとる人全員の返信入れるで"
+hideRepliesToOthersInTimelineAll: "タイムラインに今フォローしとる人の返信入れへん"
+confirmShowRepliesAll: "これは元に戻せへんから慎重に決めてや。本当にタイムラインに今フォローしとる全員の返信を入れるか?"
+confirmHideRepliesAll: "これは元に戻せへんから慎重に決めてや。本当にタイムラインに今フォローしとる全員の返信を入れへんのか?"
externalServices: "他のサイトのサービス"
+sourceCode: "ソースコード"
impressum: "運営者の情報"
impressumUrl: "運営者の情報URL"
-impressumDescription: "ドイツなどのほんま1部の国と地域ではな、表示が義務付けられててん。(Impressum)"
+impressumDescription: "ドイツとかの一部んところではな、表示が義務付けられてんねん(Impressum)。"
privacyPolicy: "プライバシーポリシー"
privacyPolicyUrl: "プライバシーポリシーURL"
tosAndPrivacyPolicy: "利用規約・プライバシーポリシー"
avatarDecorations: "アイコンデコレーション"
-attach: ""
-detach: ""
-angle: ""
+attach: "のっける"
+detach: "取る"
+detachAll: "全部とる"
+angle: "角度"
flip: "反転"
-showAvatarDecorations: ""
-releaseToRefresh: "離してリロード"
-refreshing: "リロード中"
+showAvatarDecorations: "アイコンのデコレーション映す"
+releaseToRefresh: "離したらリロード"
+refreshing: "リロードしとる"
pullDownToRefresh: "引っ張ってリロードするで"
disableStreamingTimeline: "タイムラインのリアルタイム更新をやめるで"
-useGroupedNotifications: "通知をグルーピングしてだすで"
-signupPendingError: "メールアドレスの確認中に問題が起こってえらいこっちゃ。リンクの有効期限が切れてるかもやで"
-cwNotationRequired: "「内容を隠す」がオンの場合は注釈の記述が必要やで。"
-doReaction: "ツッコミすんで"
+useGroupedNotifications: "通知をグループ分けして出すで"
+signupPendingError: "メアド確認してたらなんか変なことなったわ。リンクの期限切れてるかもしれん。"
+cwNotationRequired: "「内容を隠す」んやったら注釈書かなアカンで。"
+doReaction: "ツッコむで"
+code: "コード"
+reloadRequiredToApplySettings: "設定を見るんにはリロードが必要やで。"
+remainingN: "残り:{n}"
+overwriteContentConfirm: "今の内容に上書きされるけどいい?"
+seasonalScreenEffect: "季節にあった画面の動き"
+decorate: "デコる"
+addMfmFunction: "装飾つける"
+enableQuickAddMfmFunction: "ややこしいMFMのピッカーを出す"
+bubbleGame: "バブルゲーム"
+sfx: "効果音"
+soundWillBePlayed: "サウンドが再生されるで"
+showReplay: "リプレイ見る"
+replay: "リプレイ"
+replaying: "リプレイ中"
+ranking: "ランキング"
+lastNDays: "直近{n}日"
+backToTitle: "タイトルへ"
+hemisphere: "住んでる地域"
+withSensitive: "センシティブなファイルを含むノートを表示"
+userSaysSomethingSensitive: "{name}のセンシティブなファイルを含む投稿"
+enableHorizontalSwipe: "スワイプしてタブを切り替える"
+surrender: "やめとく"
+_bubbleGame:
+ howToPlay: "遊び方"
+ _howToPlay:
+ section1: "位置を調整してハコにモノを落とすで。"
+ section2: "同じもんがくっついたら別のやつになって、スコアがもらえるで。"
+ section3: "モノがハコからあふれたらゲームオーバーや。ハコからあふれんようにしながらモノを融合させてハイスコアを目指しいや!"
_announcement:
forExistingUsers: "もうおるユーザーのみ"
- forExistingUsersDescription: "有効にすると、このお知らせ作成時点でおるユーザーにのみお知らせが表示されます。無効にすると、このお知らせ作成後にアカウントを作成したユーザーにもお知らせが表示されます。"
- needConfirmationToRead: "既読にするのに確認が必要やで"
- needConfirmationToReadDescription: "有効にすると、このお知らせを既読にする際に確認ダイアログが表示されます。また、一括既読操作の対象にもなりません。"
- end: "お知らせを終了"
- tooManyActiveAnnouncementDescription: "アクティブなお知らせが多いため、UXが低下する可能性があります。終了したお知らせはアーカイブすることを検討した方がええよ。"
+ forExistingUsersDescription: "オンにしたらこのお知らせができた時点でおる人らにだけお知らせが行くで。切ったらこの知らせが行ったあとにアカウント作った人にもちゃんとお知らせが行くで。"
+ needConfirmationToRead: "既読にするんやったら確認してや"
+ needConfirmationToReadDescription: "オンにしたら、このお知らせを既読にする時に確認するで。ついでに、一括既読しても既読扱いにならへんで。"
+ end: "お知らせやめる"
+ tooManyActiveAnnouncementDescription: "お知らせが多すぎてUXが落ちそうや。終わったお知らせはアーカイブに突っ込んだほうがええかも。"
readConfirmTitle: "既読にしてええんやな?"
- readConfirmText: "「{title}」の内容を読み、既読にします。"
+ readConfirmText: "「{title}」はもう読んだから既読にするで。"
shouldNotBeUsedToPresentPermanentInfo: "新規ユーザーのUXを損ねやすいから、お知らせはストック情報やのうてフロー情報の掲示に使った方がええで。"
- dialogAnnouncementUxWarn: "ダイアログ形式のお知らせが同時に2つ以上ある場合、UXに悪影響を及ぼす可能性が高くなるから、使用は慎重にすんのがおすすめやで。"
+ dialogAnnouncementUxWarn: "ダイアログ形式のお知らせがいっぺんに2コ以上ある場合、UXに良うないことが多いから、使うんは慎重にすんのがおすすめやで。"
silence: "通知せんで"
- silenceDescription: "オンにすると、このお知らせは通知されないで、既読にする必要もなくなるで。"
+ silenceDescription: "オンにすると、このお知らせは通知されへんし、既読にする必要もなくなるで。"
_initialAccountSetting:
accountCreated: "アカウント作り終わったで。"
letsStartAccountSetup: "アカウントの初期設定をしよか。"
- letsFillYourProfile: "最初はあんたのプロフィールを設定しよか。"
+ letsFillYourProfile: "最初はあんたのプロフィールを設定するで。"
profileSetting: "プロフィール設定"
privacySetting: "プライバシー設定"
theseSettingsCanEditLater: "この設定はあとから変えれるで。"
youCanEditMoreSettingsInSettingsPageLater: "これ以外にもいろんな設定を「設定」ページからできるで。後で確認してみてな。"
followUsers: "タイムラインを構築するために、気になるユーザーをフォローしてみ。"
pushNotificationDescription: "プッシュ通知を有効にすると{name}の通知をあんたのデバイスで受け取れるで。"
- initialAccountSettingCompleted: "初期設定が終わったで。"
+ initialAccountSettingCompleted: "初期設定終わりや!"
haveFun: "{name}、楽しんでな~"
- youCanContinueTutorial: "このまま{name}(Misskey)の使い方のチュートリアルに進めるけど、ここで中断してすぐに使い始めることもできるで。"
- startTutorial: "チュートリアルを開始するで"
+ youCanContinueTutorial: "こんまま{name}(Misskey)の使い方のチュートリアルにも行けるけど、ここでやめてすぐに使い始めてもええで。"
+ startTutorial: "チュートリアルはじめる"
skipAreYouSure: "初期設定飛ばすか?"
laterAreYouSure: "初期設定あとでやり直すん?"
_initialTutorial:
- launchTutorial: "チュートリアルを見るで"
+ launchTutorial: "チュートリアル見るで"
title: "チュートリアルやで"
wellDone: "やるやん"
- skipAreYouSure: "チュートリアルをやめるか?"
+ skipAreYouSure: "チュートリアルやめるか?"
_landing:
title: "チュートリアルによう来たな"
- description: "ここでは、Misskeyの基本的な使い方や機能を確認できるで。"
+ description: "ここでは、Misskeyのカンタンな使い方とか機能を確かめれんで。"
_note:
title: "ノートってなんや?"
- description: "Misskeyでの投稿は「ノート」って呼ばれてるで。ノートはタイムラインに時系列で並んでいて、リアルタイムで更新されてるで。"
- reply: "返信することもできるで。返信に対しての返信も可能で、スレッドのように会話を続けることもできるで。"
- renote: "そのノートを自分のタイムラインに流して共有することもできるで。テキストを追加して引用することもできるで。"
- reaction: "ツッコミをつけることもできるで。細かいことは次のページで解説するで。"
+ description: "Misskeyでの投稿は「ノート」って呼ばれてんで。ノートは順々にタイムラインに載ってて、リアルタイムで新しくなってってんで。"
+ reply: "返信もできるで。返信の返信もできるから、スレッドっぽく会話をそのまま続けれもするで。"
+ renote: "そのノートを自分のタイムラインに流して共有できるで。テキスト入れて引用してもええな。"
+ reaction: "ツッコミをつけることもできるで。細かいことは次のページや。"
+ menu: "ノートの詳細を出したり、リンクをコピーしたり、いろいろできんねん。"
+ _reaction:
+ title: "ツッコミってなんや?"
+ description: "ノートには「ツッコミ」できんねん。「いいね」とか何言っとるかわからんし、簡単に表現できるのはええことやん?"
+ letsTryReacting: "ノートの「+」ボタンでツッコめるわ。試しに下のノートにツッコんでみ。"
+ reactToContinue: "ツッコんだら進めるようになるで。"
+ reactNotification: "あんたのノートが誰かにツッコまれたら、すぐ通知するで。"
+ reactDone: "「ー」ボタンでツッコミやめれるで。"
+ _timeline:
+ title: "タイムラインのしくみ"
+ description1: "Misskeyには、いろいろタイムラインがあんで(ただ、サーバーによっては無効化されてるところもあるな)。"
+ home: "あんたがフォローしてるアカウントの投稿が見れんねん。"
+ local: "このサーバーの中におる全員の投稿が見れるで。"
+ social: "ホームタイムラインの投稿もローカルタイムラインのも一緒に見れるで。"
+ global: "繋がってる他の全サーバーからの投稿が見れるで。"
+ description2: "それぞれのタイムラインは、いつでも画面上で切り替えられんねん。覚えとき。"
+ description3: "その他にも、リストタイムラインとかチャンネルタイムラインとかがあんねん。詳しいのは{link}を見とき。"
+ _postNote:
+ title: "ノートの投稿設定"
+ description1: "Misskeyにノートを投稿するとき、いろんなオプションが付けれるで。投稿画面はこんな感じや。"
+ _visibility:
+ description: "ノートを見れる相手を制限できるわ。"
+ public: "みんなに見せるで。"
+ home: "ホームタイムラインにだけ見せるで。フォロワーとか、プロフィールを見に来た人、リノートからも見れるから、実質は全員見れるけどな。あんまし広がりにくいってことや。"
+ followers: "フォロワーにだけ見せるで。自分以外はリノートできへんし、フォロワー以外は絶対に見れへん。"
+ direct: "指定した人にだけ公開されて、ついでに通知も送るで。ダイレクトメールの代わりとして使ってな。"
+ doNotSendConfidencialOnDirect1: "機密情報を送るときは十分注意せえよ。"
+ doNotSendConfidencialOnDirect2: "送信先のサーバーの管理者は投稿内容が見れるから、信用できへんサーバーのひとにダイレクト投稿するときには、めっちゃ用心しとくんやで。"
+ localOnly: "他のサーバーに投稿せえへんくなるで。他の公開範囲とか一切無視して、他のサーバーの人らはこの設定がされたノートは絶対に見れへん。"
+ _cw:
+ title: "内容隠し(CW)"
+ description: "本文のかわりに「注釈」に書いた内容だけ見せるで。「続き見して!」を押すと本文も見れんねん。"
+ _exampleNote:
+ cw: "飯テロ注意"
+ note: "チョコドーナツめっちゃ美味かったわ🍩😋"
+ useCases: "サーバーのガイドラインに決められとるノートに使うたり、ネタバレとかきわどい内容を自分で隠したりするとき用やな。"
+ _howToMakeAttachmentsSensitive:
+ title: "のっけたファイルをセンシティブにするんは?"
+ description: "サーバーのガイドラインに書いてあったり、そのままおっぴろげとくのはあんま良うないファイルには「センシティブ」っちゅう設定をつけるんや。"
+ tryThisFile: "試しに、これにのっけてある画像をセンシティブにしてみいや!"
+ _exampleNote:
+ note: "納豆のフタ開けるときにやらかしてもうた…"
+ method: "のっけたファイルをセンシティブにするときは、そのファイルを押してメニュー開けて、「ちょっとこれはアカン」を押すんよ。"
+ sensitiveSucceeded: "ファイルをのっけるときは、サーバーの言うこと聞いてちゃんと設定するんやで。"
+ doItToContinue: "画像をちゃんと設定したら先に進めるで。"
+ _done:
+ title: "チュートリアル終わり!おつかれさん🎉"
+ description: "ここで紹介したのは全部の中のちょび~っとだけや。もっと使い方知りたいんやったら、{link}を見ときや。"
+_timelineDescription:
+ home: "ホームタイムラインは、あんたがフォローしとるアカウントの投稿だけ見れるで。"
+ local: "ローカルタイムラインは、このサーバーにおる全員の投稿を見れるで。"
+ social: "ソーシャルタイムラインは、ホームタイムラインの投稿もローカルタイムラインのも一緒に見れるで。"
+ global: "グローバルタイムラインは、繋がっとる他のサーバーの投稿、全部ひっくるめて見れんで。"
_serverRules:
- description: "新規登録前に見せる、サーバーの簡潔なルールを設定すんで。内容は使うための決め事の要約とすることを推奨するわ。"
+ description: "新規登録前に見せる、サーバーのカンタンなルールを決めるで。内容は使うための決め事の要約がええと思うわ。"
_serverSettings:
iconUrl: "アイコン画像のURL"
appIconDescription: "{host}がアプリとして表示してるんやつをアイコンを指定すんで。"
- appIconUsageExample: "PWAや、スマートフォンのホーム画面にブックマークとして追加された時など"
- appIconStyleRecommendation: "円形もしくは角丸にクロップされる場合があるさかいに、塗り潰された余白のある背景があるものが推奨されるで。"
- appIconResolutionMustBe: "解像度は必ず{resolution}である必要があるで。"
+ appIconUsageExample: "例えば、PWAとか、スマホのホームにブックマークしたときとか"
+ appIconStyleRecommendation: "円か角丸に切り取られることがあるさかい、塗り潰した余白のある背景があるものがおすすめや。"
+ appIconResolutionMustBe: "解像度は絶対{resolution}じゃないとアカン。"
manifestJsonOverride: "manifest.jsonのオーバーライド"
shortName: "略称"
- shortNameDescription: "サーバーの名前が長い時に、代わりに表示することのできるあだ名。"
- fanoutTimelineDescription: ""
+ shortNameDescription: "サーバーの名前が長ったらしい時に、代わりに出すあだ名。"
+ fanoutTimelineDescription: "入れると、おのおのタイムラインを取得するときにめちゃめちゃ動きが良うなって、データベースが軽くなるわ。でも、Redisのメモリ使う量が増えるから注意な。サーバーのメモリが足りんときとか、動きが変なときは切れるで。"
+ fanoutTimelineDbFallback: "データベースにフォールバックする"
+ fanoutTimelineDbFallbackDescription: "有効にしたら、タイムラインがキャッシュん中に入ってないときにDBにもっかい問い合わせるフォールバック処理ってのをやっとくで。切ったらフォールバック処理をやらんからサーバーはもっと軽くなんねんけど、タイムラインの取得範囲がちょっと減るで。"
_accountMigration:
moveFrom: "別のアカウントからこのアカウントに引っ越す"
moveFromSub: "別のアカウントへエイリアスを作る"
- moveFromLabel: "引っ越し元のアカウント:"
- moveFromDescription: "別のアカウントからこのアカウントにフォロワーを引き継いで引っ越したかったら、ここでエイリアスを作っとく必要があるで。必ずお引っ越しを実行する前に作っとかなあかんで!引っ越し元のアカウントをこんな風に入力してくれへんか?:@person@instance.com"
+ moveFromLabel: "引っ越しする前のアカウント #{n}"
+ moveFromDescription: "別のアカウントからこのアカウントにフォロワーを引っ越ししたいんなら、ここでエイリアスを作っとかなアカンで。\n引っ越す前のアカウントをこんな感じに入力してや: @username@server.example.com\n入力欄空っぽやったら消しとくで(おすすめはせえへん)。"
moveTo: "このアカウントをさらのアカウントに引っ越すで"
- moveToLabel: "引っ越し先のアカウント:"
- moveCannotBeUndone: "アカウントを移行すると、取り消すことはできへんくなります。"
+ moveToLabel: "引っ越し先のアカウント:"
+ moveCannotBeUndone: "アカウント引っ越したらもう戻せへん。"
moveAccountDescription: "おニューのアカウントに移行すんで。\n ・フォロワーがおニューの方を勝手にフォローすんで。\n ・このアカウントからのフォローはまるまる全部解除されんで。\n ・このアカウントでノート作れへんようになるで。\n\nフォロワーの移行は勝手にこっちでやっとくけど、フォローの移行は自分でしてや。移行前にこのアカウントでフォローエクスポートして、移行したあとすぐにおニューのところでインポートしてくれな。\nリストとかミュート、あとブロックもおんなじや。自分で移行してな。\n\n(この説明はこのサーバー、つまりMisskey v13.12.0から後の仕様や。Mastodonとか他のActivityPubソフトやとちょっと挙動が違うこともあんで。)"
- moveAccountHowTo: "アカウントの引っ越しには、まず引っ越し先のアカウントで自分のアカウントに対しエイリアスを作成しなはれや。\nエイリアス作成した後、引っ越し先のアカウントを次のように入力してくれへんか?:@username@server.example.com"
- startMigration: "引っ越しする"
+ moveAccountHowTo: "アカウントの引っ越しには、まず引っ越し先のアカウントで自分のアカウントに対しエイリアスを作ってな。\nエイリアス作ったら、引っ越し先のアカウントをこんな感じに入れてや: @username@server.example.com"
+ startMigration: "引っ越す"
migrationConfirm: "ほんまにこのアカウントを {account} に引っ越すんか?一回引っ越してもうたら取り消されへんし、二度とこのアカウントを元に戻されへんくなるで。\nそれと、引っ越し先のアカウントでエイリアスが作れたかちゃ~んと確認しーや?"
- movedAndCannotBeUndone: "\nアカウントはもう引っ越されてます。\n引っ越しを取り消すことはできまへん。"
+ movedAndCannotBeUndone: "\nアカウントはもう引っ越し済みや。\nこれはもう戻せへん。"
postMigrationNote: "このアカウントからのフォロー解除は移行操作から丸一日経ったら実行されんで。\nこのアカウントのフォロー・フォロワー数はどっちも0や。フォローの解除はされへんから、あんたのフォロワーはこのアカウントのフォロワー向けの投稿をこの後も見れるで。"
- movedTo: "引っ越し先のアカウント:"
+ movedTo: "引っ越し先のアカウント:"
_achievements:
earnedAt: "貰った日ぃ"
_types:
@@ -1251,10 +1364,10 @@ _achievements:
title: "箕面の滝からノート"
description: "ノートを5,000回投稿した"
_notes10000:
- title: "スーパーノート"
+ title: "えげつないノート"
description: "ノートを10,000回投稿した"
_notes20000:
- title: "ニードモアノート"
+ title: "もっとノートよこせ!"
description: "ノートを20,000回投稿した"
_notes30000:
title: "ノートノートノート"
@@ -1351,7 +1464,7 @@ _achievements:
title: "はじめてのフォロー"
description: "初めてフォローした"
_following10:
- title: "ついてく、ついてく"
+ title: "すたこらさっさ"
description: "フォローが10人超えた"
_following50:
title: "友達ぎょうさん"
@@ -1404,10 +1517,10 @@ _achievements:
description: "クライアント付けてから1時間経ってもうたで。"
_noteDeletedWithin1min:
title: "*おおっと*"
- description: "投稿してから1分以内にその投稿を消した"
+ description: "投稿してから1分以内にその投稿をほかした"
_postedAtLateNight:
title: "夜行性"
- description: "深夜にノートを投稿した"
+ description: "真夜中にノートを投稿した"
flavor: "そろそろ寝よか"
_postedAt0min0sec:
title: "時報"
@@ -1424,7 +1537,7 @@ _achievements:
description: "サーバーのチャートを表示した"
_outputHelloWorldOnScratchpad:
title: "Hello, world!"
- description: "スクラッチパッドで hello worldを出力した"
+ description: "スクラッチパッドで hello world を出力した"
_open3windows:
title: "マド開けすぎ"
description: "ウィンドウを3つ以上開いた状態にした"
@@ -1433,7 +1546,7 @@ _achievements:
description: "ドライブのフォルダを再帰的な入れ子にしようとした"
_reactWithoutRead:
title: "ちゃんと読んだんか?"
- description: "100文字以上のテキストを含むノートに投稿されてから3秒以内にツッコんだ"
+ description: "100文字以上のノートに投稿3秒以内にツッコんだ"
_clickedClickHere:
title: "ここをクリック"
description: "ここをクリックした"
@@ -1442,7 +1555,7 @@ _achievements:
description: "10秒ごとに0.005%の確率で獲得"
_setNameToSyuilo:
title: "神様コンプレックス"
- description: "名前を syuilo に設定した"
+ description: "名前を syuilo にした"
_passedSinceAccountCreated1:
title: "一周年"
description: "アカウント作成から1年経過した"
@@ -1468,8 +1581,18 @@ _achievements:
description: "Brain Diverへのリンクを投稿したった"
flavor: "Misskey-Misskey La-Tu-Ma"
_smashTestNotificationButton:
- title: "テスト過剰"
- description: "通知テストをごく短時間のうちに連続して行ったねん"
+ title: "心配性"
+ description: "通知のテストしすぎやって"
+ _tutorialCompleted:
+ title: "Misskeyひよっこ講座 修了証"
+ description: "チュートリアル全部やった"
+ _bubbleGameExplodingHead:
+ title: "🤯"
+ description: "バブルゲームで最も大きいモノを出した"
+ _bubbleGameDoubleExplodingHead:
+ title: "ダブル🤯"
+ description: "バブルゲームで最も大きいモノを2つ同時に出した"
+ flavor: "これくらいの おべんとばこに 🤯 🤯 ちょっとつめて"
_role:
new: "ロールの作成"
edit: "ロールの編集"
@@ -1480,60 +1603,63 @@ _role:
assignTarget: "アサイン"
descriptionOfAssignTarget: "マニュアルは誰がこのロールに含まれてるかを手動で管理するで。\nコンディショナルは条件を設定して、それに合うユーザーが自動で含まれるようになるで。"
manual: "マニュアル"
+ manualRoles: "マニュアルロール"
conditional: "コンディショナル"
+ conditionalRoles: "コンディショナルロール"
condition: "条件"
isConditionalRole: "これはコンディショナルロールやで"
isPublic: "ロールを公開"
- descriptionOfIsPublic: "ロールにアサインされたユーザーを誰でも見ることができるで。そんで、ユーザーのプロフィールでこのロールが表示されるで。"
+ descriptionOfIsPublic: "プロフィールでこのロールが出されるで。"
options: "オプション"
policies: "ポリシー"
baseRole: "ベースロール"
- useBaseValue: "ベースロールの値を使用"
- chooseRoleToAssign: "アサインするロールを選択"
+ useBaseValue: "ベースロールの値使う"
+ chooseRoleToAssign: "アサインするロール選ぶ"
iconUrl: "アイコン画像のURL"
asBadge: "バッジとして見せる"
descriptionOfAsBadge: "オンにすると、ユーザー名の横んとこにロールのアイコンが表示されるで。"
- isExplorable: "ロールタイムラインを公開するで〜"
- descriptionOfIsExplorable: "オンにしたらロールのタイムラインを公開するで〜。でもロールの公開をオフにしたら公開されへんよ。"
+ isExplorable: "ユーザーを見つけやすくしたる"
+ descriptionOfIsExplorable: "オンにしたらロールの面子一覧が「みつける」で公開されるし、ロールのタイムラインが使えるようになるで。"
displayOrder: "表示順"
descriptionOfDisplayOrder: "数がでかいほど、UI上で先に表示されるで。"
- canEditMembersByModerator: "モデレーターのメンバー編集を許可"
- descriptionOfCanEditMembersByModerator: "オンにすると、管理者に加えてモデレーターもこのロールへユーザーをアサイン/アサイン解除できるようになるで。オフにすると管理者のみが行えるで。"
+ canEditMembersByModerator: "モデレーターがメンバーいじるのを許す"
+ descriptionOfCanEditMembersByModerator: "オンにすると、管理者だけやなくてモデレーターもこのロールにユーザーを入れたり抜いたりできるで。オフにすると管理者だけしかやれへんくなるで。"
priority: "優先度"
_priority:
low: "低い"
- middle: "中"
+ middle: "中くらい"
high: "高い"
_options:
- gtlAvailable: "グローバルタイムラインの閲覧"
- ltlAvailable: "ローカルタイムラインの閲覧"
- canPublicNote: "パブリック投稿の許可"
- canInvite: "サーバー招待コードの発行"
- inviteLimit: "招待コードの作成可能数"
- inviteLimitCycle: "招待コードの発行間隔"
- inviteExpirationTime: "招待コードの有効期限"
+ gtlAvailable: "グローバルタイムライン見る"
+ ltlAvailable: "ローカルタイムライン見る"
+ canPublicNote: "パブリック投稿できるか"
+ canInvite: "サーバー招待コード作る"
+ inviteLimit: "招待コード作れる数"
+ inviteLimitCycle: "招待コードの作れる間隔"
+ inviteExpirationTime: "招待コードの期限"
canManageCustomEmojis: "カスタム絵文字の管理"
canManageAvatarDecorations: "アバターを飾るモンの管理"
driveCapacity: "ドライブ容量"
alwaysMarkNsfw: "勝手にファイルにNSFWをくっつける"
- pinMax: "ノートのピン留めの最大数"
- antennaMax: "アンテナの作成可能数"
+ pinMax: "ノートピン留めできる数"
+ antennaMax: "アンテナ作れる数"
wordMuteMax: "ワードミュートの最大文字数"
- webhookMax: "Webhockの作成可能数"
- clipMax: "クリップの作成可能数"
- noteEachClipsMax: "クリップ内のノートの最大数"
- userListMax: "ユーザーリストの作成可能数"
+ webhookMax: "Webhook作れる数"
+ clipMax: "クリップ作れる数"
+ noteEachClipsMax: "クリップの中にノート作れる数"
+ userListMax: "ユーザーリスト作れる数"
userEachUserListsMax: "ユーザーリスト内のユーザーの最大数"
rateLimitFactor: "レートリミット"
descriptionOfRateLimitFactor: "ちっちゃいほど制限が緩なって、大きいほど制限されるで。"
- canHideAds: "広告を表示させへん"
- canSearchNotes: "ノート検索を使わすかどうか"
- canUseTranslator: "翻訳機能の利用"
+ canHideAds: "広告映さへん"
+ canSearchNotes: "ノート探せるかどうか"
+ canUseTranslator: "翻訳使えるかどうか"
+ avatarDecorationLimit: "アイコンデコのいっちばんつけれる数"
_condition:
isLocal: "ローカルユーザー"
isRemote: "リモートユーザー"
- createdLessThan: "アカウント作成から~以内"
- createdMoreThan: "アカウント作成から~経過"
+ createdLessThan: "アカウント作ってから~以内"
+ createdMoreThan: "アカウント作ってから~経過"
followersLessThanOrEq: "フォロワー数が~以下"
followersMoreThanOrEq: "フォロワー数が~以上"
followingLessThanOrEq: "フォロー数が~以下"
@@ -1542,45 +1668,46 @@ _role:
notesMoreThanOrEq: "投稿を~以上しとる"
and: "~かつ~"
or: "~または~"
- not: "~ではない"
+ not: "~じゃない"
_sensitiveMediaDetection:
- description: "機械学習を使って自動でセンシティブなメディアを検出して、モデレーションに役立てることができるで。サーバーの負荷が少し増えてまうなあ。"
+ description: "機械学習で自動できわどいメディアを検出して、運営しやすくするで。でもサーバーが少し重くなってまうわ。"
sensitivity: "検出感度やで"
sensitivityDescription: "感度を低くすると、誤検知(偽陽性)が減るで。感度を高くすると、検知漏れ(偽陰性)が減るで。"
- setSensitiveFlagAutomatically: "NSFWフラグを設定するで"
- setSensitiveFlagAutomaticallyDescription: "この設定をオフにしても内部的に判定結果は保持されるで。"
+ setSensitiveFlagAutomatically: "センシティブフラグを設定するで"
+ setSensitiveFlagAutomaticallyDescription: "この設定切っても内部的には判定結果はそのままや。"
analyzeVideos: "動画の解析をオンにするで"
- analyzeVideosDescription: "画像に加えて動画も解析するようにするで。鯖の負荷が少し増えるで。"
+ analyzeVideosDescription: "画像だけじゃなくて動画も解析するようにするで。サーバーがちょっと重くなるで。"
_emailUnavailable:
- used: "もう使われとるで"
+ used: "もう使われとるわ"
format: "形式がおかしいで"
- disposable: "永久に使えるアドレスじゃないみたいやで"
- mx: "正しいメールサーバーじゃない見たいやで"
- smtp: "メールサーバーが応答してないみたいや"
+ disposable: "ずーっと使えるアドレスじゃないみたいや"
+ mx: "正しいメールサーバーじゃないっぽいわ"
+ smtp: "メールサーバーがうんともすんとも言わへん"
+ banned: "このメールアドレスはあかん"
_ffVisibility:
public: "公開"
followers: "フォロワーだけに公開"
private: "非公開"
_signup:
- almostThere: "ほぼ完了やで"
+ almostThere: "ほぼ終わったようなもんや"
emailAddressInfo: "あんたが使っとるメアドを入力してなー。入れたメアドが公開されることはないで。"
- emailSent: "さっき入れたメールアドレス({email})宛に確認のメールが送られたで。メールに書かれたリンクにアクセスすれば、アカウントの作成が完了や!"
+ emailSent: "さっき入れたメアド({email})宛に確認メールを送ったで。メールに書かれたリンク押してアカウント作るの終わらしてな。\nメールの認証リンクの期限は30分や。"
_accountDelete:
accountDelete: "アカウントの削除"
- mayTakeTime: "アカウントの削除は負荷がかかる処理やねんて。やから作ったコンテンツの数や上げたファイルの数が多いと削除が終わるまでに時間がかかることがあるんやって。"
- sendEmail: "アカウントの削除が終わるときは、登録してたメールアドレス宛に通知を送るで。"
- requestAccountDelete: "アカウント削除をリクエスト"
+ mayTakeTime: "アカウント消すんはサーバーが重いんやって。やから作ったコンテンツとか上げたファイルの数が多いと消し終わるまでに時間がかかるかもしれへん。"
+ sendEmail: "アカウントの消し終わるときは、登録してたメアドに通知するで。"
+ requestAccountDelete: "アカウント削除頼む"
started: "削除処理が始まったで。"
- inProgress: "削除が進んでるで"
+ inProgress: "今消しよるで"
_ad:
back: "戻る"
- reduceFrequencyOfThisAd: "この広告の表示頻度を下げるで"
+ reduceFrequencyOfThisAd: "この広告ちょっとうざったらしいわ"
hide: "表示せん"
- timezoneinfo: "曜日はサーバーのタイムゾーンを元に指定されるで。"
+ timezoneinfo: "曜日はサーバーのタイムゾーンを元に決めるで。"
adsSettings: "広告配信設定"
notesPerOneAd: "リアタイ更新中に広告を出す間隔(ノートの個数な)"
setZeroToDisable: "0でリアタイ更新時の広告配信を無効にすんで"
- adsTooClose: "広告を出す間隔がめっちゃ短いから、ユーザー体験が著しく損なわれる可能性があんで。"
+ adsTooClose: "広告を出す間隔がめっちゃ短いから、ユーザー体験がめちゃめちゃ悪くなるかもしれへん。"
_forgotPassword:
enterEmail: "アカウントに登録したメールアドレスをここに入力してや。そのアドレス宛に、パスワードリセット用のリンクが送られるから待っててな~。"
ifNoEmail: "メールアドレスを登録してへんのやったら、管理者まで教えてな~。"
@@ -1599,7 +1726,7 @@ _plugin:
install: "プラグインのインストール"
installWarn: "信頼できへんプラグインはインストールせんとってな"
manage: "プラグインの管理"
- viewSource: "ソースを表示"
+ viewSource: "ソース見る"
_preferencesBackups:
list: "作ったバックアップ"
saveNew: "新しく保存"
@@ -1640,24 +1767,25 @@ _displayOfSensitiveMedia:
force: "常にメディアを隠すで"
_instanceTicker:
none: "表示せん"
- remote: "リモートユーザーに表示"
- always: "常に表示"
+ remote: "リモートユーザーに見せる"
+ always: "いつでも見せる"
_serverDisconnectedBehavior:
reload: "自動でリロード"
dialog: "ダイアログで警告"
quiet: "控えめに警告"
_channel:
- create: "チャンネルを作る"
- edit: "チャンネルを編集"
+ create: "チャンネル作る"
+ edit: "チャンネルいじる"
setBanner: "バナーを設定"
removeBanner: "バナーを削除"
featured: "トレンド"
- owned: "管理中"
+ owned: "管理しとる"
following: "フォロー中やで"
- usersCount: "{n}人が参加中やで"
+ usersCount: "{n}人が参加しとる"
notesCount: "{n}こ投稿があるで"
nameAndDescription: "名前と説明"
nameOnly: "名前だけ"
+ allowRenoteToExternal: "チャンネルの外にリノートできるようにする"
_menuDisplay:
sideFull: "横"
sideIcon: "横(アイコン)"
@@ -1683,7 +1811,7 @@ _theme:
builtinThemes: "標準のテーマ"
alreadyInstalled: "そのテーマはもうインストールされとるで?"
invalid: "テーマの形式が間違ってるみたいや"
- make: "テーマを作る"
+ make: "テーマ作る"
base: "ベース"
addConstant: "定数を追加"
constant: "定数"
@@ -1749,6 +1877,14 @@ _sfx:
notification: "通知"
antenna: "アンテナ受信"
channel: "チャンネル通知"
+ reaction: "ツッコミ選んどるとき"
+_soundSettings:
+ driveFile: "ドライブん中の音使う"
+ driveFileWarn: "ドライブん中のファイル選びや"
+ driveFileTypeWarn: "このファイルは対応しとらへん"
+ driveFileTypeWarnDescription: "音声ファイルを選びや"
+ driveFileDurationWarn: "音が長すぎるわ"
+ driveFileDurationWarnDescription: "長い音使うたらMisskey使うのに良うないかもしれへんで。それでもええか?"
_ago:
future: "未来"
justNow: "ついさっき"
@@ -1760,6 +1896,14 @@ _ago:
monthsAgo: "{n}ヶ月前"
yearsAgo: "{n}年前"
invalid: "あらへん"
+_timeIn:
+ seconds: "{n}秒後"
+ minutes: "{n}分後"
+ hours: "{n}時間後"
+ days: "{n}日後"
+ weeks: "{n}週間後"
+ months: "{n}ヶ月後"
+ years: "{n}年後"
_time:
second: "秒"
minute: "分"
@@ -1770,12 +1914,12 @@ _2fa:
registerTOTP: "認証アプリの設定はじめる"
step1: "ほんなら、{a}や{b}とかの認証アプリを使っとるデバイスにインストールしてな。"
step2: "次に、ここにあるQRコードをアプリでスキャンしてな~。"
- step2Click: "QRコードをクリックすると、今使とる端末に入っとる認証アプリとかキーリングに登録できるで。"
+ step2Click: "QRコード押したら、今使とる端末に入っとる認証アプリとかキーリングに登録できるで。"
step2Uri: "デスクトップアプリを使う時は次のURIを入れるで"
step3Title: "確認コードを入れてーや"
- step3: "アプリに表示されているトークンを入力して終わりや。"
- setupCompleted: "設定が完了したで。"
- step4: "これからログインするときも、同じようにトークンを入力するんやで"
+ step3: "アプリに映っとる確認コード(トークン)を入れて終わりや。"
+ setupCompleted: "設定が終わったで。"
+ step4: "これからログインするときも、同じようにコードを入れるんや。"
securityKeyNotSupported: "今使とるブラウザはセキュリティキーに対応してへんのやってさ。"
registerTOTPBeforeKey: "セキュリティキー・パスキーを登録するんやったら、まず認証アプリを設定してーな。"
securityKeyInfo: "FIDO2をサポートするハードウェアセキュリティキーか端末の指紋認証やPINを使ってログインするように設定できるで。"
@@ -1831,6 +1975,55 @@ _permissions:
"write:flash": "Playを操作する"
"read:flash-likes": "Playのええやん!を見る"
"write:flash-likes": "Playのええやん!を見る"
+ "read:admin:abuse-user-reports": "ユーザーからの通報を見る"
+ "write:admin:delete-account": "ユーザーアカウント消す"
+ "write:admin:delete-all-files-of-a-user": "ユーザーのファイル全部ほかす"
+ "read:admin:index-stats": "データベースインデックスの情報見る"
+ "read:admin:table-stats": "データベーステーブルの情報見る"
+ "read:admin:user-ips": "ユーザーのIPアドレスを見る"
+ "read:admin:meta": "インスタンスのメタデータ見る"
+ "write:admin:reset-password": "ユーザーのパスワードをリセット"
+ "write:admin:resolve-abuse-user-report": "ユーザーからの通報を解決する"
+ "write:admin:send-email": "メール送る"
+ "read:admin:server-info": "サーバーの情報見る"
+ "read:admin:show-moderation-log": "モデレーションログ見る"
+ "read:admin:show-user": "ユーザーのプライベートな情報見る"
+ "read:admin:show-users": "ユーザーのプライベートな情報見る"
+ "write:admin:suspend-user": "ユーザーを凍結"
+ "write:admin:unset-user-avatar": "ユーザーのアバターを削除"
+ "write:admin:unset-user-banner": "ユーザーのバナーを削除"
+ "write:admin:unsuspend-user": "ユーザーの凍結解除"
+ "write:admin:meta": "インスタンスのメタデータいじる"
+ "write:admin:user-note": "モデレーションノートいじる"
+ "write:admin:roles": "ロールをいじる"
+ "read:admin:roles": "ロール見る"
+ "write:admin:relays": "リレーいじる"
+ "read:admin:relays": "リレー見る"
+ "write:admin:invite-codes": "招待コードいじる"
+ "read:admin:invite-codes": "招待コード見る"
+ "write:admin:announcements": "お知らせいじる"
+ "read:admin:announcements": "お知らせ見る"
+ "write:admin:avatar-decorations": "アバターデコレーションをいじる"
+ "read:admin:avatar-decorations": "アバターデコレーション見る"
+ "write:admin:federation": "連合の情報いじる"
+ "write:admin:account": "ユーザーアカウントいじる"
+ "read:admin:account": "ユーザーの情報見る"
+ "write:admin:emoji": "絵文字いじる"
+ "read:admin:emoji": "絵文字見る"
+ "write:admin:queue": "ジョブキューいじる"
+ "read:admin:queue": "ジョブキューの情報見る"
+ "write:admin:promo": "プロモーションノートいじる"
+ "write:admin:drive": "ユーザーのドライブいじる"
+ "read:admin:drive": "ユーザーのドライブの情報見る"
+ "read:admin:stream": "管理者用のWebsocket API使う"
+ "write:admin:ad": "広告いじる"
+ "read:admin:ad": "広告見る"
+ "write:invite-codes": "招待コード作る"
+ "read:invite-codes": "招待コード取得"
+ "write:clip-favorite": "クリップのいいねいじる"
+ "read:clip-favorite": "クリップのいいね見る"
+ "read:federation": "連合の情報取得"
+ "write:report-abuse": "違反報告"
_auth:
shareAccessTitle: "アプリへのアクセス許してやったらどうや"
shareAccess: "「{name}」がアカウントにアクセスすることを許可してええか?"
@@ -1844,9 +2037,9 @@ _auth:
_antennaSources:
all: "みんなのノート"
homeTimeline: "フォローしとるユーザーのノート"
- users: "選らんだ一人か複数のユーザーのノート"
+ users: "選んだ一人か複数のユーザーのノート"
userList: "選んだリストのユーザーのノート"
- userBlacklist: "選んだ1人か複数のユーザーのノート"
+ userBlacklist: "選んだ一人か複数のユーザーを除いた全てのノート"
_weekday:
sunday: "日曜日"
monday: "月曜日"
@@ -1885,6 +2078,7 @@ _widgets:
_userList:
chooseList: "リストを選ぶ"
clicker: "クリッカー"
+ birthdayFollowings: "今日誕生日のツレ"
_cw:
hide: "隠す"
show: "続き見して!"
@@ -1947,9 +2141,11 @@ _profile:
changeAvatar: "アバター画像を変更するで"
changeBanner: "バナー画像を変更するで"
verifiedLinkDescription: "内容をURLに設定すると、リンク先のwebサイトに自分のプロフのリンクが含まれてる場合に所有者確認済みアイコンを表示させることができるで。"
+ avatarDecorationMax: "最大{max}つまでデコつけれんで"
_exportOrImport:
allNotes: "全てのノート"
favoritedNotes: "お気に入りにしたノート"
+ clips: "クリップ"
followingList: "フォロー"
muteList: "ミュート"
blockingList: "ブロック"
@@ -2061,19 +2257,23 @@ _notification:
youGotMention: "{name}からのメンション"
youGotReply: "{name}からのリプライ"
youGotQuote: "{name}による引用"
- youRenoted: "{name}がRenoteしたみたいやで"
+ youRenoted: "{name}がリノートしたみたいやで"
youWereFollowed: "フォローされたで"
youReceivedFollowRequest: "フォロー許可してほしいみたいやな"
yourFollowRequestAccepted: "フォローさせてもろたで"
pollEnded: "アンケートの結果が出たみたいや"
newNote: "さらの投稿"
unreadAntennaNote: "アンテナ {name}"
+ roleAssigned: "ロールが付与されたで"
emptyPushNotificationMessage: "プッシュ通知の更新をしといたで"
achievementEarned: "実績を獲得しとるで"
testNotification: "通知テスト"
checkNotificationBehavior: "通知の表示を確かめるで"
sendTestNotification: "テスト通知を送信するで"
notificationWillBeDisplayedLikeThis: "通知はこのように表示されるで"
+ reactedBySomeUsers: "{n}人がツッコんだで"
+ renotedBySomeUsers: "{n}人がリノートしたで"
+ followedBySomeUsers: "{n}人にフォローされたで"
_types:
all: "すべて"
note: "あんたらの新規投稿"
@@ -2086,6 +2286,7 @@ _notification:
pollEnded: "アンケートが終了したで"
receiveFollowRequest: "フォロー許可してほしいみたいやで"
followRequestAccepted: "フォローが受理されたで"
+ roleAssigned: "ロールが付与された"
achievementEarned: "実績の獲得"
app: "連携アプリからの通知や"
_actions:
@@ -2143,8 +2344,8 @@ _webhookSettings:
followed: "フォローもらったとき~!"
note: "ノートを投稿したとき~!"
reply: "返信があるとき~!"
- renote: "Renoteされるとき~!"
- reaction: "ツッコミがあるとき~!"
+ renote: "リノートされるとき~!"
+ reaction: "ツッコまれたとき~!"
mention: "メンションがあるとき~!"
_moderationLogTypes:
createRole: "ロールを追加すんで"
@@ -2173,13 +2374,15 @@ _moderationLogTypes:
markSensitiveDriveFile: "ファイルをセンシティブ付与"
unmarkSensitiveDriveFile: "ファイルをセンシティブ解除"
resolveAbuseReport: "苦情を解決"
- createInvitation: "招待コードを作成"
+ createInvitation: "招待コード作る"
createAd: "広告を作んで"
deleteAd: "広告ほかす"
updateAd: "広告を更新"
createAvatarDecoration: "アイコンデコレーションを作成"
updateAvatarDecoration: "アイコンデコレーションを更新"
deleteAvatarDecoration: "アイコンデコレーションを削除"
+ unsetUserAvatar: "この子のアイコン元に戻す"
+ unsetUserBanner: "この子のバナー元に戻す"
_fileViewer:
title: "ファイルの詳しい情報"
type: "ファイルの種類"
@@ -2212,6 +2415,11 @@ _externalResourceInstaller:
description: ""
_failedToFetch:
title: ""
+ fetchErrorDescription: "他のサイトに繋がらんかったわ。もっかいやってもダメやったら、サイトの管理してる人に言っといて。"
+ parseErrorDescription: "他のサイトから持ってきたデータ、よう分からんかったわ。サイトの管理してる人に言っといて。"
+ _hashUnmatched:
+ title: "ちゃんとしたデータが持ってこれんかったわ"
+ description: "もらったデータがなんかおかしいっぽいわ。ちょっと危ないからインストールはできへん。サイト管理してる人に言っといてな。"
_pluginParseFailed:
title: "AiScriptエラー起こしてもうたねん"
description: "データは取得できたものの、AiScript解析時にエラーがあったから読み込めへんかってん。すまんが、プラグインを作った人に問い合わせてくれへん?ごめんな。エラーの詳細はJavaScriptコンソール読んでな。"
@@ -2220,7 +2428,70 @@ _externalResourceInstaller:
description: "プラグインのインストール中に問題発生してもた、もう1度試してな。エラーの詳細はJavaScriptのコンソール見てや。"
_themeParseFailed:
title: "テーマ解析エラー"
- description: "データは取得できたものの、テーマファイル解析時にエラーがあったから読み込めへんかってん。すまんが、テーマ作った人に問い合わせてくれへん?ごめんな。エラーの詳細はJavaScriptコンソール読んでな。"
+ description: "データは取れたんやが、テーマファイル読み込んどる時にエラーがあったから読み込めへんかったわ。すまんけど、テーマ作った人に言うてくれへん?ごめんな。エラーの詳細はJavaScriptコンソール読んでな。"
_themeInstallFailed:
title: "テーマインストールに失敗してもた"
- description: "テーマのインストール中に問題発生してもた、もう1度試してな。エラーの詳細はJavaScriptのコンソール見てや。"
+ description: "なんかテーマインストールできんかったわ。もう一回試してな。細かいのはJavaScriptのコンソール見てや。"
+_dataSaver:
+ _media:
+ title: "メディアの読み込み"
+ description: "絵・動画が自動で読まれるのをふせぐわ。隠れてる絵・動画はタップするとひょっこりはんしてくれんで。"
+ _avatar:
+ title: "アイコンの絵"
+ description: "アイコン画像のアニメが止まるで。普通の画像よりもデータ量がでかいから、もっと通信量を節約できるねん。"
+ _urlPreview:
+ title: "URLプレビューのサムネイル画像"
+ description: "URLプレビューのサムネイル画像が読み込まへんなるで。"
+ _code:
+ title: "コードハイライト"
+ description: "MFMとかでコードハイライト記法が使われてるとき、タップするまで読み込まれへんくなるで。コードハイライトではハイライトする言語ごとにその決めてるファイルを読む必要はあんねんな。けどな、それは自動で読み込まれなくなるから、通信量を少なくできることができるねん。"
+_hemisphere:
+ N: "北半球"
+ S: "南半球"
+ caption: "一部のクライアント設定で、季節を判定するのに使用するで。"
+_reversi:
+ reversi: "リバーシ"
+ gameSettings: "対局の設定"
+ chooseBoard: "ボードを選択"
+ blackOrWhite: "先行/後攻"
+ blackIs: "{name}が黒(先行)"
+ rules: "ルール"
+ thisGameIsStartedSoon: "対局、そろそろ開始されるで。"
+ waitingForOther: "相手の準備が完了するのを待ってんで。"
+ waitingForMe: "あんさんの準備が完了すんのを待ってんで"
+ waitingBoth: "準備してなー"
+ ready: "準備完了"
+ cancelReady: "準備を再開"
+ opponentTurn: "相手のターンやで"
+ myTurn: "あんさんのターンや"
+ turnOf: "{name}のターンやで"
+ pastTurnOf: "{name}のターン"
+ surrender: "投了"
+ surrendered: "投了により"
+ timeout: "時間切れ"
+ drawn: "引き分け"
+ won: "{name}の勝ち"
+ black: "黒"
+ white: "白"
+ total: "合計"
+ turnCount: "{count}ターン目"
+ myGames: "自分の対局"
+ allGames: "みんなの対局"
+ ended: "終了"
+ playing: "対局中"
+ isLlotheo: "石の少ない方が勝ち(ロセオ)"
+ loopedMap: "ループマップ"
+ canPutEverywhere: "どこでも置けるモード"
+ timeLimitForEachTurn: "1ターンの時間制限"
+ freeMatch: "フリーマッチ"
+ lookingForPlayer: "対戦相手を探してるで"
+ gameCanceled: "対局がキャンセルされたわ"
+ shareToTlTheGameWhenStart: "初めの時に対局をタイムラインに投稿するで"
+ iStartedAGame: "対局し始めたで! #MisskeyReversi"
+ opponentHasSettingsChanged: "相手が設定変えたで"
+ allowIrregularRules: "変則許可 (完全フリー)"
+ disallowIrregularRules: "変則なし"
+_offlineScreen:
+ title: "オフライン - サーバーに接続できひんで"
+ header: "サーバーに接続できへんわ"
+
diff --git a/locales/jbo-EN.yml b/locales/jbo-EN.yml
index d4fea291d..297ca53dd 100644
--- a/locales/jbo-EN.yml
+++ b/locales/jbo-EN.yml
@@ -1,3 +1,4 @@
---
_lang_: "la .lojban."
headlineMisskey: "lo se tcana noi jorne fi loi notci"
+
diff --git a/locales/kab-KAB.yml b/locales/kab-KAB.yml
index 22e24d3ba..b976f028f 100644
--- a/locales/kab-KAB.yml
+++ b/locales/kab-KAB.yml
@@ -104,3 +104,4 @@ _deck:
_columns:
notifications: "Ilɣuyen"
list: "Tibdarin"
+
diff --git a/locales/kn-IN.yml b/locales/kn-IN.yml
index b3ad46f2b..bb6d1ee24 100644
--- a/locales/kn-IN.yml
+++ b/locales/kn-IN.yml
@@ -84,3 +84,4 @@ _deck:
notifications: "ಅಧಿಸೂಚನೆಗಳು"
tl: "ಸಮಯಸಾಲು"
mentions: "ಹೆಸರಿಸಿದ"
+
diff --git a/locales/ko-GS.yml b/locales/ko-GS.yml
new file mode 100644
index 000000000..39492d902
--- /dev/null
+++ b/locales/ko-GS.yml
@@ -0,0 +1,800 @@
+---
+_lang_: "한국어(경상)"
+headlineMisskey: "노트로 이언 네트워크"
+introMisskey: "어서 오이소! Misskey넌 오픈소스 분산헹 마이크로 블로그 서비스입니다.\n‘노트’럴 맨걸어서 지검 일나넌 일얼 노누던가 내 이바구럴 남한데 서 보이소.📡\n‘리액션’ 기넝서 남으 노트에 억수로 빠리게 답할 수 잇십니다.👍\n새롭운 세게럴 탐험해 보입시다.🚀"
+poweredByMisskeyDescription: "{name} 서버넌 오픈소스 플랫폼 Misskey으 서버 가운데 하나입니다."
+monthAndDay: "{month}월 {day}일"
+search: "찾기"
+notifications: "알림"
+username: "사용자 이럼"
+password: "비밀번호"
+forgotPassword: "비밀번호럴 잊엇뿟십니꺼?"
+fetchingAsApObject: "연합서 찾아보고 잇어예"
+ok: "예"
+gotIt: "알것어예"
+cancel: "아이예"
+noThankYou: "뎃어예"
+enterUsername: "사용자 이럼 서기"
+renotedBy: "{user}님이 리노트햇어예"
+noNotes: "노트가 없십니다"
+noNotifications: "알림이 없십니다"
+instance: "서버"
+settings: "설정"
+notificationSettings: "알림 설정"
+basicSettings: "기본 설정"
+otherSettings: "다린 설정"
+openInWindow: "창서 옐기"
+profile: "프로필"
+timeline: "타임라인"
+noAccountDescription: "자기소개가 없십니다"
+login: "로그인"
+loggingIn: "로그인하고 잇어예"
+logout: "로그아웃"
+signup: "가입하기"
+uploading: "올리고 잇어예"
+save: "저장하기"
+users: "사용자"
+addUser: "사용자 옇기"
+favorite: "질겨찾기"
+favorites: "질겨찾기"
+unfavorite: "질겨찾기서 어ᇝ애기"
+favorited: "질겨찾기에 담앗십니다."
+alreadyFavorited: "벌시로 질겨찾기에 담기 잇십니다."
+cantFavorite: "질겨찾기에 몬 담앗십니다."
+pin: "프로필에 붙이기"
+unpin: "프로필서 띠기"
+copyContent: "내용 복사하기"
+copyLink: "링크 복사하기"
+copyLinkRenote: "리노트 링크 복사"
+delete: "내삐리기"
+deleteAndEdit: "내삐리고 새로 적기"
+deleteAndEditConfirm: "요 노트럴 뭉캐고 새로 적십니꺼? 요 노트서 리액션하고 리노트, 답하기도 말캉 뭉캐집니다."
+addToList: "리스트에 옇기"
+addToAntenna: "안테나에 옇기"
+sendMessage: "메시지 보내기"
+copyRSS: "알에스에스 복사하기"
+copyUsername: "사용자 이럼 복사하기"
+copyUserId: "사용자 아이디 복사하기"
+copyNoteId: "노트 아이디 복사하기"
+copyFileId: "파일 아이디 복사하기"
+copyFolderId: "폴더 아이디 복사하기"
+copyProfileUrl: "프로필 주소 복사하기"
+searchUser: "사용자 찾기"
+reply: "답하기"
+loadMore: "더 볼래예"
+showMore: "더 볼래예"
+showLess: "꺼기"
+youGotNewFollower: "새 팔로워가 잇십니다"
+receiveFollowRequest: "팔로잉 요청이 잇십니다"
+followRequestAccepted: "팔로잉이 받아딜이젓십니다"
+mention: "멘션"
+mentions: "받언 멘션"
+directNotes: "쪽지 서기"
+importAndExport: "가오기하고 내가기"
+import: "가오기"
+export: "내가기"
+files: "파일"
+download: "내리받기"
+driveFileDeleteConfirm: "‘{name}’ 파일얼 뭉캡니꺼? 요 파일얼 서넌 콘텐츠도 뭉캐집니다."
+unfollowConfirm: "{name}님얼 고마 팔로잉합니꺼?"
+exportRequested: "내가기 요청얼 햇십니다. 시간이 쪼매 걸릴 깁니다. 요청이 껕나모 ‘드라이브’에 옇십니다."
+importRequested: "가오기 요청얼 햇십니다. 시간이 쪼매 걸릴 깁니다."
+lists: "리스트"
+noLists: "리스트가 없십니다"
+note: "노트"
+notes: "노트"
+following: "팔로잉"
+followers: "팔로워"
+followsYou: "내럴 팔로잉합니다"
+createList: "리스트 맨걸기"
+manageLists: "리스트 간리하기"
+error: "우짭니꺼"
+somethingHappened: "먼가 일낫십니다"
+retry: "다시 하기"
+pageLoadError: "하멘 부리오기가 아이뎁니다."
+pageLoadErrorDescription: "네트워크나 브라우저 캐시 때문일 깁니다. 캐시럴 뭉캐던가 쪼매 잇다 새로 해 주이소."
+serverIsDead: "서버가 대답얼 아이합니다. 쪼매 잇다 새로 해 주이소."
+youShouldUpgradeClient: "요 하멘얼 볼라먼 새로 곤치던가 새 버전으 클라이언트럴 받아 서 보이소."
+enterListName: "리스트 이럼 서기"
+privacy: "개인 정보"
+makeFollowManuallyApprove: "팔로잉얼 하나석 받아딜이기"
+defaultNoteVisibility: "기본 공개 범위"
+follow: "팔로우"
+followRequest: "팔로우 요청하기"
+followRequests: "팔로우 요청"
+unfollow: "팔로우 무루기"
+followRequestPending: "팔로우 수락 지둘림"
+enterEmoji: "이모지 서기"
+renote: "리노트"
+unrenote: "리노트 무루기"
+renoted: "리노트럴 햇십니다."
+cantRenote: "요 걸언 리노트럴 몬 합니다."
+cantReRenote: "리노트넌 지럴 리노트 몬 합니다."
+quote: "따오기"
+inChannelRenote: "채널 안 리노트"
+inChannelQuote: "채널 안 따오기"
+pinnedNote: "붙인 노트"
+pinned: "프로필에 붙이기"
+you: "나"
+clickToShow: "누질라서 보기"
+sensitive: "수ᇚ힛섭니다"
+add: "옇기"
+reaction: "반엉"
+reactions: "반엉"
+reactionSettingDescription2: "꺼시서 두고, 누질라서 뭉캐고, ‘+’럴 누질라서 옇십니다."
+rememberNoteVisibility: "공개 범위럴 기억하기"
+attachCancel: "붙임 빼기"
+deleteFile: "파일 뭉캐기"
+markAsSensitive: "수ᇚ힘 설정"
+unmarkAsSensitive: "수ᇚ힘 무루기"
+enterFileName: "파일 이럼 서기"
+mute: "수ᇚ후기"
+unmute: "수ᇚ훈 거 무루기"
+renoteMute: "리노트 수ᇚ후기"
+renoteUnmute: "리노트 수ᇚ훈 거 무루기"
+block: "차단하기"
+unblock: "차단 무루기"
+suspend: "얼우기"
+unsuspend: "얼우기 풀기"
+blockConfirm: "차단합니꺼?"
+unblockConfirm: "차단얼 무룹니꺼?"
+suspendConfirm: "얼웁니꺼?"
+unsuspendConfirm: "얼운 거 풉니꺼?"
+selectList: "리스트 개리기"
+editList: "리스트 적기"
+selectChannel: "채널 개리기"
+selectAntenna: "안테나 개리기"
+editAntenna: "안테나 적기"
+selectWidget: "위젯 개리기"
+editWidgets: "위젯 적기"
+editWidgetsExit: "고마 적기"
+customEmojis: "사용자 지정 이모지"
+emoji: "이모지"
+emojis: "이모지"
+emojiName: "이모지 이럼"
+emojiUrl: "이모지 주소"
+addEmoji: "이모지 옇기"
+settingGuide: "개않언 설정"
+cacheRemoteFiles: "웬겍 파일 캐시하기"
+cacheRemoteFilesDescription: "요 설정얼 키모 웬겍 파일얼 요 서버으 스토리지에 캐시합니다. 미디어가 사게 비이지먼 서버으 스토리지럴 마이 섭니다. 웬겍 사용자가 얼매나 캐시럴 둘 긴가넌 고 옉할으 드라이브 크기 제한마중 다립니다. 요 제한얼 넘구모 엣날 파일버터 캐시서 뭉캐지서 링크가 뎁니다. 요 설정얼 꺼모 웬겍 파일언 첨버터 링크가 뎁니다. 이미지으 섬네일얼 맨걸던 사용자으 개인 정보럴 징키던 할라먼 default.yml서 proxyRemoteFiles럴 ture로 하입시다."
+youCanCleanRemoteFilesCache: "파일 간리으 🗑️ 모냥얼 누질리모 캐시럴 말캉 뭉캘 수 잇십니다."
+cacheRemoteSensitiveFiles: "웬겍으 수ᇚ힌 파일얼 캐시하기"
+cacheRemoteSensitiveFilesDescription: "요 설정얼 꺼모 웬겍 수ᇚ힌 파일이 캐시하지 아이하고 바리 링크합니다."
+flagAsBot: "자동 게정입니다"
+flagAsBotDescription: "요 게정얼 프로그램서 설라먼 키야 합니다. 키모 다런 개발자가 반엉얼 끋없이 데풀이하지 몬 하게 도아 줄 수 잇고 Misskey으 시스템서 자동 게정이 뎁니다."
+flagAsCat: "애웅애웅애웅애웅!"
+flagAsCatDescription: "애옹?"
+flagShowTimelineReplies: "타임라인서 노트으 답하기 보기"
+flagShowTimelineRepliesDescription: "키모 타임라인서 다런 사용자덜으 답하기도 봅니다."
+autoAcceptFollowed: "팔로잉하넌 사용자으 팔로잉 요청 바리 받아딜이기"
+addAccount: "게정 옇기"
+reloadAccountsList: "게정 리스트으 정보 새로 바꾸기"
+loginFailed: "로그인이 아이뎁니다."
+showOnRemote: "웬겍서 보기"
+general: "일반"
+wallpaper: "벡지"
+setWallpaper: "벡지 설정"
+removeWallpaper: "벡지 뭉캐기"
+searchWith: "찾기: {q}"
+youHaveNoLists: "리스트가 없십니다"
+followConfirm: "{name}님얼 팔로잉합니꺼?"
+proxyAccount: "프락시 게정"
+proxyAccountDescription: "프락시 게정언 턱벨한 조겐서 웬겍 팔로잉얼 하넌 게정입니다. 사용자가 웬겍 사용자럴 리스트에 옇얼 때 리스트에 옇언 사용자럴 누도 팔로잉 아이하모 할동이 서버로 아이 오니께 요 게정이 아인 프락시 게정얼 팔로잉하게 합니다."
+host: "호스트 이럼"
+selectUser: "사용자 개리기"
+recipient: "받넌 사람"
+annotation: "주석"
+federation: "옌합"
+instances: "서버"
+registeredAt: "첫 발겐"
+latestRequestReceivedAt: "막죽에 받언 요청"
+latestStatus: "막죽 상태"
+storageUsage: "스토리지 사용량"
+charts: "차트"
+perHour: "한 시간마중"
+perDay: "하리마중"
+stopActivityDelivery: "할동 고마 보내기"
+blockThisInstance: "요 서버 차단하기"
+silenceThisInstance: "서버 수ᇚ후기"
+operations: "동작"
+software: "소프트웨어"
+version: "버전"
+metadata: "메타데이터"
+withNFiles: "파일 {n}개"
+monitor: "모니터"
+jobQueue: "작업 대기옐"
+cpuAndMemory: "시피유하고 메모리"
+network: "네트워크"
+disk: "디스크"
+instanceInfo: "서버 정보"
+statistics: "통게"
+clearQueue: "대기옐 비우기"
+clearQueueConfirmTitle: "대기옐얼 비웁니꺼?"
+clearQueueConfirmText: "대기옐에 잇넌 걸얼 아이 보냅니다. 흐이 요 동작언 할 필요가 없십니다."
+clearCachedFiles: "캐시 비우기"
+clearCachedFilesConfirm: "캐시한 웬겍 파일얼 말캉 뭉캡니꺼?"
+blockedInstances: "차단한 서버"
+blockedInstancesDescription: "차단할라넌 서버으 호스트럴 줄 바꿈해서로 비이 줍니다. 차단한 서버넌 요 서버하고 교류 몬 합니다."
+silencedInstances: "수ᇚ훈 서버"
+silencedInstancesDescription: "수ᇚ훌라넌 서버으 호스트럴 줄 바꿈해서로 비이 줍니다. 수ᇚ훈 서버으 게정언 말캉 ‘수ᇚ후기’가 데서 팔로잉 요청만 데고 팔로워가 아인 로컬 게정서 멘션얼 몬 합니다. 차단한 서버넌 상간 없십니다."
+muteAndBlock: "수ᇚ훔하고 차단"
+mutedUsers: "수ᇚ훈 사용자"
+blockedUsers: "차단한 사용자"
+noUsers: "사용자가 없십니다"
+editProfile: "프로필 적기"
+noteDeleteConfirm: "요 노트럴 뭉캡니꺼?"
+pinLimitExceeded: "더 몬 붙입니다"
+intro: "Misskey럴 다 깔앗십니다! 간리자 게정얼 맨걸어 보입시다."
+done: "햇어예"
+processing: "처리하고 잇어예"
+preview: "미리보기"
+default: "기본값"
+defaultValueIs: "기본값: {value}"
+noCustomEmojis: "이모지가 없십니다"
+noJobs: "작업이 없십니다"
+federating: "옌합하고 잇어예"
+blocked: "차단햇어예"
+suspended: "고만 보내예"
+all: "말캉"
+subscribing: "구독하고 잇어예"
+publishing: "보내고 잇어예"
+notResponding: "답이 없어예"
+instanceFollowing: "서버으 팔로잉"
+instanceFollowers: "서버으 팔로워"
+instanceUsers: "서버으 사용자"
+changePassword: "비밀번호 바꾸기"
+security: "보안"
+retypedNotMatch: "선 거가 안 맞십니다."
+currentPassword: "지검 비밀번호"
+newPassword: "새 비밀번호"
+newPasswordRetype: "새 비밀번호 다시 서기"
+attachFile: "파일 붙이기"
+more: "더 볼래예!"
+featured: "인기"
+usernameOrUserId: "사용자 이럼이나 사용자 아이디"
+noSuchUser: "사용자럴 몬 찾앗십니다"
+lookup: "찾아보기"
+announcements: "공지 걸"
+imageUrl: "이미지 주소"
+remove: "내삐리기"
+removed: "뭉캣십니다"
+removeAreYouSure: "‘{x}’(얼)럴 뭉캡니꺼?"
+deleteAreYouSure: "‘{x}’(얼)럴 뭉캡니꺼?"
+resetAreYouSure: "아시로 데돌립니꺼?"
+areYouSure: "갠찮십니꺼?"
+saved: "저장햇십니다"
+messaging: "대화"
+upload: "올리기"
+keepOriginalUploading: "온본 두기"
+keepOriginalUploadingDescription: "이미지럴 올릴 때 온본얼 고대로 둡니다. 꺼모 올릴 때 브라우저서 웹 공개 이미지럴 맨겁니다."
+fromDrive: "드라이브서"
+fromUrl: "주소서"
+uploadFromUrl: "주소 올리기"
+uploadFromUrlDescription: "올리기할라넌 파일으 주소"
+uploadFromUrlRequested: "올리기럴 요청햇십니다"
+uploadFromUrlMayTakeTime: "올리기가 껕날라먼 시간이 쪼매 걸릴 깁니다."
+explore: "살펴보기"
+messageRead: "이럿어예"
+noMoreHistory: "요카마 엣날 기록이 없십니다"
+startMessaging: "대화하기"
+nUsersRead: "{n}멩이 이럿십니다"
+agreeTo: "{0}에 동이하기"
+agree: "동이합니다"
+agreeBelow: "밑으 내용에 동이합니다"
+basicNotesBeforeCreateAccount: "주이할 내용"
+termsOfService: "이용 약간"
+start: "시작하기"
+home: "덜머리"
+remoteUserCaution: "웬겍 사용자넌 정보가 학실하지 아이할 수 잇십니다."
+activity: "할동"
+images: "이미지"
+image: "이미지"
+birthday: "생일"
+yearsOld: "{age}살"
+registeredDate: "맨건 날"
+location: "장소"
+theme: "테마"
+themeForLightMode: "볽엄 모드서 설 테마"
+themeForDarkMode: "어덥엄 모드서 설 테마"
+light: "볽엄"
+dark: "어덥엄"
+lightThemes: "볽언 테마"
+darkThemes: "어덥언 테마"
+syncDeviceDarkMode: "디바이스 쪽 어덥엄 모드하고 같구로 마추기"
+drive: "드라이브"
+fileName: "파일 이럼"
+selectFile: "파일 개리기"
+selectFiles: "파일 개리기"
+selectFolder: "폴더 개리기"
+selectFolders: "폴더 개리기"
+renameFile: "파일 이럼 바꾸기"
+folderName: "폴더 이럼"
+createFolder: "폴더 맨걸기"
+renameFolder: "폴더 이럼 바꾸기"
+deleteFolder: "폴더 뭉캐기"
+folder: "폴더"
+addFile: "파일 옇기"
+emptyDrive: "드라이브가 비잇십니다"
+emptyFolder: "폴더가 비잇십니다"
+unableToDelete: "몬 뭉캡니다"
+inputNewFileName: "새 파일 이럼얼 서 보이소"
+inputNewDescription: "새 설멩얼 서 보이소"
+inputNewFolderName: "새 폴더 이럼얼 서 보이소"
+circularReferenceFolder: "엚길 폴더으 아래 폴더입니다."
+hasChildFilesOrFolders: "요 폴더넌 아이 비잇어니께 몬 뭉캡니다."
+copyUrl: "주소 복사하기"
+rename: "이럼 바꾸기"
+avatar: "아바타"
+banner: "배너"
+displayOfSensitiveMedia: "수ᇚ힌 옝상물 보기"
+whenServerDisconnected: "서버하고 옌겔이 껂기모"
+disconnectedFromServer: "서버하고 옌겔이 껂깃십니다"
+reload: "새로곤침"
+doNothing: "무시하기"
+reloadConfirm: "새로곤침합니꺼?"
+watch: "간심 갖기"
+unwatch: "간심 고마 갖기"
+accept: "받기"
+reject: "아이 받기"
+normal: "일반"
+instanceName: "서버 이럼"
+instanceDescription: "서버 소개"
+maintainerName: "간리자 이럼"
+maintainerEmail: "간리자 전자우펜"
+tosUrl: "이용 약간 주소"
+thisYear: "올개"
+thisMonth: "요달"
+today: "오올"
+dayX: "{day}일"
+monthX: "{month}월"
+yearX: "{year}년"
+pages: "바닥"
+integration: "옌겔"
+connectService: "옌겔하기"
+disconnectService: "껂기"
+enableLocalTimeline: "로컬 타임라인 키기"
+enableGlobalTimeline: "글로벌 타임라인 키기"
+disablingTimelinesInfo: "요 타임라인얼 꺼도 간리자하고 중재자넌 고대로 설 수 잇십니다."
+registration: "맨걸기"
+enableRegistration: "누라도 새로 맨걸 수 잇거로 하기"
+invite: "초대하기"
+driveCapacityPerLocalAccount: "로컬 사용자 하나마중 드라이브 커기"
+driveCapacityPerRemoteAccount: "웬겍 사용자 하나마중 드라이브 커기"
+inMb: "메가바이트 단이"
+bannerUrl: "배너 이미지 주소"
+backgroundImageUrl: "배겡 이미지 주소"
+basicInfo: "기본 정보"
+pinnedUsers: "붙인 사용자"
+pinnedUsersDescription: "‘살펴보기’서 붙일라넌 사용자럴 줄 바꿈해서로 적십니다."
+pinnedPages: "붙인 바닥"
+pinnedPagesDescription: "서버으 대문서 붙일라넌 바닥으 겡로럴 줄 바꿈해서로 적십니다."
+pinnedClipId: "붙일 클립으 아이디"
+pinnedNotes: "붙인 노트"
+hcaptcha: "에이치캡차"
+enableHcaptcha: "에이치캡차 키기"
+hcaptchaSiteKey: "사이트키"
+hcaptchaSecretKey: "시크릿키"
+mcaptchaSiteKey: "사이트키"
+mcaptchaSecretKey: "시크릿키"
+recaptcha: "리캡차"
+enableRecaptcha: "리캡차 키기"
+recaptchaSiteKey: "사이트키"
+recaptchaSecretKey: "시크릿키"
+turnstile: "턴스타일"
+enableTurnstile: "턴스타일 키기"
+turnstileSiteKey: "사이트키"
+turnstileSecretKey: "시크릿키"
+avoidMultiCaptchaConfirm: "오만 캡차럴 서모 간섭이 잇얼 깁니다. 다린 캡차를 껍니꺼? ‘아이예’럴 누질리모 오만 캡차럴 키 둘 수도 잇십니다."
+antennas: "안테나"
+manageAntennas: "안테나 간리"
+name: "이럼"
+antennaSource: "받얼 소스"
+antennaKeywords: "받얼 검색어"
+antennaExcludeKeywords: "수ᇚ훌 검색어"
+antennaKeywordsDescription: "띠어서기럴 하모 ‘거라고’가 데고 줄 바꿈얼 하모 ‘아이먼’이 뎁니다"
+notifyAntenna: "새 노트럴 알리기"
+withFileAntenna: "파일이 붙언 노트마"
+enableServiceworker: "브라우저서 알림 포시럴 키기"
+antennaUsersDescription: "사용자 이럼얼 줄 바꿈해서로 섭니다"
+caseSensitive: "대소문자럴 구벨하기"
+withReplies: "답하기도 옇기"
+connectedTo: "요 게정하고 옌겔데어 잇십니다"
+notesAndReplies: "걸하고 답걸"
+withFiles: "파일에 붙이기"
+silence: "수ᇚ후기"
+silenceConfirm: "수ᇚ훕니꺼?"
+unsilence: "수ᇚ후기 어ᇝ애기"
+unsilenceConfirm: "수ᇚ후기럴 어ᇝ앱니꺼?"
+popularUsers: "소문난 사용자"
+recentlyUpdatedUsers: "얼마 전에 걸 선 사용자"
+recentlyRegisteredUsers: "얼마 전에 맨건 사용자"
+recentlyDiscoveredUsers: "얼마 전에 찾언 사용자"
+exploreUsersCount: "사용자 {count}멩이 잇십니다."
+exploreFediverse: "옌합우주 탐험하기"
+popularTags: "소문난 태그"
+userList: "리스트"
+about: "정보"
+aboutMisskey: "Misskey넌예"
+administrator: "간리자"
+token: "학인 기호"
+2fa: "두 단게 정멩"
+setupOf2fa: "두 단게 정멩 설정"
+totp: "정멩 앱"
+totpDescription: "정멩 앱서 단헤용 비밀번호 서기"
+moderator: "중재자"
+moderation: "중재"
+moderationNote: "중재 노트"
+addModerationNote: "중재 노트 옇기"
+moderationLogs: "중재 일지"
+nUsersMentioned: "{n}멩이 이바구하고 잇어예"
+securityKeyAndPasskey: "보안키·패스키"
+securityKey: "보안키"
+lastUsed: "마지막 쓰임"
+lastUsedAt: "마지막 쓰임: {t}"
+unregister: "맨걸기 무루기"
+passwordLessLogin: "비밀번호 없시 로그인"
+passwordLessLoginDescription: "비밀번호 말고 보안키나 패스키 같은 것만 써 가 로그인합니다."
+resetPassword: "비밀번호 재설정"
+newPasswordIs: "새 비밀번호는 \"{password}\" 입니다"
+reduceUiAnimation: "화면 움직임 효과들을 수ᇚ후기"
+share: "노누기"
+notFound: "몬 찾앗십니다"
+notFoundDescription: "고런 주소로 들어가는 하멘은 없십니다."
+uploadFolder: "기본 업로드 위치"
+markAsReadAllNotifications: "모든 알림 이럿다고 표시"
+markAsReadAllUnreadNotes: "모든 글 이럿다고 표시"
+markAsReadAllTalkMessages: "모든 대화 이럿다고 표시"
+help: "도움말"
+inputMessageHere: "여따가 메시지를 입력해주이소"
+close: "닫기"
+invites: "초대하기"
+members: "멤버"
+transfer: "양도"
+title: "제목"
+text: "글"
+enable: "키기"
+next: "다음"
+retype: "다시 서기"
+noteOf: "{user}님으 노트"
+quoteAttached: "따옴"
+quoteQuestion: "따와가 작성하겠십니까?"
+noMessagesYet: "아직 대화가 없십니다"
+newMessageExists: "새 메시지가 있십니다"
+onlyOneFileCanBeAttached: "메시지엔 파일 하나까제밖에 몬 넣십니다"
+invitations: "초대하기"
+invitationCode: "초대장"
+checking: "학인하고 잇십니다"
+tooShort: "억수로 짜립니다"
+tooLong: "억수로 집니다"
+passwordMatched: "맞십니다"
+passwordNotMatched: "안 맞십니다"
+signinFailed: "로그인 몬 했십니다. 고 이름이랑 비밀번호 제대로 썼는가 확인해 주이소."
+or: "아니면"
+language: "언어"
+uiLanguage: "UI 표시 언어"
+aboutX: "{x}에 대해서"
+emojiStyle: "이모지 모양"
+native: "기본"
+disableDrawer: "드로어 메뉴 쓰지 않기"
+showNoteActionsOnlyHover: "마우스 올맀을 때만 노트 액션 버턴 보이기"
+noHistory: "기록이 없십니다"
+signinHistory: "로그인 기록"
+enableAdvancedMfm: "복잡한 MFM 키기"
+enableAnimatedMfm: "정신사나운 MFM 키기"
+doing: "잠만예"
+category: "카테고리"
+tags: "태그"
+docSource: "요 문서의 원본"
+createAccount: "게정 맨걸기"
+existingAccount: "원래 게정"
+regenerate: "엎고 다시 맨걸기"
+fontSize: "글자 크기"
+mediaListWithOneImageAppearance: "사진 하나짜리 미디어 목록의 높이"
+limitTo: "{x}로 제한"
+noFollowRequests: "지둘리는 팔로우 요청이 없십니다"
+openImageInNewTab: "새 탭서 사진 열기"
+dashboard: "대시보드"
+local: "로컬"
+remote: "웬겍"
+total: "합계"
+weekOverWeekChanges: "저번주보다"
+dayOverDayChanges: "어제보다"
+appearance: "모냥"
+clientSettings: "클라이언트 설정"
+accountSettings: "게정 설정"
+promotion: "선전"
+promote: "선전하기"
+numberOfDays: "며칠동안"
+hideThisNote: "요 노트를 수ᇚ후기"
+showFeaturedNotesInTimeline: "타임라인에다 추천 노트 보이기"
+objectStorage: "오브젝트 스토리지"
+useObjectStorage: "오브젝트 스토리지 키기"
+objectStorageBaseUrl: "Base URL"
+objectStorageBaseUrlDesc: "오브젝트 (미디어) 참조 링크 만들 때 쓰는 URL임다. CDN 내지 프락시를 쓴다 카멘은 그 URL을 갖다 늫고, 아이면 써먹을 서비스네 가이드를 봐봐가 공개적으로 접근할 수 있는 주소를 여 넣어 주이소. 그니께, 내가 AWS S3을 쓴다 카면은 'https://.s3.amazonaws.com', GCS를 쓴다 카면 'https://storage.googleapis.com/' 처럼 쓰믄 되입니더."
+objectStorageBucket: "Bucket"
+objectStorageBucketDesc: "써먹을 서비스의 바께쓰 이름을 여 써 주이소."
+objectStoragePrefix: "Prefix"
+objectStoragePrefixDesc: "요 Prefix 디렉토리 안에다가 파일이 들어감다."
+objectStorageEndpoint: "Endpoint"
+objectStorageEndpointDesc: "AWS S3을 쓸라멘 요는 비워두고, 아이멘은 그 서비스 가이드에 맞게 endpoint를 넣어 주이소. '' 내지 ':'처럼 넣십니다."
+objectStorageRegion: "Region"
+objectStorageRegionDesc: "'xx-east-1' 같은 region 이름을 옇어 주이소. 만약에 내 서비스엔 region 같은 개념이 읎다, 카면은 대신에 'us-east-1'라고 해 두이소. AWS 설정 파일이나 환경 변수를 끌어다 쓰겠다믄 요는 비워 두이소."
+objectStorageUseSSL: "SSL 쓰기"
+objectStorageUseSSLDesc: "API 호출할 때 HTTPS 안 쓸거면은 꺼 두이소"
+objectStorageUseProxy: "연결에 프락시 사용"
+objectStorageUseProxyDesc: "오브젝트 스토리지 API 호출에 프락시 안 쓸 거면 꺼 두이소"
+objectStorageSetPublicRead: "업로드할 때 'public-read' 설정하기"
+s3ForcePathStyleDesc: "s3ForcePathStyle을 키면, 바께쓰 이름을 URL의 호스트명 말고 경로의 일부로써 취급합니다. 셀프 호스트 Minio 같은 걸 굴릴라믄 켜놔야 될 수도 있십니다."
+serverLogs: "서버 로그"
+deleteAll: "말캉 뭉캐기"
+showFixedPostForm: "타임라인 우에 글 작성 칸 박기"
+showFixedPostFormInChannel: "채널 타임라인 우에 글 작성 칸 박기"
+withRepliesByDefaultForNewlyFollowed: "팔로우 할 때 기본적으로 답걸도 타임라인에 나오게 하기"
+newNoteRecived: "새 노트 있어예"
+sounds: "소리"
+sound: "소리"
+listen: "듣기"
+none: "없음"
+showInPage: "바닥서 보기"
+popout: "새 창 열기"
+volume: "음량"
+masterVolume: "대빵 음량"
+notUseSound: "음소거하기"
+useSoundOnlyWhenActive: "Misskey가 활성화되어 있을 때만 소리 내기"
+details: "자세히"
+chooseEmoji: "이모지 선택"
+unableToProcess: "작업 다 몬 했십니다"
+recentUsed: "최근 쓴 놈"
+install: "설치"
+uninstall: "삭제"
+installedApps: "설치된 애플리케이션"
+nothing: "뭣도 없어예"
+installedDate: "설치한 날"
+lastUsedDate: "마지막 사용"
+state: "상태"
+sort: "정렬하기"
+ascendingOrder: "작은 순"
+descendingOrder: "큰 순"
+scratchpad: "스크래치 패드"
+scratchpadDescription: "스크래치 패드는 AiScript를 끼적거리는 창입니더. Misskey랑 갖다 이리저리 상호작용하는 코드를 서가 굴리멘은 그 결과도 바로 확인할 수 있십니다."
+output: "출력"
+script: "스크립트"
+disablePagesScript: "온갖 바닥서 AiScript를 쓰지 않음"
+updateRemoteUser: "원겍 사용자 근황 알아오기"
+unsetUserAvatar: "아바타 치우기"
+unsetUserAvatarConfirm: "아바타 갖다 치울까예?"
+unsetUserBanner: "배너 치우기"
+unsetUserBannerConfirm: "배너 갖다 치울까예?"
+deleteAllFiles: "파일 말캉 뭉캐기"
+deleteAllFilesConfirm: "파일을 싸그리 다 뭉캐삐릴까예?"
+removeAllFollowing: "팔로잉 말캉 무루기"
+removeAllFollowingDescription: "{host} 서버랑 걸어놓은 모든 팔로잉을 무룹니다. 고 서버가 아예 없어지삐맀든가, 그런 경우에 하이소."
+userSuspended: "요 게정은... 얼어 있십니다."
+userSilenced: "요 게정은... 수ᇚ혀 있십니다."
+relays: "릴레이"
+addRelay: "릴레이 옇기"
+addedRelays: "옇은 릴레이"
+deletedNote: "뭉캔 걸"
+enableInfiniteScroll: "알아서 더 보기"
+useCw: "내용 수ᇚ후기"
+description: "설멩"
+describeFile: "캡션 옇기"
+author: "맨던 사람"
+manage: "간리"
+emailServer: "전자우펜 서버"
+email: "전자우펜"
+emailAddress: "전자우펜 주소"
+smtpHost: "호스트 이럼"
+smtpPort: "포트"
+smtpUser: "사용자 이럼"
+smtpPass: "비밀번호"
+display: "보기"
+create: "맨걸기"
+abuseReports: "신고하기"
+reportAbuse: "신고하기"
+reportAbuseRenote: "리노트 신고하기"
+reportAbuseOf: "{name}님얼 신고하기"
+reporter: "신고한 사람"
+reporteeOrigin: "신고덴 사람"
+reporterOrigin: "신고한 곳"
+forwardReport: "웬겍 서버에 신고 보내기"
+random: "무작이"
+system: "시스템"
+clip: "클립 맨걸기"
+createNew: "새로 맨걸기"
+notesCount: "노트 수"
+renotesCount: "리노트한 수"
+renotedCount: "리노트덴 수"
+followingCount: "팔로우 수"
+followersCount: "팔로워 수"
+noteFavoritesCount: "질겨찾기한 노트 수"
+clips: "클립 맨걸기"
+clearCache: "캐시 비우기"
+unlikeConfirm: "좋네예럴 무룹니꺼?"
+info: "정보"
+user: "사용자"
+administration: "간리"
+on: "킴"
+off: "껌"
+hide: "수ᇚ후기"
+clickToFinishEmailVerification: "[{ok}]럴 누질라서 전자우펜 정멩얼 껕내이소."
+searchByGoogle: "찾기"
+tenMinutes: "십 분"
+oneHour: "한 시간"
+oneDay: "하리"
+oneWeek: "한 주"
+oneMonth: "한 달"
+file: "파일"
+tools: "도구"
+like: "좋네예!"
+unlike: "좋네예 무루기"
+numberOfLikes: "좋네예 수"
+show: "보기"
+roles: "옉할"
+role: "옉할"
+noRole: "옉할이 없십니다"
+thisPostMayBeAnnoyingCancel: "아이예"
+likeOnly: "좋네예마"
+myClips: "내 클립"
+icon: "아바타"
+replies: "답하기"
+renotes: "리노트"
+attach: "옇기"
+surrender: "아이예"
+_initialAccountSetting:
+ startTutorial: "길라잡이 하기"
+_initialTutorial:
+ launchTutorial: "길라잡이 보기"
+ title: "길라잡이"
+ skipAreYouSure: "길라잡이럴 껕냅니까?"
+ _landing:
+ title: "길라잡이에 어서 오이소"
+ _done:
+ title: "길라잡이가 껕낫십니다!🎉"
+_achievements:
+ _types:
+ _notes1:
+ description: "첫 노트럴 섯어예"
+ _notes10:
+ description: "노트럴 10번 섰어예"
+ _notes100:
+ description: "노트럴 100번 섰어예"
+ _notes500:
+ description: "노트럴 500번 섰어예"
+ _notes1000:
+ description: "노트럴 1,000번 섰어예"
+ _notes5000:
+ description: "노트럴 5,000번 섰어예"
+ _notes10000:
+ description: "노트럴 10,000번 섰어예"
+ _notes20000:
+ description: "노트럴 20,000번 섰어예"
+ _notes30000:
+ description: "노트럴 30,000번 섰어예"
+ _notes40000:
+ description: "노트럴 40,000번 섰어예"
+ _notes50000:
+ description: "노트럴 50,000번 섰어예"
+ _notes60000:
+ description: "노트럴 60,000번 섰어예"
+ _notes70000:
+ description: "노트럴 70,000번 섰어예"
+ _notes80000:
+ description: "노트럴 80,000번 섰어예"
+ _notes90000:
+ description: "노트럴 90,000번 섰어예"
+ _notes100000:
+ description: "노트럴 100,000번 섰어예"
+ _noteClipped1:
+ description: "첫 노트럴 클립햇어예"
+ _noteFavorited1:
+ description: "첫 노트럴 질겨찾기에 담앗어예"
+ _myNoteFavorited1:
+ description: "다런 사람이 내 노트럴 질겨찾기에 담앗십니다"
+ _iLoveMisskey:
+ description: "“I ❤ #Misskey”럴 섰어예"
+ _postedAt0min0sec:
+ description: "0분 0초에 노트를 섰어예"
+ _tutorialCompleted:
+ description: "길라잡이럴 껕냇십니다"
+_gallery:
+ my: "내 걸"
+ liked: "좋네예한 걸"
+ like: "좋네예!"
+ unlike: "좋네예 무루기"
+_email:
+ _follow:
+ title: "새 팔로워가 잇십니다"
+_serverDisconnectedBehavior:
+ reload: "알아서 새로곤침"
+_channel:
+ removeBanner: "배너 뭉캐기"
+ usersCount: "{n}명 참여"
+ notesCount: "노트 {n}개"
+_menuDisplay:
+ hide: "수ᇚ후기"
+_theme:
+ description: "설멩"
+ keys:
+ mention: "멘션"
+_sfx:
+ note: "새 노트"
+ notification: "알림"
+_2fa:
+ step3Title: "학인 기호럴 서기"
+ renewTOTPCancel: "뎃어예"
+_permissions:
+ "read:favorites": "질겨찾기 보기"
+ "write:favorites": "질겨찾기 곤치기"
+_widgets:
+ profile: "프로필"
+ instanceInfo: "서버 정보"
+ notifications: "알림"
+ timeline: "타임라인"
+ activity: "할동"
+ federation: "옌합"
+ jobQueue: "작업 대기옐"
+ _userList:
+ chooseList: "리스트 개리기"
+_cw:
+ hide: "수ᇚ후기"
+ show: "더 볼래예"
+ chars: "걸자 {count}개"
+ files: "파일 {count}개"
+_visibility:
+ home: "덜머리"
+ followers: "팔로워"
+_profile:
+ name: "이럼"
+ username: "사용자 이럼"
+_exportOrImport:
+ favoritedNotes: "질겨찾기한 노트"
+ clips: "클립 맨걸기"
+ followingList: "팔로잉"
+ muteList: "수ᇚ후기"
+ blockingList: "차단하기"
+ userLists: "리스트"
+_charts:
+ federation: "옌합"
+_timelines:
+ home: "덜머리"
+_play:
+ my: "내 플레이"
+ script: "스크립트"
+ summary: "설멩"
+_pages:
+ like: "좋네예"
+ unlike: "좋네예 무루기"
+ my: "내 페이지"
+ blocks:
+ image: "이미지"
+ _note:
+ id: "노트 아이디"
+_notification:
+ youWereFollowed: "새 팔로워가 잇십니다"
+ newNote: "새 걸"
+ _types:
+ follow: "팔로잉"
+ mention: "멘션"
+ quote: "따오기"
+ reaction: "반엉"
+ _actions:
+ reply: "답하기"
+_deck:
+ _columns:
+ notifications: "알림"
+ tl: "타임라인"
+ antenna: "안테나"
+ list: "리스트"
+ mentions: "받언 멘션"
+_webhookSettings:
+ name: "이럼"
+_moderationLogTypes:
+ suspend: "얼우기"
+ deleteNote: "노트 뭉캐기"
+ deleteUserAnnouncement: "사용자 공지 걸 뭉캐기"
+ resetPassword: "비밀번호 재설정"
+ resolveAbuseReport: "신고 해겔하기"
+_reversi:
+ total: "합계"
+
diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml
index ec346c9ec..3b186bf99 100644
--- a/locales/ko-KR.yml
+++ b/locales/ko-KR.yml
@@ -2,14 +2,14 @@
_lang_: "한국어"
headlineMisskey: "노트로 연결되는 네트워크"
introMisskey: "환영합니다! Misskey는 오픈 소스 분산형 마이크로 블로그 서비스입니다.\n'노트'를 작성해서 지금 일어나고 있는 일을 공유하거나, 당신만의 이야기를 모두에게 발신하세요📡\n'리액션' 기능으로 친구의 노트에 총알같이 반응을 추가할 수도 있습니다👍\n새로운 세계를 탐험해 보세요🚀"
-poweredByMisskeyDescription: "{name}은(는) 오픈소스 플랫폼Misskey를 사용한 서비스(Misskey 인스턴스라고 불립니다) 중 하나입니다."
+poweredByMisskeyDescription: "{name} 서버는 오픈소스 플랫폼 Misskey의 서버 가운데 하나입니다."
monthAndDay: "{month}월 {day}일"
search: "검색"
notifications: "알림"
username: "유저명"
password: "비밀번호"
forgotPassword: "비밀번호 재설정"
-fetchingAsApObject: "연합에 조회 중"
+fetchingAsApObject: "연합에서 찾아보는 중"
ok: "확인"
gotIt: "알겠어요"
cancel: "취소"
@@ -45,7 +45,7 @@ pin: "프로필에 고정"
unpin: "프로필에서 고정 해제"
copyContent: "내용 복사"
copyLink: "링크 복사"
-copyLinkRenote: "Renote 링크 복사"
+copyLinkRenote: "리노트 링크 복사"
delete: "삭제"
deleteAndEdit: "삭제 후 편집"
deleteAndEditConfirm: "이 노트를 삭제한 뒤 다시 편집하시겠습니까? 이 노트에 대한 리액션, 리노트, 답글 또한 모두 삭제됩니다."
@@ -53,8 +53,8 @@ addToList: "리스트에 추가"
addToAntenna: "안테나에 추가"
sendMessage: "메시지 보내기"
copyRSS: "RSS 복사"
-copyUsername: "유저명 복사"
-copyUserId: "유저 ID 복사"
+copyUsername: "사용자 이름 복사"
+copyUserId: "사용자 ID 복사"
copyNoteId: "노트 ID 복사"
copyFileId: "파일 ID 복사"
copyFolderId: "폴더 ID 복사"
@@ -75,7 +75,7 @@ import: "가져오기"
export: "내보내기"
files: "파일"
download: "다운로드"
-driveFileDeleteConfirm: "파일 \"{name}\" 을 삭제하시겠습니까? 이 파일이 첨부된 노트도 함께 삭제됩니다."
+driveFileDeleteConfirm: "‘{name}’ 파일을 삭제하시겠습니까? 이 파일을 사용하는 일부 콘텐츠도 삭제됩니다."
unfollowConfirm: "{name}님을 언팔로우하시겠습니까?"
exportRequested: "내보내기를 요청하였습니다. 이 작업은 시간이 걸릴 수 있습니다. 내보내기가 완료되면 \"드라이브\"에 추가됩니다."
importRequested: "가져오기를 요청하였습니다. 이 작업에는 시간이 걸릴 수 있습니다."
@@ -85,7 +85,7 @@ note: "노트"
notes: "노트"
following: "팔로잉"
followers: "팔로워"
-followsYou: "당신을 팔로우합니다"
+followsYou: "나를 팔로우 합니다"
createList: "리스트 만들기"
manageLists: "리스트 관리"
error: "오류"
@@ -114,23 +114,29 @@ quote: "인용"
inChannelRenote: "채널 내 리노트"
inChannelQuote: "채널 내 인용"
pinnedNote: "고정된 노트"
-pinned: "프로필에 고정"
-you: "당신"
+pinned: "고정하기"
+you: "나"
clickToShow: "클릭하여 보기"
sensitive: "열람 주의"
add: "추가"
reaction: "리액션"
reactions: "리액션"
-reactionSetting: "선택기에 표시할 리액션"
+emojiPicker: "이모지 선택기"
+pinnedEmojisForReactionSettingDescription: "리액션을 할 때 프로필에 고정하여 표시할 이모지를 설정할 수 있습니다"
+pinnedEmojisSettingDescription: "이모지를 입력할 때 프로필에 고정하여 표시할 이모지를 설정할 수 있습니다"
+emojiPickerDisplay: "선택기 표시"
+overwriteFromPinnedEmojisForReaction: "리액션 설정을 덮어쓰기"
+overwriteFromPinnedEmojis: "일반 설정을 덮어쓰기"
reactionSettingDescription2: "끌어서 순서 변경, 클릭해서 삭제, +를 눌러서 추가할 수 있습니다."
rememberNoteVisibility: "공개 범위를 기억하기"
attachCancel: "첨부 취소"
+deleteFile: "파일 삭제"
markAsSensitive: "열람주의로 설정"
unmarkAsSensitive: "열람주의 해제"
enterFileName: "파일명을 입력"
mute: "뮤트"
unmute: "뮤트 해제"
-renoteMute: "리노트를 뮤트"
+renoteMute: "리노트 뮤트하기"
renoteUnmute: "리노트 뮤트 해제"
block: "차단"
unblock: "차단 해제"
@@ -196,6 +202,7 @@ perDay: "1일마다"
stopActivityDelivery: "액티비티 보내지 않기"
blockThisInstance: "이 서버를 차단"
silenceThisInstance: "서버를 사일런스"
+sensitiveMediaThisInstance: "이 서버의 미디어를 모두 민감한 미디어로 표시"
operations: "작업"
software: "소프트웨어"
version: "버전"
@@ -217,6 +224,8 @@ blockedInstances: "차단된 서버"
blockedInstancesDescription: "차단하려는 서버의 호스트 이름을 줄바꿈으로 구분하여 설정합니다. 차단된 인스턴스는 이 인스턴스와 통신할 수 없게 됩니다."
silencedInstances: "사일런스한 서버"
silencedInstancesDescription: "사일런스하려는 서버의 호스트명을 한 줄에 하나씩 입력합니다. 사일런스된 서버에 소속된 유저는 모두 '사일런스'된 상태로 취급되며, 이 서버로부터의 팔로우가 프로필 설정과 무관하게 승인제로 변경되고, 팔로워가 아닌 로컬 유저에게는 멘션할 수 없게 됩니다. 정지된 서버에는 적용되지 않습니다."
+sensitiveMediaInstances: "민감한 미디어를 포함한 서버"
+sensitiveMediaInstancesDescription: "민감한 미디어를 포함한 서버의 호스트명을 한 줄에 하나씩 입력합니다. 이 서버에 소속된 유저가 업로드한 미디어는 모두 민감한 미디어로 표시됩니다."
muteAndBlock: "뮤트 및 차단"
mutedUsers: "뮤트한 유저"
blockedUsers: "차단한 유저"
@@ -247,13 +256,13 @@ security: "보안"
retypedNotMatch: "입력이 일치하지 않습니다."
currentPassword: "현재 비밀번호"
newPassword: "새 비밀번호"
-newPasswordRetype: "새 비밀번호 (재입력)"
+newPasswordRetype: "새 비밀번호(재입력)"
attachFile: "파일 첨부"
-more: "더보기"
-featured: "하이라이트"
+more: "더 보기!"
+featured: "유행"
usernameOrUserId: "유저명이나 ID"
noSuchUser: "유저를 찾을 수 없습니다"
-lookup: "조회"
+lookup: "찾아보기"
announcements: "공지사항"
imageUrl: "이미지 URL"
remove: "삭제"
@@ -261,6 +270,7 @@ removed: "삭제하였습니다"
removeAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
deleteAreYouSure: "\"{x}\" 을(를) 삭제하시겠습니까?"
resetAreYouSure: "초기화 하시겠습니까?"
+areYouSure: "계속 진행하시겠습니까?"
saved: "저장하였습니다"
messaging: "대화"
upload: "업로드"
@@ -272,7 +282,7 @@ uploadFromUrl: "URL 업로드"
uploadFromUrlDescription: "업로드하려는 파일의 URL"
uploadFromUrlRequested: "업로드를 요청했습니다"
uploadFromUrlMayTakeTime: "업로드가 완료될 때까지 시간이 소요될 수 있습니다."
-explore: "발견하기"
+explore: "둘러보기"
messageRead: "읽음"
noMoreHistory: "이것보다 과거의 기록이 없습니다"
startMessaging: "대화 시작하기"
@@ -307,10 +317,11 @@ selectFiles: "파일 선택"
selectFolder: "폴더 선택"
selectFolders: "폴더 선택"
renameFile: "파일 이름 변경"
-folderName: "폴더명"
+folderName: "폴더 이름"
createFolder: "폴더 만들기"
renameFolder: "폴더 이름 바꾸기"
deleteFolder: "폴더 삭제"
+folder: "폴더"
addFile: "파일 추가"
emptyDrive: "드라이브가 비어 있습니다"
emptyFolder: "폴더가 비어 있습니다"
@@ -330,10 +341,10 @@ disconnectedFromServer: "서버와의 연결이 끊어졌습니다"
reload: "새로고침"
doNothing: "무시하기"
reloadConfirm: "새로고침 하시겠습니까?"
-watch: "지켜보기"
-unwatch: "지켜보기 해제"
-accept: "허가"
-reject: "거부"
+watch: "관심 갖기"
+unwatch: "관심 해제하기"
+accept: "수락하기"
+reject: "거절하기"
normal: "일반"
instanceName: "서버 이름"
instanceDescription: "서버 소개"
@@ -341,7 +352,7 @@ maintainerName: "관리자 이름"
maintainerEmail: "관리자 이메일"
tosUrl: "이용약관 URL"
thisYear: "올해"
-thisMonth: "이번 달"
+thisMonth: "이달"
today: "오늘"
dayX: "{day}일"
monthX: "{month}월"
@@ -368,10 +379,17 @@ pinnedPages: "고정한 페이지"
pinnedPagesDescription: "서버의 대문에 고정하고 싶은 페이지의 경로를 한 줄에 하나씩 적습니다."
pinnedClipId: "고정할 클립의 ID"
pinnedNotes: "고정된 노트"
+featuredGameChannels: "Misskey Games에 고정할 채널"
+featuredGameChannelsDescription: "Misskey Games에 고정할 채널을 한 줄에 하나씩 적습니다."
hcaptcha: "hCaptcha"
enableHcaptcha: "hCaptcha 활성화"
hcaptchaSiteKey: "사이트 키"
hcaptchaSecretKey: "시크릿 키"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "mCaptcha 활성화"
+mcaptchaSiteKey: "사이트 키"
+mcaptchaSecretKey: "시크릿 키"
+mcaptchaInstanceUrl: "mCaptcha 인스턴스 URL"
recaptcha: "reCAPTCHA"
enableRecaptcha: "reCAPTCHA 활성화"
recaptchaSiteKey: "사이트 키"
@@ -385,8 +403,8 @@ antennas: "안테나"
manageAntennas: "안테나 관리"
name: "이름"
antennaSource: "받을 소스"
-antennaKeywords: "받을 키워드"
-antennaExcludeKeywords: "제외할 키워드"
+antennaKeywords: "받을 검색어"
+antennaExcludeKeywords: "제외할 검색어"
antennaKeywordsDescription: "공백으로 구분하는 경우 AND, 줄바꿈으로 구분하는 경우 OR로 지정됩니다"
notifyAntenna: "새로운 노트를 알림"
withFileAntenna: "파일이 첨부된 노트만"
@@ -418,9 +436,9 @@ setupOf2fa: "2단계 인증 설정"
totp: "인증 앱"
totpDescription: "인증 앱을 사용하여 일회성 비밀번호 입력"
moderator: "모더레이터"
-moderation: "모더레이션"
-moderationNote: "모더레이션 노트"
-addModerationNote: "모더레이션 노트 추가하기"
+moderation: "조정"
+moderationNote: "조정 기록"
+addModerationNote: "조정 기록 추가하기"
moderationLogs: "모더레이션 로그"
nUsersMentioned: "{n}명이 언급함"
securityKeyAndPasskey: "보안 키 또는 패스 키"
@@ -437,7 +455,6 @@ share: "공유"
notFound: "찾을 수 없습니다"
notFoundDescription: "지정한 URL에 해당하는 페이지가 존재하지 않습니다."
uploadFolder: "기본 업로드 위치"
-cacheClear: "캐시 지우기"
markAsReadAllNotifications: "모든 알림을 읽은 상태로 표시"
markAsReadAllUnreadNotes: "모든 글을 읽은 상태로 표시"
markAsReadAllTalkMessages: "모든 대화를 읽은 상태로 표시"
@@ -479,9 +496,12 @@ language: "언어"
uiLanguage: "UI 표시 언어"
aboutX: "{x}에 대하여"
emojiStyle: "이모지 스타일"
-native: "네이티브"
+native: "기본"
disableDrawer: "드로어 메뉴를 사용하지 않기"
showNoteActionsOnlyHover: "노트 액션 버튼을 마우스를 올렸을 때에만 표시"
+showRepliesCount: "노트의 답글 수를 표시"
+showRenotesCount: "노트의 리노트 수를 표시"
+showReactionsCount: "노트의 리액션 수를 표시"
noHistory: "기록이 없습니다"
signinHistory: "로그인 기록"
enableAdvancedMfm: "고급 MFM을 활성화"
@@ -507,7 +527,7 @@ dayOverDayChanges: "어제보다"
appearance: "모양"
clientSettings: "클라이언트 설정"
accountSettings: "계정 설정"
-promotion: "프로모션"
+promotion: "홍보"
promote: "프로모션하기"
numberOfDays: "며칠동안"
hideThisNote: "이 노트를 숨기기"
@@ -544,6 +564,8 @@ showInPage: "페이지로 보기"
popout: "새 창으로 열기"
volume: "음량"
masterVolume: "마스터 볼륨"
+notUseSound: "음소거 하기"
+useSoundOnlyWhenActive: "Misskey가 활성화 되어져 있을 때만 소리 출력하기"
details: "자세히"
chooseEmoji: "이모지 선택"
unableToProcess: "작업을 완료할 수 없습니다"
@@ -564,11 +586,16 @@ output: "출력"
script: "스크립트"
disablePagesScript: "Pages 에서 AiScript 를 사용하지 않음"
updateRemoteUser: "리모트 유저 정보 갱신"
+unsetUserAvatar: "아바타 제거"
+unsetUserAvatarConfirm: "아바타를 제거할까요?"
+unsetUserBanner: "배너 제거"
+unsetUserBannerConfirm: "배너를 제거할까요?"
deleteAllFiles: "모든 파일 삭제"
deleteAllFilesConfirm: "모든 파일을 삭제하시겠습니까?"
removeAllFollowing: "모든 팔로잉 해제"
-removeAllFollowingDescription: "{host}(으)로부터 모든 팔로잉을 해제합니다. 해당 서버가 더 이상 존재하지 않게 된 경우 등에 실행해 주세요."
+removeAllFollowingDescription: "{host} 서버의 모든 팔로잉을 해제합니다. 해당 서버가 더 이상 존재하지 않는 경우 등에 실행해 주세요."
userSuspended: "이 계정은 정지된 상태입니다."
+userLimited: "이 계정은 제한된 상태입니다."
userSilenced: "이 계정은 사일런스된 상태입니다."
yourAccountSuspendedTitle: "계정이 정지되었습니다"
yourAccountSuspendedDescription: "이 계정은 서버의 이용 약관을 위반하거나, 기타 다른 이유로 인해 정지되었습니다. 자세한 사항은 관리자에게 문의해 주십시오. 계정을 새로 생성하지 마십시오."
@@ -587,7 +614,7 @@ addedRelays: "추가된 릴레이"
serviceworkerInfo: "푸시 알림을 수행하려면 활성화해야 합니다."
deletedNote: "삭제된 노트"
invisibleNote: "비공개 노트"
-enableInfiniteScroll: "자동으로 좀 더 보기"
+enableInfiniteScroll: "자동으로 더 보기"
visibility: "공개 범위"
poll: "투표"
useCw: "내용 숨기기"
@@ -614,6 +641,7 @@ medium: "보통"
small: "작게"
generateAccessToken: "액세스 토큰 생성"
permission: "권한"
+adminPermission: "관리자 권한"
enableAll: "전체 선택"
disableAll: "전체 해제"
tokenRequested: "계정 접근 허용"
@@ -628,13 +656,14 @@ emailAddress: "메일 주소"
smtpConfig: "SMTP 서버 설정"
smtpHost: "호스트"
smtpPort: "포트"
-smtpUser: "유저명"
+smtpUser: "사용자 이름"
smtpPass: "비밀번호"
emptyToDisableSmtpAuth: "SMTP 인증을 사용하지 않으려면 공란으로 비워둡니다."
smtpSecure: "SMTP 연결에 Implicit SSL/TTS 사용"
smtpSecureInfo: "STARTTLS 사용 시에는 해제합니다."
testEmail: "이메일 전송 테스트"
wordMute: "단어 뮤트"
+hardWordMute: "하드 단어 뮤트"
regexpError: "정규 표현식 오류"
regexpErrorDescription: "{tab}단어 뮤트 {line}행의 정규 표현식에 오류가 발생했습니다:"
instanceMute: "서버 뮤트"
@@ -656,13 +685,14 @@ useGlobalSettingDesc: "활성화하면 계정의 알림 설정이 적용됩니
other: "기타"
regenerateLoginToken: "로그인 토큰을 재생성"
regenerateLoginTokenDescription: "로그인할 때 사용되는 내부 토큰을 재생성합니다. 일반적으로 이 작업을 실행할 필요는 없습니다. 이 기능을 사용하면 이 계정으로 로그인한 모든 기기에서 로그아웃됩니다."
+theKeywordWhenSearchingForCustomEmoji: "맞춤 이모티콘을 검색할 때 키워드가 됩니다."
setMultipleBySeparatingWithSpace: "공백으로 구분하여 여러 개 설정할 수 있습니다."
fileIdOrUrl: "파일 ID 또는 URL"
behavior: "동작"
sample: "예시"
abuseReports: "신고"
reportAbuse: "신고"
-reportAbuseRenote: "Renote를 신고"
+reportAbuseRenote: "리노트 신고하기"
reportAbuseOf: "{name}을 신고하기"
fillAbuseReportDescription: "신고하려는 이유를 자세히 알려주세요. 특정 게시물을 신고할 때에는 게시물의 URL도 포함해 주세요."
abuseReported: "신고를 보냈습니다. 신고해 주셔서 감사합니다."
@@ -679,7 +709,7 @@ defaultNavigationBehaviour: "기본 탐색 동작"
editTheseSettingsMayBreakAccount: "이 설정을 변경하면 계정이 손상될 수 있습니다."
instanceTicker: "노트의 서버 정보"
waitingFor: "{x}을(를) 기다리고 있습니다"
-random: "랜덤"
+random: "무작위"
system: "시스템"
switchUi: "UI 전환"
desktop: "데스크탑"
@@ -696,9 +726,9 @@ manageAccessTokens: "액세스 토큰 관리"
accountInfo: "계정 정보"
notesCount: "노트 수"
repliesCount: "답글 수"
-renotesCount: "Renote 수"
+renotesCount: "리노트 수"
repliedCount: "받은 답글 수"
-renotedCount: "받은 Renote 수"
+renotedCount: "받은 리노트 수"
followingCount: "팔로우 수"
followersCount: "팔로워 수"
sentReactionsCount: "보낸 리액션 수"
@@ -804,7 +834,7 @@ switchAccount: "계정 바꾸기"
enabled: "활성화"
disabled: "비활성화"
quickAction: "빠른 동작"
-user: "유저"
+user: "사용자"
administration: "관리"
accounts: "계정"
switch: "전환"
@@ -831,7 +861,7 @@ previewNoteText: "본문 미리보기"
customCss: "CSS 사용자화"
customCssWarn: "이 설정은 기능을 알고 있는 경우에만 사용해야 합니다. 잘못된 값을 입력하면 클라이언트가 정상적으로 작동하지 않을 수 있습니다."
global: "글로벌"
-squareAvatars: "프로필 아이콘을 사각형으로 표시"
+squareAvatars: "프로필 아바타를 사각형으로 표시"
sent: "전송"
received: "수신"
searchResult: "검색 결과"
@@ -850,8 +880,8 @@ devMode: "개발자 모드"
keepCw: "CW 유지하기"
pubSub: "Pub/Sub 계정"
lastCommunication: "마지막 통신"
-resolved: "해결됨"
-unresolved: "해결되지 않음"
+resolved: "처리함"
+unresolved: "처리되지 않음"
breakFollow: "팔로워 해제"
breakFollowConfirm: "팔로우를 해제하시겠습니까?"
itsOn: "켜져 있습니다"
@@ -866,11 +896,11 @@ manageAccounts: "계정 관리"
makeReactionsPublic: "리액션 목록을 공개하기"
makeReactionsPublicDescription: "나의 리액션을 누구나 볼 수 있게 합니다."
classic: "클래식"
-muteThread: "이 글타래를 뮤트"
+muteThread: "글타래 뮤트"
unmuteThread: "글타래 뮤트 해제"
-ffVisibility: "내 인맥의 공개 범위"
-ffVisibilityDescription: "나의 팔로우와 팔로워 정보에 대한 공개 범위를 설정할 수 있습니다."
-continueThread: "이 글타래 이어서 보기"
+followingVisibility: "팔로우의 공개 범위"
+followersVisibility: "팔로워의 공개 범위"
+continueThread: "글타래 더 보기"
deleteAccountConfirm: "계정이 삭제되고 되돌릴 수 없게 됩니다. 계속하시겠습니까? "
incorrectPassword: "비밀번호가 올바르지 않습니다."
voteConfirm: "\"{choice}\"에 투표하시겠습니까?"
@@ -969,7 +999,8 @@ show: "표시"
neverShow: "다시 보지 않기"
remindMeLater: "나중에 알림"
didYouLikeMisskey: "Misskey가 마음에 드시나요?"
-pleaseDonate: "{host}은(는) 무료 소프트웨어 Misskey를 사용합니다. 후원을 통해 저희의 개발이 이어질 수 있게 도와주세요!"
+pleaseDonate: "Misskey는 {host} 서버의 무료 소프트웨어입니다. 앞으로도 개발을 이어 나가려면 후원이 절실히 필요합니다!"
+correspondingSourceIsAvailable: "소스 코드는 {anchor}에서 받아보실 수 있습니다."
roles: "역할"
role: "역할"
noRole: "역할이 없습니다"
@@ -1001,7 +1032,7 @@ internalServerError: "내부 서버 오류"
internalServerErrorDescription: "내부 서버에서 예기치 않은 오류가 발생했습니다."
copyErrorInfo: "오류 정보 복사"
joinThisServer: "이 서버에 가입"
-exploreOtherServers: "다른 서버 둘러보기"
+exploreOtherServers: "다른 서버 찾기"
letsLookAtTimeline: "타임라인 구경하기"
disableFederationConfirm: "정말로 연합을 끄시겠습니까?"
disableFederationConfirmWarn: "연합을 끄더라도 게시물이 비공개로 전환되는 것은 아닙니다. 대부분의 경우 연합을 비활성화할 필요가 없습니다."
@@ -1014,14 +1045,20 @@ reactionAcceptance: "리액션 수신"
likeOnly: "좋아요만 받기"
likeOnlyForRemote: "리모트에서는 좋아요만 받기"
nonSensitiveOnly: "민감한 이모지를 제외하고 받기"
-nonSensitiveOnlyForLocalLikeOnlyForRemote: "민감한 이모지를 제외하고 받기 (리모트에서는 좋아요만 받기)"
+nonSensitiveOnlyForLocalLikeOnlyForRemote: "민감한 이모지를 제외하고 받기(리모트에서는 좋아요만 받기)"
rolesAssignedToMe: "나에게 할당된 역할"
resetPasswordConfirm: "비밀번호를 재설정하시겠습니까?"
sensitiveWords: "민감한 단어"
sensitiveWordsDescription: "설정한 단어가 포함된 노트의 공개 범위를 '홈'으로 강제합니다. 개행으로 구분하여 여러 개를 지정할 수 있습니다."
sensitiveWordsDescription2: "공백으로 구분하면 AND 지정이 되며, 키워드를 슬래시로 둘러싸면 정규 표현식이 됩니다."
+prohibitedWords: "금지된 단어"
+prohibitedWordsDescription: "설정한 단어가 포함된 노트는 게시할 수 없게 됩니다. 개행으로 구분하여 여러 개를 지정할 수 있습니다."
+prohibitedWordsDescription2: "공백으로 구분하면 AND 지정이 되며, 키워드를 슬래시로 둘러싸면 정규 표현식이 됩니다."
+hiddenTags: "숨긴 해시태그"
+hiddenTagsDescription: "설정한 태그를 트렌드에 표시하지 않도록 합니다. 줄 바꿈으로 하나씩 나눠서 설정할 수 있습니다."
notesSearchNotAvailable: "노트 검색을 이용하실 수 없습니다."
license: "라이선스"
+request: "요청"
unfavoriteConfirm: "즐겨찾기를 해제하시겠습니까?"
myClips: "내 클립"
drivecleaner: "드라이브 정리"
@@ -1032,9 +1069,12 @@ enableChartsForRemoteUser: "리모트 유저의 차트를 생성"
enableChartsForFederatedInstances: "리모트 서버의 차트를 생성"
showClipButtonInNoteFooter: "노트 동작에 클립을 추가"
reactionsDisplaySize: "리액션 표시 크기"
+limitWidthOfReaction: "리액션의 최대 폭을 제한하고 작게 표시하기"
noteIdOrUrl: "노트 ID 및 URL"
video: "동영상"
videos: "동영상"
+audio: "소리"
+audioFiles: "소리"
dataSaver: "데이터 절약 모드"
accountMigration: "계정 이동"
accountMoved: "이 사용자는 다음 계정으로 이사했습니다:"
@@ -1044,7 +1084,7 @@ forceShowAds: "광고를 항상 표시"
addMemo: "메모 추가"
editMemo: "메모 편집"
reactionsList: "리액션 목록"
-renotesList: "Renote 목록"
+renotesList: "리노트 목록"
notificationDisplay: "알림 표시"
leftTop: "왼쪽 상단"
rightTop: "오른쪽 상단"
@@ -1109,7 +1149,7 @@ beSureToReadThisAsItIsImportant: "중요하므로 반드시 읽어주십시오."
iHaveReadXCarefullyAndAgree: "\"{x}\"의 내용을 읽고 동의합니다."
dialog: "다이얼로그"
icon: "아바타"
-forYou: "당신에게"
+forYou: "나에게"
currentAnnouncements: "현재 공지사항"
pastAnnouncements: "과거 공지사항"
youHaveUnreadAnnouncements: "읽지 않은 공지사항이 있습니다."
@@ -1135,21 +1175,31 @@ showRepliesToOthersInTimeline: "타임라인에 다른 사람에게 보내는
hideRepliesToOthersInTimeline: "타임라인에 다른 사람에게 보내는 답글을 포함하지 않음"
showRepliesToOthersInTimelineAll: "타임라인에 현재 팔로우 중인 사람 전원의 답글을 포함하게 하기"
hideRepliesToOthersInTimelineAll: "타임라인에 현재 팔로우 중인 사람 전원의 답글이 나오지 않게 하기"
-confirmShowRepliesAll: "이 조작은 되돌릴 수 없습니다. 정말로 타임라인에 현재 팔로우 중인 사람 전원의 답글이 나오지 않게 하시겠습니까?"
+confirmShowRepliesAll: "이 조작은 되돌릴 수 없습니다. 정말로 타임라인에 현재 팔로우 중인 사람 전원의 답글이 나오게 하시겠습니까?"
confirmHideRepliesAll: "이 조작은 되돌릴 수 없습니다. 정말로 타임라인에 현재 팔로우 중인 사람 전원의 답글이 나오지 않게 하시겠습니까?"
externalServices: "외부 서비스"
+sourceCode: "소스 코드"
+sourceCodeIsNotYetProvided: "소스 코드를 아직 제공하지 않습니다. 이 문제를 해결하려면 관리자에게 문의해 주세요."
+repositoryUrl: "저장소 URL"
+repositoryUrlDescription: "소스 코드를 공개한 저장소가 있는 경우, 그 URL을 적습니다. Misskey를 원본 그대로 (소스 코드를 어떤 식으로도 변경하지 않고) 쓰고 있는 경우 https://github.com/misskey-dev/misskey 라고 적습니다."
+repositoryUrlOrTarballRequired: "저장소를 공개하지 않은 경우 대신 tarball을 제공할 필요가 있습니다. 세부사항은 .config/example.yml을 참조해 주세요."
+feedback: "피드백"
+feedbackUrl: "피드백 URL"
+support: "문의하기"
+supportThisInstance: "{name} 지원하기"
impressum: "운영자 정보"
impressumUrl: "운영자 정보 URL"
impressumDescription: "독일 등의 일부 나라와 지역에서는 꼭 표시해야 합니다(Impressum)."
privacyPolicy: "개인정보 보호 정책"
privacyPolicyUrl: "개인정보 보호 정책 URL"
tosAndPrivacyPolicy: "약관 및 개인정보 보호 정책"
-avatarDecorations: "아이콘 장식"
+avatarDecorations: "아바타 장식"
attach: "붙이기"
-detach: "떼기"
+detach: "빼기"
+detachAll: "모두 빼기"
angle: "각도"
flip: "플립"
-showAvatarDecorations: "아이콘 장식을 표시"
+showAvatarDecorations: "아바타 장식 표시"
releaseToRefresh: "놓아서 새로고침"
refreshing: "새로고침 중"
pullDownToRefresh: "아래로 내려서 새로고침"
@@ -1158,6 +1208,52 @@ useGroupedNotifications: "알림을 그룹화하고 표시"
signupPendingError: "메일 주소 확인중에 문제가 발생했습니다. 링크의 유효기간이 지났을 가능성이 있습니다."
cwNotationRequired: "'내용을 숨기기'를 체크한 경우 주석을 써야 합니다."
doReaction: "리액션 추가"
+code: "문자열"
+reloadRequiredToApplySettings: "설정을 적용하려면 새로고침을 해야 합니다."
+remainingN: "나머지: {n}"
+overwriteContentConfirm: "현재 내용을 덮어쓰기 합니다. 계속 진행하시겠습니까?"
+seasonalScreenEffect: "계절에 따른 효과 보이기"
+decorate: "장식하기"
+addMfmFunction: "장식 추가하기"
+enableQuickAddMfmFunction: "상급자용 MFM 선택기 표시하기"
+bubbleGame: "버블 게임"
+sfx: "효과음"
+soundWillBePlayed: "소리가 재생됩니다"
+showReplay: "리플레이 보기"
+replay: "리플레이"
+replaying: "리플레이 중"
+ranking: "랭킹"
+lastNDays: "최근 {n}일"
+backToTitle: "타이틀로 가기"
+hemisphere: "거주 지역"
+withSensitive: "민감한 파일이 포함된 노트 보기"
+userSaysSomethingSensitive: "{name}의 민감한 파일이 포함된 게시물"
+enableHorizontalSwipe: "스와이프하여 탭 전환"
+surrender: "그만두기"
+_bubbleGame:
+ howToPlay: "설명"
+ _howToPlay:
+ section1: "위치를 조정하여 상자에 물건을 떨어뜨립니다."
+ section2: "같은 종류의 물건이 붙으면 다른 물건으로 바뀌면서 점수를 얻게 됩니다."
+ section3: "상자에서 물건이 넘치면 게임 오버입니다. 상자에서 물건이 넘치지 않도록 하면서 물건을 융합하여 높은 점수를 획득하세요!"
+abuseReportCategory: "신고 유형"
+selectCategory: "카테고리 선택"
+reportComplete: "신고 완료"
+blockThisUser: "이 사용자 차단하기"
+muteThisUser: "이 사용자 뮤트하기"
+_abuseReportCategory:
+ nsfw: "민감한 콘텐츠가 포함된 게시물"
+ spam: "스팸"
+ explicit: "폭력적이거나 공격적인 게시물"
+ phishing: "피싱 또는 사기 행위"
+ personalInfoLeak: "본인 또는 타인의 개인 정보 유출"
+ selfHarm: "자살 또는 자해와 같은 생명에 관련된 문제"
+ criticalBreach: "중대한 약관 위반"
+ otherBreach: "기타 약관 위반"
+ violationRights: "권리 침해 또는 사칭 (본인)"
+ violationRightsOther: "타인의 권리 침해"
+ notLike: "이 사람을 싫어함"
+ other: "기타"
_announcement:
forExistingUsers: "기존 유저에게만 알림"
forExistingUsersDescription: "활성화하면 이 공지사항을 게시한 시점에서 이미 가입한 유저에게만 표시합니다. 비활성화하면 게시 후에 가입한 유저에게도 표시합니다."
@@ -1198,7 +1294,7 @@ _initialTutorial:
_note:
title: "'노트'가 무엇인가요?"
description: "미스키에서는 게시물을 '노트'라고 합니다. 노트는 타임라인에 시간순으로 정렬되어 있고, 실시간으로 갱신됩니다."
- reply: "답글을 다는 것이 가능합니다. 답글에 답글을 다는 것도 가능하며 스레드처럼 대화를 계속하는 것도 가능합니다."
+ reply: "답글을 달 수 있습니다. 답글에 답글을 달 수도 있고 글타래처럼 대화를 이어갈 수도 있습니다."
renote: "그 노트를 자기 타임라인에 가져와서 공유하는 것이 가능합니다. 글을 추가해서 인용하는 것도 가능합니다."
reaction: "리액션을 다는 것이 가능합니다. 다음 페이지에서 자세한 설명을 볼 수 있습니다."
menu: "노트의 상세 정보를 표시하거나, 링크를 복사하는 등의 다양한 조작을 할 수 있습니다."
@@ -1211,7 +1307,7 @@ _initialTutorial:
reactDone: "'-' 버튼을 눌러서 리액션을 취소할 수 있습니다."
_timeline:
title: "타임라인에 대하여"
- description1: "Misskey에는 종류에 따라 여러 가지의 타임라인으로 구성되어 있습니다. (서버에 따라서는 일부 타임라인을 사용할 수 없는 경우가 있습니다)"
+ description1: "Misskey에는 종류에 따라 여러 가지의 타임라인으로 구성되어 있습니다.(서버에 따라서는 일부 타임라인을 사용할 수 없는 경우가 있습니다)"
home: "내가 팔로우 중인 계정의 노트를 볼 수 있습니다."
local: "이 서버에 있는 모든 유저의 게시물을 볼 수 있습니다."
social: "홈 타임라인과 로컬 타임라인의 게시물을 모두 볼 수 있습니다."
@@ -1266,6 +1362,8 @@ _serverSettings:
shortName: "약칭"
shortNameDescription: "서버의 정식 명칭이 긴 경우에, 대신에 표시할 수 있는 약칭이나 통칭."
fanoutTimelineDescription: "활성화하면 각종 타임라인을 가져올 때의 성능을 대폭 향상하며, 데이터베이스의 부하를 줄일 수 있습니다. 단, Redis의 메모리 사용량이 증가합니다. 서버의 메모리 용량이 작거나, 서비스가 불안정해지는 경우 비활성화할 수 있습니다."
+ fanoutTimelineDbFallback: "데이터베이스를 예비로 사용하기"
+ fanoutTimelineDbFallbackDescription: "활성화하면 타임라인의 캐시되어 있지 않은 부분에 대해 DB에 질의하여 정보를 가져옵니다. 비활성화하면 이를 실행하지 않음으로써 서버의 부하를 줄일 수 있지만, 타임라인에서 가져올 수 있는 게시물 범위가 한정됩니다."
_accountMigration:
moveFrom: "다른 계정에서 이 계정으로 이사"
moveFromSub: "다른 계정에 대한 별칭을 생성"
@@ -1285,29 +1383,29 @@ _achievements:
earnedAt: "달성 일시"
_types:
_notes1:
- title: "미스키 시작했는데요"
+ title: "미스키 계정 만들었어요"
description: "첫 노트를 작성했습니다"
- flavor: "Misskey에 오신 것을 환영합니다!"
+ flavor: "Misskey에 어서 오세요!"
_notes10:
- title: "노트 조금"
+ title: "몇 가지 노트"
description: "10개의 노트를 작성했습니다"
_notes100:
- title: "노트 많이"
+ title: "많은 노트"
description: "100개의 노트를 작성했습니다"
_notes500:
- title: "노트로 뒤덮여버렸어"
+ title: "노트 범벅"
description: "500개의 노트를 작성했습니다"
_notes1000:
- title: "노트만 산더미"
+ title: "노트가 산더미"
description: "1,000개의 노트를 작성했습니다"
_notes5000:
- title: "노트가 어디서 솟아?"
+ title: "솟아나는 노트"
description: "5,000개의 노트를 작성했습니다"
_notes10000:
title: "슈퍼 노트"
description: "10,000개의 노트를 작성했습니다"
_notes20000:
- title: "노트 더 없어?"
+ title: "노트가 필요해요"
description: "20,000개의 노트를 작성했습니다"
_notes30000:
title: "노트노트노트"
@@ -1333,27 +1431,27 @@ _achievements:
_notes100000:
title: "ALL YOUR NOTE ARE BELONG TO US"
description: "100,000개의 노트를 작성했습니다"
- flavor: "이만큼 쓸 일도 없겠지만... 다른 할 일이 있진 않으신가요?"
+ flavor: "이렇게나 쓸 게 있어요?"
_login3:
- title: "비기너 I"
- description: "총 3일간 로그인했습니다"
- flavor: "오늘부터 여러분도 미스키스트에요!"
+ title: "초보자 I"
+ description: "총 로그인한 날이 3일"
+ flavor: "오늘부터 여러분도 미스키스트랍니다"
_login7:
- title: "비기너 II"
- description: "총 7일간 로그인했습니다"
+ title: "초보자 II"
+ description: "총 로그인한 날이 7일"
flavor: "슬슬 익숙해지셨나요?"
_login15:
- title: "비기너 III"
- description: "총 15일간 로그인했습니다"
+ title: "초보자 III"
+ description: "총 로그인한 날이 15일"
_login30:
title: "미스키스트 I"
- description: "총 30일간 로그인했습니다"
+ description: "총 로그인한 날이 30일"
_login60:
title: "미스키스트 II"
- description: "총 60일간 로그인했습니다"
+ description: "총 로그인한 날이 60일"
_login100:
title: "미스키스트 III"
- description: "총 100일간 로그인했습니다"
+ description: "총 로그인한 날이 100일"
flavor: "그 유저, 미스키스트이다"
_login200:
title: "단골 I"
@@ -1450,7 +1548,7 @@ _achievements:
title: "보물찾기"
description: "숨겨진 보물을 발견했습니다"
_client30min:
- title: "잠깐 쉬어"
+ title: "잠시 쉬어요"
description: "클라이언트를 시작하고 30분이 경과하였습니다"
_client60min:
title: "No \"Miss\" in Misskey"
@@ -1488,8 +1586,8 @@ _achievements:
title: "읽고 답하긴 하시는 건가요?"
description: "100자가 넘는 노트가 작성되고 3초 안에 반응했습니다"
_clickedClickHere:
- title: "여길 눌러보세요"
- description: "여길을 눌러봤습니다"
+ title: "여기를 누르세요"
+ description: "여기를 눌렀습니다"
_justPlainLucky:
title: "그냥 운이 좋았어"
description: "매 10초마다 0.01%의 확률로 달성됩니다"
@@ -1526,17 +1624,26 @@ _achievements:
_tutorialCompleted:
title: "Misskey 입문자 과정 수료증"
description: "튜토리얼을 완료했습니다"
+ _bubbleGameExplodingHead:
+ title: "🤯"
+ description: "버블 게임에서 가장 큰 물건을 내놓았다"
+ _bubbleGameDoubleExplodingHead:
+ title: "더블 🤯"
+ description: "버블게임에서 가장 큰 물건 2개를 동시에 내놓았다."
+ flavor: "이 정도만 도시락통에 🤯 🤯 조금만 더"
_role:
new: "새 역할 생성"
edit: "역할 수정"
name: "역할 이름"
description: "역할 설명"
permission: "역할 권한"
- descriptionOfPermission: "모더레이터는 기본적인 중재와 관련된 작업을 수행할 수 있습니다.\n관리자는 서버의 모든 설정을 변경할 수 있습니다."
+ descriptionOfPermission: "조정자는 기본적인 조정 작업을 진행할 수 있습니다.\n관리자는 서버의 모든 설정을 변경할 수 있습니다."
assignTarget: "할당 대상"
descriptionOfAssignTarget: "수동을 선택하면 누가 이 역할에 포함되는지를 수동으로 관리할 수 있습니다.\n조건부를 선택하면 조건을 설정해 일치하는 사용자를 자동으로 포함되게 할 수 있습니다."
manual: "수동"
+ manualRoles: "수동 역할"
conditional: "조건부"
+ conditionalRoles: "조건부 역할"
condition: "조건"
isConditionalRole: "조건부 역할입니다."
isPublic: "역할 공개"
@@ -1564,6 +1671,12 @@ _role:
gtlAvailable: "글로벌 타임라인 보이기"
ltlAvailable: "로컬 타임라인 보이기"
canPublicNote: "공개 노트 허용"
+ canCreateContent: "컨텐츠 생성 허용"
+ canUpdateContent: "컨텐츠 수정 허용"
+ canDeleteContent: "컨텐츠 삭제 허용"
+ canPurgeAccount: "완전한 계정 삭제 허용"
+ canUpdateAvatar: "아바타 변경 허용"
+ canUpdateBanner: "배너 변경 허용"
canInvite: "서버 초대 코드 발행"
inviteLimit: "초대 한도"
inviteLimitCycle: "초대 발급 간격"
@@ -1585,6 +1698,8 @@ _role:
canHideAds: "광고 숨기기"
canSearchNotes: "노트 검색 이용 가능 여부"
canUseTranslator: "번역 기능의 사용"
+ canUseDriveFileInSoundSettings: "사운드 설정에서 드라이브의 파일 사용 가능 여부"
+ avatarDecorationLimit: "아바타 장식의 최대 붙임 개수"
_condition:
isLocal: "로컬 사용자"
isRemote: "리모트 사용자"
@@ -1600,7 +1715,7 @@ _role:
or: "다음을 하나라도 만족"
not: "다음을 만족하지 않음"
_sensitiveMediaDetection:
- description: "기계학습을 통해 자동으로 민감한 미디어를 탐지하여, 모더레이션에 참고할 수 있도록 합니다. 서버의 부하를 약간 증가시킵니다."
+ description: "기계 학습으로 민감한 미디어를 알아서 찾아내어 조정에 참고하도록 합니다. 서버가 부하를 다소 받습니다."
sensitivity: "탐지 민감도"
sensitivityDescription: "민감도가 낮을수록 안전한 미디어가 잘못 탐지될 확률이 줄어들며, 높을수록 민감한 미디어가 탐지되지 않을 확률이 줄어듭니다."
setSensitiveFlagAutomatically: "자동으로 NSFW로 설정하기"
@@ -1613,6 +1728,7 @@ _emailUnavailable:
disposable: "임시 이메일 주소는 사용할 수 없습니다"
mx: "메일 서버가 올바르지 않습니다"
smtp: "메일 서버가 응답하지 않습니다"
+ banned: "이 메일 주소는 사용할 수 없습니다"
_ffVisibility:
public: "공개"
followers: "팔로워에게만 공개"
@@ -1681,10 +1797,12 @@ _registry:
domain: "도메인"
createKey: "키 생성"
_aboutMisskey:
- about: "Misskey는 syuilo에 의해서 2014년부터 개발되어 온 오픈소스 소프트웨어 입니다."
+ about: "Misskey는 syuilo가 2014년부터 개발한 오픈소스 소프트웨어입니다."
contributors: "주요 기여자"
allContributors: "모든 기여자"
source: "소스 코드"
+ original: "원본"
+ thisIsModifiedVersion: "{name}에서는 원본 미스키를 수정한 버전을 사용하고 있습니다."
translation: "Misskey를 번역하기"
donate: "Misskey에 기부하기"
morePatrons: "이 외에도 다른 많은 분들이 도움을 주시고 계십니다. 감사합니다🥰"
@@ -1730,7 +1848,7 @@ _instanceMute:
title: "지정한 서버의 노트를 숨깁니다."
heading: "뮤트할 서버"
_theme:
- explore: "테마 찾아보기"
+ explore: "테마 둘러보기"
install: "테마 설치"
manage: "테마 관리"
code: "테마 코드"
@@ -1796,7 +1914,7 @@ _theme:
driveFolderBg: "드라이브 폴더 배경"
wallpaperOverlay: "배경화면 오버레이"
badge: "배지"
- messageBg: "채팅 배경"
+ messageBg: "대화 배경"
accentDarken: "강조 색상 (어두움)"
accentLighten: "강조 색상 (밝음)"
fgHighlighted: "강조된 텍스트"
@@ -1806,6 +1924,14 @@ _sfx:
notification: "알림"
antenna: "안테나 수신"
channel: "채널 알림"
+ reaction: "리액션 선택"
+_soundSettings:
+ driveFile: "드라이브에 있는 오디오를 사용"
+ driveFileWarn: "드라이브에 있는 파일을 선택하세요."
+ driveFileTypeWarn: "이 파일은 지원되지 않습니다."
+ driveFileTypeWarnDescription: "오디오 파일을 선택하세요."
+ driveFileDurationWarn: "오디오가 너무 깁니다"
+ driveFileDurationWarnDescription: "긴 오디오로 설정할 경우 미스키 사용에 지장이 갈 수도 있습니다. 그래도 괜찮습니까?"
_ago:
future: "미래"
justNow: "방금 전"
@@ -1817,6 +1943,14 @@ _ago:
monthsAgo: "{n}개월 전"
yearsAgo: "{n}년 전"
invalid: "없음"
+_timeIn:
+ seconds: "{n}초 후"
+ minutes: "{n}분 후"
+ hours: "{n}시간 후"
+ days: "{n}일 후"
+ weeks: "{n}주 후"
+ months: "{n}개월 후"
+ years: "{n}년 후"
_time:
second: "초"
minute: "분"
@@ -1843,7 +1977,7 @@ _2fa:
removeKeyConfirm: "{name} 을(를) 삭제하시겠습니까?"
whyTOTPOnlyRenew: "보안 키가 등록되어 있는 경우 인증 앱을 해제할 수 없습니다."
renewTOTP: "인증 앱 재설정"
- renewTOTPConfirm: "기존에 등록되어 있던 인증 키는 사용하지 못하게 됩니다."
+ renewTOTPConfirm: "기존에 등록되어 있던 인증 키와 백업 코드는 사용하지 못하게 됩니다."
renewTOTPOk: "재설정"
renewTOTPCancel: "취소"
checkBackupCodesBeforeCloseThisWizard: "이 위자드를 닫기 전에 아래 백업 코드를 확인하십시오"
@@ -1856,9 +1990,9 @@ _permissions:
"write:account": "계정의 정보를 변경합니다"
"read:blocks": "차단 여부를 확인합니다"
"write:blocks": "차단을 하거나 해제합니다"
- "read:drive": "드라이브를 조회합니다"
+ "read:drive": "드라이브 보기"
"write:drive": "드라이브에 파일을 올리거나, 이름을 변경하거나, 삭제합니다"
- "read:favorites": "즐겨찾기를 조회합니다"
+ "read:favorites": "즐겨찾기 보기"
"write:favorites": "즐겨찾기에 추가하거나 삭제합니다"
"read:following": "팔로우 상태를 봅니다"
"write:following": "팔로우하거나 팔로우를 해제합니다"
@@ -1876,7 +2010,7 @@ _permissions:
"write:pages": "페이지를 수정합니다"
"read:page-likes": "페이지의 좋아요를 확인합니다"
"write:page-likes": "페이지에 좋아요를 추가하거나 취소합니다"
- "read:user-groups": "유저 그룹을 조회합니다"
+ "read:user-groups": "사용자 그룹 보기"
"write:user-groups": "유저 그룹을 만들거나, 초대하거나, 이름을 변경하거나, 양도하거나, 삭제합니다"
"read:channels": "채널을 보기"
"write:channels": "채널을 추가하거나 삭제합니다"
@@ -1888,9 +2022,58 @@ _permissions:
"write:flash": "Play를 조작합니다"
"read:flash-likes": "Play의 좋아요를 봅니다"
"write:flash-likes": "Play의 좋아요를 조작합니다"
+ "read:admin:abuse-user-reports": "사용자 신고 보기"
+ "write:admin:delete-account": "사용자 계정 삭제하기"
+ "write:admin:delete-all-files-of-a-user": "모든 사용자 파일 삭제하기"
+ "read:admin:index-stats": "데이터베이스 색인 정보 보기"
+ "read:admin:table-stats": "데이터베이스 테이블 정보 보기"
+ "read:admin:user-ips": "사용자 IP 주소 보기"
+ "read:admin:meta": "인스턴스 메타데이터 보기"
+ "write:admin:reset-password": "사용자 비밀번호 재설정하기"
+ "write:admin:resolve-abuse-user-report": "사용자 신고 처리하기"
+ "write:admin:send-email": "이메일 보내기"
+ "read:admin:server-info": "서버 정보 보기"
+ "read:admin:show-moderation-log": "조정 기록 보기"
+ "read:admin:show-user": "사용자 개인정보 보기"
+ "read:admin:show-users": "사용자 개인정보 보기"
+ "write:admin:suspend-user": "사용자 정지하기"
+ "write:admin:unset-user-avatar": "사용자 아바타 삭제하기"
+ "write:admin:unset-user-banner": "사용자 배너 삭제하기"
+ "write:admin:unsuspend-user": "사용자 정지 해제하기"
+ "write:admin:meta": "인스턴스 메타데이터 수정하기"
+ "write:admin:user-note": "조정 기록 수정하기"
+ "write:admin:roles": "역할 수정하기"
+ "read:admin:roles": "역할 보기"
+ "write:admin:relays": "릴레이 수정하기"
+ "read:admin:relays": "릴레이 보기"
+ "write:admin:invite-codes": "초대 코드 수정하기"
+ "read:admin:invite-codes": "초대 코드 보기"
+ "write:admin:announcements": "공지사항 수정하기"
+ "read:admin:announcements": "공지사항 보기"
+ "write:admin:avatar-decorations": "아바타 꾸미기 수정하기"
+ "read:admin:avatar-decorations": "아바타 꾸미기 보기"
+ "write:admin:federation": "연합 정보 수정하기"
+ "write:admin:account": "사용자 계정 수정하기"
+ "read:admin:account": "사용자 정보 보기"
+ "write:admin:emoji": "이모지 수정하기"
+ "read:admin:emoji": "이모지 보기"
+ "write:admin:queue": "작업 대기열 수정하기"
+ "read:admin:queue": "작업 대기열 정보 보기"
+ "write:admin:promo": "홍보 기록 수정하기"
+ "write:admin:drive": "사용자 드라이브 수정하기"
+ "read:admin:drive": "사용자 드라이브 정보 보기"
+ "read:admin:stream": "관리자용 Websocket API 사용하기"
+ "write:admin:ad": "광고 수정하기"
+ "read:admin:ad": "광고 보기"
+ "write:invite-codes": "초대 코드 만들기"
+ "read:invite-codes": "초대 코드 불러오기"
+ "write:clip-favorite": "클립의 좋아요 수정하기"
+ "read:clip-favorite": "클립의 좋아요 보기"
+ "read:federation": "연합 정보 불러오기"
+ "write:report-abuse": "위반 내용 신고하기"
_auth:
shareAccessTitle: "어플리케이션의 접근 허가"
- shareAccess: "\"{name}\" 이 계정에 접근하는 것을 허용하시겠습니까?"
+ shareAccess: "‘{name}’에서 계정에 접근하는 것을 허용하시겠습니까?"
shareAccessAsk: "이 애플리케이션이 계정에 접근하는 것을 허용하시겠습니까?"
permission: "{name}에서 다음 권한을 요청하였습니다"
permissionAsk: "이 앱은 다음의 권한을 요청합니다"
@@ -1942,6 +2125,7 @@ _widgets:
_userList:
chooseList: "리스트 선택"
clicker: "클리커"
+ birthdayFollowings: "오늘이 생일인 사용자"
_cw:
hide: "숨기기"
show: "더 보기"
@@ -1989,7 +2173,7 @@ _postForm:
b: "무슨 일이 일어나고 있나요?"
c: "무엇을 생각하고 있나요?"
d: "말하고 싶은 게 있나요?"
- e: "여기에 적어주세요"
+ e: "여기에 적어 주세요"
f: "작성해주시길 기다리고 있어요..."
_profile:
name: "이름"
@@ -2004,9 +2188,11 @@ _profile:
changeAvatar: "아바타 이미지 변경"
changeBanner: "배너 이미지 변경"
verifiedLinkDescription: "내용에 자신의 프로필로 향하는 링크가 포함된 페이지의 URL을 삽입하면 소유자 인증 마크가 표시됩니다."
+ avatarDecorationMax: "최대 {max}개까지 장식을 할 수 있습니다."
_exportOrImport:
allNotes: "모든 노트"
favoritedNotes: "즐겨찾기한 노트"
+ clips: "클립"
followingList: "팔로잉"
muteList: "뮤트"
blockingList: "차단"
@@ -2118,13 +2304,14 @@ _notification:
youGotMention: "{name}님이 멘션함"
youGotReply: "{name}님이 답글함"
youGotQuote: "{name}님이 인용함"
- youRenoted: "{name}님이 Renote"
+ youRenoted: "{name}님이 리노트했습니다"
youWereFollowed: "새로운 팔로워가 있습니다"
youReceivedFollowRequest: "새로운 팔로우 요청이 있습니다"
yourFollowRequestAccepted: "팔로우 요청이 수락되었습니다"
pollEnded: "투표 결과가 발표되었습니다"
newNote: "새 게시물"
unreadAntennaNote: "안테나 {name}"
+ roleAssigned: "역할이 부여 되었습니다."
emptyPushNotificationMessage: "푸시 알림이 갱신되었습니다"
achievementEarned: "도전 과제를 달성했습니다"
testNotification: "알림 테스트"
@@ -2132,6 +2319,7 @@ _notification:
sendTestNotification: "테스트 알림 보내기"
notificationWillBeDisplayedLikeThis: "알림이 이렇게 표시됩니다"
reactedBySomeUsers: "{n}명이 반응했습니다"
+ likedBySomeUsers: "{n}명이 좋아요했습니다"
renotedBySomeUsers: "{n}명이 리노트했습니다"
followedBySomeUsers: "{n}명에게 팔로우됨"
_types:
@@ -2146,6 +2334,7 @@ _notification:
pollEnded: "투표가 종료됨"
receiveFollowRequest: "팔로우 요청을 받았을 때"
followRequestAccepted: "팔로우 요청이 승인되었을 때"
+ roleAssigned: "역할이 부여 됨"
achievementEarned: "도전 과제 획득"
app: "연동된 앱을 통한 알림"
_actions:
@@ -2203,7 +2392,7 @@ _webhookSettings:
followed: "누군가 나를 팔로우했을 때"
note: "노트를 게시할 때"
reply: "답글을 받았을 때"
- renote: "누군가 내 글을 Renote했을 때"
+ renote: "누군가 내 글을 리노트했을 때"
reaction: "누군가 내 노트에 리액션했을 때"
mention: "누군가 나를 멘션했을 때"
_moderationLogTypes:
@@ -2218,28 +2407,31 @@ _moderationLogTypes:
updateCustomEmoji: "커스텀 이모지 수정"
deleteCustomEmoji: "커스텀 이모지 삭제"
updateServerSettings: "서버 설정 갱신"
- updateUserNote: "모더레이션 노트 갱신"
+ updateUserNote: "조정 기록 갱신"
deleteDriveFile: "파일 삭제"
deleteNote: "노트 삭제"
- createGlobalAnnouncement: "전역 공지사항 생성"
- createUserAnnouncement: "유저 공지사항 생성"
- updateGlobalAnnouncement: "전역 공지사항 수정"
- updateUserAnnouncement: "유저 공지사항 수정"
- deleteGlobalAnnouncement: "전역 공지사항 삭제"
- deleteUserAnnouncement: "유저 공지사항 삭제"
+ createGlobalAnnouncement: "모든 공지사항 만들기"
+ createUserAnnouncement: "사용자 공지사항 만들기"
+ updateGlobalAnnouncement: "모든 공지사항 수정"
+ updateUserAnnouncement: "사용자 공지사항 수정"
+ deleteGlobalAnnouncement: "모든 공지사항 삭제"
+ deleteUserAnnouncement: "사용자 공지사항 삭제"
resetPassword: "비밀번호 재설정"
suspendRemoteInstance: "리모트 서버를 정지"
unsuspendRemoteInstance: "리모트 서버의 정지를 해제"
+ updateRemoteInstanceNote: "리모트 서버의 조정 기록 갱신"
markSensitiveDriveFile: "파일에 열람주의를 설정"
unmarkSensitiveDriveFile: "파일에 열람주의를 해제"
- resolveAbuseReport: "신고 해결"
+ resolveAbuseReport: "신고 처리"
createInvitation: "초대 코드 생성"
createAd: "광고 생성"
deleteAd: "광고 삭제"
updateAd: "광고 수정"
- createAvatarDecoration: "아이콘 장식 추가"
- updateAvatarDecoration: "아이콘 장식 수정"
- deleteAvatarDecoration: "아이콘 장식 삭제"
+ createAvatarDecoration: "아바타 장식 만들기"
+ updateAvatarDecoration: "아바타 장식 수정"
+ deleteAvatarDecoration: "아바타 장식 삭제"
+ unsetUserAvatar: "유저 아바타 제거"
+ unsetUserBanner: "유저 배너 제거"
_fileViewer:
title: "파일 상세"
type: "파일 유형"
@@ -2289,3 +2481,66 @@ _externalResourceInstaller:
_themeInstallFailed:
title: "테마를 설치하지 못했습니다"
description: "테마를 설치하는 도중 문제가 발생하였습니다. 다시 한 번 시도하십시오. 자세한 사항은 브라우저에 내장된 개발자 도구의 Javascript 콘솔에서 확인하실 수 있습니다."
+_dataSaver:
+ _media:
+ title: "미디어 불러오기"
+ description: "사진이나 동영상을 자동으로 불러오지 않습니다. 숨겨 놓은 사진이나 동영상은 누르면 불러옵니다."
+ _avatar:
+ title: "아이콘 이미지"
+ description: "아이콘 이미지의 애니메이션을 멈춥니다. 애니메이션 이미지는 일반 이미지보다 파일 크기가 클 수 있으므로 데이터 사용량을 더 줄일 수 있습니다."
+ _urlPreview:
+ title: "URL 미리보기의 섬네일"
+ description: "URL 미리보기의 섬네일 이미지를 불러오지 않게 됩니다."
+ _code:
+ title: "문자열 강조"
+ description: "MFM 등으로 문자열 강조 기법을 사용할 때 누르기 전에는 불러오지 않습니다. 문자열 강조에서는 강조할 언어마다 그 정의 파일을 불러와야 하지만 이를 자동으로 불러오지 않으므로 데이터 사용량을 줄일 수 있습니다."
+_hemisphere:
+ N: "북반구"
+ S: "남반구"
+ caption: "일부 클라이언트 설정에서 계절을 판단하기 위해 사용합니다."
+_reversi:
+ reversi: "리버시"
+ gameSettings: "대국 설정"
+ chooseBoard: "보드 선택"
+ blackOrWhite: "선공/후공"
+ blackIs: "{name}님이 흑(선공)"
+ rules: "규칙"
+ thisGameIsStartedSoon: "대국이 곧 시작됩니다"
+ waitingForOther: "상대방의 준비가 완료되기를 기다리고 있습니다."
+ waitingForMe: "당신의 준비가 완료되기를 기다리고 있습니다."
+ waitingBoth: "준비하세요"
+ ready: "준비 완료"
+ cancelReady: "준비 다시 시작"
+ opponentTurn: "상대의 차례입니다"
+ myTurn: "당신의 차례입니다"
+ turnOf: "{name}의 차례입니다"
+ pastTurnOf: "{name}의 차례"
+ surrender: "기권"
+ surrendered: "기권에 의해"
+ timeout: "시간 초과"
+ drawn: "무승부"
+ won: "{name}의 승리"
+ black: "흑"
+ white: "백"
+ total: "합계"
+ turnCount: "{count}턴 째"
+ myGames: "내 대국"
+ allGames: "모두의 대국"
+ ended: "종료"
+ playing: "대국 중"
+ isLlotheo: "돌이 적은 사람이 승리 (로세오)"
+ loopedMap: "루프 지도"
+ canPutEverywhere: "어디에도 둘 수 있는 모드"
+ timeLimitForEachTurn: "1턴의 시간 제한"
+ freeMatch: "프리매치"
+ lookingForPlayer: "상대를 찾고 있습니다"
+ gameCanceled: "대국이 취소되었습니다"
+ shareToTlTheGameWhenStart: "대국 시작 시 타임라인에 대국을 게시"
+ iStartedAGame: "대국이 시작되었습니다! #MisskeyReversi"
+ opponentHasSettingsChanged: "상대방이 설정을 변경했습니다"
+ allowIrregularRules: "규칙변경 허가 (완전 자유)"
+ disallowIrregularRules: "규칙변경 없음"
+_offlineScreen:
+ title: "오프라인 - 서버에 접속할 수 없습니다"
+ header: "서버에 접속할 수 없습니다"
+
diff --git a/locales/lo-LA.yml b/locales/lo-LA.yml
index b22e047cf..6f03c914f 100644
--- a/locales/lo-LA.yml
+++ b/locales/lo-LA.yml
@@ -1,9 +1,9 @@
---
_lang_: "ພາສາລາວ"
-headlineMisskey: "ເຊື່ອມຕໍ່ເຄືອຂ່າຍໂດຍຫມາຍເຫດ"
-introMisskey: "ຍິນດີຕ້ອນຮັບ! Misskey ເປັນແຫຼ່ງເປີດ, ການບໍລິການ microblogging ກະຈາຍ\nສ້າງ \"ບັນທຶກ\" ເພື່ອແບ່ງປັນຄວາມຄິດຂອງທ່ານກັບທຸກໆຄົນທີ່ຢູ່ອ້ອມຮອບທ່ານ 📡\nດ້ວຍ \"ປະຕິກິລິຍາ\", ທ່ານຍັງສາມາດສະແດງຄວາມຮູ້ສຶກຂອງທ່ານຢ່າງໄວວາກ່ຽວກັບບັນທຶກຂອງທຸກໆຄົນ 👍\nມາສຳຫຼວດໂລກໃໝ່! 🚀"
+headlineMisskey: "ເຊື່ອມຕໍ່ເຄືອຂ່າຍໂດຍ note"
+introMisskey: "ຍິນດີຕ້ອນຮັບ! Misskey ເປັນຊອຟແວopensource, ສຳລັບບໍລິການ microblogging ແບບ decentralized\nສ້າງ “note” ເພື່ອແບ່ງປັນຄວາມຄິດຂອງທ່ານກັບທຸກໆ ຄົນທີ່ຢູ່ອ້ອມຮອບທ່ານ 📡\nຢ່າລືມ “reaction” ໂນຕຂອງລາວເພື່ອສະແດງຄວາມຮູ້ສຶກ 👍\nມາສຳຫຼວດໂລກໃໝ່ແນ! 🚀"
poweredByMisskeyDescription: "{name} ແມ່ນສ່ວນໜຶ່ງຂອງການບໍລິການທີ່ຂັບເຄື່ອນໂດຍແພລດຟອມ open source. Misskey (ເອີ້ນວ່າ \"Misskey instance\")"
-monthAndDay: "{ເດືອນ}/{ມື້}"
+monthAndDay: "ເດືອນ{month} / ວັນ{day}"
search: "ຄົ້ນຫາ"
notifications: "ການແຈ້ງເຕືອນ"
username: "ຊື່ຜູ້ໃຊ້"
@@ -15,25 +15,25 @@ gotIt: "ເຂົ້າໃຈແລ້ວ!"
cancel: "ຍົກເລີກ"
noThankYou: "ບໍ່ແມ່ນຕອນນີ້"
enterUsername: "ປ້ອນຊື່ຜູ້ໃຊ້"
-renotedBy: "Renoted ໂດຍ {ຜູ້ໃຊ້}"
-noNotes: "ບໍ່ມີຫມາຍເຫດ"
+renotedBy: "Renoted ໂດຍ {user}"
+noNotes: "ບໍ່ມີ note"
noNotifications: "ບໍ່ມີການແຈ້ງເຕືອນ"
instance: "ອີນສະແຕນ"
settings: "ກຳນົດຄ່າ"
notificationSettings: "ຕັ້ງຄ່າການແຈ້ງເຕືອນ"
basicSettings: "ການຕັ້ງຄ່າພື້ນຖານ"
otherSettings: "ການຕັ້ງຄ່າອື່ນໆ"
-openInWindow: "ເປີດຢູ່ໃນປ່ອງຢ້ຽມ"
+openInWindow: "ເປີດໃນປ່ອງຢ້ຽມ"
profile: "ໂພຼຟາຍ"
-timeline: "ເສັ້ນກຳນົດເວລາ"
+timeline: "ໄທມ໌ໄລນ໌"
noAccountDescription: "ຜູ້ໃຊ້ນີ້ຍັງບໍ່ໄດ້ຂຽນໃນຊີວະປະຫວັດຂອງເຂົາເຈົ້າເທື່ອ"
login: "ເຂົ້າສູ່ລະບົບ"
loggingIn: "ກຳລັງເຂົ້າສູ່ລະບົບ..."
logout: "ອອກຈາກລະບົບ"
signup: "ລົງທະບຽນ"
-uploading: "ການອັບໂຫຼດ..."
+uploading: "ກຳລັງອັບໂຫຼດ..."
save: "ບັນທຶກ"
-users: "ຜູ້ໃຊ້ຕ່າງໆ"
+users: "ຜູ້ໃຊ້"
addUser: "ເພີ່ມຜູ້ໃຊ້"
favorite: "ເພີ່ມໃສ່ລາຍການທີ່ມັກ"
favorites: "ລາຍການທີ່ມັກ"
@@ -41,13 +41,14 @@ unfavorite: "ລຶບອອກຈາກລາຍການທີ່ມັກ"
favorited: "ເພີ່ມໃສ່ລາຍການທີ່ມັກແລ້ວ"
alreadyFavorited: "ເພີ່ມເຂົ້າໃນລາຍການທີ່ມັກແລ້ວ."
cantFavorite: "ບໍ່ສາມາດເພີ່ມໃສ່ລາຍການທີ່ມັກໄດ້."
-pin: "ປັກໝຸດໄປຫາໂປຣໄຟລ໌"
-unpin: "ຖອດປັກໝຸດອອກຈາກໂປຣໄຟລ໌"
+pin: "ປັກໝຸດ"
+unpin: "ຖອດປັກໝຸດອອກ"
copyContent: "ຄັດລອກເນື້ອຫາ"
-copyLink: "ສຳເນົາລິ້ງ"
+copyLink: "ຄັດລອກລິ້ງ"
+copyLinkRenote: "ຄັດລອກລິ້ງຂອງ renote"
delete: "ລຶບ"
-deleteAndEdit: "ລົບແລະແກ້ໄຂ"
-deleteAndEditConfirm: "ເຈົ້າແນ່ໃຈບໍ່? ທີ່ທ່ານຕ້ອງການທີ່ຈະລຶບບັນທຶກນີ້ແລະແກ້ໄຂມັນ ທ່ານອາດຈະສູນເສຍການໂຕ້ຕອບ, ບັນທຶກ, ແລະການຕອບກັບທັງໝົດ"
+deleteAndEdit: "ລຶບແລະແກ້ໄຂ"
+deleteAndEditConfirm: "ເຈົ້າແນ່ໃຈບໍ່? ທີ່ທ່ານຕ້ອງການທີ່ຈະລຶບ note ນີ້ ແລະແກ້ໄຂມັນ ທ່ານອາດຈະສູນເສຍ reaction, renote, ແລະການຕອບກັບທັງໝົດ"
addToList: "ເພີ່ມໃສ່ລາຍຊື່"
addToAntenna: "ເພີ່ມໃສ່ເສົາອາກາດ"
sendMessage: "ສົ່ງຂໍ້ຄວາມ"
@@ -66,15 +67,15 @@ showLess: "ປິດ"
youGotNewFollower: "ໄດ້ຕິດຕາມທ່ານ"
receiveFollowRequest: "ປະຕິບັດຕາມຄໍາຮ້ອງຂໍທີ່ໄດ້ຮັບ"
followRequestAccepted: "ຜູ້ຕິດຕາມໄດ້ຍອມຮັບຄໍາຮ້ອງຂໍຂອງທ່ານ"
-mention: "ໄດ້ກ່າວມາ"
+mention: "ກ່າວຖືງ"
mentions: "ກ່າວເຖິງ"
-directNotes: "ໂດຍກົງຫມາຍເຫດ"
+directNotes: "ໂພສ Direct note"
importAndExport: "ນໍາເຂົ້າ / ສົ່ງອອກ"
import: "ນຳເຂົ້າ"
-export: "ນຳອອກ"
+export: "ສົ່ງອອກ"
files: "ໄຟລ໌"
download: "ດາວໂຫລດ"
-driveFileDeleteConfirm: "ທ່ານແນ່ໃຈບໍ່ວ່າຕ້ອງການລຶບໄຟລ໌ \"{name}\"? ບັນທຶກທີ່ມີໄຟລ໌ແນບນີ້ຈະຖືກລຶບຖິ້ມ"
+driveFileDeleteConfirm: "ທ່ານແນ່ໃຈບໍ່ວ່າຕ້ອງການລຶບໄຟລ໌ \"{name}\"? note ທີ່ມີໄຟລ໌ແນບນີ້ຈະຖືກລຶບຖິ້ມ"
unfollowConfirm: "ທ່ານແນ່ໃຈບໍ່ວ່າຕ້ອງການເຊົາຕິດຕາມ {name}?"
exportRequested: "ໃນເວລາທີ່ທ່ານໄດ້ຮ້ອງຂໍການສົ່ງອອກ ມັນອາດຈະໃຊ້ເວລາບາງເວລາ ແລະມັນຈະຖືກເພີ່ມໃສ່ drive ຂອງທ່ານເມື່ອມັນສຳເລັດແລ້ວ"
importRequested: "ໃນເວລາທີ່ທ່ານໄດ້ຮ້ອງຂໍການນໍາເຂົ້າ ມັນອາດຈະໃຊ້ເວລາບາງເວລາ"
@@ -86,7 +87,7 @@ following: "ກຳລັງຕິດຕາມ"
followers: "ຜູ້ຕິດຕາມ"
followsYou: "ຕິດຕາມເຈົ້າ"
createList: "ສ້າງລາຍຊື່"
-manageLists: "ການບໍລິຫານບັນຊີລາຍການ"
+manageLists: "ຈັດການລາຍຊື່"
error: "ຂໍ້ຜິດພາດ"
somethingHappened: "ອຸຍ, ມີບາງຢ່າງຜິດພາດ"
retry: "ລອງໃຫມ່"
@@ -96,30 +97,30 @@ serverIsDead: "ເຊີບເວີນີ້ບໍ່ຕອບສະໜອງ
youShouldUpgradeClient: "ເພື່ອເບິ່ງໜ້ານີ້, ກະລຸນາໂຫຼດຂໍ້ມູນຄືນໃໝ່ເພື່ອອັບເດດລູກຄ້າຂອງທ່ານ"
enterListName: "ໃສ່ຊື່ສຳລັບລາຍຊື່"
privacy: "ຄວາມເປັນສ່ວນຕົວ"
-makeFollowManuallyApprove: "ປະຕິບັດຕາມການຮ້ອງຂໍຮຽກຮ້ອງໃຫ້ມີການອະນຸມັດ"
-defaultNoteVisibility: "ເປັນຄ່າເລີ່ມຕົ້ນ"
+makeFollowManuallyApprove: "ຕິດຕາມຄຳຂໍທີ່ຕ້ອງໄດ້ຮັບການອະນຸມັດ"
+defaultNoteVisibility: "ການເບິ່ງເຫັນທີ່ເປັນຄ່າເລີ່ມຕົ້ນ"
follow: "ກຳລັງຕິດຕາມ"
-followRequest: "ສົ່ງການຮ້ອງຂໍປະຕິບຕາມ"
-followRequests: "ປະຕິບັດຕາມຄໍາຮ້ອງຂໍ"
+followRequest: "ສົ່ງຄຳຂໍຕິດຕາມ"
+followRequests: "ສົ່ງຄຳຂໍຕິດຕາມ"
unfollow: "ເຊົາຕິດຕາມ"
-followRequestPending: "ປະຕິບັດຕາມຄໍາຮ້ອງຂໍທີ່ລໍຖ້າຢູ່"
-enterEmoji: "ປ້ອນອີໂມຈິ"
+followRequestPending: "ລໍຖ້າການອະນຸມັດໃຫ້ຕິດຕາມ"
+enterEmoji: "ປ້ອນເອໂມຈິ"
renote: "Renote"
unrenote: "ເລີກ Renote"
-renoted: "ເກັບບັນທຶກໄວ້"
-cantRenote: "ໂພສນີ້ບໍ່ສາມາດຖືກບັນທຶກໄວ້ຄືນໃໝ່ໄດ້"
+renoted: "renote ແລ້ວ"
+cantRenote: "ໂພສນີ້ບໍ່ສາມາດ renote ໃໝ່ໄດ້"
cantReRenote: "ບໍ່ສາມາດບັນທຶກຄືນໃໝ່ໄດ້"
-quote: "ລວມຂໍ້ຄວາມອ້າງອີງ"
-inChannelRenote: "ຊ່ອງພຽງແຕ່ Renote"
-inChannelQuote: "ຊ່ອງເທົ່ານັ້ນ Quote"
-pinnedNote: "ບັນທຶກທີ່ປັກໝຸດໄວ້"
-pinned: "ປັກໝຸດໄປຫາໂປຣໄຟລ໌"
+quote: "ອ້າງອີງ"
+inChannelRenote: "Renote ໃນ channel ເທົ່ານັ້ນ"
+inChannelQuote: "ອ້າງອິງໃນ channel ເທົ່ານັ້ນ"
+pinnedNote: "note ທີ່ປັກໝຸດໄວ້"
+pinned: "ປັກໝຸດ"
you: "ເຈົ້າ"
clickToShow: "ກົດເພື່ອສະແດງໃຫ້ເຫັນ"
sensitive: "NSFW"
add: "ເພີ່ມ"
-reaction: "ປະຕິກິລິຍາ"
-reactions: "ປະຕິກິລິຍາ"
+reaction: "reaction"
+reactions: "reaction"
attachCancel: "ເອົາໄຟລ໌ແນບ"
mute: "ປີດສຽງ"
unmute: "ເປີດສຽງ"
@@ -306,6 +307,8 @@ basicInfo: "ຂໍ້ມຸນເບື້ອງຕົ້ນ"
pinnedNotes: "ບັນທຶກທີ່ປັກໝຸດໄວ້"
hcaptchaSiteKey: "ກະແຈໄຊທ໌"
hcaptchaSecretKey: "ກະແຈລັບ"
+mcaptchaSiteKey: "ກະແຈໄຊທ໌"
+mcaptchaSecretKey: "ກະແຈລັບ"
recaptcha: "reCAPTCHA"
enableRecaptcha: "ເປີດໃຊ້ງານລີແຄ໋ບຈາ"
recaptchaSiteKey: "ກະແຈໄຊທ໌"
@@ -320,7 +323,6 @@ administrator: "ຜູ້ບໍລິຫານ"
token: "ໂທເຄັນ"
share: "ແບ່ງປັນ"
notFound: "ບໍ່ພົບ"
-cacheClear: "ລຶບລ້າງແຄສ"
help: "ຊ່ວຍເຫຼືອ"
close: "ປິດ"
invites: "ເຊີນ"
@@ -464,3 +466,4 @@ _webhookSettings:
name: "ຊື່"
_moderationLogTypes:
suspend: "ລະງັບ"
+
diff --git a/locales/nl-NL.yml b/locales/nl-NL.yml
index 1c207d89c..e3ff42617 100644
--- a/locales/nl-NL.yml
+++ b/locales/nl-NL.yml
@@ -119,7 +119,6 @@ sensitive: "NSFW"
add: "Toevoegen"
reaction: "Reacties"
reactions: "Reacties"
-reactionSetting: "Reacties die in de reactie-selector worden getoond"
reactionSettingDescription2: "Sleep om opnieuw te ordenen, Klik om te verwijderen, Druk op \"+\" om toe te voegen"
rememberNoteVisibility: "Vergeet niet de notitie zichtbaarheidsinstellingen"
attachCancel: "Verwijder bijlage"
@@ -349,6 +348,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Inschakelen hCaptcha"
hcaptchaSiteKey: "Site sleutel"
hcaptchaSecretKey: "Geheime sleutel"
+mcaptchaSiteKey: "Site sleutel"
+mcaptchaSecretKey: "Geheime sleutel"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Inschakelen reCAPTCHA"
recaptchaSiteKey: "Site sleutel"
@@ -396,7 +397,6 @@ reduceUiAnimation: "Verminder beweging in de UI"
share: "Delen"
notFound: "Niet gevonden"
uploadFolder: "Standaardmap voor uploaden"
-cacheClear: "Cache verwijderen"
markAsReadAllNotifications: "Markeer alle meldingen als gelezen"
markAsReadAllUnreadNotes: "Markeer alle berichten als gelezen"
markAsReadAllTalkMessages: "Markeer alle berichten als gelezen"
@@ -497,3 +497,4 @@ _webhookSettings:
_moderationLogTypes:
suspend: "Opschorten"
resetPassword: "Wachtwoord terugzetten"
+
diff --git a/locales/no-NO.yml b/locales/no-NO.yml
index 44944f846..098faa8ad 100644
--- a/locales/no-NO.yml
+++ b/locales/no-NO.yml
@@ -102,7 +102,6 @@ clickToShow: "Klikk for å vise"
add: "Legg til"
reaction: "Reaksjon"
reactions: "Reaksjoner"
-reactionSetting: "Reaksjoner som vises i reaksjonsvelgeren"
reactionSettingDescription2: "Dra for å endre rekkefølgen, klikk for å slette, trykk \"+\" for å legge til."
rememberNoteVisibility: "Husk innstillingene for synlighet av Notes"
attachCancel: "Fjern vedlegg"
@@ -464,6 +463,7 @@ options: "Alternativ"
icon: "Avatar"
replies: "Svar"
renotes: "Renote"
+surrender: "Avbryt"
_initialAccountSetting:
theseSettingsCanEditLater: "Du kan endre disse innstillingene senere."
_achievements:
@@ -721,3 +721,4 @@ _webhookSettings:
name: "Navn"
_moderationLogTypes:
suspend: "Suspender"
+
diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml
index 1a15532c0..99eb1f302 100644
--- a/locales/pl-PL.yml
+++ b/locales/pl-PL.yml
@@ -111,7 +111,6 @@ sensitive: "NSFW"
add: "Dodaj"
reaction: "Reakcja"
reactions: "Reakcja"
-reactionSetting: "Reakcje do pokazania w wyborniku reakcji"
reactionSettingDescription2: "Przeciągnij aby zmienić kolejność, naciśnij aby usunąć, naciśnij „+” aby dodać"
rememberNoteVisibility: "Zapamiętuj ustawienia widoczności wpisu"
attachCancel: "Usuń załącznik"
@@ -346,6 +345,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Włącz hCaptcha"
hcaptchaSiteKey: "Klucz strony"
hcaptchaSecretKey: "Tajny klucz"
+mcaptchaSiteKey: "Klucz strony"
+mcaptchaSecretKey: "Tajny klucz"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Włącz reCAPTCHA"
recaptchaSiteKey: "Klucz strony"
@@ -407,7 +408,6 @@ share: "Udostępnij"
notFound: "Nie znaleziono"
notFoundDescription: "Nie ma strony odpowiadającej określonemu adresowi URL."
uploadFolder: "Domyślne położenie wysłanych"
-cacheClear: "Wyczyść pamięć podręczną"
markAsReadAllNotifications: "Oznacz wszystkie powiadomienia jako przeczytane"
markAsReadAllUnreadNotes: "Oznacz wszystkie wpisy jako przeczytane"
markAsReadAllTalkMessages: "Oznacz wszystkie wiadomości jako przeczytane"
@@ -808,8 +808,6 @@ makeReactionsPublicDescription: "To spowoduje, że lista wszystkich Twoich dotyc
classic: "Klasyczny"
muteThread: "Wycisz wątek"
unmuteThread: "Wyłącz wyciszenie wątku"
-ffVisibility: "Widoczność obserwowanych/obserwujących"
-ffVisibilityDescription: "Pozwala skonfigurować, kto może zobaczyć, kogo obserwujesz i kto Cię obserwuje."
continueThread: "Pokaż kontynuację wątku"
deleteAccountConfirm: "Spowoduje to nieodwracalne usunięcie Twojego konta. Kontynuować?"
incorrectPassword: "Nieprawidłowe hasło."
@@ -873,6 +871,7 @@ youFollowing: "Śledzeni"
icon: "Awatar"
replies: "Odpowiedz"
renotes: "Udostępnij"
+sourceCode: "Kod źródłowy"
flip: "Odwróć"
_role:
priority: "Priorytet"
@@ -1236,6 +1235,7 @@ _profile:
_exportOrImport:
allNotes: "Wszystkie wpisy"
favoritedNotes: "Ulubione wpisy"
+ clips: "Klip"
followingList: "Obserwowani"
muteList: "Wycisz"
blockingList: "Zablokuj"
@@ -1398,3 +1398,6 @@ _webhookSettings:
_moderationLogTypes:
suspend: "Zawieś"
resetPassword: "Zresetuj hasło"
+_reversi:
+ total: "Łącznie"
+
diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml
index 32740175e..f62557fb2 100644
--- a/locales/pt-PT.yml
+++ b/locales/pt-PT.yml
@@ -121,7 +121,6 @@ sensitive: "Conteúdo sensível"
add: "Adicionar"
reaction: "Reações"
reactions: "Reações"
-reactionSetting: "Quais reações exibir no seletor de reações"
reactionSettingDescription2: "Arraste para reordenar, clique para excluir, pressione + para adicionar."
rememberNoteVisibility: "Lembrar das configurações de visibilidade de notas"
attachCancel: "Remover anexo"
@@ -369,6 +368,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Ativar hCaptcha"
hcaptchaSiteKey: "Chave do sítio ‘web’"
hcaptchaSecretKey: "Chave secreta"
+mcaptchaSiteKey: "Chave do sítio ‘web’"
+mcaptchaSecretKey: "Chave secreta"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Habilitar reCAPTCHA"
recaptchaSiteKey: "Chave do sítio ‘web’"
@@ -431,7 +432,6 @@ share: "Compartilhar"
notFound: "Não encontrado"
notFoundDescription: "Não havia página correspondente ao URL especificado."
uploadFolder: "Destino de upload padrão"
-cacheClear: "Excluir memória transitória"
markAsReadAllNotifications: "Marcar todas as notificações como lidas"
markAsReadAllUnreadNotes: "Marcar todas as postagens como lidas"
markAsReadAllTalkMessages: "Marcar todas as conversas como lidas"
@@ -860,8 +860,6 @@ makeReactionsPublicDescription: "Isto vai deixar o histórico de todas as suas r
classic: "Clássico"
muteThread: "Silenciar esta conversa"
unmuteThread: "Desativar silêncio desta conversa"
-ffVisibility: "Visibilidade de Seguidos/Seguidores"
-ffVisibilityDescription: "Permite configurar quem pode ver quem lhe segue e quem você está seguindo."
continueThread: "Ver mais desta conversa"
deleteAccountConfirm: "Deseja realmente excluir a conta?"
incorrectPassword: "Senha inválida."
@@ -1012,6 +1010,8 @@ replies: "Responder"
renotes: "Repostar"
keepScreenOn: "Manter a tela do dispositivo sempre ligada"
flip: "Inversão"
+lastNDays: "Últimos {n} dias"
+surrender: "Cancelar"
_initialAccountSetting:
followUsers: "Siga usuários que lhe interessam para criar a sua linha do tempo."
_serverSettings:
@@ -1404,6 +1404,7 @@ _profile:
username: "Nome de usuário"
_exportOrImport:
favoritedNotes: "Notas nos favoritos"
+ clips: "Clipe"
followingList: "Seguindo"
muteList: "Silenciar"
blockingList: "Bloquear"
@@ -1498,3 +1499,6 @@ _webhookSettings:
_moderationLogTypes:
suspend: "Suspender"
resetPassword: "Redefinir senha"
+_reversi:
+ total: "Total"
+
diff --git a/locales/ro-RO.yml b/locales/ro-RO.yml
index 77bccb7e6..c1158e47b 100644
--- a/locales/ro-RO.yml
+++ b/locales/ro-RO.yml
@@ -2,6 +2,7 @@
_lang_: "Română"
headlineMisskey: "O rețea conectată prin note"
introMisskey: "Bine ai venit! Misskey este un serviciu de microblogging open source și decentralizat.\nCreează \"note\" cu care să îți poți împărți gândurile cu oricine din jurul tău. 📡\nCu \"reacții\" îți poți expirma rapid părerea despre notele oricui. 👍\nHai să explorăm o lume nouă! 🚀"
+poweredByMisskeyDescription: "{name} este unul dintre serviciile care se folosește de platforma open source Misskey."
monthAndDay: "{day}/{month}"
search: "Caută"
notifications: "Notificări"
@@ -12,12 +13,14 @@ fetchingAsApObject: "Se aduce din Fediverse..."
ok: "OK"
gotIt: "Am înțeles!"
cancel: "Anulează"
+noThankYou: "Nu, mulțumesc."
enterUsername: "Introdu numele de utilizator"
renotedBy: "Re-notat de {user}"
noNotes: "Nicio notă"
noNotifications: "Nicio notificare"
instance: "Instanță"
settings: "Setări"
+notificationSettings: "Setări notificări"
basicSettings: "Setări generale"
otherSettings: "Alte Setări"
openInWindow: "Deschide într-o fereastră"
@@ -42,12 +45,20 @@ pin: "Fixează pe profil"
unpin: "Anulati fixare"
copyContent: "Copiază conținutul"
copyLink: "Copiază link-ul"
+copyLinkRenote: "Copiază linkul pentru renote"
delete: "Şterge"
deleteAndEdit: "Șterge și editează"
deleteAndEditConfirm: "Ești sigur că vrei să ștergi această notă și să o editezi? Vei pierde reacțiile, re-notele și răspunsurile acesteia."
addToList: "Adaugă în listă"
+addToAntenna: "Adaugă la antenă"
sendMessage: "Trimite un mesaj"
+copyRSS: "Copiază RSS"
copyUsername: "Copiază numele de utilizator"
+copyUserId: "Copiază numele de utilizator"
+copyNoteId: "Copiază ID-ul notiței"
+copyFileId: "Copiază ID-ul fișierului"
+copyFolderId: "Copiază ID-ul folderului"
+copyProfileUrl: "Copiază URL profil"
searchUser: "Caută un utilizator"
reply: "Răspunde"
loadMore: "Incarcă mai mult"
@@ -100,6 +111,8 @@ renoted: "Re-notat."
cantRenote: "Această postare nu poate fi re-notată."
cantReRenote: "O re-notă nu poate fi re-notată."
quote: "Citează"
+inChannelRenote: "Renotează în canal"
+inChannelQuote: "Citează în canal"
pinnedNote: "Notă fixată"
pinned: "Fixat pe profil"
you: "Tu"
@@ -108,7 +121,6 @@ sensitive: "NSFW"
add: "Adaugă"
reaction: "Reacție"
reactions: "Reacție"
-reactionSetting: "Reacții care să apară in selectorul de reacții"
reactionSettingDescription2: "Trage pentru a rearanja, apasă pe \"+\" pentru a adăuga."
rememberNoteVisibility: "Amintește setarea de vizibilitate a notelor"
attachCancel: "Înlătură atașament"
@@ -117,6 +129,8 @@ unmarkAsSensitive: "Demarchează ca NSFW"
enterFileName: "Introduceţi numele fişierului"
mute: "Amuțește"
unmute: "Înlătură amuțirea"
+renoteMute: "Renotări pe modul silențios"
+renoteUnmute: "Scoate renotările de pe modul silențios"
block: "Blochează"
unblock: "Deblochează"
suspend: "Suspendă"
@@ -126,7 +140,10 @@ unblockConfirm: "Ești sigur ca vrei să deblochezi acest cont?"
suspendConfirm: "Ești sigur ca vrei să suspendezi acest cont?"
unsuspendConfirm: "Ești sigur ca vrei să nu mai suspendezi acest cont?"
selectList: "Selectează o listă"
+editList: "Editați lista"
+selectChannel: "Selectaţi canalul"
selectAntenna: "Selectează o antenă"
+editAntenna: "Editează antena"
selectWidget: "Selectați un widget"
editWidgets: "Editează widget-urile"
editWidgetsExit: "Terminat"
@@ -139,6 +156,7 @@ addEmoji: "Adaugă un emoji"
settingGuide: "Setări recomandate"
cacheRemoteFiles: "Ține fișierele externe in cache"
cacheRemoteFilesDescription: "Când această setare este dezactivată, fișierele externe sunt încărcate direct din instanța externă. Dezactivarea va scădea utilizarea spațiului de stocare, dar va crește traficul, deoarece thumbnail-urile nu vor fi generate."
+youCanCleanRemoteFilesCache: "Poți goli cache-ul prin a apăsa pe butonul de 🗑️ din fereastra de gestionare a fișierelor."
flagAsBot: "Marchează acest cont ca bot"
flagAsBotDescription: "Activează această opțiune dacă acest cont este controlat de un program. Daca e activată, aceasta va juca rolul unui indicator pentru dezvoltatori pentru a preveni interacțiunea în lanțuri infinite cu ceilalți boți și ajustează sistemele interne al Misskey pentru a trata acest cont drept un bot."
flagAsCat: "Marchează acest cont ca pisică"
@@ -341,6 +359,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Activează hCaptcha"
hcaptchaSiteKey: "Site key"
hcaptchaSecretKey: "Secret key"
+mcaptchaSiteKey: "Site key"
+mcaptchaSecretKey: "Secret key"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Activează reCAPTCHA"
recaptchaSiteKey: "Site key"
@@ -393,7 +413,6 @@ share: "Distribuie"
notFound: "Nu a fost găsit"
notFoundDescription: "N-a fost găsită nicio pagină cu acest URL."
uploadFolder: "Folder implicit pentru încărcări"
-cacheClear: "Golește cache-ul"
markAsReadAllNotifications: "Marchează toate notificările drept citit"
markAsReadAllUnreadNotes: "Marchează toate notele drept citit"
markAsReadAllTalkMessages: "Marchează toate mesajele drept citit"
@@ -649,6 +668,8 @@ _sfx:
notification: "Notificări"
_ago:
invalid: "Nu e nimic de văzut aici"
+_2fa:
+ renewTOTPCancel: "Nu, mulțumesc."
_widgets:
profile: "Profil"
instanceInfo: "Informații despre instanță"
@@ -706,3 +727,6 @@ _webhookSettings:
_moderationLogTypes:
suspend: "Suspendă"
resetPassword: "Resetează parola"
+_reversi:
+ total: "Total"
+
diff --git a/locales/ru-RU.yml b/locales/ru-RU.yml
index d8f7fe519..d666b6949 100644
--- a/locales/ru-RU.yml
+++ b/locales/ru-RU.yml
@@ -53,15 +53,15 @@ addToAntenna: "Добавить к антенне"
sendMessage: "Отправить сообщение"
copyRSS: "Скопировать RSS"
copyUsername: "Скопировать имя пользователя"
-copyUserId: "Скопировать ID пользователя"
-copyNoteId: "Скопировать ID заметки"
+copyUserId: "Скопировать идентификатор пользователя"
+copyNoteId: "Скопировать идентификатор заметки"
copyFileId: "Скопировать ID файла"
copyFolderId: "Скопировать ID папки"
copyProfileUrl: "Скопировать URL профиля "
searchUser: "Поиск людей"
reply: "Ответ"
loadMore: "Показать еще"
-showMore: "Показать еще"
+showMore: "Показать ещё"
showLess: "Закрыть"
youGotNewFollower: "Новый подписчик"
receiveFollowRequest: "Получен запрос на подписку"
@@ -120,7 +120,12 @@ sensitive: "Содержимое не для всех"
add: "Добавить"
reaction: "Реакции"
reactions: "Реакции"
-reactionSetting: "Реакции, отображаемые в палитре"
+emojiPicker: "Палитра эмодзи"
+pinnedEmojisForReactionSettingDescription: "Здесь можно закрепить эмодзи для реакций"
+pinnedEmojisSettingDescription: "Здесь можно закрепить эмодзи в общей палитре"
+emojiPickerDisplay: "Внешний вид палитры"
+overwriteFromPinnedEmojisForReaction: "Заменить на эмодзи из списка реакций"
+overwriteFromPinnedEmojis: "Заменить на эмодзи из общего списка закреплённых"
reactionSettingDescription2: "Расставляйте перетаскиванием, удаляйте нажатием, добавляйте кнопкой «+»."
rememberNoteVisibility: "Запоминать видимость заметок"
attachCancel: "Удалить вложение"
@@ -129,8 +134,8 @@ unmarkAsSensitive: "Снять отметку «не для всех»"
enterFileName: "Введите имя файла"
mute: "Скрыть"
unmute: "Отменить скрытие"
-renoteMute: "Заглушить репосты"
-renoteUnmute: "Включить репосты"
+renoteMute: "Скрыть репосты"
+renoteUnmute: "Открыть репосты"
block: "Заблокировать"
unblock: "Разблокировать"
suspend: "Заморозить"
@@ -156,8 +161,8 @@ addEmoji: "Добавить эмодзи"
settingGuide: "Рекомендуемые настройки"
cacheRemoteFiles: "Кешировать внешние файлы"
cacheRemoteFilesDescription: "Когда эта настройка отключена, файлы с других сайтов будут загружаться прямо оттуда. Это сэкономит место на сервере, но увеличит трафик, так как не будут создаваться эскизы."
-cacheRemoteSensitiveFiles: "Кешировать внешние файлы"
-cacheRemoteSensitiveFilesDescription: "Описание удаленных внешних файлов в кэше"
+cacheRemoteSensitiveFiles: "Кэшировать внешние файлы «не для всех»"
+cacheRemoteSensitiveFilesDescription: "Если отключено, файлы «не для всех» загружаются непосредственно с удалённых серверов, не кэшируясь."
flagAsBot: "Аккаунт бота"
flagAsBotDescription: "Включите, если этот аккаунт управляется программой. Это позволит системе Misskey учитывать это, а также поможет разработчикам других ботов предотвратить бесконечные циклы взаимодействия."
flagAsCat: "Аккаунт кота"
@@ -256,6 +261,7 @@ removed: "Удалено"
removeAreYouSure: "Хотите удалить «{x}»?"
deleteAreYouSure: "Хотите удалить «{x}»?"
resetAreYouSure: "На самом деле сбросить?"
+areYouSure: "Вы уверены?"
saved: "Сохранено"
messaging: "Сообщения"
upload: "Загрузить"
@@ -273,7 +279,7 @@ noMoreHistory: "История закончилась"
startMessaging: "Начать общение"
nUsersRead: "Прочитали {n}"
agreeTo: "Я соглашаюсь с {0}"
-agree: "Согласиться"
+agree: "Согласен"
agreeBelow: "Согласен со следующими"
basicNotesBeforeCreateAccount: "Записи, перед созданием аккаунта"
termsOfService: "Условия использования"
@@ -319,7 +325,7 @@ copyUrl: "Копировать ссылку"
rename: "Переименовать"
avatar: "Аватар"
banner: "Шапка"
-displayOfSensitiveMedia: "Определение деликатного контента"
+displayOfSensitiveMedia: "Отображение содержимого не для всех"
whenServerDisconnected: "Когда соединение с сервером потеряно"
disconnectedFromServer: "Разорвано соединение с сервером"
reload: "Перезагрузить"
@@ -367,6 +373,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Включить hCaptcha"
hcaptchaSiteKey: "Ключ сайта"
hcaptchaSecretKey: "Секретный ключ"
+mcaptchaSiteKey: "Ключ сайта"
+mcaptchaSecretKey: "Секретный ключ"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Включить reCAPTCHA"
recaptchaSiteKey: "Ключ сайта"
@@ -408,7 +416,7 @@ about: "Описание"
aboutMisskey: "О Misskey"
administrator: "Администратор"
token: "Токен"
-2fa: "2-х факторная аутентификация"
+2fa: "Двухфакторная аутентификация"
setupOf2fa: "Настроить двухфакторную аутентификацию"
totp: "Приложение-аутентификатор"
totpDescription: "Описание приложения-аутентификатора"
@@ -429,7 +437,6 @@ share: "Поделиться"
notFound: "Не найдено"
notFoundDescription: "Страница по указанной ссылке не найдена"
uploadFolder: "Место загрузки по умолчанию"
-cacheClear: "Очистка кэша"
markAsReadAllNotifications: "Отметить все уведомления как прочитанные"
markAsReadAllUnreadNotes: "Отметить все заметки как прочитанные"
markAsReadAllTalkMessages: "Отметить все реплики как прочитанные"
@@ -473,7 +480,7 @@ aboutX: "Описание {x}"
emojiStyle: "Стиль эмодзи"
native: "Системные"
disableDrawer: "Не использовать выдвижные меню"
-showNoteActionsOnlyHover: "Показывать кнопки управления заметкой только при наведении"
+showNoteActionsOnlyHover: "Показывать кнопки у заметок только при наведении"
noHistory: "История пока пуста"
signinHistory: "Журнал посещений"
enableAdvancedMfm: "Включить расширенный MFM"
@@ -486,8 +493,8 @@ createAccount: "Новая учётная запись"
existingAccount: "Существующая учётная запись"
regenerate: "Создать повторно"
fontSize: "Размер шрифта"
-mediaListWithOneImageAppearance: "Показывать список медиа только одним изображением"
-limitTo: "Обрезать до {x}"
+mediaListWithOneImageAppearance: "Вид изображения, если оно единственное в списке"
+limitTo: "Ограничить до {x}"
noFollowRequests: "Нерассмотренные запросы на подписку отсутствуют"
openImageInNewTab: "Открыть изображение в новой вкладке"
dashboard: "Панель управления"
@@ -521,7 +528,7 @@ objectStorageUseSSLDesc: "Отключите, если не собираетес
objectStorageUseProxy: "Использовать прокси"
objectStorageUseProxyDesc: "Отключите, если не будете испоьзовать прокси для соединений по протоколу ObjectStorage."
objectStorageSetPublicRead: "Устанавливать public-read при загрузке на сервер"
-s3ForcePathStyleDesc: "Включение s3ForcePathStyle принудительно указывает имя корзины как часть пути в URL-адресе вместо имени хоста. Может потребоваться активация при использовании таких вещей, как локальный Minio."
+s3ForcePathStyleDesc: "Включение s3ForcePathStyle приводит к тому, что имя корзины указывается как часть пути в URL, а не в имени хоста. Может потребоваться включить при использовании локального Minio или чего-то подобного."
serverLogs: "Журнал сервера"
deleteAll: "Удалить всё"
showFixedPostForm: "Показывать поле для ввода новой заметки наверху ленты"
@@ -565,7 +572,7 @@ yourAccountSuspendedTitle: "Эта учетная запись заблокир
yourAccountSuspendedDescription: "Эта учетная запись была заблокирована из-за нарушения условий предоставления услуг сервера. Свяжитесь с администратором, если вы хотите узнать более подробную причину. Пожалуйста, не создавайте новую учетную запись."
tokenRevoked: "Токен недействителен"
tokenRevokedDescription: "Срок действия вашего токена входа истек. Пожалуйста, войдите снова."
-accountDeleted: "Эта учетная запись удалена"
+accountDeleted: "Учетная запись удалена"
accountDeletedDescription: "Эта учетная запись удалена"
menu: "Меню"
divider: "Линия-разделитель"
@@ -643,10 +650,11 @@ create: "Создать"
notificationSetting: "Настройки уведомлений"
notificationSettingDesc: "Выберите тип уведомлений для отображения"
useGlobalSetting: "Использовать глобальные настройки"
-useGlobalSettingDesc: "Если включено, будут использоваться настройки учётной записи. Если включить, этот виджет можно будет настроить индивидуально."
+useGlobalSettingDesc: "Если включено, будут использоваться настройки учётной записи. Если отключить, этот виджет можно будет настроить индивидуально."
other: "Другие"
regenerateLoginToken: "Создать новый токен для входа"
regenerateLoginTokenDescription: "Создаёт новый токен, используемый внутри программы во время входа. Обычно в этом нет необходимости. При создании все устройства будут отключены."
+theKeywordWhenSearchingForCustomEmoji: "Это ключевое слово будет использовано при поиске эмодзи."
setMultipleBySeparatingWithSpace: "Можно написать несколько через пробел"
fileIdOrUrl: "Идентификатор файла или ссылка"
behavior: "Поведение"
@@ -681,7 +689,7 @@ createNewClip: "Новая подборка"
unclip: "Убрать из подборки"
confirmToUnclipAlreadyClippedNote: "Эта заметка уже есть в подборке «{name}». Удалить из этой подборки?"
public: "Общедоступно"
-private: "Показываются только вам"
+private: "Личное"
i18nInfo: "Misskey переводят на разные языки добровольцы со всего света. Ваша помощь тоже пригодится здесь: {link}."
manageAccessTokens: "Управление токенами доступа"
accountInfo: "Сведения об учётной записи"
@@ -717,7 +725,7 @@ useSystemFont: "Использовать шрифт, предлагаемый с
clips: "Подборки"
experimentalFeatures: "Экспериментальные функции"
experimental: "Экспериментальные"
-thisIsExperimentalFeature: "Это экспериментальная функция. Технические характеристики могут измениться или он может работать неправильно."
+thisIsExperimentalFeature: "Это экспериментальная функция. Её поведение, вероятно, поменяется в следующей версии, а ещё она может работать не так, как задумано."
developer: "Разработчик"
makeExplorable: "Опубликовать профиль в «Обзоре»."
makeExplorableDescription: "Если выключить, ваш профиль не будет показан в разделе «Обзор»."
@@ -802,7 +810,7 @@ noMaintainerInformationWarning: "Не заполнены сведения об
noBotProtectionWarning: "Ботозащита не настроена"
configure: "Настроить"
postToGallery: "Опубликовать в галерею"
-postToHashtag: "Опубликовать пост с этим хештегом"
+postToHashtag: "Написать заметку с этим хэштегом"
gallery: "Галерея"
recentPosts: "Недавние публикации"
popularPosts: "Популярные публикации"
@@ -831,7 +839,7 @@ useBlurEffect: "Размытие в интерфейсе"
learnMore: "Подробнее"
misskeyUpdated: "Misskey обновился!"
whatIsNew: "Что новенького?"
-translate: "Перевод"
+translate: "Перевести"
translatedFrom: "Перевод. Язык оригинала — {x}"
accountDeletionInProgress: "В настоящее время выполняется удаление учетной записи"
usernameInfo: "Имя, которое отличает вашу учетную запись от других на этом сервере. Вы можете использовать алфавит (a~z, A~Z), цифры (0~9) или символы подчеркивания (_). Имена пользователей не могут быть изменены позже."
@@ -843,11 +851,11 @@ lastCommunication: "Последнее сообщение"
resolved: "Решено"
unresolved: "Без решения"
breakFollow: "Отписка"
-breakFollowConfirm: "Удалить из подписок пользователя ?"
+breakFollowConfirm: "Действительно удалить этого подписчика?"
itsOn: "Включено"
itsOff: "Выключено"
-on: "Вкл"
-off: "Выкл"
+on: "Вкл."
+off: "Выкл."
emailRequiredForSignup: "Для регистрации учётной записи нужен адрес электронной почты"
unread: "Непрочитанное"
filter: "Фильтры"
@@ -858,8 +866,6 @@ makeReactionsPublicDescription: "Список сделанных вами реа
classic: "Классика"
muteThread: "Скрыть цепочку"
unmuteThread: "Отменить сокрытие цепочки"
-ffVisibility: "Видимость подписок и подписчиков"
-ffVisibilityDescription: "Здесь можно настроить, кто будет видеть ваши подписки и подписчиков."
continueThread: "Показать следующие ответы"
deleteAccountConfirm: "Учётная запись будет безвозвратно удалена. Подтверждаете?"
incorrectPassword: "Пароль неверен."
@@ -878,7 +884,7 @@ numberOfColumn: "Количество столбцов"
searchByGoogle: "Поиск"
instanceDefaultLightTheme: "Светлая тема по умолчанию"
instanceDefaultDarkTheme: "Темная тема по умолчанию"
-instanceDefaultThemeDescription: "Описание темы по умолчанию для инстанса"
+instanceDefaultThemeDescription: "Введите код темы в формате объекта."
mutePeriod: "Продолжительность скрытия"
period: "Опрос длится"
indefinitely: "вечно"
@@ -902,7 +908,7 @@ thereIsUnresolvedAbuseReportWarning: "Остались нерешённые жа
recommended: "Рекомендуем"
check: "Проверить"
driveCapOverrideLabel: "Изменение лимита дискового пространства для этого пользователя"
-driveCapOverrideCaption: "Укажите меньше или равное нулю для отмены"
+driveCapOverrideCaption: "Введите нуль или меньше, чтобы использовать значение по умолчанию."
requireAdminForView: "Для просмотра необходимо иметь аккаунт администратора"
isSystemAccount: "Данная учётная запись создана автоматически и управляется системой"
typeToConfirm: "Введите {x} для продолжения"
@@ -922,7 +928,7 @@ type: "Тип"
speed: "Скорость"
slow: "Медленная"
fast: "Быстрая"
-sensitiveMediaDetection: "Определение содержимого деликатного характера"
+sensitiveMediaDetection: "Распознание содержимого не для всех"
localOnly: "Локально"
remoteOnly: "Только удалённо"
failedToUpload: "Сбой выгрузки"
@@ -955,7 +961,7 @@ numberOfProfileView: "Количество профилей для просмо
like: "Нравится!"
unlike: "Отменить «нравится»"
numberOfLikes: "Количество лайков"
-show: "Отображение"
+show: "Показать"
neverShow: "Больше не показывать"
remindMeLater: "Напомнить позже"
didYouLikeMisskey: "Вам нравится Misskey?"
@@ -999,15 +1005,17 @@ invitationRequiredToRegister: "Этот сервер в настоящее вр
emailNotSupported: "Доставка почты не поддерживается на этом сервере"
postToTheChannel: "Отправить в канал"
cannotBeChangedLater: "Это нельзя изменить позже"
-reactionAcceptance: "Принятие реакций"
-likeOnly: "Только лайки"
-likeOnlyForRemote: "Только лайки с удалённых серверов"
-nonSensitiveOnly: "Безопасный серфинг"
+reactionAcceptance: "Допустимые реакции"
+likeOnly: "Только «нравится!»"
+likeOnlyForRemote: "Всё (с других серверов только «нравится!»)"
+nonSensitiveOnly: "Только безопасные"
+nonSensitiveOnlyForLocalLikeOnlyForRemote: "Только безопасные (с других серверов только «нравится!»)"
rolesAssignedToMe: "Мои роли"
resetPasswordConfirm: "Сбросить пароль?"
sensitiveWords: "Чувствительные слова"
sensitiveWordsDescription: "Установите общедоступный диапазон заметки, содержащей заданное слово, на домашний. Можно сделать несколько настроек, разделив их переносами строк."
sensitiveWordsDescription2: "Разделение пробелом создаёт спецификацию AND, а разделение косой чертой создаёт регулярное выражение."
+prohibitedWordsDescription2: "Разделение пробелом создаёт спецификацию AND, а разделение косой чертой создаёт регулярное выражение."
notesSearchNotAvailable: "Поиск заметок недоступен"
license: "Лицензия"
unfavoriteConfirm: "Удалить избранное?"
@@ -1022,20 +1030,20 @@ noteIdOrUrl: "ID или ссылка на заметку"
video: "Видео"
videos: "Видео"
dataSaver: "Экономия трафика"
-accountMigration: "Перенести учётную запись"
-accountMoved: "Учетная запись перенесена"
+accountMigration: "Перенос учётной записи"
+accountMoved: "Учётная запись перенесена"
accountMovedShort: "Эта учётная запись перемещена"
-operationForbidden: "Эта операция невозможна."
+operationForbidden: "Это действие запрещено"
forceShowAds: "Всегда отображать рекламу"
-addMemo: "Добавить заметку"
-editMemo: "Редактировать заметку"
-reactionsList: "Реакции"
+addMemo: "Добавить памятку"
+editMemo: "Изменить памятку"
+reactionsList: "Список реакций"
renotesList: "Репосты"
-notificationDisplay: "Отображение уведомления"
-leftTop: "Верхний левый угол"
-rightTop: "Сверху справа"
-leftBottom: "Снизу слева"
-rightBottom: "Снизу справа"
+notificationDisplay: "Отображение уведомлений"
+leftTop: "Влево вверх"
+rightTop: "Вправо вверх"
+leftBottom: "Влево вниз"
+rightBottom: "Вправо вниз"
vertical: "Вертикальная"
horizontal: "Сбоку"
position: "Позиция"
@@ -1057,6 +1065,8 @@ options: "Настройки ролей"
specifyUser: "Указанный пользователь"
failedToPreviewUrl: "Предварительный просмотр недоступен"
update: "Обновить"
+rolesThatCanBeUsedThisEmojiAsReaction: "Роли тех, кому можно использовать эти эмодзи как реакцию"
+rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "Если здесь ничего не указать, в качестве реакции эту эмодзи сможет использовать каждый."
later: "Позже"
goToMisskey: "К Misskey"
additionalEmojiDictionary: "Дополнительные словари эмодзи"
@@ -1071,7 +1081,11 @@ doYouAgree: "Согласны?"
icon: "Аватар"
replies: "Ответы"
renotes: "Репост"
+loadReplies: "Показать ответы"
+sourceCode: "Исходный код"
flip: "Переворот"
+lastNDays: "Последние {n} сут"
+surrender: "Этот пост не может быть отменен."
_initialAccountSetting:
accountCreated: "Аккаунт успешно создан!"
letsStartAccountSetup: "Давайте настроим вашу учётную запись."
@@ -1082,6 +1096,11 @@ _initialAccountSetting:
_initialTutorial:
_note:
description: "Посты в Misskey называются 'Заметками.' Заметки отсортированы в хронологическом порядке в ленте и обновляются в режиме реального времени."
+_timelineDescription:
+ home: "В персональной ленте располагаются заметки тех, на которых вы подписаны."
+ local: "Местная лента показывает заметки всех пользователей этого сайта."
+ social: "В социальной ленте собирается всё, что есть в персональной и местной лентах."
+ global: "В глобальную ленту попадает вообще всё со связанных инстансов."
_serverSettings:
iconUrl: "Адрес на иконку роли"
_achievements:
@@ -1589,6 +1608,14 @@ _ago:
monthsAgo: "{n} мес. назад"
yearsAgo: "{n} г. назад"
invalid: "Ничего нет"
+_timeIn:
+ seconds: "Через {n} с"
+ minutes: "Через {n} мин"
+ hours: "Через {n} ч"
+ days: "Через {n} сут"
+ weeks: "Через {n} нед."
+ months: "Через {n} мес."
+ years: "Через {n} г."
_time:
second: "с"
minute: "мин"
@@ -1675,7 +1702,7 @@ _weekday:
_widgets:
profile: "Профиль"
instanceInfo: "Информация об инстансе"
- memo: "Напоминания"
+ memo: "Памятки"
notifications: "Уведомления"
timeline: "Лента"
calendar: "Календарь"
@@ -1704,7 +1731,7 @@ _widgets:
clicker: "Счётчик щелчков"
_cw:
hide: "Спрятать"
- show: "Показать еще"
+ show: "Показать"
chars: "знаков: {count}"
files: "файлов: {count}"
_poll:
@@ -1766,6 +1793,7 @@ _profile:
_exportOrImport:
allNotes: "Все заметки\n"
favoritedNotes: "Избранное"
+ clips: "Подборка"
followingList: "Подписки"
muteList: "Скрытые"
blockingList: "Заблокированные"
@@ -1941,4 +1969,10 @@ _webhookSettings:
active: "Вкл."
_moderationLogTypes:
suspend: "Заморозить"
+ addCustomEmoji: "Добавлено эмодзи"
+ updateCustomEmoji: "Изменено эмодзи"
+ deleteCustomEmoji: "Удалено эмодзи"
resetPassword: "Сброс пароля:"
+_reversi:
+ total: "Всего"
+
diff --git a/locales/si-LK.yml b/locales/si-LK.yml
index ed97d539c..cd21505a4 100644
--- a/locales/si-LK.yml
+++ b/locales/si-LK.yml
@@ -1 +1,2 @@
---
+
diff --git a/locales/sk-SK.yml b/locales/sk-SK.yml
index 903891fdb..251496b10 100644
--- a/locales/sk-SK.yml
+++ b/locales/sk-SK.yml
@@ -113,7 +113,6 @@ sensitive: "NSFW"
add: "Pridať"
reaction: "Reakcie"
reactions: "Reakcie"
-reactionSetting: "Reakcie zobrazené vo výbere reakcií"
reactionSettingDescription2: "Ťahaním preusporiadate, kliknutím odstránite, Stlačením \"+\" pridáte"
rememberNoteVisibility: "Zapamätať nastavenia viditeľnosti poznámky"
attachCancel: "Odstrániť prílohu"
@@ -350,6 +349,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Zapnúť hCaptchu"
hcaptchaSiteKey: "Site key"
hcaptchaSecretKey: "Secret key"
+mcaptchaSiteKey: "Site key"
+mcaptchaSecretKey: "Secret key"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Zapnúť ReCAPTCHA"
recaptchaSiteKey: "Site key"
@@ -411,7 +412,6 @@ share: "Zdieľať"
notFound: "Nenájdené"
notFoundDescription: "Nenašla sa žiadna stránka na zadanej URL."
uploadFolder: "Predvolený priečinok pre nahrávanie"
-cacheClear: "Vyčistiť cache"
markAsReadAllNotifications: "Označiť všetky oznámenia ako prečítané"
markAsReadAllUnreadNotes: "Označiť všetky poznámky ako prečítané"
markAsReadAllTalkMessages: "Označiť všetky správy ako prečítané"
@@ -823,8 +823,6 @@ makeReactionsPublicDescription: "Toto spraví všetky vaše minulé reakcie vidi
classic: "Klasika"
muteThread: "Ztíšiť vlákno"
unmuteThread: "Zrušiť stíšenie vlákna"
-ffVisibility: "Viditeľnosť sledujúcich/sledovaných"
-ffVisibilityDescription: "Umožňuje nastaviť kto vidí koho sledujete a kto vás sleduje."
continueThread: "Zobraziť pokračovanie vlákna"
deleteAccountConfirm: "Toto nezvrátiteľne vymaže váš účet. Pokračovať?"
incorrectPassword: "Nesprávne heslo."
@@ -921,7 +919,9 @@ youFollowing: "Sledované"
icon: "Avatar"
replies: "Odpovedať"
renotes: "Preposlať"
+sourceCode: "Zdrojový kód"
flip: "Preklopiť"
+lastNDays: "Posledných {n} dní"
_role:
priority: "Priorita"
_priority:
@@ -1288,6 +1288,7 @@ _profile:
changeBanner: "Zmeniť banner"
_exportOrImport:
allNotes: "Všetky poznámky"
+ clips: "Klip"
followingList: "Sledujete"
muteList: "Vypnúť zvuk"
blockingList: "Zablokovať"
@@ -1445,3 +1446,6 @@ _webhookSettings:
_moderationLogTypes:
suspend: "Zmraziť"
resetPassword: "Resetovať heslo"
+_reversi:
+ total: "Celkom"
+
diff --git a/locales/sv-SE.yml b/locales/sv-SE.yml
index 92678afef..07d5509a6 100644
--- a/locales/sv-SE.yml
+++ b/locales/sv-SE.yml
@@ -118,7 +118,6 @@ sensitive: "Känsligt innehåll"
add: "Lägg till"
reaction: "Reaktioner"
reactions: "Reaktioner"
-reactionSetting: "Reaktioner som ska visas i reaktionsväljaren"
reactionSettingDescription2: "Dra för att omordna, klicka för att radera, tryck \"+\" för att lägga till."
rememberNoteVisibility: "Komihåg notvisningsinställningar"
attachCancel: "Ta bort bilaga"
@@ -346,6 +345,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Aktivera hCaptcha"
hcaptchaSiteKey: "Webbplatsnyckel"
hcaptchaSecretKey: "Hemlig nyckel"
+mcaptchaSiteKey: "Webbplatsnyckel"
+mcaptchaSecretKey: "Hemlig nyckel"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Aktivera reCAPTCHA"
recaptchaSiteKey: "Webbplatsnyckel"
@@ -575,3 +576,4 @@ _webhookSettings:
_moderationLogTypes:
suspend: "Suspendera"
resetPassword: "Återställ Lösenord"
+
diff --git a/locales/th-TH.yml b/locales/th-TH.yml
index 8df36a682..c0e79d5e1 100644
--- a/locales/th-TH.yml
+++ b/locales/th-TH.yml
@@ -1,20 +1,20 @@
---
_lang_: "ภาษาไทย"
-headlineMisskey: "เชื่อมต่อระบบ Network ด้วย Note"
-introMisskey: "ยินดีต้อนรับทุกคนจ้า! Misskey คือ บริการไมโครบล็อกกิ้ง (MicroBlogging) แบบกระจายศูนย์อำนาจ (Decentralized) \n\nเขียน \"โน้ต (Note)\" เพื่อส่งต่อเรื่องราวของคุณให้ทั้งโลกได้รับรู้📡\nและอย่าลืมที่จะ \"React\" กับเรื่องราวของคนอื่น ๆ ด้วย! 👍\n\nมุ่งสู่โลกใบใหม่กันเถอะ🚀"
+headlineMisskey: "เชื่อมต่อเครือข่ายโดยโน้ต"
+introMisskey: "ยินดีต้อนรับทุกคนจ้า! Misskey คือ ซอฟต์แวร์โอเพนซอร์สสำหรับบริการไมโครบล็อกกิ้ง (MicroBlogging) แบบกระจายศูนย์อำนาจ (Decentralized) \n\nเขียน “โน้ต (Note)” เพื่อส่งต่อเรื่องราวของคุณให้ทั้งโลกได้รับรู้📡\nและอย่าลืมที่จะ “รีแอคชั่น” กับเรื่องราวของคนอื่น ๆ ด้วยนะ! 👍\n\nท่องสำรวจโลกใบใหม่กันเถอะ🚀"
poweredByMisskeyDescription: "{name} เป็นส่วนหนึ่งในบริการที่ถูกขับเคลื่อนโดยแพลตฟอร์มโอเพ่นซอร์ส Misskey (เรียกว่า \"อินสแตนซ์ Misskey\")"
monthAndDay: "{month}/{day}"
search: "ค้นหา"
notifications: "การเเจ้งเตือน"
username: "ชื่อผู้ใช้"
password: "รหัสผ่าน"
-forgotPassword: "ลืมรหัสผ่านใช่ไหม"
-fetchingAsApObject: "กำลังดึงข้อมูล จาก เฟดิเวิร์ส..."
-ok: "โอเค"
+forgotPassword: "ลืมรหัสผ่าน"
+fetchingAsApObject: "กำลังดึงข้อมูลจากสหพันธ์..."
+ok: "ตกลง"
gotIt: "เข้าใจแล้ว !"
cancel: "ยกเลิก"
-noThankYou: "ไม่เป็นไร"
-enterUsername: "ใส่ชื่อผู้ใช้"
+noThankYou: "ไม่เอาดีกว่า"
+enterUsername: "กรอกชื่อผู้ใช้"
renotedBy: "รีโน้ตโดย {user}"
noNotes: "ไม่มีโน้ต"
noNotifications: "ไม่มีการแจ้งเตือน"
@@ -26,30 +26,30 @@ otherSettings: "การตั้งค่าอื่นๆ"
openInWindow: "เปิดในหน้าต่าง"
profile: "โปรไฟล์"
timeline: "ไทม์ไลน์"
-noAccountDescription: "ผู้ใช้รายนี้ยังไม่ได้เขียนลงประวัติของพวกเขา"
+noAccountDescription: "ผู้ใช้รายนี้ยังไม่ได้เขียนคำแนะนำตัว"
login: "เข้าสู่ระบบ"
loggingIn: "กำลังเข้าสู่ระบบ"
logout: "ออกจากระบบ"
signup: "สร้างบัญชีผู้ใช้"
-uploading: "กำลังอัพโหลด..."
+uploading: "กำลังอัปโหลด"
save: "บันทึก"
users: "ผู้ใช้งาน"
addUser: "เพิ่มผู้ใช้"
favorite: "รายการโปรด"
favorites: "รายการโปรด"
unfavorite: "ลบออกจากรายการโปรด"
-favorited: "เพิ่มแล้วในรายการโปรด"
-alreadyFavorited: "เพิ่มในรายการโปรดอยู่แล้ว"
-cantFavorite: "ไม่สามารถเพิ่มในรายการโปรดได้"
-pin: "ปักหมุดไปยังโปรไฟล์"
-unpin: "เลิกปักหมุดจากโปรไฟล์"
+favorited: "เพิ่มลงรายการโปรดแล้ว"
+alreadyFavorited: "เพิ่มลงรายการโปรดอยู่แล้ว"
+cantFavorite: "ไม่สามารถเพิ่มลงรายการโปรดได้"
+pin: "ปักหมุด"
+unpin: "เลิกปักหมุด"
copyContent: "คัดลอกเนื้อหา"
copyLink: "คัดลอกลิงก์"
copyLinkRenote: "คัดลอกลิงก์รีโน้ต"
delete: "ลบ"
deleteAndEdit: "ลบและแก้ไข"
-deleteAndEditConfirm: "นายแน่ใจแล้วเหรอ? ว่าต้องการลบโน้ตนี้และแก้ไข คุณอาจจะสูญเสียการโต้ตอบ, โน้ต, และการตอบกลับทั้งหมดได้นะ"
-addToList: "เพิ่มในลิสต์"
+deleteAndEditConfirm: "คุณต้องการลบโน้ตนี้และแก้ไขใหม่ใช่ไหม? รีแอคชั่น รีโน้ต และการตอบกลับต่อโน้ตนี้ทั้งหมดจะถูกลบออกด้วย"
+addToList: "เพิ่มลงรายชื่อ"
addToAntenna: "เพิ่มไปยังเสาอากาศ"
sendMessage: "ส่งข้อความ"
copyRSS: "คัดลอก RSS"
@@ -59,35 +59,35 @@ copyNoteId: "คัดลอก ID โน้ต "
copyFileId: "คัดลอกไฟล์ ID"
copyFolderId: "คัดลอกโฟลเดอร์ ID"
copyProfileUrl: "คัดลอกโปรไฟล์ URL"
-searchUser: "ค้นหาผู้ใช้งาน"
+searchUser: "ค้นหาผู้ใช้"
reply: "ตอบกลับ"
-loadMore: "โหลดเพิ่มเติม"
+loadMore: "แสดงเพิ่มเติม"
showMore: "แสดงเพิ่มเติม"
showLess: "ปิด"
youGotNewFollower: "ได้ติดตามคุณ"
-receiveFollowRequest: "คำขอผู้ติดตามที่ได้รับ"
-followRequestAccepted: "ผู้ติดตามได้ตอบรับคำขอร้องของคุณแล้ว"
+receiveFollowRequest: "มีคำขอติดตามส่งมาหา"
+followRequestAccepted: "การติดตามได้รับการอนุมัติแล้ว"
mention: "กล่าวถึง"
mentions: "พูดถึง"
-directNotes: "ไดเร็คโน้ต"
+directNotes: "โพสต์แบบไดเร็กต์"
importAndExport: "นำเข้า / ส่งออก"
import: "นำเข้า"
-export: "นำออก"
+export: "ส่งออก"
files: "ไฟล์"
download: "ดาวน์โหลด"
-driveFileDeleteConfirm: "คุณต้องการลบไฟล์ \"{name}\" ใช่หรือไม่? โน้ตย่อที่แนบมากับไฟล์นี้ก็จะถูกลบไปด้วย"
-unfollowConfirm: "นายแน่ใจแล้วหรอว่าต้องการเลิกติดตาม {name}?"
-exportRequested: "เมื่อคุณได้ร้องขอการส่งออก อาจจะต้องใช้เวลาสักครู่ และจะถูกเพิ่มในไดรฟ์ของคุณเมื่อเสร็จสิ้นแล้ว"
-importRequested: "เมื่อคุณได้ร้องขอการนำเข้า อาจจะต้องใช้เวลาสักครู่นะ"
-lists: "รายการ"
-noLists: "คุณไม่มีลิสต์ใด ๆ"
+driveFileDeleteConfirm: "ต้องการลบไฟล์ “{name}” ใช่ไหม? โน้ตที่แนบมากับไฟล์นี้ก็จะถูกลบไปด้วย"
+unfollowConfirm: "ต้องการเลิกติดตาม {name} ใช่ไหม?"
+exportRequested: "คุณได้ร้องขอการส่งออก อาจใช้เวลาสักครู่ และจะถูกเพิ่มในไดรฟ์ของคุณเมื่อเสร็จสิ้นแล้ว"
+importRequested: "คุณได้ร้องขอการนำเข้า การดำเนินการนี้อาจใช้เวลาสักครู่"
+lists: "รายชื่อ"
+noLists: "คุณไม่มีรายชื่อใดๆ"
note: " โน้ต"
-notes: "ตัวโน้ต"
+notes: " โน้ต"
following: "กำลังติดตาม"
followers: "ผู้ติดตาม"
followsYou: "ติดตามคุณ"
-createList: "สร้างลิสต์"
-manageLists: "จัดการลิสต์"
+createList: "สร้างรายชื่อ"
+manageLists: "จัดการรายชื่อ"
error: "ผิดพลาด!"
somethingHappened: "อุ๊ย ! มีอะไรบางอย่างผิดพลาด"
retry: "ลองใหม่อีกครั้ง"
@@ -95,75 +95,81 @@ pageLoadError: "เกิดข้อผิดพลาดในการโห
pageLoadErrorDescription: "โดยปกติแล้วมักจะเกิดจากข้อผิดพลาดของเครือข่ายหรือแคชของเบราว์เซอร์ ลองล้างแคชแล้วลองใหม่อีกครั้งหลังจากรอสักครู่ "
serverIsDead: "เซิร์ฟเวอร์นี้ไม่มีการตอบสนอง โปรดกรุณารอสักครู่แล้วลองใหม่อีกครั้ง"
youShouldUpgradeClient: "หากต้องการดูหน้านี้ กรุณาโหลดหน้าใหม่เพื่ออัปเดตไคลเอ็นต์ของคุณ"
-enterListName: "ใส่ชื่อสำหรับรายการลิสต์"
+enterListName: "ป้อนนามเรียกของรายชื่อชุดนี้"
privacy: "ความเป็นส่วนตัว"
-makeFollowManuallyApprove: "ติดตามคำขอที่ต้องได้รับการอนุมัติ"
+makeFollowManuallyApprove: "อนุมัติคำขอติดตามด้วยตนเอง"
defaultNoteVisibility: "การมองเห็นที่เป็นค่าเริ่มต้น"
follow: "ติดตาม"
followRequest: "ส่งคำขอติดตาม"
followRequests: "ส่งคำขอติดตาม"
unfollow: "เลิกติดตาม"
-followRequestPending: "กำลังรอดำเนินการร้องขอติดตาม"
-enterEmoji: "ใส่อีโมจิ"
+followRequestPending: "รออนุมัติคำขอติดตาม"
+enterEmoji: "พิมพ์เอโมจิ"
renote: "รีโน้ต"
unrenote: "เลิกรีโน้ต"
renoted: "รีโน้ตแล้ว"
-cantRenote: "โพสต์นี้ไม่สามารถรีโน้ตไว้ใหม่ได้นะ"
-cantReRenote: "ไม่สามารถรีโน้ตเอาไว้ใหม่ได้นะ"
+cantRenote: "โพสต์นี้ไม่สามารถรีโน้ตใหม่ได้"
+cantReRenote: "รีโน้ตไม่สามารถรีโน้ตซ้ำได้"
quote: "อ้างอิง"
-inChannelRenote: "รีโน้ตช่องแชลแนลเท่านั้น"
-inChannelQuote: "อ้างช่องเท่านั้น"
-pinnedNote: "โน้ตที่ปักหมุดเอาไว้"
-pinned: "ปักหมุดไปยังโปรไฟล์"
+inChannelRenote: "รีโน้ตในช่องเท่านั้น"
+inChannelQuote: "อ้างอิงในช่องเท่านั้น"
+pinnedNote: "โน้ตที่ปักหมุดไว้"
+pinned: "ปักหมุด"
you: "คุณ"
clickToShow: "คลิกเพื่อแสดง"
-sensitive: "เนื้อหาที่ละเอียดอ่อน NSFW"
+sensitive: "เนื้อหาที่ละเอียดอ่อน"
add: "เพิ่ม"
reaction: "รีแอคชั่น"
reactions: "รีแอคชั่น"
-reactionSetting: "รีแอคชั่นไปยังแสดงผลในตัวเลือกการรีแอคชั่น"
-reactionSettingDescription2: "กดลากเพื่อจัดลำดับใหม่ กดคลิกเพื่อลบ กด \"+\" เพื่อเพิ่ม"
-rememberNoteVisibility: "จดจำการตั้งค่าการมองเห็นตัวโน้ต"
-attachCancel: "ลบไฟล์ออกที่แนบมา"
-markAsSensitive: "ทำเครื่องหมายว่าละเอียดอ่อน"
-unmarkAsSensitive: "ยกเลิกทำเครื่องหมายเป็น NSFW"
+emojiPicker: "ตัวจิ้มเอโมจิ"
+pinnedEmojisForReactionSettingDescription: "ตรึงเอโมจิไว้ด้านบนสำหรับรีแอคชั่นอย่างเร่งด่วน"
+pinnedEmojisSettingDescription: "ตรึงเอโมจิไว้ด้านบนสำหรับพิมพ์เอโมจิอย่างเร่งด่วน"
+emojiPickerDisplay: "แสดงตัวจิ้มเอโมจิ"
+overwriteFromPinnedEmojisForReaction: "เขียนทับการตั้งค่ารีแอคชั่น"
+overwriteFromPinnedEmojis: "เขียนทับการตั้งค่าทั่วไป"
+reactionSettingDescription2: "ลากเพื่อจัดลำดับใหม่ คลิกที่เอโมจินั้นเพื่อลบ กด “+” เพื่อเพิ่ม"
+rememberNoteVisibility: "จำการตั้งค่าการมองเห็นโน้ต"
+attachCancel: "ยกเลิกแนบไฟล์"
+deleteFile: "ลบไฟล์ออก"
+markAsSensitive: "ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน"
+unmarkAsSensitive: "ยกเลิกทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน"
enterFileName: "พิมพ์ชื่อไฟล์"
mute: "ปิดเสียง"
unmute: "ยกเลิกการปิดเสียง"
renoteMute: "ปิดเสียงรีโน้ต"
renoteUnmute: "เปิดเสียง รีโน้ต"
-block: "บล็อค"
-unblock: "เลิกปิดกั้น"
-suspend: "ถูกระงับ"
-unsuspend: "ยกเลิกระงับ"
-blockConfirm: "คุณแน่ใจแล้วเหรอ? ว่าต้องการบล็อกบัญชีนี้"
-unblockConfirm: "คุณแน่ใจแล้วเหรอ? ว่าต้องการปลดบล็อคบัญชีนี้"
-suspendConfirm: "แน่ใจว่าคุณต้องการระงับบัญชีนี้?"
-unsuspendConfirm: "นายแน่ใจแล้วหรอ? ว่าต้องการยกเลิกการระงับบัญชีนี้"
-selectList: "เลือกรายการ"
-editList: "แก้ไขรายการ"
-selectChannel: "เลือกแชนแนล"
+block: "บล็อก"
+unblock: "เลิกบล็อก"
+suspend: "ระงับ"
+unsuspend: "เลิกระงับ"
+blockConfirm: "ต้องการบล็อกบัญชีนี้ใช่ไหม?"
+unblockConfirm: "ต้องการเลิกบล็อกบัญชีนี้ใช่ไหม?"
+suspendConfirm: "ต้องการระงับบัญชีนี้ใช่ไหม?"
+unsuspendConfirm: "ต้องการยกเลิกการระงับบัญชีนี้ใช่ไหม?"
+selectList: "เลือกรายชื่อ"
+editList: "แก้ไขรายชื่อ"
+selectChannel: "เลือกช่อง"
selectAntenna: "เลือกเสาอากาศ"
editAntenna: "แก้ไขเสาอากาศ"
selectWidget: "เลือกวิดเจ็ต"
editWidgets: "แก้ไขวิดเจ็ต"
editWidgetsExit: "เรียบร้อย"
-customEmojis: "กำหนดอีโมจิเอง"
-emoji: "อีโมจิ"
+customEmojis: "เอโมจิที่กำหนดเอง"
+emoji: "เอโมจิ"
emojis: "อีโมจิ"
-emojiName: "ชื่ออิโมจิ"
-emojiUrl: "อิโมจิ URL"
-addEmoji: "แทรกอีโมจิ"
+emojiName: "ชื่อเอโมจิ"
+emojiUrl: "URL ของเอโมจิ"
+addEmoji: "แทรกเอโมจิ"
settingGuide: "การตั้งค่าที่แนะนำ"
cacheRemoteFiles: "แคชไฟล์ระยะไกล"
-cacheRemoteFilesDescription: "เมื่อปิดใช้งานการตั้งค่านี้ ไฟล์ระยะไกลนั้นจะถูกโหลดโดยตรงจากอินสแตนซ์ระยะไกล แต่กรณีการปิดใช้งานนี้จะช่วยลดปริมาณการใช้พื้นที่จัดเก็บข้อมูล แต่เพิ่มปริมาณการใช้งาน เพราะเนื่องจากจะไม่มีการสร้างภาพขนาดย่อ"
+cacheRemoteFilesDescription: "หากเปิดใช้งาน ไฟล์ระยะไกลจะถูกแคชไว้ ทำให้แสดงภาพเร็วขึ้น แต่ก็ใช้พื้นที่เก็บข้อมูลของเซิร์ฟเวอร์มากขึ้นเช่นกัน สำหรับขีดจำกัดที่ผู้ใช้ระยะไกลถูกแคชไว้จะขึ้นอยู่กับความจุไดรฟ์ตามบทบาทของเขา เมื่อเกินแล้วไฟล์เก่าจะถูกลบออกและเก็บเป็นลิงก์แทน หากปิดใช้งาน ไฟล์ระยะไกลจะถูกเก็บเป็นลิงก์ตั้งแต่ต้น เราแนะนำให้ตั้งค่า proxyRemoteFiles ใน default.yml เป็น true เพื่อสร้างธัมบ์เนลและปกป้องความเป็นส่วนตัวของผู้ใช้"
youCanCleanRemoteFilesCache: "คุณสามารถล้างแคชได้โดยคลิกที่ปุ่ม 🗑️ ในมุมมองการจัดการไฟล์"
-cacheRemoteSensitiveFiles: "ไฟล์ระยะไกลที่มีความละเอียดอ่อนแคช"
-cacheRemoteSensitiveFilesDescription: "เมื่อปิดการใช้งานแล้วการตั้งค่านี้ ไฟล์รีโมตที่มีความละเอียดอ่อนนั้นจะถูกโหลดโดยตรงจากอินสแตนซ์ระยะไกลโดยที่ไม่มีการแคช"
-flagAsBot: "ทำเครื่องหมายบอกว่าบัญชีนี้เป็นบอท"
+cacheRemoteSensitiveFiles: "แคชไฟล์ระยะไกลที่มีเนื้อหาละเอียดอ่อน"
+cacheRemoteSensitiveFilesDescription: "เมื่อปิดการใช้งานการตั้งค่านี้ ไฟล์ระยะไกลที่มีเครื่องหมายว่ามีเนื้อหาละเอียดอ่อนนั้นจะถูกโหลดโดยตรงจากอินสแตนซ์ระยะไกลโดยที่ไม่มีการแคช"
+flagAsBot: "ทำเครื่องหมายบอกว่าบัญชีนี้เป็นบอต"
flagAsBotDescription: "การเปิดใช้งานตัวเลือกนี้หากบัญชีนี้ถูกควบคุมโดยนักเขียนโปรแกรม หรือ ถ้าหากเปิดใช้งาน มันจะทำหน้าที่เป็นแฟล็กสำหรับนักพัฒนารายอื่นๆ และเพื่อป้องกันการโต้ตอบแบบไม่มีที่สิ้นสุดกับบอทตัวอื่นๆ และยังสามารถปรับเปลี่ยนระบบภายในของ Misskey เพื่อปฏิบัติต่อบัญชีนี้เป็นบอท"
-flagAsCat: "ทำเครื่องหมายบอกว่าบัญชีนี้เป็นแมว"
-flagAsCatDescription: "การเปิดใช้งานตัวเลือกนี้เพื่อทำเครื่องหมายบอกว่าบัญชีนี้เป็นแมว"
+flagAsCat: "เมี้ยววววววววววววววว!!!!!!!!!!!"
+flagAsCatDescription: "เหมียวเหมียวเมี้ยว??"
flagShowTimelineReplies: "แสดงตอบกลับ ในไทม์ไลน์"
flagShowTimelineRepliesDescription: "แสดงการตอบกลับของผู้ใช้งานไปยังโน้ตของผู้ใช้งานรายอื่นๆในไทม์ไลน์หากได้เปิดเอาไว้"
autoAcceptFollowed: "อนุมัติคำขอติดตามโดยอัตโนมัติทันที จากผู้ใช้งานที่คุณกำลังติดตาม"
@@ -172,22 +178,22 @@ reloadAccountsList: "รีโหลดรายการบัญชีให
loginFailed: "การเข้าสู่ระบบไม่สำเร็จ"
showOnRemote: "ดูบนอินสแตนซ์ระยะไกล"
general: "ทั่วไป"
-wallpaper: "วอลล์เปเปอร์"
-setWallpaper: "ตั้งวอลเปเปอร์"
-removeWallpaper: "นำวอลเปเปอร์ออก"
+wallpaper: "ภาพพื้นหลัง"
+setWallpaper: "ตั้งค่าภาพพื้นหลัง"
+removeWallpaper: "นำภาพพื้นหลังออก"
searchWith: "ค้นหา: {q}"
-youHaveNoLists: "คุณไม่มีลิสต์ใด ๆ "
-followConfirm: "คุณแน่ใจแล้วหรอว่าต้องการที่จะติดตาม {name}?"
-proxyAccount: "บัญชี พร็อกซี่"
+youHaveNoLists: "คุณไม่มีรายชื่อใดๆ "
+followConfirm: "ต้องการติดตาม {name} ใช่ไหม?"
+proxyAccount: "บัญชีพร็อกซี่"
proxyAccountDescription: "บัญชีพร็อกซี่ คือ บัญชีที่จะทำหน้าที่เป็นผู้ติดตามระยะไกลสำหรับผู้ใช้งานที่อยู่ภายใต้ด้วยเงื่อนไขบางอย่าง ยกตัวอย่าง เช่น เมื่อมีผู้ใช้งานนั้นได้เพิ่มผู้ใช้งานจากระยะไกลลงในรายการ แต่กิจกรรมของผู้ใช้ในระยะไกลนั้นจะไม่ถูกส่งไปยังอินสแตนซ์หากไม่มีผู้ใช้งานในพื้นที่ติดตามผู้ใช้รายนั้น ดังนั้นบัญชีพร็อกซีนี้จะติดตามแทน"
host: "โฮสต์"
selectUser: "เลือกผู้ใช้งาน"
recipient: "ผู้รับ"
-annotation: "ความคิดเห็น"
-federation: "เฟดิเวิร์ส"
-instances: "Server"
-registeredAt: "จดทะเบียนที่"
-latestRequestReceivedAt: "ได้รับคำขอล่าสุดไปแล้ว"
+annotation: "หมายเหตุประกอบ"
+federation: "สหพันธ์"
+instances: "อินสแตนซ์"
+registeredAt: "วันที่ลงทะเบียน"
+latestRequestReceivedAt: "คำขอล่าสุดที่ได้รับ"
latestStatus: "สถานะล่าสุด"
storageUsage: "พื้นที่จัดเก็บข้อมูลที่ใช้ไป"
charts: "โดดเด่น"
@@ -195,31 +201,34 @@ perHour: "ทุกชั่วโมง"
perDay: "ต่อวัน"
stopActivityDelivery: "หยุดส่งกิจกรรม"
blockThisInstance: "บล็อกอินสแตนซ์นี้"
+silenceThisInstance: "ปิดปากอินสแตนซ์นี้"
operations: "ดำเนินการ"
software: "ซอฟต์แวร์"
version: "เวอร์ชั่น"
metadata: "Metadata"
-withNFiles: "{n} ไฟล์(s)"
+withNFiles: "{n} ไฟล์"
monitor: "มอนิเตอร์"
jobQueue: "คิวงาน"
cpuAndMemory: "ซีพียู และ หน่วยความจำ"
-network: "เน็ตเวิร์ก"
+network: "เครือข่าย"
disk: "ดิสก์"
-instanceInfo: "ข้อมูล อินสแตนซ์"
+instanceInfo: "ข้อมูลอินสแตนซ์"
statistics: "สถิติการใช้งาน"
clearQueue: "ล้างคิว"
-clearQueueConfirmTitle: "คุณแน่ใจแล้วหรอว่าต้องการที่จะล้างคิว?"
-clearQueueConfirmText: "บันทึกย่อที่ยังไม่ได้ส่งที่เหลืออยู่ในคิวนั้นมักจะ ไม่ถูกรวมเข้าด้วยกัน โดยปกติแล้วไม่จำเป็นต้องดำเนินการนี้"
+clearQueueConfirmTitle: "ต้องการล้างคิวใช่ไหม?"
+clearQueueConfirmText: "โพสต์ที่ยังค้างในคิวจะไม่ถูกจัดส่งอีกต่อไป โดยปกติแล้วการดำเนินการนี้ไม่จำเป็น"
clearCachedFiles: "ล้างแคช"
-clearCachedFilesConfirm: "นายแน่ใจแล้วหรอว่าต้องการที่จะลบไฟล์ระยะไกลที่แคชไว้ทั้งหมด?"
-blockedInstances: "อินสแตนซ์ที่ ถูกบล็อก"
+clearCachedFilesConfirm: "ต้องการลบไฟล์ระยะไกลที่แคชไว้ทั้งหมดใช่ไหม?"
+blockedInstances: "อินสแตนซ์ที่ถูกบล็อก"
blockedInstancesDescription: "ระบุชื่อโฮสต์ของอินสแตนซ์ที่คุณต้องการบล็อก อินสแตนซ์ที่อยู่ในรายการนั้นจะไม่สามารถพูดคุยกับอินสแตนซ์นี้ได้อีกต่อไป"
+silencedInstances: "ปิดปากอินสแตนซ์นี้แล้ว"
+silencedInstancesDescription: "ตั้งค่ารายชื่อโฮสต์ของอินสแตนซ์ที่คุณต้องการปิดปาก บัญชีทั้งหมดของอินสแตนซ์ที่อยู่ในรายชื่อนั้นๆ จะถือว่าถูกปิดปากเช่นกัน ทำได้เฉพาะคำขอติดตามเท่านั้น และไม่สามารถกล่าวถึงบัญชีในพื้นที่ได้หากไม่ได้ติดตาม | สิ่งนี้ไม่มีผลต่ออินสแตนซ์ที่ถูกบล็อก"
muteAndBlock: "ปิดเสียงและบล็อก"
mutedUsers: "ผู้ใช้ที่ถูกปิดเสียง"
blockedUsers: "ผู้ใช้ที่ถูกบล็อก"
noUsers: "ไม่พบผู้ใช้งาน"
editProfile: "แก้ไขโปรไฟล์"
-noteDeleteConfirm: "นายแน่ใจแล้วหรอว่าต้องการลบโน้ตนี้นะ?"
+noteDeleteConfirm: "ต้องการลบโน้ตนี้ใช่ไหม?"
pinLimitExceeded: "คุณไม่สามารถปักหมุดโน้ตเพิ่มเติมใดๆได้อีก"
intro: "การติดตั้ง Misskey เสร็จสิ้นแล้วนะ! โปรดสร้างผู้ใช้งานที่เป็นผู้ดูแลระบบ"
done: "เสร็จสิ้น"
@@ -227,8 +236,8 @@ processing: "กำลังประมวลผล..."
preview: "แสดงตัวอย่าง"
default: "ค่าเริ่มต้น"
defaultValueIs: "ค่าเริ่มต้น: {value}"
-noCustomEmojis: "ไม่มีอีโมจิ"
-noJobs: "ไม่มีชิ้นงาน"
+noCustomEmojis: "ไม่มีเอโมจิ"
+noJobs: "ไม่มีงาน"
federating: "สหพันธ์"
blocked: "ถูกบล็อก"
suspended: "ถูกระงับ"
@@ -236,42 +245,43 @@ all: "ทั้งหมด"
subscribing: "สมัครแล้ว"
publishing: "กำลังเผยแพร่"
notResponding: "ไม่มีการตอบสนอง"
-instanceFollowing: "กำลังติดตาม บน อินสแตนซ์"
+instanceFollowing: "กำลังติดตามบนอินสแตนซ์"
instanceFollowers: "ผู้ติดตามของอินสแตนซ์"
instanceUsers: "ผู้ใช้งานของอินสแตนซ์นี้"
changePassword: "เปลี่ยนรหัสผ่าน"
security: "ความปลอดภัย"
-retypedNotMatch: "อินพุตไม่ตรงกันนะ"
+retypedNotMatch: "ทั้งสองป้อนข้อมูลไม่สอดคล้องกัน"
currentPassword: "รหัสผ่านปัจจุบัน"
newPassword: "รหัสผ่านใหม่"
newPasswordRetype: "ใส่รหัสผ่านใหม่อีกครั้ง"
attachFile: "แนบไฟล์"
-more: "เพิ่มเติม"
+more: "เพิ่มเติม!"
featured: "ไฮไลท์"
usernameOrUserId: "ชื่อผู้ใช้หรือรหัสผู้ใช้งาน"
noSuchUser: "ไม่พบผู้ใช้"
lookup: "การค้นหา"
announcements: "ประกาศ"
-imageUrl: "url รูปภาพ"
+imageUrl: "URL รูปภาพ"
remove: "ลบ"
removed: "ถูกลบไปแล้ว"
-removeAreYouSure: "นายแน่ใจจริงหรอว่าต้องการที่จะลบออก \"{x}\""
-deleteAreYouSure: "ต้องการลบ {x} หรือไม่คะ?"
-resetAreYouSure: "รีเซ็ตเลยไหม"
+removeAreYouSure: "ต้องการลบ “{x}” ใช่ไหม?"
+deleteAreYouSure: "ต้องการลบ “{x}” ใช่ไหม?"
+resetAreYouSure: "รีเซ็ตเลยไหม?"
+areYouSure: "แน่ใจแล้วใช่ไหมคะ?"
saved: "บันทึกแล้ว"
messaging: "แชท"
-upload: "อัพโหลด"
+upload: "อัปโหลด"
keepOriginalUploading: "เก็บภาพต้นฉบับ"
-keepOriginalUploadingDescription: "บันทึกรูปภาพที่อัพโหลดต้นฉบับตามที่เป็นอยู่ ถ้าหากปิดอยู่ ระบบจะสร้างเวอร์ชั่นที่จะแสดงบนเว็บเมื่ออัพโหลดนะ"
+keepOriginalUploadingDescription: "เก็บภาพต้นฉบับไว้เมื่ออัปโหลดภาพ หากปิด รูปภาพสำหรับการเผยแพร่ทางเว็บจะถูกสร้างขึ้นในเบราว์เซอร์เมื่อทำการอัปโหลด"
fromDrive: "จากไดรฟ์"
fromUrl: "จาก URL"
-uploadFromUrl: "อัพโหลดจาก URL"
+uploadFromUrl: "อัปโหลดจาก URL"
uploadFromUrlDescription: "URL ของไฟล์ที่คุณต้องการอัปโหลด"
-uploadFromUrlRequested: "อัพโหลดที่ร้องขอ"
-uploadFromUrlMayTakeTime: "มันอาจจะต้องใช้เวลาสักครู่จนกว่าการอัพโหลดจะเสร็จสมบูรณ์นะ"
+uploadFromUrlRequested: "ร้องขอการอัปโหลดแล้ว"
+uploadFromUrlMayTakeTime: "การอัปโหลดอาจใช้เวลาสักครู่จึงจะเสร็จสมบูรณ์"
explore: "สำรวจ"
messageRead: "อ่านแล้ว"
-noMoreHistory: "ในนั้นไม่มีประวัติอีกต่อไปแล้วนะ"
+noMoreHistory: "ไม่มีประวัติเพิ่มเติม"
startMessaging: "เริ่มการสนทนา"
nUsersRead: "อ่านโดย {n}"
agreeTo: "ฉันยอมรับที่จะ {0}"
@@ -279,9 +289,9 @@ agree: "ยอมรับ"
agreeBelow: "ฉันยอมรับถึงด้านล่าง"
basicNotesBeforeCreateAccount: "หมายเหตุสำคัญ"
termsOfService: "เงื่อนไขการให้บริการ"
-start: "เริ่มต้นใช้งาน"
+start: "เริ่ม"
home: "หน้าแรก"
-remoteUserCaution: "เนื่องจากผู้ใช้งานรายนี้นั้น มาจากอินสแตนซ์ระยะไกล ข้อมูลที่แสดงดังกล่าวนั้นอาจจะไม่สมบูรณ์ก็ได้นะ"
+remoteUserCaution: "ข้อมูลอาจไม่สมบูรณ์เนื่องจากผู้ใช้รายนี้มาจากอินสแตนซ์ระยะไกล"
activity: "กิจกรรม"
images: "รูปภาพ"
image: "รูปภาพ"
@@ -290,13 +300,13 @@ yearsOld: "{age} ปี"
registeredDate: "วันที่สมัครสมาชิก"
location: "ตำแหน่งที่ตั้ง"
theme: "ธีม"
-themeForLightMode: "ธีมที่จะใช้ในโหมดแสง"
+themeForLightMode: "ธีมที่จะใช้ในโหมดสว่าง"
themeForDarkMode: "ธีมที่จะใช้ในโหมดมืด"
light: "สว่าง"
dark: "มืด"
lightThemes: "ธีมสว่าง"
darkThemes: "ธีมมืด"
-syncDeviceDarkMode: "ซิงค์โหมดมืดด้วยการตั้งค่ากับอุปกรณ์"
+syncDeviceDarkMode: "ซิงค์โหมดมืดกับการตั้งค่าอุปกรณ์ของคุณ"
drive: "ไดรฟ์"
fileName: "ชื่อไฟล์"
selectFile: "เลือกไฟล์"
@@ -304,46 +314,47 @@ selectFiles: "เลือกไฟล์"
selectFolder: "เลือกโฟลเดอร์"
selectFolders: "เลือกโฟลเดอร์"
renameFile: "เปลี่ยนชื่อไฟล์"
-folderName: "ชื่อแฟ้ม"
+folderName: "ชื่อโฟลเดอร์"
createFolder: "สร้างโฟลเดอร์"
renameFolder: "เปลี่ยนชื่อโฟลเดอร์"
deleteFolder: "ลบโฟลเดอร์"
+folder: "โฟลเดอร์"
addFile: "เพิ่มไฟล์"
emptyDrive: "ไดรฟ์ของคุณว่างเปล่านะ"
emptyFolder: "โฟลเดอร์นี้ว่างเปล่า"
unableToDelete: "ไม่สามารถลบออกได้"
-inputNewFileName: "ป้อนชื่อไฟล์ใหม่นะ"
+inputNewFileName: "ป้อนชื่อไฟล์ใหม่"
inputNewDescription: "กรุณาใส่แคปชั่นใหม่"
-inputNewFolderName: "กรุณาใส่ชื่อโฟลเดอร์ใหม่นะ\n"
-circularReferenceFolder: "โฟลเดอร์ปลายทาง คือ โฟลเดอร์ย่อยของโฟลเดอร์ที่คุณต้องการที่จะย้ายล่ะนะ"
-hasChildFilesOrFolders: "เนื่องจากโฟลเดอร์นี้ไม่ว่างเปล่า จึงไม่สามารถลบได้นะ"
+inputNewFolderName: "กรุณาใส่ชื่อโฟลเดอร์ใหม่"
+circularReferenceFolder: "โฟลเดอร์ปลายทางคือโฟลเดอร์ย่อยของโฟลเดอร์ที่คุณกำลังย้าย"
+hasChildFilesOrFolders: "เนื่องจากโฟลเดอร์นี้ไม่ว่างเปล่า จึงไม่สามารถลบ"
copyUrl: "คัดลอก URL"
rename: "เปลี่ยนชื่อ"
avatar: "ไอคอน"
banner: "แบนเนอร์"
-displayOfSensitiveMedia: "แสดงผลสื่อละเอียดอ่อน"
-whenServerDisconnected: "สูญเสียการเชื่อมต่อกับเซิร์ฟเวอร์"
-disconnectedFromServer: "ถูกตัดการเชื่อมต่อออกจากเซิร์ฟเวอร์"
+displayOfSensitiveMedia: "แสดงสื่อที่มีเนื้อหาละเอียดอ่อน"
+whenServerDisconnected: "เมื่อสูญเสียการเชื่อมต่อกับเซิร์ฟเวอร์"
+disconnectedFromServer: "การเชื่อมต่อเซิร์ฟเวอร์ถูกตัด"
reload: "รีโหลด"
doNothing: "เมิน"
-reloadConfirm: "นายต้องการรีเฟรชไทม์ไลน์หรือป่าว?"
+reloadConfirm: "รีโหลดเลยไหม?"
watch: "ดู"
unwatch: "หยุดดู"
accept: "ยอมรับ"
reject: "ปฏิเสธ"
normal: "ปกติ"
-instanceName: "ชื่อ อินสแตนซ์"
+instanceName: "ชื่ออินสแตนซ์"
instanceDescription: "คำอธิบายอินสแตนซ์"
maintainerName: "ผู้ดูแล"
-maintainerEmail: "อีเมล์แอดมิน"
-tosUrl: "เงื่อนไขการให้บริการ URL"
+maintainerEmail: "อีเมลผู้ดูแลระบบ"
+tosUrl: "URL เงื่อนไขการให้บริการ"
thisYear: "ปีนี้"
thisMonth: "เดือนนี้"
today: "วันนี้"
dayX: "{day}"
monthX: "เดือน {month}"
yearX: "{year}"
-pages: "หน้า"
+pages: "หน้าเพจ"
integration: "รวบรวม"
connectService: "เชื่อมต่อ"
disconnectService: "ตัดการเชื่อมต่อ"
@@ -352,23 +363,28 @@ enableGlobalTimeline: "เปิดใช้งานไทม์ไลน์ท
disablingTimelinesInfo: "ผู้ดูแลระบบและผู้ควบคุมจะสามารถเข้าถึงไทม์ไลน์ทั้งหมด ถึงแม้ว่าจะไม่ได้เปิดใช้งานก็ตาม"
registration: "ลงทะเบียน"
enableRegistration: "เปิดใช้งานการลงทะเบียนผู้ใช้ใหม่"
-invite: "เชิญชวน"
+invite: "คำเชิญ"
driveCapacityPerLocalAccount: "ความจุของไดรฟ์ต่อผู้ใช้ภายในเครื่อง"
driveCapacityPerRemoteAccount: "ความจุของไดรฟ์ต่อผู้ใช้ระยะไกล"
inMb: "เป็นเมกะไบต์"
bannerUrl: "URL รูปภาพแบนเนอร์"
backgroundImageUrl: "URL ภาพพื้นหลัง"
basicInfo: "ข้อมูลเบื้องต้น"
-pinnedUsers: "ผู้ใช้งานที่ได้รับการปักหมุด"
-pinnedUsersDescription: "ลิสต์ชื่อผู้ใช้โดยคั่นด้วยการขึ้นบรรทัดใหม่เพื่อปักหมุดในแท็บ \"สำรวจ\""
-pinnedPages: "หน้าที่ปักหมุด"
-pinnedPagesDescription: "ป้อนเส้นทางของหน้าที่คุณต้องการตรึงไว้ที่หน้าแรกของอินสแตนซ์นี้ โดยคั่นด้วยตัวแบ่งบรรทัด"
+pinnedUsers: "ผู้ใช้ที่ถูกปักหมุด"
+pinnedUsersDescription: "ป้อนชื่อผู้ใช้ที่คุณต้องการปักหมุดในหน้า “ค้นพบ” ฯลฯ คั่นด้วยการขึ้นบรรทัดใหม่"
+pinnedPages: "หน้าเพจที่ปักหมุด"
+pinnedPagesDescription: "ป้อนเส้นทางของหน้าเพจที่คุณต้องการปักหมุดไว้ที่หน้าแรกของอินสแตนซ์นี้ คั่นด้วยขึ้นบรรทัดใหม่"
pinnedClipId: "ID ของคลิปที่จะปักหมุด"
pinnedNotes: "โน้ตที่ปักหมุดไว้"
hcaptcha: "hCaptcha"
enableHcaptcha: "เปิดใช้ hCaptcha"
hcaptchaSiteKey: "คีย์ไซต์"
hcaptchaSecretKey: "คีย์ลับ"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "เปิดใช้ mCaptcha"
+mcaptchaSiteKey: "คีย์ไซต์"
+mcaptchaSecretKey: "คีย์ลับ"
+mcaptchaInstanceUrl: "URL ของอินสแตนซ์ของ mCaptcha"
recaptcha: "reCAPTCHA"
enableRecaptcha: "เปิดใช้ reCAPTCHA"
recaptchaSiteKey: "คีย์ไซต์"
@@ -384,26 +400,26 @@ name: "ชื่อ"
antennaSource: "แหล่งเสาอากาศ"
antennaKeywords: "คีย์เวิร์ดที่ควรฟัง"
antennaExcludeKeywords: "คีย์เวิร์ดที่จะยกเว้น"
-antennaKeywordsDescription: "คั่นด้วยช่องว่างสำหรับเงื่อนไข AND หรือด้วยการขึ้นบรรทัดใหม่สำหรับเงื่อนไข OR นะ"
+antennaKeywordsDescription: "คั่นด้วยช่องว่างสำหรับเงื่อนไข AND หรือด้วยการขึ้นบรรทัดใหม่สำหรับเงื่อนไข OR"
notifyAntenna: "แจ้งเตือนเกี่ยวกับโน้ตใหม่"
withFileAntenna: "เฉพาะโน้ตที่มีไฟล์"
-enableServiceworker: "เปิดใช้งาน การแจ้งเตือนแบบพุชสำหรับเบราว์เซอร์ของคุณ"
+enableServiceworker: "เปิดใช้งานการแจ้งเตือนแบบพุชไปยังเบราว์เซอร์ของคุณ"
antennaUsersDescription: "ระบุหนึ่งชื่อผู้ใช้ต่อบรรทัด"
-caseSensitive: "กรณีที่สำคัญ"
+caseSensitive: "อักษรพิมพ์ใหญ่-พิมพ์เล็กความหมายต่างกัน"
withReplies: "รวมตอบกลับ"
connectedTo: "บัญชีดังต่อไปนี้มีการเชื่อมต่อกัน"
notesAndReplies: "โพสต์และการตอบกลับ"
-withFiles: "รวบรวมไฟล์"
+withFiles: "มีไฟล์"
silence: "ถูกปิดปาก"
-silenceConfirm: "นายแน่ใจแล้วหรอว่าต้องการที่จะ ปิดปาก ผู้ใช้งานรายนี้?"
+silenceConfirm: "ต้องการปิดปากผู้ใช้รายนี้ใช่ไหม?"
unsilence: "ยกเลิกการปิดปาก"
-unsilenceConfirm: "นายแน่ใจแล้วหรอว่าต้องการที่จะยกเลิกปิดปากผู้ใช้งานรายนี้?"
+unsilenceConfirm: "ต้องการเลิกปิดปากผู้ใช้รายนี้ใช่ไหม?"
popularUsers: "ผู้ใช้ที่เป็นที่นิยม"
recentlyUpdatedUsers: "ผู้ใช้ที่เพิ่งใช้งานล่าสุด"
recentlyRegisteredUsers: "ผู้ใช้ที่เข้าร่วมใหม่"
recentlyDiscoveredUsers: "ผู้ใช้ที่เพิ่งค้นพบใหม่"
-exploreUsersCount: "มีผู้ใช้ {จำนวน} ราย"
-exploreFediverse: "สำรวจเฟดดิเวิร์ส"
+exploreUsersCount: "มีผู้ใช้ {count} ราย"
+exploreFediverse: "สำรวจสหพันธ์"
popularTags: "แท็กยอดนิยม"
userList: "ลิสต์"
about: "เกี่ยวกับ"
@@ -418,8 +434,8 @@ moderator: "ผู้ควบคุม"
moderation: "การกลั่นกรอง"
moderationNote: "โน้ตการกลั่นกรอง"
addModerationNote: "เพิ่มโน้ตการกลั่นกรอง"
-moderationLogs: "บันทึกการกลั่นกรอง"
-nUsersMentioned: "กล่าวถึงโดยผู้ใช้ {n} รายนี้"
+moderationLogs: "ปูมการแก้ไข"
+nUsersMentioned: "กล่าวถึงโดยผู้ใช้ {n} ราย"
securityKeyAndPasskey: "ความปลอดภัยและรหัสผ่าน"
securityKey: "กุญแจความปลอดภัย"
lastUsed: "ใช้ล่าสุด"
@@ -428,20 +444,19 @@ unregister: "เลิกติดตาม"
passwordLessLogin: "เข้าสู่ระบบแบบไม่ใช้รหัสผ่าน"
passwordLessLoginDescription: "อนุญาตให้เข้าสู่ระบบโดยไม่ต้องใช้รหัสผ่านโดยใช้รหัสรักษาความปลอดภัยหรือรหัสผ่านเท่านั้น"
resetPassword: "รีเซ็ตรหัสผ่าน"
-newPasswordIs: "รหัสผ่านใหม่คือ \"{password}\""
+newPasswordIs: "รหัสผ่านใหม่คือ “{password}”"
reduceUiAnimation: "ลดภาพเคลื่อนไหว UI"
-share: "แชร์"
+share: "แบ่งปัน"
notFound: "ไม่พบหน้าที่ต้องการ"
-notFoundDescription: "ไม่พบหน้าที่สอดคล้องตรงกันกับ URL นี้นะ"
-uploadFolder: "โฟลเดอร์เริ่มต้นสำหรับอัพโหลด"
-cacheClear: "ล้างแคช"
+notFoundDescription: "ไม่พบหน้าตาม URL ที่ระบุ"
+uploadFolder: "โฟลเดอร์เริ่มต้นสำหรับอัปโหลด"
markAsReadAllNotifications: "ทำเครื่องหมายการแจ้งเตือนทั้งหมดว่าอ่านแล้ว"
markAsReadAllUnreadNotes: "ทำเครื่องหมายโน้ตทั้งหมดว่าอ่านแล้ว"
markAsReadAllTalkMessages: "ทำเครื่องหมายข้อความทั้งหมดว่าอ่านแล้ว"
help: "ช่วยเหลือ"
inputMessageHere: "พิมพ์ข้อความที่นี่"
close: "ปิด"
-invites: "เชิญชวน"
+invites: "คำเชิญ"
members: "สมาชิก"
transfer: "ถ่ายโอน"
title: "หัวข้อ"
@@ -449,15 +464,15 @@ text: "ข้อความ"
enable: "เปิดใช้งาน"
next: "ถัดไป"
retype: "พิมพ์รหัสอีกครั้ง"
-noteOf: "โน้ต โดย {user}"
+noteOf: "โน้ตของ {user}"
quoteAttached: "อ้างอิง"
-quoteQuestion: "นายต้องการที่จะอ้างอิงหรอ?"
-noMessagesYet: "ยังไม่มีข้อความนะ"
+quoteQuestion: "ต้องการที่จะแนบมันเพื่ออ้างอิงใช่ไหม?"
+noMessagesYet: "ยังไม่มีข้อความ"
newMessageExists: "คุณมีข้อความใหม่"
-onlyOneFileCanBeAttached: "คุณสามารถแนบไฟล์กับข้อความได้เพียงไฟล์เดียวเท่านั้นนะ"
-signinRequired: "กรุณาลงทะเบียนหรือลงชื่อเข้าใช้ก่อนดำเนินการต่อนะ"
-invitations: "เชิญชวน"
-invitationCode: "รหัสคำเชิญ"
+onlyOneFileCanBeAttached: "สามารถแนบไฟล์ได้เพียงไฟล์เดียวต่อ 1 ข้อความ"
+signinRequired: "กรุณาลงทะเบียนหรือลงชื่อเข้าใช้ก่อนดำเนินการต่อ"
+invitations: "คำเชิญ"
+invitationCode: "รหัสเชิญ"
checking: "Checking"
available: "พร้อมใช้งาน"
unavailable: "ไม่พร้อมใช้"
@@ -475,11 +490,11 @@ or: "หรือ"
language: "ภาษา"
uiLanguage: "ภาษาอินเทอร์เฟซผู้ใช้งาน"
aboutX: "เกี่ยวกับ {x}"
-emojiStyle: "สไตล์อิโมจิ"
+emojiStyle: "สไตล์เอโมจิ"
native: "ภาษาแม่"
disableDrawer: "อย่าใช้ลิ้นชักสไตล์เมนู"
showNoteActionsOnlyHover: "แสดงการดำเนินการเฉพาะโน้ตเมื่อโฮเวอร์"
-noHistory: "ไม่มีรายการ"
+noHistory: "ไม่มีประวัติ"
signinHistory: "ประวัติการเข้าสู่ระบบ"
enableAdvancedMfm: "เปิดใช้งาน MFM ขั้นสูง"
enableAnimatedMfm: "เปิดการใช้งาน MFM ด้วยแอนิเมชั่น"
@@ -491,7 +506,7 @@ createAccount: "สร้างบัญชี"
existingAccount: "บัญชีที่มีอยู่"
regenerate: "สร้างอีกครั้ง"
fontSize: "ขนาดตัวอักษร"
-mediaListWithOneImageAppearance: "ความสูงของลิสต์สื่อจะต้องมีรูปภาพเดียวเท่านั้น"
+mediaListWithOneImageAppearance: "ความสูงของรายการสื่อที่มีเพียงรูปเดียว"
limitTo: "จำกัดไว้ที่ {x}"
noFollowRequests: "คุณไม่มีคำขอติดตามที่รอดำเนินการ"
openImageInNewTab: "เปิดรูปภาพในแท็บใหม่"
@@ -509,14 +524,14 @@ promote: "โปรโมท"
numberOfDays: "จำนวนวัน"
hideThisNote: "ซ่อนโน้ตนี้"
showFeaturedNotesInTimeline: "แสดงโน้ตเด่นในไทม์ไลน์"
-objectStorage: "อ็อบเจ็กต์ ที่จัดเก็บ"
-useObjectStorage: "ใช้ อ็อบเจ็กต์ ที่จัดเก็บ"
-objectStorageBaseUrl: "URL ฐาน"
+objectStorage: "การจัดเก็บในรูปแบบอ็อบเจกต์"
+useObjectStorage: "ใช้การจัดเก็บในรูปแบบอ็อบเจกต์"
+objectStorageBaseUrl: "Base URL"
objectStorageBaseUrlDesc: "URL ที่ใช้เป็นข้อมูลอ้างอิง ระบุ URL ของ CDN หรือ Proxy ถ้าหากคุณใช้อย่างใดอย่างหนึ่ง\n สำหรับการใช้งาน S3 'https://.s3.amazonaws.com' และสำหรับ GCS หรือบริการที่เทียบเท่าใช้ 'https://storage.googleapis.com/', เป็นต้น"
objectStorageBucket: "Bucket"
objectStorageBucketDesc: "โปรดระบุชื่อที่เก็บข้อมูลที่ใช้กับผู้ให้บริการของคุณ"
objectStoragePrefix: "คำนำหน้า"
-objectStoragePrefixDesc: "ไฟล์ทั้งหมดจะถูกเก็บไว้ภายใต้ไดเร็กทอรีที่มีคำนำหน้านี้นะ"
+objectStoragePrefixDesc: "ไฟล์ทั้งหมดจะถูกเก็บไว้ภายใต้ไดเร็กทอรีที่มีคำนำหน้านี้"
objectStorageEndpoint: "ปลายทาง"
objectStorageEndpointDesc: "เว้นว่างไว้หากคุณใช้ AWS S3 หรือระบุปลายทางเป็น '' หรือ ':' ทั้งนี้ขึ้นอยู่กับผู้ให้บริการที่คุณใช้อยู่ด้วย"
objectStorageRegion: "ภูมิภาค"
@@ -525,12 +540,13 @@ objectStorageUseSSL: "ใช้ SSL"
objectStorageUseSSLDesc: "ปิดการทำงานนี้ไว้ ถ้าหากคุณจะไม่ใช้ HTTPS สำหรับการเชื่อมต่อ API"
objectStorageUseProxy: "เชื่อมต่อผ่านพร็อกซี"
objectStorageUseProxyDesc: "ปิดสิ่งนี้ไว้ถ้าหากคุณจะไม่ใช้ Proxy สำหรับการเชื่อมต่อ API"
-objectStorageSetPublicRead: "ตั้งค่า \"public-read\" ในการอัปโหลด"
+objectStorageSetPublicRead: "ตั้งค่าเป็น “public-read” เมื่ออัปโหลด"
s3ForcePathStyleDesc: "ถ้าหากเปิดใช้งาน s3ForcePathStyle ชื่อบัคเก็ตนั้นอาจจะต้องรวมอยู่ในเส้นทางของ URL ซึ่งตรงข้ามกับชื่อโฮสต์ของ URL คุณอาจจะต้องเปิดใช้งานการตั้งค่านี้เมื่อใช้บริการต่างๆ เช่น อินสแตนซ์ Minio ที่โฮสต์เองนะ"
-serverLogs: "บันทึกของเซิร์ฟเวอร์"
+serverLogs: "ปูมของเซิร์ฟเวอร์"
deleteAll: "ลบทั้งหมด"
showFixedPostForm: "แสดงแบบฟอร์มการโพสต์ที่ด้านบนสุดของไทม์ไลน์"
-showFixedPostFormInChannel: "แสดงแบบฟอร์มกำลังโพสต์ที่ด้านบนของไทม์ไลน์ (แชนแนล)"
+showFixedPostFormInChannel: "แสดงแบบฟอร์มการโพสต์ที่ด้านบนของไทม์ไลน์ (ช่อง)"
+withRepliesByDefaultForNewlyFollowed: "แสดงการตอบกลับจากผู้ใช้ที่คุณเพิ่งติดตามลงไทม์ไลน์ตามค่าเริ่มต้น"
newNoteRecived: "มีโน้ตใหม่"
sounds: "เสียง"
sound: "เสียง"
@@ -538,10 +554,12 @@ listen: "ฟัง"
none: "ไม่มี"
showInPage: "แสดงในเพจ"
popout: "ป๊อปเอาต์"
-volume: "ความดัง"
-masterVolume: "มาสเตอร์วอลุ่ม"
+volume: "ระดับเสียง"
+masterVolume: "ระดับเสียงหลัก"
+notUseSound: "ไม่ใช้เสียง"
+useSoundOnlyWhenActive: "มีเสียงออกเฉพาะตอนกำลังใช้ Misskey อยู่เท่านั้น"
details: "รายละเอียด"
-chooseEmoji: "เลือกโมจิของเธอ"
+chooseEmoji: "เลือกเอโมจิ"
unableToProcess: "ไม่สามารถดำเนินการให้เสร็จสิ้นได้"
recentUsed: "ใช้ล่าสุด"
install: "ติดตั้ง"
@@ -552,20 +570,24 @@ installedDate: "วันที่ติดตั้ง"
lastUsedDate: "ใช้งานครั้งล่าสุด"
state: "สถานะ"
sort: "เรียงลำดับ"
-ascendingOrder: "เรียงจากน้อยไปมาก"
-descendingOrder: "เรียงจากมากไปน้อย"
-scratchpad: "กระดานทดลอง"
+ascendingOrder: "เรียงลำดับขึ้น"
+descendingOrder: "เรียงลำดับลง"
+scratchpad: "Scratchpad"
scratchpadDescription: "Scratchpad เป็นการจัดเตรียมสภาพแวดล้อมสำหรับการทดลอง AiScript แต่คุณสามารถเขียน ดำเนินการ และตรวจสอบผลลัพธ์ของการโต้ตอบกับ Misskey มันได้ด้วยนะ"
output: "เอาท์พุต"
script: "สคริปต์"
disablePagesScript: "ปิดการใช้งาน AiScript บนเพจ"
updateRemoteUser: "อัปเดตข้อมูลผู้ใช้งานระยะไกล"
+unsetUserAvatar: "เลิกตั้งอวตาร"
+unsetUserAvatarConfirm: "ต้องการเลิกตั้งอวตารใข่ไหม?"
+unsetUserBanner: "เลิกตั้งแบนเนอร์"
+unsetUserBannerConfirm: "ต้องการเลิกตั้งแบนเนอร์?"
deleteAllFiles: "ลบไฟล์ทั้งหมด"
-deleteAllFilesConfirm: "นายแน่ใจแล้วหรอว่าต้องการที่จะลบไฟล์ทั้งหมด?"
+deleteAllFilesConfirm: "ต้องการลบไฟล์ทั้งหมดใช่ไหม?"
removeAllFollowing: "เลิกติดตามผู้ใช้ที่ติดตามทั้งหมด"
-removeAllFollowingDescription: "การที่คุณดำเนินการนี้จะเลิกติดตามบัญชีทั้งหมดจาก {host} โปรดเรียกใช้คำสั่งสิ่งนี้หากต้องการยกเลิกอินสแตนซ์ เช่น ไม่มีอยู่แล้ว"
+removeAllFollowingDescription: "เลิกติดตามทั้งหมดจาก {host} โปรดเรียกใช้สิ่งนี้เมื่ออินสแตนซ์ดังกล่าวได้สูญหายตายจากไปแล้ว"
userSuspended: "ผู้ใช้รายนี้ถูกระงับการใช้งาน"
-userSilenced: "ผู้ใช้รายนี้กำลังถูกปิดกั้น"
+userSilenced: "ผู้ใช้รายนี้ถูกปิดปากอยู่"
yourAccountSuspendedTitle: "บัญชีนี้นั้นถูกระงับ"
yourAccountSuspendedDescription: "บัญชีนี้ถูกระงับ เนื่องจากละเมิดข้อกำหนดในการให้บริการของเซิร์ฟเวอร์หรืออาจจะละเมิดหลักเกณฑ์ชุมชน หรือ อาจจะโดนร้องเรียนเรื่องการละเมิดลิขสิทธิ์และอื่นๆอย่างต่อเนื่องซ้ำๆ หากคุณคิดว่าไม่ได้ทำผิดจริงๆหรือตัดสินผิดพลาด ได้โปรดกรุณาติดต่อผู้ดูแลระบบหากคุณต้องการทราบเหตุผลโดยละเอียดเพิ่มเติม และขอความกรุณาอย่าสร้างบัญชีใหม่"
tokenRevoked: "โทเค็นไม่ถูกต้อง"
@@ -578,7 +600,7 @@ addItem: "เพิ่มรายการ"
rearrange: "จัดใหม่"
relays: "รีเลย์"
addRelay: "เพิ่มรีเลย์"
-inboxUrl: "อินบ็อกซ์ URL"
+inboxUrl: "URL ของอินบ็อกซ์"
addedRelays: "เพิ่มรีเลย์แล้ว"
serviceworkerInfo: "ต้องเปิดใช้งานสำหรับการแจ้งเตือนแบบพุช"
deletedNote: "โน้ตที่ถูกลบ"
@@ -595,14 +617,14 @@ description: "รายละเอียด"
describeFile: "เพิ่มแคปชั่น"
enterFileDescription: "ใส่แคปชั่น"
author: "ผู้เขียน"
-leaveConfirm: "คุณมีการเปลี่ยนแปลงที่ไม่ได้บันทึกนะ นายต้องการทิ้งการเปลี่ยนแปลงเหล่านั้นหรอ?"
+leaveConfirm: "มีการเปลี่ยนแปลงที่ยังไม่ได้บันทึก ต้องการละทิ้งมันใช่ไหม?"
manage: "การจัดการ"
plugins: "ปลั๊กอิน"
preferencesBackups: "ตั้งค่าการสำรองข้อมูล"
deck: "เด็ค"
undeck: "ออกจากเด็ค"
useBlurEffectForModal: "ใช้เอฟเฟกต์เบลอสำหรับโมดอล"
-useFullReactionPicker: "ใช้เครื่องมือเลือกปฏิกิริยาขนาดเต็ม"
+useFullReactionPicker: "ใช้ตัวจิ้มรีแอคชั่นอย่างเต็มรูปแบบ"
width: "ความกว้าง"
height: "ความสูง"
large: "ใหญ่"
@@ -610,17 +632,18 @@ medium: "ปานกลาง"
small: "เล็ก"
generateAccessToken: "สร้างการเข้าถึงโทเค็น"
permission: "การอนุญาต"
+adminPermission: "สิทธิ์ของผู้ดูแลระบบ"
enableAll: "เปิดใช้งานทั้งหมด"
disableAll: "ปิดการใช้งานทั้งหมด"
tokenRequested: "ให้สิทธิ์การเข้าถึงบัญชี"
pluginTokenRequestedDescription: "ปลั๊กอินนี้จะสามารถใช้การอนุญาตที่ตั้งค่าไว้ที่นี่นะ"
notificationType: "ประเภทการแจ้งเตือน"
edit: "แก้ไข"
-emailServer: "อีเมล์เซิร์ฟเวอร์"
+emailServer: "อีเมลเซิร์ฟเวอร์"
enableEmail: "เปิดใช้งานการกระจายอีเมล"
emailConfigInfo: "ใช้เพื่อยืนยันอีเมลของคุณระหว่างการสมัครหรือถ้าหากคุณลืมรหัสผ่าน"
-email: "อีเมล์"
-emailAddress: "ที่อยู่อีเมล์"
+email: "อีเมล"
+emailAddress: "ที่อยู่อีเมล"
smtpConfig: "กำหนดค่าเซิร์ฟเวอร์ SMTP"
smtpHost: "โฮสต์"
smtpPort: "พอร์ต"
@@ -631,6 +654,7 @@ smtpSecure: "ใช้โดยนัย SSL/TLS สำหรับการเ
smtpSecureInfo: "ปิดสิ่งนี้เมื่อใช้ STARTTLS"
testEmail: "ทดสอบการส่งอีเมล"
wordMute: "ปิดเสียงคำ"
+hardWordMute: "ปิดเสียงคำยาก"
regexpError: "ข้อผิดพลาดของนิพจน์ทั่วไป"
regexpErrorDescription: "เกิดข้อผิดพลาดในนิพจน์ทั่วไปในบรรทัดที่ {line} ของการปิดเสียงคำ {tab} ของคุณ:"
instanceMute: "ปิดเสียง อินสแตนซ์"
@@ -640,41 +664,42 @@ display: "แสดงผล"
copy: "คัดลอก"
metrics: "เมตริก"
overview: "ภาพรวม"
-logs: "บันทึกข้อมูลระบบ"
+logs: "ปูม"
delayed: "ดีเลย์"
database: "ฐานข้อมูล"
-channel: "แชนแนล"
+channel: "ช่อง"
create: "สร้าง"
notificationSetting: "ตั้งค่าการแจ้งเตือน"
notificationSettingDesc: "เลือกประเภทการแจ้งเตือนที่ต้องการจะแสดง"
useGlobalSetting: "ใช้การตั้งค่าส่วนกลาง"
-useGlobalSettingDesc: "หากเปิดไว้ ระบบจะใช้การตั้งค่าการแจ้งเตือนของบัญชีของคุณ หากปิดอยู่ สามารถทำการกำหนดค่าแต่ละรายการได้นะ"
+useGlobalSettingDesc: "เมื่อเปิดใช้งาน ใช้การตั้งค่าการแจ้งเตือนจากบัญชีคุณ เมื่อปิดใช้งาน สามารถตั้งค่าได้อย่างอิสระ"
other: "อื่น ๆ"
regenerateLoginToken: "สร้างโทเค็นการเข้าสู่ระบบอีกครั้ง"
regenerateLoginTokenDescription: "สร้างโทเค็นใหม่ที่ใช้ภายในระหว่างการเข้าสู่ระบบ โดยตามหลักปกติแล้วการดำเนินการนี้ไม่จำเป็น หากสร้างใหม่ อุปกรณ์ทั้งหมดจะถูกออกจากระบบนะ"
+theKeywordWhenSearchingForCustomEmoji: "คีย์เวิร์ดสำหรับใช้ค้นหาเอโมจิที่กำหนดเอง"
setMultipleBySeparatingWithSpace: "คั่นหลายรายการด้วยช่องว่าง"
-fileIdOrUrl: "ไฟล์ ID หรือ URL"
+fileIdOrUrl: "ID ของไฟล์ หรือ URL"
behavior: "พฤติกรรม"
sample: "ตัวอย่าง"
abuseReports: "รายงาน"
reportAbuse: "รายงาน"
reportAbuseRenote: "รายงานรีโน้ต"
-reportAbuseOf: "รายงาน {ชื่อ}"
+reportAbuseOf: "รายงาน {name}"
fillAbuseReportDescription: "กรุณากรอกรายละเอียดเกี่ยวกับรายงานนี้ หากเป็นเรื่องเกี่ยวกับโน้ตโดยเฉพาะ ได้โปรดระบุ URL"
abuseReported: "เราได้ส่งรายงานของคุณไปแล้ว ขอบคุณมากๆนะ"
-reporter: "นักข่าว"
+reporter: "ผู้รายงาน"
reporteeOrigin: "รายงานต้นทาง"
-reporterOrigin: "นักข่าวต้นทาง"
+reporterOrigin: "แหล่งผู้รายงาน"
forwardReport: "ส่งต่อรายงานไปยังอินสแตนซ์ระยะไกล"
-forwardReportIsAnonymous: "แทนที่จะเป็นบัญชีของคุณ บัญชีระบบที่ไม่ระบุตัวตนจะแสดงเป็นนักข่าวที่อินสแตนซ์ระยะไกล"
+forwardReportIsAnonymous: "ข้อมูลของคุณจะไม่ปรากฏบนอินสแตนซ์ระยะไกลและปรากฏเป็นบัญชีระบบที่ไม่ระบุชื่อ"
send: "ส่ง"
abuseMarkAsResolved: "ทำเครื่องหมายรายงานว่าแก้ไขแล้ว"
openInNewTab: "เปิดในแท็บใหม่"
openInSideView: "เปิดในมุมมองด้านข้าง"
defaultNavigationBehaviour: "พฤติกรรมการนำทางที่เป็นค่าเริ่มต้น"
editTheseSettingsMayBreakAccount: "การแก้ไขการตั้งค่าเหล่านี้อาจทำให้บัญชีของคุณเสียหายนะ"
-instanceTicker: "ข้อมูลอินสแตนซ์ของบันทึกย่อ"
-waitingFor: "กำลังรอคอย {x}"
+instanceTicker: "ข้อมูลอินสแตนซ์ของโน้ต"
+waitingFor: "กำลังรอ {x}"
random: "สุ่มค่า"
system: "ระบบ"
switchUi: "สลับ UI"
@@ -684,7 +709,7 @@ createNew: "สร้างใหม่"
optional: "ไม่บังคับ"
createNewClip: "สร้างคลิปใหม่"
unclip: "ลบคลิป"
-confirmToUnclipAlreadyClippedNote: "โน้ตนี้เป็นส่วนหนึ่งของคลิป \"{name}\" แล้ว คุณต้องการลบออกจากคลิปนี้แทนอย่างงั้นหรอ?"
+confirmToUnclipAlreadyClippedNote: "โน้ตนี้เป็นส่วนหนึ่งของคลิป “{name}” อยู่แล้ว ต้องการนำมันออกจากคลิปใช่ไหม?"
public: "สาธารณะ"
private: "ส่วนตัว"
i18nInfo: "Misskey กำลังได้รับการแปลเป็นภาษาต่างๆ โดยอาสาสมัคร คุณสามารถช่วยเหลือได้ที่ {link}"
@@ -697,8 +722,8 @@ repliedCount: "จำนวนของการตอบกลับที่
renotedCount: "จำนวนรีโน้ตที่ได้รับแล้ว"
followingCount: "จำนวนบัญชีที่ติดตาม"
followersCount: "จำนวนผู้ติดตาม"
-sentReactionsCount: "จำนวนปฏิกิริยาที่ส่ง"
-receivedReactionsCount: "จำนวนปฏิกิริยาที่ได้รับ"
+sentReactionsCount: "จำนวนรีแอคชั่นที่ส่ง"
+receivedReactionsCount: "จำนวนรีแอคชั่นที่ได้รับ"
pollVotesCount: "จำนวนโหวตที่ส่งไป"
pollVotedCount: "จำนวนโหวตที่ได้รับ"
yes: "ใช่"
@@ -706,17 +731,17 @@ no: "ไม่"
driveFilesCount: "จำนวนไฟล์ไดรฟ์"
driveUsage: "การใช้พื้นที่ไดรฟ์"
noCrawle: "ปฏิเสธการจัดทำดัชนีของโปรแกรมรวบรวมข้อมูล"
-noCrawleDescription: "ขอให้เครื่องมือค้นหาไม่จัดทำดัชนีหน้าโปรไฟล์ บันทึกย่อ หน้า ฯลฯ"
-lockedAccountInfo: "เว้นแต่ว่าคุณจะต้องตั้งค่าการเปิดเผยโน้ตเป็น \"ผู้ติดตามเท่านั้น\" โน้ตย่อของคุณจะปรากฏแก่ทุกคน ถึงแม้ว่าคุณจะเป็นกำหนดให้ผู้ติดตามต้องได้รับการอนุมัติด้วยตนเองก็ตาม"
-alwaysMarkSensitive: "ทำเครื่องหมายเป็น NSFW เป็นค่าเริ่มต้น"
+noCrawleDescription: "ขอให้เครื่องมือค้นหาไม่จัดทำดัชนีหน้าโปรไฟล์ โน้ต หน้าเพจ ฯลฯ"
+lockedAccountInfo: "แม้ว่าการอนุมัติการติดตามถูกเปิดใช้งานอยู่ทุกคนก็ยังคงสามารถเห็นโน้ตของคุณได้ เว้นแต่ว่าคุณจะเปลี่ยนการเปิดเผยโน้ตของคุณเป็น “เฉพาะผู้ติดตาม”"
+alwaysMarkSensitive: "ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อนเป็นค่าเริ่มต้น"
loadRawImages: "โหลดภาพต้นฉบับแทนการแสดงภาพขนาดย่อ"
disableShowingAnimatedImages: "ไม่ต้องเล่นภาพเคลื่อนไหว"
-highlightSensitiveMedia: "ไฮไลท์สื่อที่ละเอียดอ่อน"
+highlightSensitiveMedia: "ไฮไลท์สื่อที่มีเนื้อหาละเอียดอ่อน"
verificationEmailSent: "ส่งอีเมลยืนยันแล้วนะ ได้โปรดกรุณาไปที่ลิงก์ที่รวมไว้เพื่อทำการตรวจสอบให้เสร็จสิ้น"
notSet: "ไม่ได้ตั้งค่า"
emailVerified: "อีเมลได้รับการยืนยันแล้ว"
noteFavoritesCount: "จำนวนโน้ตที่ชื่นชอบ"
-pageLikesCount: "จำนวนเพจที่ชอบ"
+pageLikesCount: "จำนวนเพจที่ถูกใจ"
pageLikedCount: "จำนวนการกดถูกใจเพจที่ได้รับแล้ว"
contact: "ติดต่อ"
useSystemFont: "ใช้ฟอนต์เริ่มต้นของระบบ"
@@ -725,15 +750,15 @@ experimentalFeatures: "ฟังก์ชั่นทดสอบ"
experimental: "ทดลอง"
thisIsExperimentalFeature: "นี่คือฟีเจอร์ทดลองนะค่ะ ฟังก์ชันการทำงานบางอย่างอาจเปลี่ยนแปลงได้ และอาจไม่ทำงานหรือไม่เสถียรตามที่ตั้งใจไว้นะ"
developer: "สำหรับนักพัฒนา"
-makeExplorable: "ทำให้บัญชีมองเห็นใน \"สำรวจ\""
-makeExplorableDescription: "ถ้าหากคุณปิดการทำงานนี้ บัญชีของคุณนั้นจะไม่แสดงในส่วน \"สำรวจ\" นะ"
+makeExplorable: "ทำให้บัญชีมองเห็นใน “สำรวจ”"
+makeExplorableDescription: "ถ้าหากคุณปิดการทำงานนี้ บัญชีของคุณนั้นจะไม่แสดงในส่วน “สำรวจ”"
showGapBetweenNotesInTimeline: "แสดงช่องว่างระหว่างโพสต์บนไทม์ไลน์"
duplicate: "ทำซ้ำ"
left: "ซ้าย"
-center: "ศูนย์กลาง"
+center: "กึ่งกลาง"
wide: "กว้าง"
narrow: "ชิด"
-reloadToApplySetting: "การตั้งค่านี้จะมีผลหลังจากโหลดหน้าซ้ำเท่านั้น ต้องการที่จะโหลดใหม่เลยมั้ย"
+reloadToApplySetting: "การตั้งค่านี้จะมีผลหลังจากโหลดหน้าซ้ำเท่านั้น ต้องการที่จะโหลดใหม่เลยไหม?"
needReloadToApply: "จำเป็นต้องโหลดซ้ำถึงจะมีผลนะ"
showTitlebar: "แสดงแถบชื่อ"
clearCache: "ล้างแคช"
@@ -743,57 +768,57 @@ nNotes: "{n} โน้ต"
sendErrorReports: "ส่งรายงานว่าข้อผิดพลาด"
sendErrorReportsDescription: "เมื่อเปิดใช้งาน ข้อมูลข้อผิดพลาดโดยรายละเอียดนั้นจะถูกแชร์ให้กับ Misskey เมื่อเกิดปัญหา ซึ่งช่วยปรับปรุงคุณภาพของ Misskey\nซึ่งจะรวมถึงข้อมูล เช่น เวอร์ชั่นของระบบปฏิบัติการ เบราว์เซอร์ที่คุณใช้ กิจกรรมของคุณใน Misskey เป็นต้น"
myTheme: "ธีมของฉัน"
-backgroundColor: "ภาพพื้นหลัง"
-accentColor: "รูปแบบสี"
+backgroundColor: "สีพื้นหลัง"
+accentColor: "สีหลัก"
textColor: "สีข้อความ"
saveAs: "บันทึกเป็น..."
advanced: "ขั้นสูง"
advancedSettings: "การตั้งค่าขั้นสูง"
value: "ค่า"
createdAt: "สร้างเมื่อ"
-updatedAt: "อัพเดทล่าสุด"
+updatedAt: "อัปเดตล่าสุด"
saveConfirm: "บันทึกเปลี่ยนแปลงมั้ย?"
deleteConfirm: "ลบจริงๆเหรอ?"
invalidValue: "ค่านี้ไม่ถูกต้อง"
registry: "ทะเบียน"
closeAccount: "ปิด บัญชี"
currentVersion: "เวอร์ชั่นปัจจุบัน"
-latestVersion: "รุ่นปัจจุบัน"
+latestVersion: "เวอร์ชั่นล่าสุด"
youAreRunningUpToDateClient: "คุณกำลังใช้ไคลเอ็นต์เวอร์ชันใหม่ล่าสุดนะ"
newVersionOfClientAvailable: "มีไคลเอ็นต์เวอร์ชันใหม่กว่าของคุณพร้อมใช้งานนะ"
usageAmount: "การใช้งาน"
capacity: "ความจุ"
inUse: "ใช้แล้ว"
editCode: "แก้ไขโค้ด"
-apply: "ตกลง"
+apply: "นำไปใช้"
receiveAnnouncementFromInstance: "รับการแจ้งเตือนจากอินสแตนซ์นี้"
-emailNotification: "การแจ้งเตือนทางอีเมล์"
+emailNotification: "การแจ้งเตือนทางอีเมล"
publish: "เผยแพร่"
inChannelSearch: "ค้นหาในช่อง"
-useReactionPickerForContextMenu: "เปิดตัวเลือกปฏิกิริยาเมื่อคลิกขวา"
-typingUsers: "{users} กำลัง/กำลังพิมพ์..."
+useReactionPickerForContextMenu: "คลิกขวาเพื่อเปิดตัวจิ้มรีแอคชั่น"
+typingUsers: "{users} กำลังพิมพ์..."
jumpToSpecifiedDate: "ข้ามไปยังวันที่เฉพาะเจาะจง"
showingPastTimeline: "กำลังแสดงผลไทม์ไลน์เก่า"
clear: "ล้าง"
markAllAsRead: "ทำเครื่องหมายทั้งหมดว่าอ่านแล้ว"
goBack: "ย้อนกลับ"
-unlikeConfirm: "ลบไลค์ของคุณออกจริงๆหรอ"
+unlikeConfirm: "ต้องการเลิกถูกใจใช่ไหม?"
fullView: "มุมมองแบบเต็ม"
quitFullView: "ออกจากมุมมองแบบเต็ม"
addDescription: "เพิ่มคำอธิบาย"
-userPagePinTip: "คุณสามารถแสดงผลโน้ตย่อได้ที่นี่โดยเลือก \"ปักหมุดที่โปรไฟล์\" จากเมนูของโน้ตย่อแต่ละรายการนะ"
+userPagePinTip: "ปักหมุดโน้ตให้แสดงที่นี่ได้โดยเลือกเมนู “ปักหมุด” ของโน้ตนั้นๆ"
notSpecifiedMentionWarning: "โน้ตนี้มีการกล่าวถึงผู้ใช้งานที่ไม่รวมอยู่ในผู้รับ"
info: "เกี่ยวกับ"
userInfo: "ข้อมูลผู้ใช้"
unknown: "ไม่ทราบสถานะ"
onlineStatus: "สถานะออนไลน์"
hideOnlineStatus: "ซ่อนสถานะออนไลน์"
-hideOnlineStatusDescription: "การซ่อนสถานะออนไลน์ของคุณช่วยลดความสะดวกของคุณสมบัติบางอย่าง เช่น การค้นหา อ่ะนะ"
+hideOnlineStatusDescription: "การซ่อนสถานะออนไลน์อาจทำให้ฟังก์ชันบางอย่าง เช่น การค้นหา สะดวกน้อยลง"
online: "ออนไลน์"
active: "ใช้งานอยู่"
offline: "ออฟไลน์"
-notRecommended: "ไม่ใช้งาน"
-botProtection: "การป้องกัน Bot (or AI)"
+notRecommended: "ไม่แนะนำ"
+botProtection: "การป้องกัน Bot"
instanceBlocking: "อินสแตนซ์ที่ถูกบล็อก"
selectAccount: "เลือกบัญชี"
switchAccount: "สลับบัญชีผู้ใช้"
@@ -815,19 +840,19 @@ popularPosts: "โพสต์ติดอันดับ"
shareWithNote: "แบ่งปันด้วยโน้ต"
ads: "โฆษณา"
expiration: "กำหนดเวลา"
-startingperiod: "เริ่ม"
-memo: "ข้อควรจำ"
+startingperiod: "เริ่มเมื่อ"
+memo: "เมโม"
priority: "ลำดับความสำคัญ"
high: "สูง"
middle: "ปานกลาง"
low: "ต่ำ"
-emailNotConfiguredWarning: "ไม่ได้ตั้งค่าที่อยู่อีเมลนะ"
+emailNotConfiguredWarning: "ยังไม่ได้ตั้งค่าที่อยู่อีเมล"
ratio: "อัตราส่วน"
previewNoteText: "แสดงตัวอย่าง"
customCss: "CSS ที่กำหนดเอง"
-customCssWarn: "ควรใช้การตั้งค่านี้เฉพาะต่อเมื่อคุณรู้ว่าการตั้งค่านี้ใช้ทำอะไร การป้อนค่าที่ไม่เหมาะสมอาจทำให้ไคลเอ็นต์หยุดทำงานตามปกติได้นะ"
+customCssWarn: "ควรใช้การตั้งค่านี้เฉพาะต่อเมื่อคุณรู้มันใช้ทำอะไร การตั้งค่าที่ไม่เหมาะสมอาจทำให้ไคลเอ็นต์ไม่สามารถใช้งานได้อย่างถูกต้อง"
global: "ทั่วโลก"
-squareAvatars: "แสดงผลอวตารสี่เหลี่ยม"
+squareAvatars: "แสดงผลอวตารเป็นสี่เหลี่ยม"
sent: "ส่ง"
received: "ได้รับแล้ว"
searchResult: "ผลการค้นหา"
@@ -844,10 +869,10 @@ usernameInfo: "ชื่อที่ระบุบัญชีของคุ
aiChanMode: "โหมด Ai "
devMode: "โหมดนักพัฒนา"
keepCw: "เก็บคำเตือนเนื้อหา"
-pubSub: "บัญชีผับ/ย่อย"
+pubSub: "บัญชี Pub/Sub"
lastCommunication: "การสื่อสารครั้งสุดท้ายล่าสุด"
resolved: "คลี่คลายแล้ว"
-unresolved: "รอการเฉลย"
+unresolved: "ยังไม่ได้รับการแก้ไข"
breakFollow: "ลบผู้ติดตาม"
breakFollowConfirm: "ลบผู้ติดตามนี้ออกจริงหรอ?"
itsOn: "เปิดใช้งาน"
@@ -855,38 +880,38 @@ itsOff: "ปิดใช้งาน"
on: "เปิด"
off: "ปิด"
emailRequiredForSignup: "จำเป็นต้องการใช้ที่อยู่อีเมลสำหรับการสมัคร"
-unread: "ไม่ได้อ่าน"
+unread: "ยังไม่ได้อ่าน"
filter: "กรอง"
controlPanel: "แผงควบคุม"
manageAccounts: "จัดการบัญชี"
-makeReactionsPublic: "ตั้งค่าประวัติปฏิกิริยาต่อสาธารณะ"
-makeReactionsPublicDescription: "การทำเช่นนี้จะทำให้รายการปฏิกิริยาที่ผ่านมาของคุณจะปรากฏต่อสาธารณะนะ"
+makeReactionsPublic: "ตั้งค่าประวัติการรีแอคชั่นเป็นสาธารณะ"
+makeReactionsPublicDescription: "การทำเช่นนี้จะทำให้รายการรีแอคชั่นของคุณที่ผ่านมาทั้งหมดปรากฏต่อสาธารณะ"
classic: "คลาสสิค"
muteThread: "ปิดเสียงเธรด"
-unmuteThread: "เปิดเสียงเธรด"
-ffVisibility: "การมองเห็นผู้ติดตาม/ผู้ติดตาม"
-ffVisibilityDescription: "ช่วยให้คุณสามารถกำหนดค่าได้ว่าใครสามารถดูได้ว่าคุณติดตามใครและใครติดตามคุณบ้าง"
+unmuteThread: "เลิกปิดเสียงเธรด"
+followingVisibility: "การมองเห็นที่เรากำลังติดตาม"
+followersVisibility: "การมองเห็นผู้ที่กำลังติดตามเรา"
continueThread: "ดูความต่อเนื่องเธรด"
deleteAccountConfirm: "การดำเนินการนี้จะลบบัญชีของคุณอย่างถาวรเลยนะ แน่ใจหรอดำเนินการ?"
incorrectPassword: "รหัสผ่านไม่ถูกต้อง"
-voteConfirm: "ยืนยันการโหวต \"{choice}\" มั้ย?"
+voteConfirm: "ต้องการโหวต “{choice}” ใช่ไหม?"
hide: "ซ่อน"
-useDrawerReactionPickerForMobile: "แสดงผล ตัวเลือกปฏิกิริยาเป็นลิ้นชักบนมือถือ"
-welcomeBackWithName: "ยินดีต้อนรับการกลับมานะคะ, {name}"
-clickToFinishEmailVerification: "กรุณาคลิก [{ok}] เพื่อดำเนินการยืนยันอีเมลให้เสร็จสมบูรณ์นะ"
+useDrawerReactionPickerForMobile: "แสดง ตัวจิ้มรีแอคชั่น เป็นแบบลิ้นชัก เมื่อใช้บนมือถือ"
+welcomeBackWithName: "ยินดีต้อนรับการกลับมานะคะ, คุณ{name}"
+clickToFinishEmailVerification: "กรุณาคลิก [{ok}] เพื่อดำเนินการยืนยันอีเมลให้เสร็จสมบูรณ์"
overridedDeviceKind: "ประเภทอุปกรณ์"
smartphone: "สมาร์ทโฟน"
tablet: "แท็บเล็ต"
auto: "อัตโนมัติ"
-themeColor: "อินสแตนซ์ Ticker Color"
+themeColor: "สีธีม"
size: "ขนาด"
numberOfColumn: "จำนวนคอลัมน์"
searchByGoogle: "ค้นหา"
-instanceDefaultLightTheme: "ธีมสว่างค่าเริ่มต้นสำหรับอินสแตนซ์"
-instanceDefaultDarkTheme: "ธีมมืดค่าเริ่มต้นอินสแตนซ์"
+instanceDefaultLightTheme: "ธีมสว่างตามค่าเริ่มต้นของอินสแตนซ์"
+instanceDefaultDarkTheme: "ธีมมืดตามค่าเริ่มต้นของอินสแตนซ์"
instanceDefaultThemeDescription: "ป้อนรหัสธีมในรูปแบบออบเจ็กต์"
mutePeriod: "ระยะเวลาปิดเสียง"
-period: "สิ้นสุดการสำรวจความคิดเห็น"
+period: "ระยะเวลา"
indefinitely: "ตลอดไป"
tenMinutes: "10 นาที"
oneHour: "1 ชั่วโมง"
@@ -916,28 +941,28 @@ deleteAccount: "ลบบัญชี"
document: "เอกสาร"
numberOfPageCache: "จำนวนหน้าเพจที่แคช"
numberOfPageCacheDescription: "การเพิ่มจำนวนนี้จะช่วยเพิ่มความสะดวกให้กับผู้ใช้งาน แต่จะทำให้เซิร์ฟเวอร์โหลดมากขึ้นและต้องใช้หน่วยความจำมากขึ้นอีกด้วย"
-logoutConfirm: "คุณแน่ใจว่าต้องการออกจากระบบ?"
-lastActiveDate: "ใช้งานล่าสุดที่"
-statusbar: "ไอคอนบนแถบสถานะ"
+logoutConfirm: "ต้องการออกจากระบบใช่ไหม?"
+lastActiveDate: "ใช้งานล่าสุดเมื่อ"
+statusbar: "แถบสถานะ"
pleaseSelect: "ตัวเลือก"
-reverse: "ย้อนกลับ"
+reverse: "พลิก"
colored: "สี"
-refreshInterval: "รอบการอัพเดต"
+refreshInterval: "ความถี่ในการอัปเดต"
label: "ป้ายชื่อ"
type: "รูปแบบ"
speed: "ความเร็ว"
slow: "ช้า"
fast: "เร็ว"
-sensitiveMediaDetection: "การตรวจจับของสื่อ NSFW"
+sensitiveMediaDetection: "การตรวจจับสื่อที่มีเนื้อหาละเอียดอ่อน"
localOnly: "เฉพาะท้องถิ่น"
-remoteOnly: "รีโมทเท่านั้น"
+remoteOnly: "ระยะไกลเท่านั้น"
failedToUpload: "การอัปโหลดล้มเหลว"
cannotUploadBecauseInappropriate: "ไม่สามารถอัปโหลดไฟล์นี้ได้เนื่องจากระบบตรวจพบบางส่วนของไฟล์ว่านี้อาจจะเป็น NSFW"
-cannotUploadBecauseNoFreeSpace: "การอัปโหลดนั้นล้มเหลวเนื่องจากไม่มีความจุของไดรฟ์"
+cannotUploadBecauseNoFreeSpace: "ไม่สามารถอัปโหลดได้เนื่องจากไม่มีพื้นที่ว่างในไดรฟ์เหลือแล้ว"
cannotUploadBecauseExceedsFileSizeLimit: "ไม่สามารถอัปโหลดไฟล์นี้ได้แล้วเนื่องจากเกินขีดจำกัดของขนาดไฟล์แล้ว"
beta: "เบต้า"
-enableAutoSensitive: "ทำเครื่องหมาย NSFW อัตโนมัติ"
-enableAutoSensitiveDescription: "อนุญาตให้ตรวจหาและทำเครื่องหมายสื่อ NSFW โดยอัตโนมัติผ่านการเรียนรู้ของเครื่องหากเป็นไปได้ แม้ว่าตัวเลือกนี้จะถูกปิดใช้งาน แต่ก็สามารถเปิดใช้งานได้ทั้งอินสแตนซ์นี้"
+enableAutoSensitive: "ทำเครื่องหมายว่ามีเนื้อหาที่ละเอียดอ่อนโดยอัตโนมัติ"
+enableAutoSensitiveDescription: "อนุญาตให้ตรวจหาและทำเครื่องหมายสื่อว่ามีเนื้อหาโดยละเอียดอ่อนโดยอัตโนมัติ ผ่าน Machine Learning หากเป็นไปได้ แม้ว่าคุณจะปิดคุณสมบัตินี้ ก็อาจถูกตั้งค่าโดยอัตโนมัติ ทั้งนี้ขึ้นอยู่กับเซิร์ฟเวอร์"
activeEmailValidationDescription: "เปิดใช้งานการตรวจสอบที่อยู่อีเมลให้มีความเข้มงวดยิ่งขึ้น ซึ่งอาจจะรวมไปถึงการตรวจสอบที่อยู่อีเมล์ที่ใช้แล้วทิ้งและโดยให้พิจารณาว่าสามารถสื่อสารด้วยได้หรือไม่ เมื่อไม่เลือกระบบจะตรวจสอบเฉพาะรูปแบบของอีเมลเท่านั้น"
navbar: "แถบนำทาง"
shuffle: "สลับ"
@@ -949,32 +974,34 @@ unsubscribePushNotification: "ปิดการแจ้งเตือนแ
pushNotificationAlreadySubscribed: "การแจ้งเตือนแบบพุชได้เปิดใช้งานแล้ว"
pushNotificationNotSupported: "เบราว์เซอร์หรืออินสแตนซ์ของคุณนั้นไม่รองรับการแจ้งเตือนแบบพุช"
sendPushNotificationReadMessage: "ลบการแจ้งเตือนแบบพุชเมื่ออ่านการแจ้งเตือนหรือข้อความที่เกี่ยวข้องแล้ว"
-sendPushNotificationReadMessageCaption: "การแจ้งเตือนที่มีข้อความ \"{emptyPushNotificationMessage}\" จะแสดงขึ้นมาในช่วงระยะเวลาสั้นๆ การดำเนินการนี้อาจทำให้เพิ่มการใช้งานแบตเตอรี่ของอุปกรณ์ถ้าหากมีนะ"
-windowMaximize: "ขยายใหญ่สุดแล้ว"
+sendPushNotificationReadMessageCaption: "อาจทำให้อุปกรณ์ของคุณใช้พลังงานมากขึ้น"
+windowMaximize: "ขยายใหญ่สุด"
windowMinimize: "ย่อเล็กที่สุด"
windowRestore: "เลิกทำ"
-caption: "รายละเอียด"
+caption: "คำอธิบาย"
loggedInAsBot: "ล็อกอินเป็นบอตอยู่ในขณะนี้"
tools: "เครื่องมือ"
cannotLoad: "ไม่สามารถโหลดได้"
numberOfProfileView: "มุมมองโปรไฟล์"
-like: "ชื่นชอบ"
-unlike: "ไม่ชอบ"
-numberOfLikes: "จำนวนไลค์"
+like: "ถูกใจ!"
+unlike: "เลิกถูกใจ"
+numberOfLikes: "จำนวนยอดถูกใจ"
show: "แสดงผล"
neverShow: "ไม่ต้องแสดงข้อความนี้อีก"
remindMeLater: "ไว้ครั้งหน้าแล้วกัน"
-didYouLikeMisskey: "คุณเคยชอบ Misskey ไหม?"
+didYouLikeMisskey: "คุณชอบ Misskey ไหม?"
pleaseDonate: "Misskey เป็นซอฟต์แวร์ฟรีที่ใช้งานโดย {host} เราขอขอบคุณการสนับสนุนของคุณอย่างสูงเพื่อให้การพัฒนา Misskey สามารถดำเนินต่อไปได้!"
+correspondingSourceIsAvailable: "ซอร์สโค้ดที่เกี่ยวข้องมีอยู่ที่ {anchor}"
roles: "บทบาท"
role: "บทบาท"
noRole: "ไม่พบบทบาท"
normalUser: "ผู้ใช้มาตรฐาน"
undefined: "ไม่ได้กำหนด"
-assign: "กำหนด"
-unassign: "ยังไม่มอบหมาย"
+assign: "มอบหมาย"
+unassign: "เลิกมอบหมาย"
color: "สี"
-manageCustomEmojis: "จัดการอีโมจิแบบกำหนดเอง"
+manageCustomEmojis: "จัดการเอโมจิที่กำหนดเอง"
+manageAvatarDecorations: "จัดการตกแต่งอวตาร"
youCannotCreateAnymore: "คุณถึงขีดจํากัดการสร้างแล้วนะ"
cannotPerformTemporary: "ไม่สามารถใช้การได้ชั่วคราว"
cannotPerformTemporaryDescription: "ไม่สามารถดําเนินการได้ชั่วคราว เนื่องจากเกินขีดจํากัดการดําเนินการ กรุณารอสักครู่แล้วลองใหม่อีกครั้ง"
@@ -988,33 +1015,38 @@ achievements: "ความสำเร็จ"
gotInvalidResponseError: "การตอบสนองเซิร์ฟเวอร์ไม่ถูกต้อง"
gotInvalidResponseErrorDescription: "เซิร์ฟเวอร์อาจไม่สามารถเข้าถึงได้หรืออาจจะกำลังอยู่ในระหว่างปรับปรุง กรุณาลองใหม่อีกครั้งในภายหลังนะคะ"
thisPostMayBeAnnoying: "โน้ตนี้อาจจะเป็นการรบกวนผู้อื่นนะคะ"
-thisPostMayBeAnnoyingHome: "โพสต์ไปยังบ้านไทม์ไลน์"
+thisPostMayBeAnnoyingHome: "โพสต์ไปยังไทม์ไลน์หน้าแรก"
thisPostMayBeAnnoyingCancel: "เลิก"
thisPostMayBeAnnoyingIgnore: "โพสต์ยังไงก็แล้วแต่"
-collapseRenotes: "ยุบ renotes ที่คุณได้เห็นแล้ว"
+collapseRenotes: "ยุบรีโน้ตที่คุณเคยเห็นแล้ว"
internalServerError: "เซิร์ฟเวอร์ภายในเกิดข้อผิดพลาด"
internalServerErrorDescription: "เซิร์ฟเวอร์รันค้นพบข้อผิดพลาดที่ไม่คาดคิด"
copyErrorInfo: "คัดลอกรายละเอียดข้อผิดพลาด"
joinThisServer: "ลงชื่อสมัครใช้ในอินสแตนซ์นี้"
exploreOtherServers: "มองหาอินสแตนซ์อื่น"
-letsLookAtTimeline: "ลองดูที่ไทม์ไลน์"
+letsLookAtTimeline: "มาดูไทม์ไลน์กัน"
disableFederationConfirm: "ปิดใช้งานสหพันธ์จริงๆหรอแน่ใจแล้วนะ?"
disableFederationConfirmWarn: "โพสต์จะยังคงเป็นสาธารณะต่อไป เว้นแต่จะตั้งค่าเป็นอย่างอื่น"
disableFederationOk: "ปิดการใช้งาน"
-invitationRequiredToRegister: "อินสแตนซ์นี้เป็นแบบรับเชิญเท่านั้น คุณต้องป้อนรหัสเชิญ เพื่องลงทะเบียนเข้าใช้งาน"
+invitationRequiredToRegister: "อินสแตนซ์นี้เป็นแบบรับเชิญ เฉพาะผู้ที่มีรหัสเชิญเท่านั้นที่สามารถลงทะเบียนได้"
emailNotSupported: "อินสแตนซ์นี้ไม่รองรับการส่งอีเมล"
postToTheChannel: "โพสต์ลงช่อง"
cannotBeChangedLater: "สิ่งนี้ไม่สามารถเปลี่ยนแปลงได้ในภายหลังนะ"
reactionAcceptance: "การยอมรับรีแอคชั่น"
-likeOnly: "ที่ชอบเท่านั้น"
-likeOnlyForRemote: "ไลค์สำหรับอินสแตนซ์ระยะไกลเท่านั้น"
-nonSensitiveOnly: "ไม่มีความอ่อนไหวเท่านั้น"
-nonSensitiveOnlyForLocalLikeOnlyForRemote: "ไม่มีความอ่อนไหวเท่านั้น (เฉพาะไลค์จากระยะไกลเท่านั้น)"
+likeOnly: "ที่ถูกใจเท่านั้น"
+likeOnlyForRemote: "ทั้งหมด (เฉพาะการถูกใจจากอินสแตนซ์ระยะไกล)"
+nonSensitiveOnly: "เฉพาะไม่มีเนื้อหาละเอียดอ่อน"
+nonSensitiveOnlyForLocalLikeOnlyForRemote: "เฉพาะไม่มีเนื้อหาละเอียดอ่อน (เฉพาะการถูกใจจากระยะไกลเท่านั้น)"
rolesAssignedToMe: "บทบาทที่ได้รับมอบหมายให้ฉัน"
resetPasswordConfirm: "รีเซ็ตรหัสผ่านของคุณจริงๆหรอ?"
-sensitiveWords: "คำที่ละเอียดอ่อน"
+sensitiveWords: "คำที่มีเนื้อหาละเอียดอ่อน"
sensitiveWordsDescription: "การเปิดเผยโน้ตทั้งหมดที่มีคำที่กำหนดค่าไว้จะถูกตั้งค่าเป็น \"หน้าแรก\" โดยอัตโนมัติ คุณยังสามารถแสดงหลายรายการได้โดยแยกรายการโดยใช้ตัวแบ่งบรรทัดได้นะ"
sensitiveWordsDescription2: "การใช้ช่องว่างนั้นอาจจะสร้างนิพจน์ AND และคำหลักที่มีเครื่องหมายทับล้อมรอบจะเปลี่ยนเป็นนิพจน์ทั่วไปนะ"
+prohibitedWords: "คำต้องห้าม"
+prohibitedWordsDescription: "จะแจ้งเตือนว่าเกิดข้อผิดพลาดเมื่อพยายามโพสต์โน้ตที่มีคำที่กำหนดไว้ สามารถตั้งได้หลายคำด้วยการขึ้นบรรทัดใหม่"
+prohibitedWordsDescription2: "การใช้ช่องว่างนั้นอาจจะสร้างนิพจน์ AND และคำหลักที่มีเครื่องหมายทับล้อมรอบจะเปลี่ยนเป็นนิพจน์ทั่วไปนะ"
+hiddenTags: "แฮชแท็กที่ซ่อนอยู่"
+hiddenTagsDescription: "เลือกแท็กที่จะไม่แสดงในรายการเทรนด์ สามารถลงทะเบียนหลายแท็กได้โดยขึ้นบรรทัดใหม่"
notesSearchNotAvailable: "การค้นหาโน้ตไม่พร้อมใช้งาน"
license: "ใบอนุญาต"
unfavoriteConfirm: "ลบออกจากรายการโปรดแน่ใจหรอ?"
@@ -1025,21 +1057,24 @@ retryAllQueuesConfirmTitle: "ลองใหม่ทั้งหมดจริ
retryAllQueuesConfirmText: "สิ่งนี้จะเพิ่มการโหลดเซิร์ฟเวอร์ชั่วคราวนะ"
enableChartsForRemoteUser: "สร้างแผนภูมิข้อมูลผู้ใช้ระยะไกล"
enableChartsForFederatedInstances: "สร้างแผนภูมิข้อมูลอินสแตนซ์ระยะไกล"
-showClipButtonInNoteFooter: "เพิ่ม \"คลิป\" เพื่อบันทึกเมนูการทำงาน"
-reactionsDisplaySize: "รีแอคชั่นแสดงผลขนาด"
-noteIdOrUrl: "โน้ต ID หรือ URL"
+showClipButtonInNoteFooter: "เพิ่ม “คลิป” ไปยังเมนูสั่งการของโน้ต"
+reactionsDisplaySize: "ขนาดของรีแอคชั่น"
+limitWidthOfReaction: "จำกัดความกว้างสูงสุดของรีแอคชั่นและแสดงให้เล็กลง"
+noteIdOrUrl: "ID ของโน้ต หรือ URL"
video: "วีดีโอ"
videos: "วีดีโอ"
+audio: "เสียง"
+audioFiles: "เสียง"
dataSaver: "ประหยัดข้อมูล"
-accountMigration: "การโยกย้ายบัญชี"
+accountMigration: "โยกย้ายบัญชี"
accountMoved: "ผู้ใช้รายนี้ได้ย้ายไปยังบัญชีใหม่แล้ว:"
accountMovedShort: "บัญชีนี้ถูกโอนย้ายไปแล้วค่ะ"
-operationForbidden: "ห้ามดำเนินการ"
+operationForbidden: "การดำเนินการถูกห้าม"
forceShowAds: "แสดงโฆษณาเสมอ"
-addMemo: "เพิ่มมีโม"
-editMemo: "แก้ไขมีโม"
-reactionsList: "ปฏิกิริยา"
-renotesList: "Renotes รีโน้ต"
+addMemo: "เพิ่มเมโม"
+editMemo: "แก้ไขเมโม"
+reactionsList: "รายการรีแอคชั่น"
+renotesList: "รายการรีโน้ต"
notificationDisplay: "การแจ้งเตือน"
leftTop: "บนซ้าย"
rightTop: "บนขวา"
@@ -1047,101 +1082,175 @@ leftBottom: "ล่างซ้าย"
rightBottom: "ล่างขวา"
stackAxis: "ทิศทางการซ้อน"
vertical: "แนวตั้ง"
-horizontal: "ด้านข้าง"
+horizontal: "แนวนอน"
position: "ตำแหน่ง"
-serverRules: "กฎของเซิฟเวอร์"
+serverRules: "กฎของเซิร์ฟเวอร์"
pleaseConfirmBelowBeforeSignup: "โปรดยืนยันที่ด้านล่างก่อนสมัครใช้งาน"
pleaseAgreeAllToContinue: "คุณต้องยอมรับทุกช่องตรงด้านบนเพื่อดำเนินการต่อค่ะ"
continue: "ดำเนินการต่อ"
preservedUsernames: "ชื่อผู้ใช้ที่สงวนไว้"
-preservedUsernamesDescription: "ลิสต์ชื่อผู้ใช้ที่จะสำรองโดยคั่นด้วยการแบ่งบรรทัดนั้น เพราะสิ่งเหล่านี้จะไม่สามารถทำได้ในระหว่างการสร้างบัญชีตามปกติ บัญชีที่มีอยู่แล้วนั้นโดยใช้ชื่อผู้ใช้เหล่านี้จะไม่ได้รับผลกระทบอะไร"
+preservedUsernamesDescription: "ระบุชื่อผู้ใช้ที่จะสงวนชื่อไว้ คั่นด้วยการขึ้นบรรทัดใหม่ ชื่อผู้ใช้ที่ระบุที่นี่จะไม่สามารถใช้งานได้อีกต่อไปเมื่อสร้างบัญชีใหม่ ยกเว้นเมื่อผู้ดูแลระบบสร้างบัญชี นอกจากนี้ บัญชีที่มีอยู่แล้วจะไม่ได้รับผลกระทบ"
createNoteFromTheFile: "เรียบเรียงโน้ตจากไฟล์นี้"
archive: "เก็บถาวร"
-channelArchiveConfirmTitle: "เก็บถาวรจริงๆ {name} มั้ย?"
-channelArchiveConfirmDescription: "ช่องที่ถูกเก็บถาวรแล้วนั้นจะไม่ปรากฏในรายการช่องหรือผลการค้นหานั้นอีกต่อไปไม่สามารถเพิ่มโพสต์ใหม่ได้อีกต่อไปนะ"
+channelArchiveConfirmTitle: "ต้องการเก็บถาวรเจ้า {name} ใช่ไหม?"
+channelArchiveConfirmDescription: "เมื่อเก็บถาวรแล้ว จะไม่ปรากฏในรายการช่องหรือผลการค้นหาอีกต่อไป และจะไม่สามารถโพสต์ใหม่ได้อีกต่อไป"
thisChannelArchived: "ช่องนี้ถูกเก็บถาวรแล้วนะ"
displayOfNote: "การแสดงโน้ต"
initialAccountSetting: "ตั้งค่าโปรไฟล์"
youFollowing: "ติดตามแล้ว"
-preventAiLearning: "ปฏิเสธการใช้งาน ในการเรียนรู้ของเครื่อง (Generative AI)"
-preventAiLearningDescription: "การส่งคำร้องขอโปรแกรมรวบรวมข้อมูลไม่ให้ใช้ข้อความที่โพสต์หรือรูปภาพ ฯลฯ ในชุดข้อมูลแมชชีนเลิร์นนิง (Predictive / Generative AI) สิ่งนี้นั้นทำได้โดยการเพิ่มแฟล็กการตอบสนอง \"noai\" HTML ให้กับเนื้อหาที่เกี่ยวข้อง แต่อย่างไรก็ตามแล้ว การป้องกันโดยสมบูรณ์นั้นไม่สามารถทำได้ผ่านแฟล็กนี้เนื่องจากอาจจะทำให้ถูกเพิกเฉยได้"
+preventAiLearning: "ปฏิเสธการเรียนรู้ด้วย generative AI"
+preventAiLearningDescription: "ส่งคำร้องขอไม่ให้ใช้ ข้อความในโน้ตที่โพสต์, หรือเนื้อหารูปภาพ ฯลฯ ในการเรียนรู้ของเครื่อง(machine learning) / Predictive AI / Generative AI โดยการเพิ่มแฟล็ก “noai” ลง HTML-Response ให้กับเนื้อหาที่เกี่ยวข้อง แต่ทั้งนี้ ไม่ได้ป้องกัน AI จากการเรียนรู้ได้อย่างสมบูรณ์ เนื่องจากมี AI บางตัวเท่านั้นที่จะเคารพคำขอดังกล่าว"
options: "ตัวเลือกบทบาท"
specifyUser: "ผู้ใช้เฉพาะ"
failedToPreviewUrl: "ไม่สามารถดูตัวอย่างได้"
update: "อัปเดต"
-rolesThatCanBeUsedThisEmojiAsReaction: "บทบาทที่สามารถใช้อิโมจินี้เป็นรีแอคชั่นได้"
-rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "ถ้าหากไม่ได้ระบุบทบาท ทุกคนนั้นก็สามารถใช้อิโมจินี้เป็นการแสดงความรู้สึกได้นะ"
+rolesThatCanBeUsedThisEmojiAsReaction: "บทบาทที่สามารถใช้เอโมจินี้เป็นรีแอคชั่นได้"
+rolesThatCanBeUsedThisEmojiAsReactionEmptyDescription: "ถ้าหากไม่ได้ระบุบทบาท ใคร ๆ ก็สามารถใช้เอโมจินี้เพื่อรีแอคชั่นได้"
rolesThatCanBeUsedThisEmojiAsReactionPublicRoleWarn: "บทบาทเหล่านี้ต้องเป็นสาธารณะ"
-cancelReactionConfirm: "ต้องการลบรีแอคชั่นของคุณจริงๆหรอ?"
-changeReactionConfirm: "ต้องการเปลี่ยนรีแอคชั่นของคุณจริงๆหรอ?"
+cancelReactionConfirm: "ต้องการลบรีแอคชั่นใช่ไหม?"
+changeReactionConfirm: "ต้องการเปลี่ยนรีแอคชั่นใช่ไหม?"
later: "ไว้ทีหลัง"
goToMisskey: "ถึง Misskey"
-additionalEmojiDictionary: "พจนานุกรมอีโมจิเพิ่มเติม"
+additionalEmojiDictionary: "พจนานุกรมเอโมจิเพิ่มเติม"
installed: "ติดตั้งแล้ว"
branding: "แบรนดิ้ง"
enableServerMachineStats: "เผยแพร่สถานะฮาร์ดแวร์ของเซิร์ฟเวอร์"
enableIdenticonGeneration: "เปิดใช้งานผู้ใช้สร้างตัวระบุ"
turnOffToImprovePerformance: "การปิดส่วนนี้สามารถเพิ่มประสิทธิภาพได้"
-createInviteCode: "สร้างคำเชิญ"
+createInviteCode: "สร้างรหัสเชิญ"
createWithOptions: "สร้างด้วยตัวเลือก"
-createCount: "จำนวนการเชิญ"
-inviteCodeCreated: "สร้างคำเชิญแล้ว"
-inviteLimitExceeded: "คุณสร้างคำเชิญเกินถึงขีดจำกัดแล้วนะ"
-createLimitRemaining: "ขีดจำกัดการเชิญ: {limit} ที่เหลืออยู่"
-inviteLimitResetCycle: "ขีดจำกัดนี้จะถูกรีเซ็ตเป็น {limit} ที่ {time}."
+createCount: "จำนวนรหัสเชิญ"
+inviteCodeCreated: "สร้างรหัสเชิญแล้ว"
+inviteLimitExceeded: "จำนวนรหัสเชิญที่สามารถสร้างได้ถึงขีดจำกัดแล้ว"
+createLimitRemaining: "รหัสเชิญที่สามารถสร้างได้: เหลืออยู่ {limit} รหัส"
+inviteLimitResetCycle: "สามารถสร้างรหัสเชิญได้อีกสูงสุด {limit} รหัส ภายใน {time}"
expirationDate: "วันที่หมดอายุ"
noExpirationDate: "ไม่มีหมดอายุ"
-inviteCodeUsedAt: "รหัสคำเชิญใช้แล้วที่"
-registeredUserUsingInviteCode: "ใช้คำเชิญแล้วโดย"
+inviteCodeUsedAt: "วันเวลาที่ใช้รหัสเชิญ"
+registeredUserUsingInviteCode: "ผู้ใช้ที่ใช้รหัสเชิญ"
waitingForMailAuth: "กำลังรอการยืนยันอีเมล"
-inviteCodeCreator: "สร้างการเชิญแล้วโดย"
-usedAt: "ใช้แล้วที่"
-unused: "ไม่ใช้แล้ว"
-used: "ใช้แล้ว"
+inviteCodeCreator: "ผู้ใช้ที่สร้างรหัสเชิญ"
+usedAt: "วันเวลาที่ถูกใช้"
+unused: "ยังไม่ได้ใช้"
+used: "ถูกใช้แล้ว"
expired: "หมดอายุแล้ว"
-doYouAgree: "ยอมรับมั้ย?"
+doYouAgree: "ยอมรับไหม?"
beSureToReadThisAsItIsImportant: "กรุณาอ่านข้อมูลที่สำคัญอันนี้"
-iHaveReadXCarefullyAndAgree: "ฉันได้อ่านข้อความ \"{x}\" และยินยอม"
+iHaveReadXCarefullyAndAgree: "ฉันได้อ่านและยินยอมเนื้อหาของ “{x}”"
dialog: "ไดอะล็อก"
icon: "ไอคอน"
forYou: "สำหรับคุณ"
currentAnnouncements: "ประกาศในปัจจุบัน"
pastAnnouncements: "ประกาศที่ผ่านมา"
youHaveUnreadAnnouncements: "มีการประกาศที่ยังไม่ได้อ่าน"
+useSecurityKey: "โปรดปฏิบัติตามคำแนะนำของเบราว์เซอร์หรืออุปกรณ์ของคุณเพื่อใช้ security key หรือ passkey"
replies: "ตอบกลับ"
renotes: "รีโน้ต"
loadReplies: "แสดงการตอบกลับ"
loadConversation: "แสดงบทสนทนา"
-pinnedList: "รายการที่ปักหมุดไว้แล้ว"
-keepScreenOn: "เปิดหน้าจอไว้"
+pinnedList: "รายชื่อที่ปักหมุดไว้"
+keepScreenOn: "เปิดหน้าจออุปกรณ์ค้างไว้"
+verifiedLink: "ความเป็นเจ้าของลิงก์ได้รับการยืนยันแล้ว"
notifyNotes: "แจ้งเตือนเกี่ยวกับโพสต์ใหม่"
unnotifyNotes: "หยุดการแจ้งเตือนเกี่ยวกับโน้ตใหม่"
authentication: "การตรวจสอบสิทธิ์"
-authenticationRequiredToContinue: "กรุณาตรวจสอบการรับรองความถูกต้องเพื่อดำเนินการต่อ"
+authenticationRequiredToContinue: "กรุณายืนยันตัวตนทางอิเล็กทรอนิกส์เพื่อดำเนินการต่อ"
dateAndTime: "เวลาประทับ"
showRenotes: "แสดงรีโน้ต"
edited: "แก้ไขแล้ว"
notificationRecieveConfig: "การตั้งค่าการแจ้งเตือน"
mutualFollow: "ติดตามซึ่งกันและกัน"
+followingOrFollower: "กำลังติดตามหรือผู้ติดตาม"
fileAttachedOnly: "เฉพาะโน้ตที่มีไฟล์เท่านั้น"
-showRepliesToOthersInTimeline: "แสดงการตอบกลับไปยังอื่นๆในไทม์ไลน์"
-hideRepliesToOthersInTimeline: "ซ่อนการตอบกลับไปยังอื่นๆจากไทม์ไลน์"
+showRepliesToOthersInTimeline: "แสดงการตอบกลับผู้อื่นลงในไทม์ไลน์"
+hideRepliesToOthersInTimeline: "ไม่แสดงการตอบกลับผู้อื่นลงในไทม์ไลน์"
+showRepliesToOthersInTimelineAll: "รวมตอบกลับจากทุกคนที่คุณติดตามไว้ในไทม์ไลน์ของคุณ"
+hideRepliesToOthersInTimelineAll: "ซ่อนตอบกลับจากทุกคนที่คุณติดตามไปจากไทม์ไลน์ของคุณ"
+confirmShowRepliesAll: "การดำเนินการนี้ไม่สามารถย้อนกลับได้ คุณต้องการแสดงการตอบกลับผู้อื่นจากผู้ใช้ทุกคนที่คุณติดตามอยู่ในไทม์ไลน์ของคุณหรือไม่?"
+confirmHideRepliesAll: "การดำเนินการนี้ไม่สามารถย้อนกลับได้ คุณต้องการซ่อนการตอบกลับผู้อื่นจากผู้ใช้ทุกคนที่คุณติดตามอยู่ในไทม์ไลน์ของคุณหรือไม่?"
externalServices: "บริการภายนอก"
+sourceCode: "ซอร์สโค้ด"
+sourceCodeIsNotYetProvided: "ซอร์สโค้ดยังไม่พร้อมใช้งาน โปรดติดต่อผู้ดูแลระบบของคุณเพื่อแก้ไขปัญหานี้"
+repositoryUrl: "URL ของ repository"
+repositoryUrlDescription: "หากมีที่เก็บซอร์สโค้ดที่เปิดเผยต่อสาธารณะ ให้ป้อน URL ที่เก็บซอร์สโค้ดนั้น แต่หากคุณใช้ Misskey ตามต้นฉบับ (ไม่มีการเปลี่ยนแปลงซอร์สโค้ด) ให้ป้อน https://github.com/misskey-dev/misskey"
+repositoryUrlOrTarballRequired: "หากคุณไม่มี repository สาธารณะ คุณจะต้องจัดเตรียม tarball แทน ดู .config/example.yml สำหรับรายละเอียด"
+feedback: "ฟีดแบ็ก"
+feedbackUrl: "URLของฟีดแบ็ก"
impressum: "อิมเพรสชั่น"
impressumUrl: "URL อิมเพรสชั่น"
+impressumDescription: "การติดป้ายกำกับ (Impressum) มีผลบังคับใช้ในบางประเทศและภูมิภาค เช่น ประเทศเยอรมนี"
privacyPolicy: "นโยบายความเป็นส่วนตัว"
privacyPolicyUrl: "URL นโยบายความเป็นส่วนตัว"
tosAndPrivacyPolicy: "เงื่อนไขในการให้บริการและนโยบายความเป็นส่วนตัว"
-flip: "ย้อนกลับ"
+avatarDecorations: "การตกแต่งอวตาร"
+attach: "แนบ"
+detach: "นำออก"
+detachAll: "เอาออกทั้งหมด"
+angle: "แองเกิล"
+flip: "พลิก"
+showAvatarDecorations: "แสดงตกแต่งอวตาร"
+releaseToRefresh: "ปล่อยเพื่อรีเฟรช"
+refreshing: "กำลังรีเฟรช..."
+pullDownToRefresh: "ดึงลงเพื่อรีเฟรช"
+disableStreamingTimeline: "ปิดใช้งานอัปเดตไทม์ไลน์แบบเรียลไทม์"
+useGroupedNotifications: "แสดงผลการแจ้งเตือนแบบกลุ่มแล้ว"
+signupPendingError: "มีปัญหาในการตรวจสอบที่อยู่อีเมลลิงก์อาจหมดอายุแล้ว"
+cwNotationRequired: "หากเปิดใช้งาน “ซ่อนเนื้อหา” จะต้องระบุคำอธิบาย"
+doReaction: "เพิ่มรีแอคชั่น"
+code: "โค้ด"
+reloadRequiredToApplySettings: "จำเป็นต้องมีการโหลดซ้ำเพื่อให้การตั้งค่ามีผล"
+remainingN: "เหลือ : {n}"
+overwriteContentConfirm: "แน่ใจหรือไม่ว่าต้องการเขียนทับเนื้อหาปัจจุบัน?"
+seasonalScreenEffect: "เอฟเฟกต์หน้าจอตามฤดูกาล"
+decorate: "ตกแต่ง"
+addMfmFunction: "เพิ่มการตกแต่ง"
+enableQuickAddMfmFunction: "แสดงตัวจิ้มเลือก MFM ขั้นสูง"
+bubbleGame: "เกมบับเบิ้ล"
+sfx: "เสียงเอฟเฟ็กต์"
+soundWillBePlayed: "จะมีการเล่นเอฟเฟกต์เสียง"
+showReplay: "ดูรีเพลย์"
+replay: "รีเพลย์"
+replaying: "กำลังรีเพลย์"
+endReplay: "ออกจากรีเพลย์"
+copyReplayData: "คัดลอกข้อมูลรีเพลย์"
+ranking: "อันดับ"
+lastNDays: "ล่าสุด {n} วันที่แล้ว"
+backToTitle: "กลับไปหน้าไตเติ้ล"
+hemisphere: "พื้นที่ที่อาศัยอยู่"
+withSensitive: "แสดงโน้ตที่มีไฟล์เนื้อหาละเอียดอ่อน"
+userSaysSomethingSensitive: "โพสต์ที่มีไฟล์เนื้อหาละเอียดอ่อนของ {name}"
+enableHorizontalSwipe: "ปัดเพื่อสลับแท็บ"
+loading: "กำลังโหลด"
+surrender: "ยอมแพ้"
+gameRetry: "เริ่มเกมใหม่"
+_bubbleGame:
+ howToPlay: "วิธีเล่น"
+ hold: "หยุดชั่วคราว"
+ _score:
+ score: "คะแนน"
+ scoreYen: "จำนวนเงินที่ได้รับ"
+ highScore: "คะแนนสูงสุด"
+ maxChain: "จำนวน chain สูงสุด"
+ yen: "{yen} เยน"
+ estimatedQty: "{qty} อัน"
+ scoreSweets: "โอนิงิริ {onigiriQtyWithUnit}"
+ _howToPlay:
+ section1: "ขยับตำแหน่งและวางวัตถุลงในกล่อง"
+ section2: "เมื่อวัตถุประเภทเดียวกันมารวมกัน พวกมันจะกลายเป็นวัตถุใหม่และคุณจะได้รับคะแนน"
+ section3: "หากวัตถุล้นออกมาจากกล่อง เกมก็จะจบลง ตั้งเป้าทำคะแนนให้สูงด้วยการหลอมวัตถุต่าง ๆ โดยไม่ทำให้ล้นกล่อง!"
_announcement:
forExistingUsers: "ผู้ใช้งานที่มีอยู่เท่านั้น"
forExistingUsersDescription: "การประกาศนี้จะแสดงต่อผู้ใช้ที่มีอยู่ ณ จุดที่เผยแพร่นั้นๆถ้าหากเปิดใช้งาน ถ้าหากปิดใช้งานผู้ที่กำลังสมัครใหม่หลังจากโพสต์แล้วนั้นก็จะเห็นเช่นกัน"
- needConfirmationToRead: "จำเป็นต้องยืนยันเพื่อทำเครื่องหมายบอกว่าอ่านแล้ว"
- needConfirmationToReadDescription: "ข้อความแจ้งแยก ถ้าหากต้องการเพื่อยืนยันว่ากำลังทำเครื่องหมายประกาศนี้ว่าอ่านแล้วจะแสดงขึ้นถ้าหากเปิดใช้งาน การประกาศนั้นจะไม่รวมอยู่ในฟังก์ชั่นว่า \"ทำเครื่องหมายทั้งหมดว่าอ่านแล้ว\""
- end: "ประกาศเก็บถาวร"
+ needConfirmationToRead: "จำเป็นต้องยืนยันว่าอ่านแล้ว"
+ needConfirmationToReadDescription: "กล่องโต้ตอบการยืนยันจะปรากฏขึ้นเมื่อจะทำเครื่องหมายว่าอ่านแล้ว นอกจากนี้ยังทำให้ประกาศนี้ยังไม่ถูกอ่านเมื่อใช้ฟังก์ชั่น “ทำเครื่องหมายฯ ทั้งหมดว่าอ่านแล้ว”"
+ end: "เก็บประกาศ"
tooManyActiveAnnouncementDescription: "การมีประกาศที่ใช้งานมากเกินไปนั้นอาจจะทำให้ประสบการณ์ของผู้ใช้งานนั้นดูแย่ลง โปรดกรุณาพิจารณาการเก็บประกาศที่ล้าสมัยด้วยนะค่ะ"
- readConfirmTitle: "ทำเครื่องหมายบอกว่าอ่านแล้วเลยมั้ย?"
- readConfirmText: "การดำเนินการนี้จะทำเครื่องหมายเนื้อหาของ \"{title}\" บอกว่าอ่านแล้วนะ"
+ readConfirmTitle: "ทำเครื่องหมายว่าอ่านแล้วเลยไหม?"
+ readConfirmText: "จะทำเครื่องหมายใส่ “{title}” ว่าอ่านแล้ว"
+ shouldNotBeUsedToPresentPermanentInfo: "เราขอแนะนำให้ใช้ประกาศเพื่อโพสต์ข้อมูลแบบ flow มากกว่าข้อมูลแบบ stock เนื่องจากมีแนวโน้มที่จะส่งผลเสียต่อ UX โดยเฉพาะสำหรับผู้ใช้ใหม่"
+ dialogAnnouncementUxWarn: "เราขอแนะนำให้ใช้ด้วยความระมัดระวัง เนื่องจากการแจ้งเตือนแบบกล่องโต้ตอบตั้งแต่ 2 รายการขึ้นไปพร้อมกันอาจส่งผลเสียต่อ UX ได้อย่างมาก"
+ silence: "ไม่มีการแจ้งเตือน"
+ silenceDescription: "หากเปิดใช้งาน จะไม่มีการแจ้งเตือนประกาศนี้ และผู้ใช้จะไม่จำเป็นต้องทำเครื่องหมายว่าอ่านแล้ว"
_initialAccountSetting:
accountCreated: "คุณได้สร้างบัญชีของคุณสำเร็จเรียบร้อยแล้ว!"
letsStartAccountSetup: "สำหรับผู้เริ่มต้นมาตั้งค่าโปรไฟล์ของคุณกันเถอะ"
@@ -1153,17 +1262,92 @@ _initialAccountSetting:
followUsers: "ลองติดตามผู้ใช้บางคนที่คุณอาจจะสนใจเพื่อสร้างไทม์ไลน์ของคุณสิ !"
pushNotificationDescription: "กำลังเปิดใช้งานการแจ้งเตือนแบบพุชจะช่วยให้คุณได้รับการแจ้งเตือนจาก {name} โดยตรงบนอุปกรณ์ของคุณนะ"
initialAccountSettingCompleted: "ตั้งค่าโปรไฟล์เสร็จสมบูรณ์แล้ว!"
- haveFun: "ขอให้สนุก {name}!"
+ haveFun: "ขอให้สนุกกับ {name}!"
+ youCanContinueTutorial: "คุณสามารถดำเนินการต่อด้วยบทช่วยสอนเกี่ยวกับวิธีใช้ {name} (Misskey) หรือออกจากบทช่วยสอนแล้วเริ่มใช้งานได้ทันที"
+ startTutorial: "เริ่มการฝึกสอน"
skipAreYouSure: "ต้องการข้ามการตั้งค่าโปรไฟล์จริงๆแบบนั้นหรอ?"
laterAreYouSure: "ต้องการตั้งค่าโปรไฟล์ในภายหลังจริงๆอย่างงั้นหรอ?"
+_initialTutorial:
+ launchTutorial: "เริ่มบทช่วยสอน"
+ title: "บทช่วยสอน"
+ wellDone: "ทำได้ดีมาก!"
+ skipAreYouSure: "ต้องการออกจากบทช่วยสอนใช่ไหม?"
+ _landing:
+ title: "ยินดีต้อนรับสู่บทช่วยสอน"
+ description: "คุณสามารถตรวจสอบการใช้งานและฟังก์ชั่นพื้นฐานของ Misskey ได้ที่นี่"
+ _note:
+ title: "โน้ตคืออะไร?"
+ description: "โพสต์ใน Misskey เรียกว่า “โน้ต” ซึ่งจะจัดเรียงตามลำดับเวลาบนไทม์ไลน์และอัปเดตแบบเรียลไทม์"
+ reply: "คุณสามารถตอบกลับได้ และคุณยังสามารถตอบกลับใส่การตอบกลับเพื่อสนทนาต่อได้เสมือนดั่งเธรด"
+ renote: "คุณสามารถแชร์โน้ตไปยังไทม์ไลน์ของคุณเอง คุณยังสามารถเพิ่มข้อความและเครื่องหมายคำพูดได้"
+ reaction: "คุณสามารถเพิ่มรีแอคชั่นได้ รายละเอียดจะอธิบายอยู่ในหน้าถัดไป"
+ menu: "คุณสามารถดูรายละเอียดโน้ต คัดลอกลิงก์ และดำเนินการอื่นๆ ได้"
+ _reaction:
+ title: "รีแอคชั่นคืออะไร?"
+ description: "โน้ตสามารถ“รีแอคชั่น”ด้วยเอโมจิต่างๆ ซึ่งทำให้สามารถแสดงความแตกต่างเล็กๆ น้อยๆ ที่อาจไม่สามารถสื่อออกมาได้ด้วยการแค่การกด “ถูกใจ”"
+ letsTryReacting: "คุณสามารถเพิ่มรีแอคชั่นได้ด้วยการคลิกปุ่ม “+” บนโน้ต ลองรีแอคชั่นโน้ตตัวอย่างนี้ดูสิ!"
+ reactToContinue: "เพิ่มรีแอคชั่นเพื่อดำเนินการต่อ"
+ reactNotification: "คุณจะได้รับการแจ้งเตือนแบบเรียลไทม์เมื่อมีคนตอบรีแอคชั่นโน้ตของคุณ"
+ reactDone: "คุณสามารถยกเลิกรีแอคชั่นได้โดยการกดปุ่ม “-”"
+ _timeline:
+ title: "แนวคิดเรื่องของไทม์ไลน์"
+ description1: "Misskey มีหลายไทม์ไลน์ขึ้นอยู่กับวิธีการใช้งานของคุณ (บางไทม์ไลน์อาจไม่สามารถใช้ได้ขึ้นอยู่กับนโยบายของเซิร์ฟเวอร์)"
+ home: "คุณสามารถดูโพสต์จากบัญชีที่คุณติดตามได้"
+ local: "คุณสามารถดูโพสต์จากผู้ใช้ทั้งหมดบนเซิร์ฟเวอร์นี้"
+ social: "โพสต์จากทั้งไทม์ไลน์หน้าแรกและไทม์ไลน์ในพื้นที่ของคุณจะปรากฏขึ้น"
+ global: "คุณสามารถดูโพสต์จากเซิร์ฟเวอร์ที่เชื่อมต่ออื่นๆ ทั้งหมดได้"
+ description2: "คุณสามารถสลับระหว่างแต่ละไทม์ไลน์ได้ตลอดเวลาได้ที่บริเวณด้านบนของหน้าจอ"
+ description3: "นอกจากนี้ยังมีรายการไทม์ไลน์ ไทม์ไลน์ของช่อง ฯลฯ โปรดดู {link} สำหรับรายละเอียดเพิ่มเติม"
+ _postNote:
+ title: "ตั้งค่าการโพสต์โน้ต"
+ description1: "เมื่อโพสต์โน้ตบน Misskey คุณสามารถตั้งค่าตัวเลือกต่างๆ ได้ แบบฟอร์มการส่งมีลักษณะดังนี้"
+ _visibility:
+ description: "คุณสามารถจำกัดผู้ที่สามารถดูโน้ตของคุณได้นะ"
+ public: "โน้ตของคุณนั้นจะปรากฏแก่ผู้ใช้งานทุกคน"
+ home: "เผยแพร่บนไทม์ไลน์หน้าแรกเท่านั้น ผู้คนที่เข้าชมโปรไฟล์ของคุณ ผ่านผู้ติดตาม และผ่านการรีโน้ตสามารถเห็นได้"
+ followers: "มองเห็นได้เฉพาะผู้ติดตามเท่านั้น ไม่มีใครอื่นนอกจากตัวคุณเองที่สามารถรีโน้ตได้ และมีเพียงผู้ติดตามของคุณเท่านั้นที่สามารถดูได้"
+ direct: "เปิดให้เห็นเฉพาะผู้ใช้ที่ระบุเท่านั้น และพวกเขาจะได้รับแจ้งเตือนด้วย คุณสามารถใช้มันแทนข้อความโดยตรง (dm)"
+ doNotSendConfidencialOnDirect1: "โปรดใช้ความระมัดระวังในการส่งข้อมูลที่ละเอียดอ่อน"
+ doNotSendConfidencialOnDirect2: "ผู้ดูแลระบบเซิร์ฟเวอร์ปลายทางสามารถดูเนื้อหาที่โพสต์ได้ ดังนั้นหากคุณส่งโพสต์โดยตรงไปยังผู้ใช้บนเซิร์ฟเวอร์ที่ไม่น่าเชื่อถือ คุณจะต้องใช้ความระมัดระวังในการจัดการข้อมูลที่เป็นความลับ"
+ localOnly: "การโพสต์ด้วย flag นี้จะไม่รวมโน้ตไปยังเซิร์ฟเวอร์อื่น ผู้ใช้บนเซิร์ฟเวอร์อื่นจะไม่สามารถดูโน้ตเหล่านี้ได้โดยตรง โดยไม่คำนึงถึงการตั้งค่าการแสดงผลข้างต้น"
+ _cw:
+ title: "คำเตือนเกี่ยวกับเนื้อหา"
+ description: "เนื้อหาที่เขียนด้วย “คำอธิบายประกอบ” จะแสดงแทนข้อความหลัก คลิก “ดูเพิ่มเติม” เพื่อแสดงข้อความเต็ม"
+ _exampleNote:
+ cw: "นี่อาจจะทำให้คุณหิวอย่างแน่นอน!"
+ note: "เพิ่งไปกินโดนัทเคลือบช็อคโกแลตมา 🍩😋"
+ useCases: "ใช้สิ่งนี้เพื่อระบุโน้ตที่ต้องตามแนวทางปฏิบัติของเซิร์ฟเวอร์ หรือเพื่อควบคุมการสปอยล์และข้อความที่ละเอียดอ่อนด้วยตนเอง"
+ _howToMakeAttachmentsSensitive:
+ title: "จะทำเครื่องหมายไฟล์แนบว่ามีเนื้อหาละเอียดอ่อนได้อย่างไร?"
+ description: "ทำเครื่องหมายไฟล์แนบว่า “มีเนื้อหาละเอียดอ่อน” เมื่อจำเป็นตามแนวทางของเซิร์ฟเวอร์ หรือเมื่อไฟล์แนบไม่ควรปรากฏให้เห็น"
+ tryThisFile: "ลองทำให้รูปภาพที่แนบมากับแบบฟอร์มนี้มีเนื้อหาละเอียดอ่อน!"
+ _exampleNote:
+ note: "อุ้ย นัตโตะ ฝาเปิดเละเทะ..."
+ method: "หากต้องการทำให้ไฟล์แนบมีเนื้อหาละเอียดอ่อน ให้คลิกไฟล์เพื่อเปิดเมนูแล้วคลิก “ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน”"
+ sensitiveSucceeded: "เมื่อแนบไฟล์ โปรดตั้งค่าเครื่องหมายว่ามีเนื้อหาละเอียดอ่อนตามแนวทางของเซิร์ฟเวอร์"
+ doItToContinue: "ทำเครื่องหมายกับรูปภาพว่ามีเนื้อหาละเอียดอ่อน เพื่อดำเนินการต่อ"
+ _done:
+ title: "บทเรียนจบลงแล้วจ้า เย่เย่เย่ 🎉"
+ description: "คุณสมบัติที่แนะนำในที่นี่เป็นเพียงบางส่วนเท่านั้น หากต้องการเรียนรู้เพิ่มเติมเกี่ยวกับวิธีใช้ Misskey โปรดไปที่ {link}"
+_timelineDescription:
+ home: "บนไทม์ไลน์หน้าแรก คุณสามารถดูโพสต์จากบัญชีที่คุณติดตามได้"
+ local: "ไทม์ไลน์ในพื้นที่ช่วยให้คุณเห็นโพสต์จากผู้ใช้ทั้งหมดบนเซิร์ฟเวอร์นี้"
+ social: "ไทม์ไลน์โซเชียลจะแสดงโพสต์จากทั้งไทม์ไลน์หน้าแรกและไทม์ไลน์ในพื้นที่"
+ global: "ในไทม์ไลน์ทั่วโลก คุณสามารถดูโน้ตจากเซิร์ฟเวอร์ที่เชื่อมต่อทั้งหมดได้"
_serverRules:
description: "ชุดของกฎที่จะแสดงก่อนการลงทะเบียนเราขอแนะนำให้ตั้งค่าสรุปข้อกำหนดในการให้บริการ"
_serverSettings:
- iconUrl: "ไอคอน URL"
+ iconUrl: "URL ไอคอน"
+ appIconDescription: "ระบุไอคอนที่จะใช้เมื่อ {host} แสดงเป็นแอป"
appIconUsageExample: "E.g. เป็น PWA หรือเมื่อแสดงผลเป็นบุ๊กมาร์กหน้าจอหลักบนโทรศัพท์"
+ appIconStyleRecommendation: "เนื่องจากไอคอนอาจถูกครอบตัดเป็นสี่เหลี่ยมจัตุรัสหรือวงกลม จึงแนะนำให้ใช้ไอคอนที่มีขอบสีรอบๆ เนื้อหา"
appIconResolutionMustBe: "ความละเอียดขั้นต่ำไว้คือ {resolution}."
- manifestJsonOverride: "manifest.json โอเวอร์ลาย"
+ manifestJsonOverride: "เขียนทับ manifest.json"
shortName: "ชื่อย่อ"
+ shortNameDescription: "ตัวย่อหรือชื่อทั่วไปที่สามารถแสดงแทนชื่ออย่างเป็นทางการแบบยาวของเซิร์ฟเวอร์"
+ fanoutTimelineDescription: "เพิ่มประสิทธิภาพการดึงข้อมูลไทม์ไลน์อย่างมาก และลดภาระในฐานข้อมูลเมื่อเปิดใช้งาน ในทางกลับกัน การใช้หน่วยความจำของ Redis จะเพิ่มขึ้น ลองปิดการใช้งานนี้ในกรณีที่หน่วยความจำเซิร์ฟเวอร์เหลือน้อยหรือเซิร์ฟเวอร์ไม่เสถียร"
+ fanoutTimelineDbFallback: "ฟอลแบ๊กกลับฐานข้อมูล"
+ fanoutTimelineDbFallbackDescription: "เมื่อเปิดใช้งาน หากไม่ได้แคชไทม์ไลน์ ไทม์ไลน์จะฟอลแบ๊กไปยังฐานข้อมูลสำหรับการ query เพิ่มเติม การปิดใช้งานจะช่วยลดภาระของเซิร์ฟเวอร์ด้วยการกำจัดกระบวนฟอลแบ๊ก แต่มันก็จะจำกัดช่วงเวลาไทม์ไลน์ที่สามารถดึงข้อมูลได้"
_accountMigration:
moveFrom: "ย้ายข้อมูลบัญชีอื่นไปยังอีกบัญชีนี้หนึ่ง"
moveFromSub: "สร้างนามแฝงไปยังบัญชีอื่น"
@@ -1172,7 +1356,7 @@ _accountMigration:
moveTo: "ย้ายข้อมูลบัญชีนี้ไปยังบัญชีอีกหนึ่ง"
moveToLabel: "บัญชีที่จะย้ายไปที่:"
moveCannotBeUndone: "ไม่สามารถยกเลิกการโอนย้ายบัญชีได้"
- moveAccountDescription: "การกระทำนี้ไม่สามารถย้อนกลับได้นะ ขั้นตอนแรก ต้องสร้างนามแฝงสำหรับบัญชีนี้ในบัญชีที่คุณต้องการย้ายไป หลังจากนั้นแล้ว ป้อนบัญชีที่จะย้ายไปในรูปแบบดังต่อไปนี้: @person@instance.com"
+ moveAccountDescription: "การดำเนินการนี้จะย้ายบัญชีของคุณไปยังบัญชีอื่น\n・ผู้ที่กำลังติดตามคุณจากบัญชีนี้จะถูกย้ายไปยังบัญชีใหม่โดยอัตโนมัติ\n・บัญชีนี้จะเลิกติดตามผู้ใช้ทั้งหมดที่กำลังติดตามอยู่\n・คุณจะไม่สามารถสร้างโน้ต ฯลฯ ในบัญชีนี้ได้\n\nแม้ว่าการย้ายผู้ที่ติดตามคุณจะเป็นไปโดยอัตโนมัติ แต่คุณต้องเตรียมขั้นตอนบางอย่างด้วยตนเอง เพื่อย้ายรายชื่อผู้ใช้ที่คุณกำลังติดตาม โดยดำเนินการส่งออกรายชื่อแล้วค่อยนำเข้ามาภายหลังในเมนูการตั้งค่าของบัญชีใหม่ ใช้ขั้นตอนเดียวกันนี้ใช้รายชื่อผู้ใช้ที่ถูกปิดเสียงและถูกบล็อก\n\n(คำอธิบายนี้ใช้กับ Misskey v13.12.0 ขึ้นไป, ซอฟต์แวร์ ActivityPub อื่นๆ เช่น Mastodon อาจทำงานแตกต่างออกไป)"
moveAccountHowTo: "หากต้องการย้ายข้อมูลก่อนอื่นให้สร้างชื่อแทนสำหรับบัญชีนี้ ในบัญชีที่จะต้องการย้ายไป\nหลังจากที่คุณสร้างนามแฝงนั้นแล้ว ให้ป้อนบัญชีที่ต้องการจะย้ายไปในรูปแบบดังต่อไปนี้: @username@server.example.com"
startMigration: "โอนย้าย"
migrationConfirm: "ยืนยันการย้ายข้อมูลบัญชีนี้ไปที่ {account} เมื่อเริ่มแล้วจะไม่สามารถหยุดหรือนำกลับคืนมาได้ และคุณจะไม่สามารถใช้บัญชีนี้ในสถานะดั้งเดิมได้อีกต่อไป\n\nนอกจากนี้ คุณจำเป็นต้องสร้างบัญชีสำรองสำหรับการย้ายบัญชี"
@@ -1187,31 +1371,31 @@ _achievements:
description: "โพสต์โน้ตแรกของคุณ"
flavor: "ขอให้มีช่วงเวลาที่ดีกับ Misskey นะคะ!"
_notes10:
- title: "โน้ตบางอย่าง"
+ title: "โน้ตไม่กี่ชิ้น"
description: "โพสต์ 10 โน้ต"
_notes100:
- title: "โน้ตจำนวนมาก"
+ title: "โน้ตเยอะอยู่"
description: "โพสต์ 100 โน้ต"
_notes500:
- title: "ครอบคลุมในโน้ต"
+ title: "จมคากองโน้ต"
description: "โพสต์ 500 โน้ต"
_notes1000:
title: "ภูเขาแห่งโน้ต"
description: "โพสต์ 1,000 โน้ต"
_notes5000:
- title: "โน้ตล้น"
+ title: "โน้ตล้นไปแล้ว"
description: "โพสต์ 5,000 โน้ต"
_notes10000:
title: "ซุปเปอร์โน้ต"
description: "โพสต์ 10,000 โน้ต"
_notes20000:
- title: "ต้องการ... เพิ่มเติม... โน้ต..."
+ title: "ต้ อ ง ก า ร โ น้ ต เ พิ่ ม อี ก !"
description: "โพสต์ 20,000 โน้ต"
_notes30000:
title: "โน้ต โน้ต โน้ต!"
description: "โพสต์ 30,000 โน้ต"
_notes40000:
- title: "โน้ตโรงงาน"
+ title: "โรงงานผลิตโน้ต"
description: "โพสต์ 40,000 โน้ต"
_notes50000:
title: "ดาวเคราะห์แห่งโน้ต"
@@ -1220,26 +1404,26 @@ _achievements:
title: "โน้ตควอซาร์"
description: "โพสต์ 60,000 โน้ต"
_notes70000:
- title: "โน้ตหลุมดำ"
+ title: "หลุม-โน้ต-ดำ"
description: "โพสต์ 70,000 โน้ต"
_notes80000:
- title: "โน้ต กาแล็กซี่"
+ title: "ดาราจักรโน้ต"
description: "โพสต์ 80,000 โน้ต"
_notes90000:
- title: "โน้ต จักรวาล"
+ title: "จักรวาลโน้ต"
description: "โพสต์ 90,000 โน้ต"
_notes100000:
title: "ALL YOUR NOTE ARE BELONG TO US"
description: "โพสต์ 100,000 โน้ต"
- flavor: "นายแน่ใจล่ะก็ มีอะไรพูดมาได้นะ"
+ flavor: "มีเรื่องจะเขียนมากขนาดนั้นเลยเหรอนั่น?"
_login3:
title: "มือใหม่ I"
description: "เข้าสู่ระบบเป็นเวลารวม 3 วัน"
- flavor: "เริ่มตั้งแต่วันนี้ เรียกฉันว่ามิสคิสต์"
+ flavor: "ตั้งแต่วันนี้เป็นต้นไป ฉันคือมิสคิสต์"
_login7:
title: "มือใหม่ II"
description: "เข้าสู่ระบบเป็นเวลารวม 7 วัน"
- flavor: "รู้สึกเหมือนคุณได้แขวนของสิ่งต่างๆ หรือยังคะ?"
+ flavor: "ชินกับมันแล้วหรือยัง?"
_login15:
title: "มือใหม่ III"
description: "เข้าสู่ระบบเป็นเวลารวม 15 วัน"
@@ -1252,7 +1436,7 @@ _achievements:
_login100:
title: "มิสคิสท์ III"
description: "เข้าสู่ระบบเป็นเวลารวม 100 วัน"
- flavor: "ความรุนแรง Misskist"
+ flavor: "มิสคิสต์หัวรุนแรง"
_login200:
title: "ลูกค้าประจำ I"
description: "เข้าสู่ระบบเป็นเวลารวม 200 วัน"
@@ -1265,7 +1449,7 @@ _achievements:
_login500:
title: "ผู้เชี่ยวชาญ I"
description: "เข้าสู่ระบบเป็นเวลารวม 500 วัน"
- flavor: "เพื่อนของผมนะมักจะกล่าวว่าผมนะชอบจดโน้ต"
+ flavor: "ทุกท่าน ผมชอบโน้ต (กล่าวโดย เดอะ เ_เ_อร์)"
_login600:
title: "ผู้เชี่ยวชาญ II"
description: "เข้าสู่ระบบเป็นเวลารวม 600 วัน"
@@ -1283,7 +1467,7 @@ _achievements:
description: "เข้าสู่ระบบเป็นเวลารวม 1,000 วัน"
flavor: "ขอบคุณที่ใช้ Misskey นะ !"
_noteClipped1:
- title: "จะต้อง... คลิป..."
+ title: "อดไม่ได้ที่จะต้องคลิปมันเอาไว้"
description: "คลิปโน้ตตัวแรกของคุณ"
_noteFavorited1:
title: "สตาร์เกเซอร์"
@@ -1292,15 +1476,15 @@ _achievements:
title: "แสวงหาดวงดาว"
description: "มีคนอื่นๆที่ชื่นชอบหนึ่งในโน้ตของคุณ"
_profileFilled:
- title: "เตรียมไว้อย่างดี"
+ title: "เตรียมตัวอย่างดี"
description: "ตั้งค่าโปรไฟล์ของคุณ"
_markedAsCat:
title: "ฉันเป็นแมว"
description: "ทำเครื่องหมายบัญชีของคุณว่าเป็นแมว"
- flavor: "ฉันจะให้ชื่อคุณภายหลังนะ"
+ flavor: "แมวน้อยไร้ชื่อ"
_following1:
- title: "กำลังติดตามผู้ใช้คนแรกของคุณ"
- description: "ติดตามผู้ใช้"
+ title: "ก้าวแรกสู่...กดติดตาม"
+ description: "กดติดตามชาวบ้านครั้งแรก"
_following10:
title: "ทำต่อไป... ทำต่อไป..."
description: "ติดตาม 10 บัญชีผู้ใช้"
@@ -1311,7 +1495,7 @@ _achievements:
title: "เพื่อน 100 คน"
description: "ติดตาม 100 บัญชี"
_following300:
- title: "เพื่อนโอเวอร์โหลด"
+ title: "มีเพื่อนมากเกินไปละ"
description: "ติดตาม 300 บัญชี"
_followers1:
title: "ผู้ติดตามคนแรก"
@@ -1338,12 +1522,12 @@ _achievements:
title: "นักสะสมความสำเร็จ"
description: "ได้รับความสำเร็จ 30 ครั้ง"
_viewAchievements3min:
- title: "ชอบบรรลุผลสําเร็จ"
+ title: "ชอบบรรลุความสําเร็จ"
description: "มองดูรายการความสำเร็จของคุณเป็นเวลาอย่างน้อย 3 นาที"
_iLoveMisskey:
title: "ฉันรัก Misskey"
- description: "โพสต์ \"I ❤ #Misskey\""
- flavor: "ขอบคุณที่ใช้ Misskey! by ทีมผู้พัฒนา"
+ description: "โพสต์ “I ❤ #Misskey”"
+ flavor: "ขอบคุณพระคุณเป็นอย่างสูงที่ท่านใช้ Misskey นะคะ ! by ทีมผู้พัฒนา"
_foundTreasure:
title: "ล่าสมบัติ"
description: "คุณพบสมบัติที่ซ่อนอยู่"
@@ -1351,25 +1535,25 @@ _achievements:
title: "พักผ่อนสักหน่อย"
description: "ใช้เวลา 30 นาทีบน Misskey"
_client60min:
- title: "ไม่มี \"Miss\" ใน Misskey "
+ title: "Misskey ต้องไม่มีสิ่งใด “Miss”"
description: "เปิด Misskey ค้างไว้แล้วอย่างน้อย 60 นาที"
_noteDeletedWithin1min:
title: "ไม่เป็นไร"
description: "ลบโน้ตภายในหนึ่งนาทีหลังจากที่โพสต์"
_postedAtLateNight:
- title: "กลางคืน"
+ title: "ออกหากินยามดึกดื่น"
description: "โพสต์โน้ตตอนดึกๆ"
flavor: "ได้เวลาเข้านอนแล้วนะ"
_postedAt0min0sec:
- title: "นาฬิกาพูดได้"
- description: "โพสต์บนโน้ตเมื่อเวลา 00:00 น."
- flavor: "คลิก คลิก คลิก แกล๊งๆ"
+ title: "นาฬิกาเทียบเวลา"
+ description: "โพสต์โน้ตเมื่อเวลา 00:00 น."
+ flavor: "โป๊ะ โป๊ะ โป๊ะ ปิ้งงงงง"
_selfQuote:
title: "อ้างอิงตนเอง"
- description: "อ้างโน้ตย่อของคุณเอง"
+ description: "อ้างโน้ตของคุณเอง"
_htl20npm:
title: "ไทม์ไลน์ไหล"
- description: "มีการทำความเร็วของไทม์ไลน์ที่บ้านของคุณเกิน 20 npm (โน้ตต่อนาที)"
+ description: "มีการทำความเร็วของไทม์ไลน์หน้าแรกเกิน 20 npm (โน้ตต่อนาที)"
_viewInstanceChart:
title: "วิเคราะห์"
description: "ดูแผนภูมิอินสแตนซ์ของคุณ"
@@ -1386,14 +1570,14 @@ _achievements:
title: "คุณอ่านมันจริงๆหรือเปล่า?"
description: "มีการโต้ตอบกับโน้ตที่มีความยาวมากกว่า 100 ตัวอักษรภายใน 3 วินาทีหลังจากที่โพสต์"
_clickedClickHere:
- title: "คลิ๊กที่นี่"
+ title: "คลิกที่นี่"
description: "คุณได้คลิกที่นี่"
_justPlainLucky:
title: "แค่ลัคกี้ธรรมดา"
description: "มีโอกาสที่จะได้รับด้วยความน่าจะเป็นไปได้ 0.005% ทุก ๆ 10 วินาที"
_setNameToSyuilo:
- title: "พระเจ้าคอมเพล็กซ์"
- description: "ตั้งชื่อของคุณเป็น \"syuilo\""
+ title: "คอมเพล็กซ์ของพระเจ้า"
+ description: "ตั้งชื่อของคุณเป็น “syuilo”"
_passedSinceAccountCreated1:
title: "ครบรอบหนึ่งปี"
description: "ผ่านไปหนึ่งปีแล้วนะตั้งแต่บัญชีของคุณถูกสร้างขึ้นมาน่ะ"
@@ -1413,7 +1597,7 @@ _achievements:
_cookieClicked:
title: "เกมที่คุณคลิกที่คุกกี้"
description: "คลิกคุกกี้"
- flavor: "เดี๋ยวก่อนนะ คุณอยู่ในเว็บไซต์ที่ถูกต้องแน่อย่างงั้นเหรอ?"
+ flavor: "ใช่หรอ? แน่ใจว่าซอฟต์แวร์ทำงานถูกต้องนะ?"
_brainDiver:
title: "Brain Diver"
description: "โพสต์ลิงก์ไปยัง Brain Diver"
@@ -1421,35 +1605,47 @@ _achievements:
_smashTestNotificationButton:
title: "ทดสอบโอเวอร์โฟลว์"
description: "ทดสอบการแจ้งเตือนทริกเกอร์ซ้ำๆ ภายในระยะเวลาอันสั้นๆ"
+ _tutorialCompleted:
+ title: "ใบรับรองการสำเร็จหลักสูตร Misskey มือใหม่"
+ description: "เสร็จสิ้นการสอนแล้ว"
+ _bubbleGameExplodingHead:
+ title: "🤯"
+ description: "สร้างวัตถุที่ใหญ่ที่สุดในเกมบับเบิ้ล"
+ _bubbleGameDoubleExplodingHead:
+ title: "ดับเบิ้ล"
+ description: "สร้างวัตถุที่ใหญ่ที่สุดในเกมบับเบิ้ลสองชิ้นในเวลาเดียวกัน"
+ flavor: "ปิ่นโตขนาดนี้ น่าจะเพิ่ม 🤯 🤯 เข้าไปนิดหน่อย"
_role:
new: "บทบาทใหม่"
edit: "แก้ไขบทบาท"
name: "ชื่อบทบาท"
description: "คำอธิบายบทบาท"
permission: "สิทธิ์ตามบทบาท"
- descriptionOfPermission: "ผู้ดูแลกลั่นกรองเนื้อหา สามารถดำเนินการดูแลขั้นพื้นฐานได้นะ\nผู้ดูแลระบบ สามารถเปลี่ยนการตั้งค่าทั้งหมดของอินสแตนซ์ได้นะ"
+ descriptionOfPermission: "ผู้ควบคุม สามารถดำเนินการดูแลขั้นพื้นฐานได้\nผู้ดูแลระบบ สามารถเปลี่ยนการตั้งค่าทั้งหมดของอินสแตนซ์ได้"
assignTarget: "มอบหมาย"
- descriptionOfAssignTarget: "แมนนวล เพื่อเปลี่ยนผู้ที่เป็นส่วนหนึ่งของบทบาทนี้และใครที่ไม่ใช่ด้วยตนเอง\nเงื่อนไข เพื่อให้ผู้ใช้ได้รับการกำหนดและนำออกจากบทบาทนี้โดยอัตโนมัติตามเงื่อนไขชุดหนึ่ง"
+ descriptionOfAssignTarget: "แบบปรับเอง เพิ่มถอนบทบาทนี้แก่ผู้ใช้ด้วยตัวเอง\nแบบมีเงื่อนไข เพิ่มถอนบทบาทนี้แก่ผู้ใช้โดยอัตโนมัติหากเข้าเงื่อนไขใดต่อไปนี้"
manual: "ปรับเอง"
+ manualRoles: "บทบาทแบบทำมือ"
conditional: "มีเงื่อนไข"
+ conditionalRoles: "บทบาทแบบมีเงื่อนไข"
condition: "เงื่อนไข"
isConditionalRole: "นี่คือบทบาทที่มีเงื่อนไข"
- isPublic: "บทบาทสาธารณะ"
- descriptionOfIsPublic: "ทุกคนสามารถดูได้ว่าผู้ใช้งานนั้นได้รับมอบหมายบทบาทด้วยหรือไม่ \n\nบทบาทจะแสดงในโปรไฟล์ของผู้ใช้ด้วย"
+ isPublic: "ทำให้บทบาทเปิดเผยต่อสาธารณะ"
+ descriptionOfIsPublic: "บทบาทจะปรากฏบนโปรไฟล์ของผู้ใช้และเปิดเผยต่อสาธารณะ (ทุกคนสามารถเห็นได้ว่าผู้ใช้รายนี้มีบทบาทนี้)"
options: "ตัวเลือกบทบาท"
policies: "นโยบาย"
- baseRole: "บทบาทพื้นฐาน"
- useBaseValue: "ใช้บทบาทพื้นฐานเริ่มต้น"
+ baseRole: "เทมเพลตบทบาท"
+ useBaseValue: "ใช้ตามเทมเพลตบทบาท"
chooseRoleToAssign: "เลือกบทบาทที่ต้องการกำหนด"
- iconUrl: "ไอคอน URL"
+ iconUrl: "URL ไอคอน"
asBadge: "แสดงเป็นตรา"
- descriptionOfAsBadge: "ไอคอนของบทบาทนี้จะปรากฏถัดจากชื่อผู้ใช้ของผู้ใช้งานด้วยบทบาทนี้ถ้าหากเปิดใช้งาน"
- isExplorable: "บทบาทไทม์ไลน์เป็นแบบสาธารณะ"
- descriptionOfIsExplorable: "ไทม์ไลน์ของบทบาทนี้จะสามารถเข้าถึงได้แบบสาธารณะถ้าหากเปิดใช้งาน เส้นเวลาของบทบาทนั้นจะไม่ถูกเปิดเผยต่อสาธารณะ ถึงแม้ว่าจะไม่เปิดเผยต่อสาธารณะแม้แต่ว่า...จะตั้งค่าไว้ยังไงก็ตาม"
- displayOrder: "ตำแหน่ง"
- descriptionOfDisplayOrder: "ยิ่งตัวเลขสูง ตำแหน่ง UI ก็ยิ่งสูงขึ้นนะ"
- canEditMembersByModerator: "อนุญาตให้ผู้ดูแลแก้ไขสมาชิก"
- descriptionOfCanEditMembersByModerator: "เมื่อเปิดใช้ ผู้ดูแลนอกเหนือจากผู้ดูแลระบบแล้ว จะสามารถกำหนดและยกเลิกการมอบหมายบทบาทนี้ให้กับผู้ใช้ได้ เมื่อปิด เฉพาะผู้ดูแลระบบเท่านั้นที่จะสามารถกำหนดผู้ใช้ได้นะ"
+ descriptionOfAsBadge: "เมื่อเปิดใช้งาน ไอคอนบทบาทจะปรากฏถัดจากชื่อผู้ใช้"
+ isExplorable: "ค้นหาผู้ใช้ได้ง่ายขึ้นโดยดูจากบทบาท"
+ descriptionOfIsExplorable: "เมื่อเปิดใช้งาน ไทมไลน์บทบาทนี้และสมาชิกที่มีบทบาทนี้จะเปิดเผยเป็นสาธารณะ"
+ displayOrder: "ลำดับการแสดงผล"
+ descriptionOfDisplayOrder: "เลขที่สูงกว่าจะแสดงบน UI ก่อน"
+ canEditMembersByModerator: "อนุญาตให้ผู้ควบคุมแก้ไขสมาชิก"
+ descriptionOfCanEditMembersByModerator: "เมื่อเปิดใช้ นอกเหนือจากผู้ควบคุมและผู้ดูแลระบบแล้ว จะสามารถเพิ่มถอนบทบาทนี้แก่ผู้ใช้ได้ แต่เมื่อปิดใช้ จะมีเฉพาะผู้ดูแลระบบเท่านั้นที่จะสามารถดำเนินการได้"
priority: "ลำดับความสำคัญ"
_priority:
low: "ต่ำ"
@@ -1458,12 +1654,14 @@ _role:
_options:
gtlAvailable: "การดูไทม์ไลน์ทั่วโลก"
ltlAvailable: "การดูไทม์ไลน์ในท้องถิ่น"
- canPublicNote: "สามารถส่งโน้ตสาธารณะ"
+ canPublicNote: "สามารถโพสต์แบบสาธารณะ"
+ mentionMax: "จำนวนการกล่าวถึงสูงสุดต่อโน้ต"
canInvite: "สร้างรหัสเชิญอินสแตนซ์"
inviteLimit: "จำกัดการเชิญ"
- inviteLimitCycle: "จำกัดการเชิญไว้คูลดาวน์"
+ inviteLimitCycle: "คูลดาวน์ในการเชิญ"
inviteExpirationTime: "วันหมดอายุของรหัสการเชิญ"
- canManageCustomEmojis: "จัดการอีโมจิแบบกำหนดเอง"
+ canManageCustomEmojis: "จัดการเอโมจิที่กำหนดเอง"
+ canManageAvatarDecorations: "จัดการตกแต่งอวตาร"
driveCapacity: "ความจุของไดรฟ์"
alwaysMarkNsfw: "ทำเครื่องหมายไฟล์ว่าเป็น NSFW เสมอ"
pinMax: "จํานวนสูงสุดของโน้ตที่ปักหมุดไว้"
@@ -1474,13 +1672,15 @@ _role:
noteEachClipsMax: "จำนวนโน้ตสูงสุดภายในคลิป"
userListMax: "จำนวนรายชื่อผู้ใช้สูงสุด"
userEachUserListsMax: "จำนวนผู้ใช้สูงสุดภายในรายการผู้ใช้"
- rateLimitFactor: "ขีดจำกัดอัตรา"
- descriptionOfRateLimitFactor: "ขีดจํากัดอัตราที่ต่ำกว่ามีข้อจํากัดน้อยกว่าข้อจํากัดที่สูงกว่า"
+ rateLimitFactor: "อัตราการจำกัด"
+ descriptionOfRateLimitFactor: "ยิ่งตัวเลขน้อยก็ยิ่งจำกัดน้อย ยิ่งมากก็ยิ่งเข้มงวดมากขึ้น"
canHideAds: "ซ่อนโฆษณา"
canSearchNotes: "การใช้การค้นหาโน้ต"
canUseTranslator: "การใช้งานแปล"
+ avatarDecorationLimit: "จำนวนการตกแต่งไอคอนสูงสุดที่สามารถติดตั้งได้"
_condition:
- isLocal: "ผู้ใช้ภายใน"
+ roleAssignedTo: "มอบหมายให้มีบทบาทแบบทำมือ"
+ isLocal: "ผู้ใช้ในพื้นที่"
isRemote: "ผู้ใช้ระยะไกล"
createdLessThan: "สร้างน้อยกว่า"
createdMoreThan: "สร้างมากกว่า"
@@ -1494,10 +1694,10 @@ _role:
or: "หรือ"
not: "ไม่"
_sensitiveMediaDetection:
- description: "ลดความพยายามในการดูแลเซิร์ฟเวอร์ผ่านการจดจำสื่อ NSFW โดยอัตโนมัติผ่านการเรียนรู้ของเครื่อง การทำสิ่งนี้อาจจะเพิ่มภาระบนเซิร์ฟเวอร์เล็กน้อย"
- sensitivity: "การตรวจจับความไว"
- sensitivityDescription: "การลดความไวนั้นจะนำไปสู่การตรวจจับที่ผิดพลาดน้อยลง (ผลบวกที่ผิดพลาด) แต่ในขณะที่การเพิ่มนั้นจะนำไปสู่การตรวจหาที่พลาดน้อยลง (ผลลบเท็จ)"
- setSensitiveFlagAutomatically: "ทำเครื่องหมายว่าเป็น NSFW"
+ description: "ใช้ Machine Learning เพื่อตรวจจับสื่อที่มีเนื้อหาละเอียดอ่อนโดยอัตโนมัติและใช้เพื่อการกลั่นกรอง ภาระของเซิร์ฟเวอร์จะเพิ่มขึ้นเล็กน้อย"
+ sensitivity: "ความไวในการตรวจจับ"
+ sensitivityDescription: "เมื่อความไวต่ำ Misdetection (ผลบวกลวง) จะลดลง, เมื่อความไวสูง Missed detection (ผลลบลวง) จะลดลง"
+ setSensitiveFlagAutomatically: "ทำเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน"
setSensitiveFlagAutomaticallyDescription: "ผลลัพธ์ของการตรวจจับภายในนั้นจะยังคงอยู่ ถึงแม้ว่าจะปิดตัวเลือกนี้"
analyzeVideos: "เปิดใช้งานวิเคราะห์ของวิดีโอ"
analyzeVideosDescription: "การวิเคราะห์วิดีโอนอกเหนือจากรูปภาพนั้น การทำสิ่งนี้จะทำให้เพิ่มภาระบนเซิร์ฟเวอร์เล็กน้อย"
@@ -1507,18 +1707,19 @@ _emailUnavailable:
disposable: "ไม่สามารถใช้อีเมลชั่วคราวได้"
mx: "เซิร์ฟเวอร์อีเมลนี้ไม่ถูกต้อง"
smtp: "เซิร์ฟเวอร์อีเมลนี้ไม่มีการตอบสนอง"
+ banned: "คุณไม่สามารถลงทะเบียนด้วยที่อยู่อีเมลนี้ได้"
_ffVisibility:
- public: "เผยแพร่"
+ public: "สาธารณะ"
followers: "ปรากฏให้แก่ผู้ติดตามเท่านั้น"
private: "ส่วนตัว"
_signup:
- almostThere: "เกือบจะมี"
- emailAddressInfo: "โปรดกรอกอีเมลของคุณ มันจะไม่เปิดเผยต่อสาธารณะ"
- emailSent: "เราได้ส่งอีเมลยืนยันไปยังที่อยู่อีเมลของคุณแล้วนะ ({email}) โปรดคลิกลิงก์ที่รวมไว้เพื่อสร้างบัญชีให้เสร็จสิ้น"
+ almostThere: "เกือบจะเสร็จแล้ว"
+ emailAddressInfo: "กรุณากรอกที่อยู่อีเมลที่คุณใช้ ที่อยู่อีเมลของคุณจะไม่ถูกเผยแพร่สู่สาธารณชน"
+ emailSent: "อีเมลยืนยันได้ถูกส่งไปยังที่อยู่อีเมลที่คุณป้อน ({email}) แล้ว กรุณาติดตามลิงก์ในอีเมลเพื่อสร้างบัญชีให้เสร็จสมบูรณ์ ลิงก์ที่ให้ไว้จะหมดอายุใน 30 นาที"
_accountDelete:
accountDelete: "ลบบัญชีผู้ใช้"
mayTakeTime: "เนื่องจากการลบบัญชีนี้จะเป็นกระบวนการที่ต้องใช้ทรัพยากรมาก จึงอาจจะต้องใช้เวลาสักครู่ถึงจะเสร็จสมบูรณ์ ทั้งนี้ขึ้นอยู่กับจำนวนเนื้อหาที่คุณสร้างและจำนวนไฟล์ที่คุณอัปโหลดนะ"
- sendEmail: "เมื่อการลบบัญชีนี้เสร็จสิ้น เราอาจจะส่งอีเมลไปยังที่อยู่อีเมลของคุณที่เคยลงทะเบียนไว้กับบัญชีนี้นะ"
+ sendEmail: "เมื่อการลบบัญชีเสร็จสิ้น การแจ้งเตือนจะถูกส่งไปยังที่อยู่อีเมลที่ลงทะเบียนไว้"
requestAccountDelete: "ร้องขอให้ลบบัญชี"
started: "การลบได้เริ่มต้นขึ้น"
inProgress: "ปัจจุบันกำลังดำเนินการลบอยู่"
@@ -1528,7 +1729,9 @@ _ad:
hide: "ไม่ต้องแสดง"
timezoneinfo: "วันในสัปดาห์นี้จะถูกกำหนดจากโซนเวลาของเซิร์ฟเวอร์"
adsSettings: "ตั้งค่าการโฆษณา"
+ notesPerOneAd: "อัปเดตช่วงเวลาตำแหน่งโฆษณาแบบเรียลไทม์ (จำนวนโน้ตต่อโฆษณา)"
setZeroToDisable: "ตั้งค่านี้ให้เป็น 0 เพื่อปิดใช้งานโฆษณาอัปเดตแบบเรียลไทม์"
+ adsTooClose: "เนื่องจากช่วงเวลาการแสดงโฆษณาสั้นมาก ประสบการณ์ผู้ใช้จึงอาจลดลงอย่างมาก"
_forgotPassword:
enterEmail: "ป้อนที่อยู่อีเมลที่คุณเคยใช้ในการลงทะเบียนไว้ ลิงก์ที่คุณสามารถรีเซ็ตรหัสผ่านได้นั้นจะถูกส่งไปนะ"
ifNoEmail: "ถ้าหากคุณไม่ได้ใช้อีเมลระหว่างการลงทะเบียน กรุณาติดต่อผู้ดูแลระบบอินสแตนซ์แทนนะ"
@@ -1536,8 +1739,8 @@ _forgotPassword:
_gallery:
my: "แกลลอรี่ของฉัน"
liked: "โพสต์ที่ถูกใจ"
- like: "ชื่นชอบ"
- unlike: "ลบไลค์"
+ like: "ถูกใจ!"
+ unlike: "เลิกถูกใจ"
_email:
_follow:
title: "ได้ติดตามคุณ"
@@ -1550,7 +1753,7 @@ _plugin:
viewSource: "ดูต้นฉบับ"
_preferencesBackups:
list: "สร้างการสำรองข้อมูล"
- saveNew: "บันทึกใหม่"
+ saveNew: "บันทึกข้อมูลสำรองใหม่"
loadFile: "โหลดจากไฟล์"
apply: "นำไปใช้กับอุปกรณ์นี้"
save: "บันทึก"
@@ -1560,8 +1763,8 @@ _preferencesBackups:
applyConfirm: "คุณต้องการใช้ข้อมูลสำรอง \"{name}\" กับอุปกรณ์นี้อย่างงั้นจริงหรอ การตั้งค่าที่มีอยู่ของอุปกรณ์นี้จะถูกเขียนทับนะ"
saveConfirm: "บันทึกข้อมูลสำรองเป็น {name} มั้ย?"
deleteConfirm: "ลบข้อมูลสำรอง {name} มั้ย?"
- renameConfirm: "เปลี่ยนชื่อข้อมูลสำรองนี้จาก \"{old}\" เป็น \"{new}\" หรือป่าว"
- noBackups: "ไม่มีข้อมูลสำรองนะ คุณสามารถสำรองข้อมูลการตั้งค่าไคลเอนต์ของคุณบนเซิร์ฟเวอร์นี้โดยใช้ \"สร้างการสำรองข้อมูลใหม่\"ได้นะ"
+ renameConfirm: "ต้องการเปลี่ยนชื่อข้อมูลสำรองจาก “{old}” เป็น “{new}” ใช่ไหม?"
+ noBackups: "ไม่มีข้อมูลสำรอง สามารถบันทึกการตั้งค่าไคลเอนต์ปัจจุบันไปยังเซิร์ฟเวอร์ด้วย “บันทึกข้อมูลสำรองใหม่”"
createdAt: "สร้างเมื่อ: {date} {time}"
updatedAt: "อัปเดตเมื่อ: {date} {time}"
cannotLoad: "การโหลดล้มเหลว"
@@ -1577,13 +1780,16 @@ _aboutMisskey:
contributors: "ผู้สนับสนุนหลัก"
allContributors: "ผู้มีส่วนร่วมทั้งหมด"
source: "ซอร์สโค้ด"
+ original: "ต้นฉบับ"
+ thisIsModifiedVersion: "{name} ใช้ Misskey เวอร์ชันดัดแปลง"
translation: "แปลภาษา Misskey"
donate: "บริจาคให้กับ Misskey"
- morePatrons: " ขอบคุณทุกท่านที่ร่วมกันช่วยเหลือตลอดมานะคะ 🥰"
- patrons: "สมาชิกพันธมิตร"
+ morePatrons: "และอีกหลายท่านที่ไม่ได้เอ่ยนาม ขอบคุณที่ร่วมช่วยเหลือตลอดมานะคะ 🥰"
+ patrons: "ผู้อุปถัมภ์"
+ projectMembers: "สมาชิกในโครงการ"
_displayOfSensitiveMedia:
- respect: "ซ่อนสื่อทำเครื่องหมายบอกว่าละเอียดอ่อน"
- ignore: "แสดงผลสื่อทำเครื่องหมายบอกว่าละเอียดอ่อน"
+ respect: "ซ่อนสื่อที่มีเนื้อหาละเอียดอ่อน"
+ ignore: "แสดงสื่อที่มีเนื้อหาละเอียดอ่อน"
force: "ซ่อนสื่อทั้งหมด"
_instanceTicker:
none: "ไม่ต้องแสดง"
@@ -1594,17 +1800,18 @@ _serverDisconnectedBehavior:
dialog: "แสดงกล่องโต้ตอบคำเตือน"
quiet: "แสดงคำเตือนที่ไม่เป็นการรบกวน"
_channel:
- create: "สร้างแชนแนลใหม่"
- edit: "แก้ไขแชนแนล"
+ create: "สร้างช่องใหม่"
+ edit: "แก้ไขช่อง"
setBanner: "เซตแบนเนอร์"
removeBanner: "ลบแบนเนอร์"
featured: "เทรนด์"
owned: "เจ้าของ"
following: "ติดตามแล้ว"
usersCount: "{n} ผู้เข้าร่วม"
- notesCount: "{n} โน้ต"
+ notesCount: "มี {n} โน้ต"
nameAndDescription: "ชื่อและคำอธิบาย"
nameOnly: "ชื่อเท่านั้น"
+ allowRenoteToExternal: "อนุญาตให้รีโน้ตและอ้างอิงนอกช่องได้"
_menuDisplay:
sideFull: "ด้านข้าง"
sideIcon: "ด้านข้าง (ไอคอน)"
@@ -1617,7 +1824,7 @@ _wordMute:
_instanceMute:
instanceMuteDescription: "การดำเนินการนี้จะปิดเสียง\"โน้ต/รีโน้ต\"จากอินสแตนซ์ที่อยู่ในรายการ รวมถึงบันทึกของผู้ใช้ที่ตอบกลับผู้ใช้จากอินสแตนซ์ที่ปิดเสียง"
instanceMuteDescription2: "คั่นด้วยการขึ้นบรรทัดใหม่"
- title: "ซ่อนโน้ตจากอินสแตนซ์ที่มีอยู่ในรายการ"
+ title: "ซ่อนโน้ตจากอินสแตนซ์ที่มีอยู่ในรายชื่อ"
heading: "รายชื่ออินสแตนซ์ที่ถูกปิดเสียง"
_theme:
explore: "สำรวจธีม"
@@ -1650,8 +1857,8 @@ _theme:
importInfo: "ถ้าหากต้องการป้อนโค้ดที่นี่ คุณยังสามารถนำเข้าไปยังโปรแกรมแก้ไขธีมได้"
deleteConstantConfirm: "คุณต้องการลบค่าคงที่ {const} หรือป่าว?"
keys:
- accent: "เน้น"
- bg: "ภาพพื้นหลัง"
+ accent: "สีหลัก"
+ bg: "พื้นหลัง"
fg: "ข้อความ"
focus: "โฟกัส"
indicator: "ตัวบ่งชี้"
@@ -1687,15 +1894,23 @@ _theme:
wallpaperOverlay: "วอลล์เปเปอร์ซ้อนทับ"
badge: "ตรา"
messageBg: "พื้นหลังแชท"
- accentDarken: "เน้น (มืด)"
- accentLighten: "เน้น (สว่าง)"
+ accentDarken: "สีหลัก (มืด)"
+ accentLighten: "สีหลัก (สว่าง)"
fgHighlighted: "ข้อความที่ไฮไลต์"
_sfx:
- note: "หมายเหตุ"
+ note: "โน้ต"
noteMy: "โน้ตของตัวเอง"
notification: "การเเจ้งเตือน"
antenna: "เสาอากาศ"
channel: "การแจ้งเตือนช่อง"
+ reaction: "เมื่อเลือกรีแอคชั่น"
+_soundSettings:
+ driveFile: "ใช้เสียงจากไดรฟ์"
+ driveFileWarn: "เลือกไฟล์ในไดรฟ์ของคุณ"
+ driveFileTypeWarn: "ไม่รองรับไฟล์นี้"
+ driveFileTypeWarnDescription: "กรุณาเลือกไฟล์เสียง"
+ driveFileDurationWarn: "เสียงยาวเกินไป"
+ driveFileDurationWarnDescription: "การใช้เสียงที่ยาวอาจรบกวนการใช้งาน Misskey, ต้องการดำเนินการต่อหรือไม่?"
_ago:
future: "อนาคต"
justNow: "เมื่อกี๊นี้"
@@ -1707,6 +1922,14 @@ _ago:
monthsAgo: "{n} เดือนที่แล้ว"
yearsAgo: "{n} ปีที่ผ่านมา"
invalid: "ไม่พบผลลัพธ์"
+_timeIn:
+ seconds: "ใน {n} วินาที"
+ minutes: "ใน {n} นาที"
+ hours: "ใน {n} ชั่วโมง"
+ days: "ใน {n} วัน"
+ weeks: "ใน {n} สัปดาห์"
+ months: "ใน {n} เดือน"
+ years: "ใน {n} ปี"
_time:
second: "วินาที"
minute: "นาที"
@@ -1736,7 +1959,9 @@ _2fa:
renewTOTPConfirm: "วิธีการแบบนี้จะทําให้รหัสยืนยันจากแอพก่อนหน้าของคุณหยุดทํางานเลยนะ"
renewTOTPOk: "ตั้งค่าคอนฟิกใหม่"
renewTOTPCancel: "ไม่เป็นไร"
+ checkBackupCodesBeforeCloseThisWizard: "โปรดตรวจสอบรหัสสำรองด้านล่างก่อนที่จะปิดวิซาร์ดนี้"
backupCodes: "รหัสสำรองข้อมูล"
+ backupCodesDescription: "หากแอปยืนยันตัวตนของคุณไม่พร้อมใช้งาน คุณสามารถใช้รหัสสำรองด้านล่างเพื่อเข้าถึงบัญชีของคุณได้ อย่าลืมเก็บรหัสเหล่านี้ไว้ในที่ปลอดภัย แต่ละรหัสสามารถใช้ได้เพียงครั้งเดียวเท่านั้น"
backupCodeUsedWarning: "มีการใช้รหัสสำรองแล้ว โปรดกรุณากำหนดค่าการตรวจสอบสิทธิ์แบบสองปัจจัยโดยเร็วที่สุดถ้าหากคุณยังไม่สามารถใช้งานได้อีก"
backupCodesExhaustedWarning: "รหัสสำรองทั้งหมดถูกใช้แล้ว ถ้าหากคุณยังสูญเสียการเข้าถึงแอปการตรวจสอบสิทธิ์แบบสองปัจจัยคุณจะยังไม่สามารถเข้าถึงบัญชีนี้ได้ กรุณากำหนดค่าการรับรองความถูกต้องด้วยการยืนยันสองชั้น"
_permissions:
@@ -1757,29 +1982,78 @@ _permissions:
"write:notes": "เขียนหรือลบโน้ต"
"read:notifications": "ดูการแจ้งเตือนของคุณ"
"write:notifications": "จัดการแจ้งเตือนของคุณ"
- "read:reactions": "ดูปฏิกิริยาของคุณ"
- "write:reactions": "แก้ไขปฏิกิริยาของคุณ"
+ "read:reactions": "ดูรีแอคชั่นของคุณ"
+ "write:reactions": "แก้ไขรีแอคชั่นของคุณ"
"write:votes": "โหวตบนสำรวจความคิดเห็น"
- "read:pages": "ดูหน้า"
+ "read:pages": "ดูหน้าเพจ"
"write:pages": "แก้ไขหรือลบเพจของคุณ"
- "read:page-likes": "ดูไลค์ของคุณบนเพจ"
- "write:page-likes": "แก้ไขการถูกใจของคุณบนเพจ"
+ "read:page-likes": "ดูรายการเพจที่ถูกใจไว้"
+ "write:page-likes": "แก้ไขรายการเพจที่ถูกใจ"
"read:user-groups": "ดูกลุ่มผู้ใช้ของคุณ"
"write:user-groups": "แก้ไขหรือลบกลุ่มผู้ใช้ของคุณ"
"read:channels": "ดูแชนแนลของคุณ"
"write:channels": "แก้ไขแชนแนลของคุณ"
"read:gallery": "ดูแกลเลอรี่"
"write:gallery": "แก้ไขแกลเลอรี่ของคุณ"
- "read:gallery-likes": "ดูรายการโพสต์ในแกลเลอรีที่ชอบของคุณ"
- "write:gallery-likes": "แก้ไขรายการโพสต์ในแกลเลอรีที่ชอบของคุณ"
- "read:flash": "วิว เพลย์"
- "write:flash": "แก้ไขเพลย์"
- "read:flash-likes": "ดูรายชื่อของไลค์ เพลย์"
- "write:flash-likes": "แก้ไขรายชื่อของไลค์ เพลย์"
+ "read:gallery-likes": "ดูรายการโพสต์แกลเลอรีที่ถูกใจไว้"
+ "write:gallery-likes": "แก้ไขรายการโพสต์แกลเลอรีที่ถูกใจไว้"
+ "read:flash": "ดู Play"
+ "write:flash": "แก้ไข Play"
+ "read:flash-likes": "ดูรายการ play ที่ถูกใจไว้"
+ "write:flash-likes": "แก้ไขรายการ play ที่ถูกใจไว้"
+ "read:admin:abuse-user-reports": "ดูรายงานจากผู้ใช้"
+ "write:admin:delete-account": "ลบบัญชีผู้ใช้"
+ "write:admin:delete-all-files-of-a-user": "ลบไฟล์ทั้งหมดของผู้ใช้"
+ "read:admin:index-stats": "ดูข้อมูลเกี่ยวกับดัชนีฐานข้อมูล"
+ "read:admin:table-stats": "ดูข้อมูลเกี่ยวกับตารางฐานข้อมูล"
+ "read:admin:user-ips": "ดูที่อยู่ IP ของผู้ใช้"
+ "read:admin:meta": "ดูข้อมูลเมตาของอินสแตนซ์"
+ "write:admin:reset-password": "รีเซ็ตรหัสผ่านของผู้ใช้"
+ "write:admin:resolve-abuse-user-report": "แก้ไขรายงานจากผู้ใช้"
+ "write:admin:send-email": "ส่งอีเมล"
+ "read:admin:server-info": "ดูข้อมูลเซิร์ฟเวอร์"
+ "read:admin:show-moderation-log": "ดูปูมการแก้ไข"
+ "read:admin:show-user": "ดูข้อมูลส่วนตัวของผู้ใช้"
+ "read:admin:show-users": "ดูข้อมูลส่วนตัวของผู้ใช้"
+ "write:admin:suspend-user": "ระงับผู้ใช้"
+ "write:admin:unset-user-avatar": "ลบอวตารผู้ใช้"
+ "write:admin:unset-user-banner": "ลบแบนเนอร์ผู้ใช้"
+ "write:admin:unsuspend-user": "ยกเลิกการระงับผู้ใช้"
+ "write:admin:meta": "จัดการข้อมูลเมตาของอินสแตนซ์"
+ "write:admin:user-note": "จัดการโน้ตการกลั่นกรอง"
+ "write:admin:roles": "จัดการบทบาท"
+ "read:admin:roles": "ดูบทบาท"
+ "write:admin:relays": "จัดการรีเลย์"
+ "read:admin:relays": "ดูรีเลย์"
+ "write:admin:invite-codes": "จัดการรหัสเชิญ"
+ "read:admin:invite-codes": "ดูรหัสเชิญ"
+ "write:admin:announcements": "จัดการประกาศ"
+ "read:admin:announcements": "ดูประกาศ"
+ "write:admin:avatar-decorations": "จัดการการตกแต่งอวตาร"
+ "read:admin:avatar-decorations": "ดูการตกแต่งอวตาร"
+ "write:admin:federation": "จัดการข้อมูลเกี่ยวกับสหพันธ์"
+ "write:admin:account": "จัดการบัญชีผู้ใช้"
+ "read:admin:account": "ดูข้อมูลเกี่ยวกับผู้ใช้"
+ "write:admin:emoji": "จัดการเอโมจิ"
+ "read:admin:emoji": "ดูเอโมจิ"
+ "write:admin:queue": "จัดการคิวงาน"
+ "read:admin:queue": "ดูข้อมูลเกี่ยวกับคิวงาน"
+ "write:admin:promo": "จัดการโน้ตโปรโมชั่น"
+ "write:admin:drive": "จัดการไดรฟ์ของผู้ใช้"
+ "read:admin:drive": "ดูข้อมูลเกี่ยวกับไดรฟ์ของผู้ใช้"
+ "read:admin:stream": "ใช้ Websocket API สำหรับผู้ดูแลระบบ"
+ "write:admin:ad": "จัดการโฆษณา"
+ "read:admin:ad": "ดูโฆษณา"
+ "write:invite-codes": "สร้างรหัสเชิญ"
+ "read:invite-codes": "รับรหัสเชิญ"
+ "write:clip-favorite": "ควบคุมการถูกใจของคลิป"
+ "read:clip-favorite": "ดูการถูกใจของคลิป"
+ "read:federation": "รับข้อมูลเกี่ยวกับสหพันธ์"
+ "write:report-abuse": "รายงานการละเมิด"
_auth:
shareAccessTitle: "การให้สิทธิ์แอปพลิเคชัน"
shareAccess: "คุณต้องการอนุญาตให้ \"{name}\" เข้าถึงบัญชีนี้เลยมั้ย?"
- shareAccessAsk: "คุณแน่ใจแล้วจริงๆหรอว่าต้องการอนุญาตให้แอปพลิเคชันนี้เข้าถึงบัญชีของคุณแน่ใจแล้วหรอ?"
+ shareAccessAsk: "ต้องการอนุญาตให้แอปพลิเคชันนี้เข้าถึงบัญชีของคุณหรือไม่?"
permission: "{name} ได้ขอสิทธิ์การเข้าถึงดังต่อไปนี้"
permissionAsk: "แอปพลิเคชันนี้ขอสิทธิ์ดังต่อไปนี้"
pleaseGoBack: "กรุณากลับไปที่แอปพลิเคชัน"
@@ -1815,7 +2089,7 @@ _widgets:
photos: "รูปภาพ"
digitalClock: "นาฬิกาดิจิตอล"
unixClock: "นาฬิกา UNIX"
- federation: "Fediration"
+ federation: "สหพันธ์"
instanceCloud: "อินสแตนซ์คลาวด์"
postForm: "แบบฟอร์มการโพสต์"
slideshow: "แสดงภาพนิ่ง"
@@ -1823,13 +2097,14 @@ _widgets:
onlineUsers: "ผู้ใช้ที่ออนไลน์"
jobQueue: "คิวงาน"
serverMetric: "ตัวชี้วัดเซิร์ฟเวอร์"
- aiscript: "AiScript คอนโซล"
- aiscriptApp: "AiScript แอพ"
+ aiscript: " คอนโซล AiScript"
+ aiscriptApp: "แอป AiScript"
aichan: "ไอ"
userList: "รายชื่อผู้ใช้"
_userList:
- chooseList: "เลือกรายการ"
+ chooseList: "เลือกรายชื่อ"
clicker: "คลิกเกอร์"
+ birthdayFollowings: "วันเกิดผู้ใช้ในวันนี้"
_cw:
hide: "ซ่อน"
show: "โหลดเพิ่มเติม"
@@ -1837,15 +2112,15 @@ _cw:
files: "{count} ไฟล์"
_poll:
noOnlyOneChoice: "จำเป็นต้องมีอย่างน้อยสองตัวเลือก"
- choiceN: "ตัวเลือก {n}"
- noMore: "คุณไม่สามารถเพิ่มตัวเลือกอื่นได้"
+ choiceN: "ตัวเลือกที่ {n}"
+ noMore: "เพิ่มตัวเลือกอีกไม่ได้แล้ว"
canMultipleVote: "สามารถตอบได้หลายคำตอบ"
- expiration: "สิ้นสุดการสำรวจความคิดเห็น"
- infinite: "ไม่ต้องเลย"
- at: "จบที่..."
- after: "สิ้นสุดหลัง..."
+ expiration: "สิ้นสุดโพล"
+ infinite: "ไม่กำหนดระยะเวลา"
+ at: "ระบุวันเวลา"
+ after: "ระบุระยะเวลา"
deadlineDate: "วันสิ้นสุด"
- deadlineTime: "ชั่วโมง"
+ deadlineTime: "เวลา"
duration: "ระยะเวลา"
votesCount: "{n} คะแนนเสียง"
totalVotes: "{n} คะแนนเสียงทั้งหมด"
@@ -1853,37 +2128,37 @@ _poll:
showResult: "ดูผลลัพธ์"
voted: "โหวตแล้ว"
closed: "สิ้นสุดแล้ว"
- remainingDays: "{d} วัน(s) {h} ชั่วโมง(s) ที่เหลืออยู่"
- remainingHours: "{h} ชั่วโมง(s) {m} นาที(s) ที่เหลืออยู่"
- remainingMinutes: "{m} นาที(s) {s} วินาที(s) ที่เหลืออยู่"
- remainingSeconds: "{s} นาที(s) ที่เหลืออยู่"
+ remainingDays: "เหลืออีก {d} วัน {h} ชั่วโมง"
+ remainingHours: "เหลืออีก {h} ชั่วโมง {m} นาที"
+ remainingMinutes: "เหลืออีก {m} นาที {s} วินาที"
+ remainingSeconds: "เหลืออีก {s} วินาที"
_visibility:
public: "สาธารณะ"
publicDescription: "โน้ตของคุณจะปรากฏแก่ผู้ใช้ทุกคน"
home: "หน้าแรก"
homeDescription: "โพสลงไทม์ไลน์ที่บ้านเท่านั้น"
followers: "ผู้ติดตาม"
- followersDescription: "ทำให้ผู้ติดตามนั้นมองเห็นแค่คุณเท่านั้น"
+ followersDescription: "เฉพาะผู้ติดตามเท่านั้นที่มองเห็นได้"
specified: "ไดเร็ค"
specifiedDescription: "ทำให้มองเห็นได้เฉพาะผู้ใช้ที่ระบุเท่านั้น"
- disableFederation: "ไม่มีสหภาพ"
+ disableFederation: "ไม่มีสหพันธ์"
disableFederationDescription: "อย่าส่งไปยังอินสแตนซ์อื่น"
_postForm:
replyPlaceholder: "ตอบกลับโน้ตนี้..."
quotePlaceholder: "อ้างโน้ตนี้..."
channelPlaceholder: "โพสต์ลงช่อง..."
_placeholders:
- a: "คุณเป็นอะไรไปหรอ?"
- b: "เกิดอะไรขึ้นรอบตัวคุณ?"
- c: "คุณกำลังคิดอะไรอยู่?"
- d: "คุณต้องการจะพูดอะไร?"
- e: "เริ่มเขียน..."
+ a: "ตอนนี้เป็นยังไงบ้าง?"
+ b: "มีอะไรเกิดขึ้นหรือเปล่า?"
+ c: "กำลังคิดอะไรอยู่?"
+ d: "ต้องการจะพูดอะไรไหม?"
+ e: "มาเขียนกันเถอะ"
f: "กำลังรอให้คุณเขียน..."
_profile:
name: "ชื่อ"
username: "ชื่อผู้ใช้"
- description: "ประวัติ"
- youCanIncludeHashtags: "คุณยังสามารถใส่แฮชแท็กในประวัติของคุณได้นะ"
+ description: "แนะนำตัว"
+ youCanIncludeHashtags: "คุณสามารถใส่แฮชแท็กในส่วนแนะนำตัวของคุณได้"
metadata: "ข้อมูลเพิ่มเติม"
metadataEdit: "แก้ไขข้อมูลเพิ่มเติม"
metadataDescription: "ใช้สิ่งเหล่านี้ คุณสามารถแสดงฟิลด์ข้อมูลเพิ่มเติมในโปรไฟล์ของคุณ"
@@ -1891,14 +2166,16 @@ _profile:
metadataContent: "เนื้อหา"
changeAvatar: "เปลี่ยนอวาตาร์"
changeBanner: "เปลี่ยนแบนเนอร์"
- verifiedLinkDescription: "โดยการป้อน URL ที่มีลิงก์ไปยังโปรไฟล์ของคุณตรงนี้ ส่วนไอคอนการยืนยันความเป็นเจ้าของนั้นก็สามารถแสดงถัดจากฟิลด์ได้นะ"
+ verifiedLinkDescription: "หากป้อน URL ที่มีลิงก์ไปยังโปรไฟล์ของคุณ ไอคอนการยืนยันความเป็นเจ้าของจะแสดงถัดจากฟิลด์นั้น ๆ"
+ avatarDecorationMax: "คุณสามารถเพิ่มการตกแต่งได้สูงสุด {max}"
_exportOrImport:
allNotes: "โน้ตทั้งหมด"
- favoritedNotes: "บันทึกที่ชื่นชอบ"
+ favoritedNotes: "โน้ตที่ถูกใจไว้"
+ clips: "คลิป"
followingList: "กำลังติดตาม"
muteList: "ปิดเสียง"
blockingList: "บล็อค"
- userLists: "รายการ"
+ userLists: "รายชื่อ"
excludeMutingUsers: "ยกเว้นผู้ใช้ที่ปิดเสียง"
excludeInactiveUsers: "ยกเว้นผู้ใช้ที่ไม่ได้ใช้งาน"
withReplies: "รวมการตอบกลับจากผู้ใช้ที่นำเข้าไว้ในไทม์ไลน์"
@@ -1934,16 +2211,16 @@ _timelines:
social: "โซเชี่ยล"
global: "ทั่วโลก"
_play:
- new: "สร้างการเล่น"
- edit: "แก้ไขเล่น"
- created: "สร้างการเล่นแล้ว"
- updated: "แก้ไขการเล่นแล้ว"
- deleted: "ลบการเล่นแล้ว"
- pageSetting: "ตั้งค่าการเล่น"
+ new: "สร้าง Play"
+ edit: "แก้ไข Play"
+ created: "สร้าง Play แล้ว"
+ updated: "แก้ไข Play แล้ว"
+ deleted: "ลบ Play แล้ว"
+ pageSetting: "ตั้งค่า Play"
editThisPage: "แก้ไข Play นี้"
viewSource: "ดูต้นฉบับ"
- my: "มาย เพลย์"
- liked: "ไลค์ เพลย์"
+ my: "Play ของฉัน"
+ liked: "Play ที่ถูกใจไว้"
featured: "เป็นที่นิยม"
title: "หัวข้อ"
script: "สคริปต์"
@@ -1955,15 +2232,15 @@ _pages:
created: "สร้างหน้าเพจสำเร็จเรียบร้อยแล้ว"
updated: "แก้ไขหน้าเพจสำเร็จเรียบร้อยแล้ว"
deleted: "ลบหน้าเพจสำเร็จเรียบร้อยแล้ว"
- pageSetting: "การตั้งค่าหน้า"
+ pageSetting: "การตั้งค่าหน้าเพจ"
nameAlreadyExists: "URL ของหน้าที่ระบุนั้นมีอยู่แล้ว"
invalidNameTitle: "URL ของหน้าที่ระบุนั้นไม่ถูกต้อง"
invalidNameText: "ตรวจสอบให้แน่ใจนะว่าชื่อหน้าไม่ว่างเปล่า"
editThisPage: "แก้ไขเพจนี้"
viewSource: "ดูต้นฉบับ"
- viewPage: "ดูหน้า"
+ viewPage: "ดูหน้าเพจ"
like: "ถูกใจ"
- unlike: "ลบไลค์"
+ unlike: "เลิกถูกใจ"
my: "หน้าเพจของฉัน"
liked: "หน้าเพจที่ถูกใจ"
featured: "เป็นที่นิยม"
@@ -1976,7 +2253,7 @@ _pages:
summary: "สรุปเพจ"
alignCenter: "เซ็นเตอร์"
hideTitleWhenPinned: "ซ่อนชื่อหน้าเพจเมื่อปักหมุดไว้ที่โปรไฟล์"
- font: "ตัวอักษร"
+ font: "แบบอักษร"
fontSerif: "Serif"
fontSansSerif: "Sans Serif"
eyeCatchingImageSet: "ตั้งค่าภาพขนาดย่อ"
@@ -1984,7 +2261,7 @@ _pages:
chooseBlock: "เพิ่มบล็อค"
selectType: "เลือกชนิด"
contentBlocks: "เนื้อหา"
- inputBlocks: "อินพุต"
+ inputBlocks: "ป้อนข้อมูล"
specialBlocks: "พิเศษ"
blocks:
text: "ข้อความ"
@@ -2002,23 +2279,28 @@ _relayStatus:
accepted: "ได้รับการอนุมัติ"
rejected: "ถูกปฏิเสธ"
_notification:
- fileUploaded: "ไฟล์ถูกอัพโหลดแล้วน่ะ"
+ fileUploaded: "ไฟล์ถูกอัปโหลดแล้ว"
youGotMention: "{name} กล่าวถึงคุณ"
youGotReply: "{name} ตอบกลับถึงคุณ"
- youGotQuote: "{name} อ้างถึงคุณ"
+ youGotQuote: "{name} อ้างอิงคุณ"
youRenoted: "รีโน้ตจาก {name}"
youWereFollowed: "ได้ติดตามคุณ"
- youReceivedFollowRequest: "คุณมีคำขอติดตามใหม่น่ะ"
- yourFollowRequestAccepted: "คำขอติดตามของคุณได้รับการยอมรับแล้วน่ะ"
- pollEnded: "โพลสำรวจความคิดเห็นผลลัพธ์มีพร้อมใช้งาน"
+ youReceivedFollowRequest: "ได้รับคำขอติดตาม"
+ yourFollowRequestAccepted: "คำขอติดตามได้รับการอนุมัติแล้ว"
+ pollEnded: "ผลโพลออกมาแล้ว"
newNote: "โพสต์ใหม่"
unreadAntennaNote: "เสาอากาศ {name}"
- emptyPushNotificationMessage: "การแจ้งเตือนแบบพุชได้รับการอัพเดทแล้ว"
+ roleAssigned: "ได้รับบทบาท"
+ emptyPushNotificationMessage: "อัปเดตการแจ้งเตือนแบบพุชแล้ว"
achievementEarned: "รับความสำเร็จ"
testNotification: "ทดสอบการแจ้งเตือน"
- checkNotificationBehavior: "ตรวจสอบลักษณะที่ปรากฏการแจ้งเตือน"
+ checkNotificationBehavior: "กดเพื่อดูลักษณะการแจ้งเตือน"
sendTestNotification: "ส่งทดสอบการแจ้งเตือน"
notificationWillBeDisplayedLikeThis: "การแจ้งเตือนมีลักษณะแบบนี้"
+ reactedBySomeUsers: "ถูกรีแอคชั่นโดยผู้ใช้ {n} ราย"
+ renotedBySomeUsers: "รีโน้ตจากผู้ใช้ {n} ราย"
+ followedBySomeUsers: "มีผู้ติดตาม {n} ราย"
+ flushNotification: "ล้างประวัติการแจ้งเตือน"
_types:
all: "ทั้งหมด"
note: "โน้ตใหม่"
@@ -2028,9 +2310,10 @@ _notification:
renote: "รีโน้ต"
quote: "อ้างคำพูด"
reaction: "รีแอคชั่น"
- pollEnded: "โพลนี้สิ้นสุดลงแล้ว"
- receiveFollowRequest: "ได้รับคำขอติดตาม\n"
- followRequestAccepted: "ยอมรับคำขอติดตาม"
+ pollEnded: "โพลสิ้นสุดแล้ว"
+ receiveFollowRequest: "ได้รับคำร้องขอติดตาม"
+ followRequestAccepted: "อนุมัติให้ติดตามแล้ว"
+ roleAssigned: "ให้บทบาท"
achievementEarned: "ปลดล็อกความสำเร็จแล้ว"
app: "การแจ้งเตือนจากแอปที่มีลิงก์"
_actions:
@@ -2064,9 +2347,9 @@ _deck:
tl: "ไทม์ไลน์"
antenna: "เสาอากาศ"
list: "รายการ"
- channel: "แชนแนล"
+ channel: "ช่อง"
mentions: "พูดถึง"
- direct: "ไดเร็ค"
+ direct: "ไดเร็กต์"
roleTimeline: "บทบาทไทม์ไลน์"
_dialog:
charactersExceeded: "คุณกำลังมีตัวอักขระเกินขีดจำกัดสูงสุดแล้วนะ! ปัจจุบันอยู่ที่ {current} จาก {max}"
@@ -2097,11 +2380,11 @@ _moderationLogTypes:
updateRole: "อัปเดตบทบาทแล้ว"
assignRole: "ได้รับมอบหมายบทบาท"
unassignRole: "ถอดออกจากบทบาทแล้ว"
- suspend: "ถูกระงับ"
- unsuspend: "เลิกถูกระงับ"
- addCustomEmoji: "เพิ่มอีโมจิที่กำหนดเองแล้ว"
- updateCustomEmoji: "อัปเดตอีโมจิที่กำหนดเองแล้ว"
- deleteCustomEmoji: "ลบอีโมจิที่กำหนดเองออกแล้ว"
+ suspend: "ระงับ"
+ unsuspend: "เลิกระงับ"
+ addCustomEmoji: "เพิ่มเอโมจิที่กำหนดเองแล้ว"
+ updateCustomEmoji: "อัปเดตเอโมจิที่กำหนดเองแล้ว"
+ deleteCustomEmoji: "ลบเอโมจิที่กำหนดเองออกแล้ว"
updateServerSettings: "อัปเดตการตั้งค่าเซิร์ฟเวอร์แล้ว"
updateUserNote: "อัปเดตโน้ตการกลั่นกรองแล้ว"
deleteDriveFile: "ลบไฟล์ออกแล้ว"
@@ -2113,15 +2396,21 @@ _moderationLogTypes:
deleteGlobalAnnouncement: "ลบประกาศทั่วโลกออกแล้ว"
deleteUserAnnouncement: "ลบประกาศผู้ใช้ออกแล้ว"
resetPassword: "รีเซ็ตรหัสผ่าน"
- suspendRemoteInstance: "อินสแตนซ์ระยะไกลถูกระงับ"
- unsuspendRemoteInstance: "อินสแตนซ์ระยะไกลเลิกการระงับ"
- markSensitiveDriveFile: "ทำเครื่องหมายไฟล์บอกว่าละเอียดอ่อน"
- unmarkSensitiveDriveFile: "ยกเลิกทำเครื่องหมายไฟล์ว่าละเอียดอ่อน"
+ suspendRemoteInstance: "ระงับอินสแตนซ์ระยะไกล"
+ unsuspendRemoteInstance: "เลิกระงับอินสแตนซ์ระยะไกล"
+ updateRemoteInstanceNote: "อัปเดตโน้ตการกลั่นกรองของอินสแตนซ์ระยะไกลแล้ว"
+ markSensitiveDriveFile: "ทำเครื่องหมายไฟล์ว่ามีเนื้อหาละเอียดอ่อน"
+ unmarkSensitiveDriveFile: "ยกเลิกทำเครื่องหมายไฟล์ว่ามีเนื้อหาละเอียดอ่อน"
resolveAbuseReport: "รายงานได้รับการแก้ไขแล้ว"
- createInvitation: "สร้างคำเชิญ"
+ createInvitation: "สร้างรหัสเชิญ"
createAd: "สร้างโฆษณาแล้ว"
deleteAd: "ลบโฆษณาออกแล้ว"
updateAd: "อัปเดตโฆษณาแล้ว"
+ createAvatarDecoration: "สร้างการตกแต่งไอคอนแล้ว"
+ updateAvatarDecoration: "อัปเดตการตกแต่งไอคอนแล้ว"
+ deleteAvatarDecoration: "ลบการตกแต่งไอคอนแล้ว"
+ unsetUserAvatar: "ลบไอคอนผู้ใช้"
+ unsetUserBanner: "ลบแบนเนอร์ผู้ใช้"
_fileViewer:
title: "รายละเอียดไฟล์"
type: "ประเภทไฟล์"
@@ -2130,3 +2419,109 @@ _fileViewer:
uploadedAt: "วันที่เข้าร่วม"
attachedNotes: "โน้ตที่แนบมาด้วย"
thisPageCanBeSeenFromTheAuthor: "หน้าเพจนี้จะสามารถปรากฏได้โดยผู้ใช้ที่อัปโหลดไฟล์นี้เท่านั้น"
+_externalResourceInstaller:
+ title: "ติดตั้งจากไซต์ภายนอก"
+ checkVendorBeforeInstall: "โปรดตรวจสอบให้แน่ใจว่าแหล่งแจกหน่ายมีความน่าเชื่อถือก่อนทำการติดตั้ง"
+ _plugin:
+ title: "ต้องการติดตั้งปลั๊กอินนี้หรือไม่?"
+ metaTitle: "ข้อมูลส่วนเสริม"
+ _theme:
+ title: "ต้องการติดตั้งธีมนี้หรือไม่?"
+ metaTitle: "ข้อมูลธีม"
+ _meta:
+ base: "โทนสีพื้นฐาน"
+ _vendorInfo:
+ title: "ข้อมูลผู้จัดจำหน่าย"
+ endpoint: "จุดอ้างอิงปลายทาง (Referenced endpoint)"
+ hashVerify: "การตรวจสอบแฮช (ความสมบูรณ์ของไฟล์)"
+ _errors:
+ _invalidParams:
+ title: "พารามิเตอร์ไม่ถูกต้อง"
+ description: "มีสารสนเทศไม่เพียงพอที่จะโหลดข้อมูลจากไซต์ภายนอก โปรดยืนยัน URL ที่ป้อน"
+ _resourceTypeNotSupported:
+ title: "ไม่รองรับทรัพยากรภายนอกนี้"
+ description: "ไม่รองรับประเภทของทรัพยากรภายนอกนี้ โปรดติดต่อผู้ดูแลเว็บไซต์"
+ _failedToFetch:
+ title: "รับข้อมูลล้มเหลว"
+ fetchErrorDescription: "เกิดข้อผิดพลาดในการสื่อสารกับไซต์ภายนอก หากการลองอีกครั้งไม่สามารถแก้ไขปัญหานี้ได้ โปรดติดต่อผู้ดูแลไซต์"
+ parseErrorDescription: "เกิดข้อผิดพลาดในการประมวลผลข้อมูลที่โหลดจากไซต์ภายนอก โปรดติดต่อผู้ดูแลเว็บไซต์"
+ _hashUnmatched:
+ title: "การยืนยัน/ตรวจสอบข้อมูลล้มเหลว"
+ description: "เกิดข้อผิดพลาดในการตรวจสอบความสมบูรณ์ของข้อมูลที่ดึงมา เพื่อเป็นมาตรการรักษาความปลอดภัย การติดตั้งไม่สามารถดำเนินการต่อได้ โปรดติดต่อผู้ดูแลเว็บไซต์"
+ _pluginParseFailed:
+ title: "ข้อผิดพลาด AiScript"
+ description: "ดึงข้อมูลที่ร้องขอสำเร็จแล้ว แต่มีข้อผิดพลาดเกิดขึ้นระหว่างการแยกวิเคราะห์ AiScript โปรดติดต่อผู้เขียนปลั๊กอิน รายละเอียดข้อผิดพลาดสามารถดูได้ในคอนโซล Javascript"
+ _pluginInstallFailed:
+ title: "ติดตั้งปลั๊กอินล้มเหลว"
+ description: "เกิดปัญหาขณะติดตั้งปลั๊กอิน กรุณาลองอีกครั้ง. โปรดดูคอนโซล Javascript สำหรับรายละเอียดข้อผิดพลาด"
+ _themeParseFailed:
+ title: "การแยกวิเคราะห์ธีมล้มเหลว"
+ description: "ดึงข้อมูลที่ร้องขอสำเร็จแล้ว แต่มีข้อผิดพลาดเกิดขึ้นระหว่างการแยกวิเคราะห์ธีม โปรดติดต่อผู้เขียนธีม รายละเอียดข้อผิดพลาดสามารถดูได้ในคอนโซล Javascript"
+ _themeInstallFailed:
+ title: "ติดตั้งธีมล้มเหลว"
+ description: "เกิดปัญหาระหว่างการติดตั้งธีม กรุณาลองอีกครั้ง. รายละเอียดข้อผิดพลาดสามารถดูได้ในคอนโซล Javascript"
+_dataSaver:
+ _media:
+ title: "โหลดมีเดีย"
+ description: "กันไม่ให้ภาพและวิดีโอโหลดโดยอัตโนมัติ แตะรูปภาพ/วิดีโอที่ซ่อนอยู่เพื่อโหลด"
+ _avatar:
+ title: "รูปไอคอน"
+ description: "ระงับการเคลื่อนไหวของภาพไอคอน ภาพเคลื่อนไหวอาจมีขนาดไฟล์ใหญ่กว่าภาพปกติ ดังนั้นจึงสามารถช่วยในการลดการใช้ข้อมูล"
+ _urlPreview:
+ title: "ธัมบ์เนลแสดงตัวอย่าง URL"
+ description: "ธัมบ์เนลแสดงตัวอย่าง URL จะไม่โหลดโดยอัตโนมัติ"
+ _code:
+ title: "ไฮไลต์โค้ด"
+ description: "หากใช้สัญลักษณ์ไฮไลต์โค้ดใน MFM ฯลฯ สัญลักษณ์เหล่านั้นจะไม่โหลดจนกว่าจะแตะ การไฮไลต์ไวยากรณ์(syntax)จำเป็นต้องดาวน์โหลดไฟล์คำจำกัดความของไฮไลต์สำหรับแต่ละภาษา ดังนั้นการปิดใช้งานการโหลดไฟล์เหล่านี้โดยอัตโนมัติจึงคาดว่าจะช่วยลดปริมาณข้อมูลการสื่อสารได้"
+_hemisphere:
+ N: "ซีกโลกเหนือ"
+ S: "ซีกโลกใต้"
+ caption: "ใช้เพื่อกำหนดฤดูกาลของไคลเอ็นต์"
+_reversi:
+ reversi: "รีเวอร์ซี"
+ gameSettings: "ตั้งค่าการเล่น"
+ chooseBoard: "เลือกกระดาน"
+ blackOrWhite: "ดำ/ขาว"
+ blackIs: "{name}เป็นสีดำ"
+ rules: "กฎ"
+ thisGameIsStartedSoon: "การเล่นจะเริ่มแล้ว"
+ waitingForOther: "กำลังรออีกฝ่ายเตรียมตัวให้เสร็จ"
+ waitingForMe: "กำลังรอฝ่ายคุณเตรียมตัวให้เสร็จ"
+ waitingBoth: "กรุณาเตรียมตัว"
+ ready: "เตรียมตัวพร้อมแล้ว"
+ cancelReady: "ยกเลิกการเตรียมตัวพร้อม"
+ opponentTurn: "ตาอีกฝ่าย"
+ myTurn: "ตาของคุณ"
+ turnOf: "ตาของ{name}"
+ pastTurnOf: "ตาของ{name}"
+ surrender: "ยอมแพ้"
+ surrendered: "ยอมแพ้แล้ว"
+ timeout: "หมดเวลาแล้ว"
+ drawn: "เสมอ"
+ won: "{name}ชนะ"
+ black: "ดำ"
+ white: "ขาว"
+ total: "รวมทั้งหมด"
+ turnCount: "ตาที่{count}"
+ myGames: "การเล่นของตัวเอง"
+ allGames: "การเล่นของทุกคน"
+ ended: "จบ"
+ playing: "กำลังเล่น"
+ isLlotheo: "คนที่มีตัวหมากน้อยกว่าชนะ (Roseo)"
+ loopedMap: "ลูปแมป"
+ canPutEverywhere: "โหมดที่สามารถวางได้ทุกที่"
+ timeLimitForEachTurn: "จำกัดเวลาต่อแต่ละตา"
+ freeMatch: "ฟรีแมตช์"
+ lookingForPlayer: "กำลังมองหาคู่ต่อสู้อยู่"
+ gameCanceled: "ยกเลิกการเล่นแล้ว"
+ shareToTlTheGameWhenStart: "โพสต์ลงไทม์ไลน์เมื่อเริ่มการเล่น"
+ iStartedAGame: "เริ่มเล่นหมากรีเวอร์ซีแล้ว! #MisskeyReversi"
+ opponentHasSettingsChanged: "อีกฝ่ายเปลี่ยนการตั้งค่า"
+ allowIrregularRules: "อนุญาตกฎที่ไม่ปรกติ (โหมดฟรีทุกอย่าง)"
+ disallowIrregularRules: "ไม่อนุญาตกฎที่ไม่ปรกติ"
+ showBoardLabels: "แสดงหมายเลขแถว/คอลัมน์บนกระดาน"
+ useAvatarAsStone: "ใช้รูปอวตารเป็นหมาก"
+_offlineScreen:
+ title: "ออฟไลน์ - ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ได้"
+ header: "ไม่สามารถเชื่อมต่อกับเซิร์ฟเวอร์ได้"
+
diff --git a/locales/tr-TR.yml b/locales/tr-TR.yml
index 3dd7a5b79..e93a6e43e 100644
--- a/locales/tr-TR.yml
+++ b/locales/tr-TR.yml
@@ -121,7 +121,6 @@ sensitive: "Hassas içerik"
add: "Ekle"
reaction: "Tepkiler"
reactions: "Tepkiler"
-reactionSetting: "Palette görünecek tepkiler"
reactionSettingDescription2: "Sıralamak için sürükleyin, silmek için tıklayın, eklemek için \"+\" tuşuna tıklayın."
rememberNoteVisibility: "Görünürlük ayarlarını hatırla"
attachCancel: "Eki sil"
@@ -456,3 +455,4 @@ _deck:
_moderationLogTypes:
suspend: "askıya al"
resetPassword: "Şifre sıfırlama"
+
diff --git a/locales/ug-CN.yml b/locales/ug-CN.yml
index e48f64511..e06cee11a 100644
--- a/locales/ug-CN.yml
+++ b/locales/ug-CN.yml
@@ -17,3 +17,4 @@ _2fa:
renewTOTPCancel: "ئۇنى توختىتىڭ"
_widgets:
profile: "profile"
+
diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml
index 016f41a8d..df36f43c0 100644
--- a/locales/uk-UA.yml
+++ b/locales/uk-UA.yml
@@ -55,6 +55,7 @@ copyRSS: "Скопіювати RSS"
copyUsername: "Скопіювати ім’я користувача"
copyUserId: "Копіювати ID користувача"
copyNoteId: "блокнот ID користувача"
+copyFileId: "Скопіювати ідентифікатор файлу."
searchUser: "Пошук користувачів"
reply: "Відповісти"
loadMore: "Показати більше"
@@ -115,7 +116,6 @@ sensitive: "NSFW"
add: "Додати"
reaction: "Реакції"
reactions: "Реакції"
-reactionSetting: "Налаштування реакцій"
reactionSettingDescription2: "Перемістити щоб змінити порядок, Клацнути мишою щоб видалити, Натиснути \"+\" щоб додати."
rememberNoteVisibility: "Пам’ятати параметри видимісті"
attachCancel: "Видалити вкладення"
@@ -133,6 +133,7 @@ unblockConfirm: "Ви впевнені, що хочете розблокуват
suspendConfirm: "Ви впевнені, що хочете призупинити цей акаунт?"
unsuspendConfirm: "Ви впевнені, що хочете відновити цей акаунт?"
selectList: "Виберіть список"
+editList: "Редагувати список."
selectChannel: "Виберіть канал"
selectAntenna: "Виберіть антену"
selectWidget: "Виберіть віджет"
@@ -351,6 +352,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Увімкнути hCaptcha"
hcaptchaSiteKey: "Ключ сайту"
hcaptchaSecretKey: "Секретний ключ"
+mcaptchaSiteKey: "Ключ сайту"
+mcaptchaSecretKey: "Секретний ключ"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Увімкнути reCAPTCHA"
recaptchaSiteKey: "Ключ сайту"
@@ -408,7 +411,6 @@ share: "Поділитись"
notFound: "Не знайдено"
notFoundDescription: "Сторінка за вказаною адресою не знайдена."
uploadFolder: "Місце для завантаження за замовчуванням"
-cacheClear: "Очистити кеш"
markAsReadAllNotifications: "Позначити всі сповіщення як прочитані"
markAsReadAllUnreadNotes: "Позначити всі нотатки як прочитані"
markAsReadAllTalkMessages: "Позначити всі повідомлення як прочитані"
@@ -449,6 +451,7 @@ or: "або"
language: "Мова"
uiLanguage: "Мова інтерфейсу"
aboutX: "Про {x}"
+native: "місцевий"
disableDrawer: "Не використовувати висувні меню"
noHistory: "Історія порожня"
signinHistory: "Історія входів"
@@ -527,6 +530,8 @@ output: "Вихід"
script: "Скрипт"
disablePagesScript: "Вимкнути AiScript на Сторінках"
updateRemoteUser: "Оновити інформацію про віддаленого користувача"
+unsetUserAvatar: "Деактивувати піктограму."
+unsetUserBanner: "Випустити прапор."
deleteAllFiles: "Видалити всі файли"
deleteAllFilesConfirm: "Ви дійсно хочете видалити всі файли?"
removeAllFollowing: "Скасувати всі підписки"
@@ -814,7 +819,6 @@ makeReactionsPublicDescription: "Це зробить список усіх ва
classic: "Класичний"
muteThread: "Приглушити тред"
unmuteThread: "Скасувати глушіння"
-ffVisibility: "Видимість підписок/підписників"
continueThread: "Показати продовження треду"
deleteAccountConfirm: "Це незворотно видалить ваш акаунт. Продовжити?"
incorrectPassword: "Неправильний пароль."
@@ -907,7 +911,9 @@ youFollowing: "Підписки"
icon: "Аватар"
replies: "Відповісти"
renotes: "Поширити"
+sourceCode: "Вихідний код"
flip: "Перевернути"
+lastNDays: "Останні {n} днів"
_achievements:
earnedAt: "Відкрито"
_types:
@@ -1466,6 +1472,7 @@ _profile:
changeBanner: "Змінити банер"
_exportOrImport:
allNotes: "Всі нотатки"
+ clips: "Добірка"
followingList: "Підписки"
muteList: "Ігнорувати"
blockingList: "Заблокувати"
@@ -1614,3 +1621,6 @@ _webhookSettings:
_moderationLogTypes:
suspend: "Призупинити"
resetPassword: "Скинути пароль"
+_reversi:
+ total: "Всього"
+
diff --git a/locales/uz-UZ.yml b/locales/uz-UZ.yml
index e9b3915f0..b87b59692 100644
--- a/locales/uz-UZ.yml
+++ b/locales/uz-UZ.yml
@@ -120,7 +120,6 @@ sensitive: "Sezuvchan"
add: "Qo'shish"
reaction: "Reaktsiyalar"
reactions: "Reaktsiyalar"
-reactionSetting: "Reaksiyalar ro'yxati"
reactionSettingDescription2: "Qayta tartiblash uchun ushlab turib siljiting, oʻchirish uchun bosing, qoʻshish uchun “+” tugmasini bosing."
rememberNoteVisibility: "Qaydning ko'rinish sozlamarini eslab qolish"
attachCancel: "Qo'shimchani olib tashlash"
@@ -367,6 +366,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "hCaptchani yoqish"
hcaptchaSiteKey: "Sayt kaliti"
hcaptchaSecretKey: "Mahfiy kalit"
+mcaptchaSiteKey: "Sayt kaliti"
+mcaptchaSecretKey: "Maxfiy kalit"
recaptcha: "reCAPTCHA"
enableRecaptcha: "reCAPTCHA ni yoqish"
recaptchaSiteKey: "Sayt kaliti"
@@ -428,7 +429,6 @@ share: "Yuborish"
notFound: "Topilmadi"
notFoundDescription: "Ushbu sahifa topilmadi"
uploadFolder: "Jildni yuklash"
-cacheClear: "Keshni tozalash"
markAsReadAllNotifications: "Bildirishnomalarni o'qilgan deb belgilash"
markAsReadAllUnreadNotes: "Barch xabarlarni oq'ilgan deb belgilash"
markAsReadAllTalkMessages: "Barcha suhbatlarni o'qilgan deb belgilang"
@@ -975,6 +975,7 @@ _profile:
changeBanner: "Bannerni o'zgartirish"
_exportOrImport:
allNotes: "Barcha qaydlar"
+ clips: "Klip"
followingList: "Obuna bo‘lish"
muteList: "Ovozni o‘chirish"
blockingList: "Bloklangan foydalanuvchilar"
@@ -1087,3 +1088,6 @@ _webhookSettings:
_moderationLogTypes:
suspend: "To'xtatish"
resetPassword: "Parolni tiklash"
+_reversi:
+ total: "Jami"
+
diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml
index c816fc314..59883f4a6 100644
--- a/locales/vi-VN.yml
+++ b/locales/vi-VN.yml
@@ -121,7 +121,6 @@ sensitive: "Nhạy cảm"
add: "Thêm"
reaction: "Biểu cảm"
reactions: "Biểu cảm"
-reactionSetting: "Chọn những biểu cảm hiển thị"
reactionSettingDescription2: "Kéo để sắp xếp, nhấn để xóa, nhấn \"+\" để thêm."
rememberNoteVisibility: "Lưu kiểu tút mặc định"
attachCancel: "Gỡ tập tin đính kèm"
@@ -369,6 +368,8 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "Bật hCaptcha"
hcaptchaSiteKey: "Khóa của trang"
hcaptchaSecretKey: "Khóa bí mật"
+mcaptchaSiteKey: "Khóa của trang"
+mcaptchaSecretKey: "Khóa bí mật"
recaptcha: "reCAPTCHA"
enableRecaptcha: "Bật reCAPTCHA"
recaptchaSiteKey: "Khóa của trang"
@@ -433,7 +434,6 @@ share: "Chia sẻ"
notFound: "Không tìm thấy"
notFoundDescription: "Không tìm thấy trang nào tương ứng với URL này."
uploadFolder: "Thư mục tải lên mặc định"
-cacheClear: "Xóa bộ nhớ đệm"
markAsReadAllNotifications: "Đánh dấu tất cả các thông báo là đã đọc"
markAsReadAllUnreadNotes: "Đánh dấu tất cả các tút là đã đọc"
markAsReadAllTalkMessages: "Đánh dấu tất cả các tin nhắn là đã đọc"
@@ -859,8 +859,6 @@ makeReactionsPublicDescription: "Điều này sẽ hiển thị công khai danh
classic: "Cổ điển"
muteThread: "Không quan tâm nữa"
unmuteThread: "Quan tâm tút này"
-ffVisibility: "Hiển thị Theo dõi/Người theo dõi"
-ffVisibilityDescription: "Quyết định ai có thể xem những người bạn theo dõi và những người theo dõi bạn."
continueThread: "Tiếp tục xem chuỗi tút"
deleteAccountConfirm: "Điều này sẽ khiến tài khoản bị xóa vĩnh viễn. Vẫn tiếp tục?"
incorrectPassword: "Sai mật khẩu."
@@ -1047,7 +1045,10 @@ loadReplies: "Hiển thị các trả lời"
pinnedList: "Các mục đã được ghim"
keepScreenOn: "Giữ màn hình luôn bật"
verifiedLink: "Chúng tôi đã xác nhận bạn là chủ sở hữu của đường dẫn này"
+sourceCode: "Mã nguồn"
flip: "Lật"
+lastNDays: "{n} ngày trước"
+surrender: "Từ chối"
_announcement:
forExistingUsers: "Chỉ những người dùng đã tồn tại"
forExistingUsersDescription: "Nếu được bật, thông báo này sẽ chỉ hiển thị với những người dùng đã tồn tại vào lúc thông báo được tạo. Nếu tắt đi, những tài khoản mới đăng ký sau khi thông báo được đăng lên cũng sẽ thấy nó."
@@ -1673,6 +1674,7 @@ _profile:
_exportOrImport:
allNotes: "Toàn bộ tút"
favoritedNotes: "Bài viết đã thích"
+ clips: "Lưu bài viết"
followingList: "Đang theo dõi"
muteList: "Ẩn"
blockingList: "Chặn"
@@ -1850,3 +1852,6 @@ _webhookSettings:
_moderationLogTypes:
suspend: "Vô hiệu hóa"
resetPassword: "Đặt lại mật khẩu"
+_reversi:
+ total: "Tổng cộng"
+
diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml
index 76bc5c327..681d44e26 100644
--- a/locales/zh-CN.yml
+++ b/locales/zh-CN.yml
@@ -11,7 +11,7 @@ password: "密码"
forgotPassword: "忘记密码"
fetchingAsApObject: "在联邦宇宙查询中..."
ok: "OK"
-gotIt: "我明白了"
+gotIt: "好"
cancel: "取消"
noThankYou: "不用,谢谢"
enterUsername: "输入用户名"
@@ -121,15 +121,21 @@ sensitive: "敏感内容"
add: "添加"
reaction: "回应"
reactions: "回应"
-reactionSetting: "在选择器中显示回应"
+emojiPicker: "表情符号选择器"
+pinnedEmojisForReactionSettingDescription: "可以设置发表回应时置顶显示的表情符号"
+pinnedEmojisSettingDescription: "可以设置输入表情符号时置顶显示的表情符号"
+emojiPickerDisplay: "选择器显示设置"
+overwriteFromPinnedEmojisForReaction: "从「置顶(回应)」设置覆盖"
+overwriteFromPinnedEmojis: "从全局设置覆盖"
reactionSettingDescription2: "拖动重新排序,单击删除,点击 + 添加。"
rememberNoteVisibility: "保存上次设置的可见性"
attachCancel: "删除附件"
+deleteFile: "删除文件"
markAsSensitive: "标记为敏感内容"
unmarkAsSensitive: "取消标记为敏感内容"
enterFileName: "输入文件名"
mute: "屏蔽"
-unmute: "解除屏蔽"
+unmute: "解除静音"
renoteMute: "屏蔽转帖"
renoteUnmute: "解除屏蔽转帖"
block: "拉黑"
@@ -210,15 +216,15 @@ instanceInfo: "服务器信息"
statistics: "统计"
clearQueue: "清除队列"
clearQueueConfirmTitle: "确定清除队列?"
-clearQueueConfirmText: "未送达的帖子将不会投递。 通常,您不需要这样做。"
+clearQueueConfirmText: "未送达的帖子将不会被投递。 通常无需执行此操作。"
clearCachedFiles: "清除缓存"
-clearCachedFilesConfirm: "确定要清除缓存文件?"
+clearCachedFilesConfirm: "确定要清除所有缓存的远程文件?"
blockedInstances: "被封锁的服务器"
blockedInstancesDescription: "设定要封锁的服务器,以换行来进行分割。被封锁的服务器将无法与本服务器进行交换通讯。子域名也同样会被封锁。"
-silencedInstances: "沉默的服务器"
-silencedInstancesDescription: "设置要静音的服务器的主机,以换行符分隔。属于静默服务器的所有帐户都将被视为“静默”,所有关注都将成为请求,并且您将无法提及非关注者的本地帐户。被阻止的实例不受影响。"
-muteAndBlock: "屏蔽/拉黑"
-mutedUsers: "已屏蔽用户"
+silencedInstances: "被静音的服务器"
+silencedInstancesDescription: "设置要静音的服务器,以换行符分隔。被静音的服务器内所有的账户将默认处于「静音」状态,仅能发送关注请求,并且在未关注状态下无法提及本地账户。被阻止的实例不受影响。"
+muteAndBlock: "静音/拉黑"
+mutedUsers: "已静音用户"
blockedUsers: "已拉黑的用户"
noUsers: "无用户"
editProfile: "编辑资料"
@@ -261,6 +267,7 @@ removed: "已删除"
removeAreYouSure: "要删掉「{x}」吗?"
deleteAreYouSure: "要删掉「{x}」吗?"
resetAreYouSure: "恢复默认设置?"
+areYouSure: "你确定吗?"
saved: "已保存"
messaging: "聊天"
upload: "本地上传"
@@ -311,6 +318,7 @@ folderName: "文件夹名称"
createFolder: "创建文件夹"
renameFolder: "重命名文件夹"
deleteFolder: "删除文件夹"
+folder: "文件夹"
addFile: "添加文件"
emptyDrive: "网盘中无文件"
emptyFolder: "此文件夹中无文件"
@@ -328,7 +336,7 @@ displayOfSensitiveMedia: "显示敏感媒体"
whenServerDisconnected: "与服务器连接中断时"
disconnectedFromServer: "已和服务器断开连接"
reload: "重新加载"
-doNothing: "关闭弹窗"
+doNothing: "关闭"
reloadConfirm: "确定要重新加载吗?"
watch: "关注"
unwatch: "取消关注"
@@ -352,7 +360,7 @@ connectService: "连接"
disconnectService: "断开连接"
enableLocalTimeline: "启用本地时间线"
enableGlobalTimeline: "启用全局时间线"
-disablingTimelinesInfo: "即使时间线功能被禁用,出于方便,管理员和协作者也可以继续使用。"
+disablingTimelinesInfo: "即使时间线功能被禁用,出于方便,管理员和监察员也可以继续使用。"
registration: "注册"
enableRegistration: "允许任何人注册"
invite: "邀请"
@@ -372,15 +380,20 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "启用 hCaptcha"
hcaptchaSiteKey: "网站密钥"
hcaptchaSecretKey: "hCaptcha 密钥(SecretKey)"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "启用 mCaptcha"
+mcaptchaSiteKey: "网站密钥"
+mcaptchaSecretKey: "mCaptcha 密钥(SecretKey)"
+mcaptchaInstanceUrl: "mCaptcha 实例地址"
recaptcha: "reCAPTCHA"
enableRecaptcha: "启用 reCAPTCHA\n(请注意, 此功能在中国大陆不可用. 如果启用, 可能导致无法正常使用登录或注册等功能)"
recaptchaSiteKey: "网站密钥"
-recaptchaSecretKey: "reCAPTCHA 密钥(SecretKey)"
+recaptchaSecretKey: "mCaptcha 密钥(SecretKey)"
turnstile: "Turnstile"
enableTurnstile: "启用 Turnstile"
turnstileSiteKey: "网站密钥"
turnstileSecretKey: "Turnstile 密钥(SecretKey)"
-avoidMultiCaptchaConfirm: "使用多种验证方式可能会造成干扰,您要禁用其他验证方式吗?您可以按“取消”按钮,继续保持启用多种验证方式。"
+avoidMultiCaptchaConfirm: "使用多个 Captcha 可能会互相干扰,您要禁用其它 Captcha 吗?您可以按“取消”按钮,继续保持启用多种验证方式。"
antennas: "天线"
manageAntennas: "天线管理"
name: "名称"
@@ -437,7 +450,6 @@ share: "分享"
notFound: "未找到"
notFoundDescription: "没有与指定 URL 对应的页面。"
uploadFolder: "默认上传文件夹"
-cacheClear: "清空缓存"
markAsReadAllNotifications: "将所有通知标为已读"
markAsReadAllUnreadNotes: "将所有帖子标记为已读"
markAsReadAllTalkMessages: "将所有聊天标记为已读"
@@ -478,7 +490,7 @@ or: "或者"
language: "语言"
uiLanguage: "显示语言"
aboutX: "关于 {x}"
-emojiStyle: "emoji 的样式"
+emojiStyle: "表情符号的样式"
native: "原生"
disableDrawer: "不显示抽屉菜单"
showNoteActionsOnlyHover: "仅在悬停时显示帖子操作"
@@ -515,7 +527,7 @@ showFeaturedNotesInTimeline: "在时间线上显示热门推荐"
objectStorage: "对象存储"
useObjectStorage: "使用对象存储"
objectStorageBaseUrl: "Base URL"
-objectStorageBaseUrlDesc: "这里是用于参考的 URL,如果您正在使用 CDN 或反向代理,请指定其 URL,例如 S3:“https://.s3.amazonaws.com”,GCS:“https://storage.googleapis.com/”"
+objectStorageBaseUrlDesc: "用于参考的 URL,如果您正在使用 CDN 或 Proxy,请填入服务商提供的 URL;S3:“https://.s3.amazonaws.com”;GCS:“https://storage.googleapis.com/”"
objectStorageBucket: "存储桶"
objectStorageBucketDesc: "请指定使用的对象存储服务的存储桶名称。"
objectStoragePrefix: "前缀"
@@ -534,6 +546,7 @@ serverLogs: "服务器日志"
deleteAll: "全部删除"
showFixedPostForm: "在时间线顶部显示发帖框"
showFixedPostFormInChannel: "在时间线顶部显示发帖对话框(频道)"
+withRepliesByDefaultForNewlyFollowed: "在时间线中默认包含新关注用户的回复"
newNoteRecived: "有新的帖子"
sounds: "提示音"
sound: "提示音"
@@ -543,6 +556,8 @@ showInPage: "在页面中显示"
popout: "弹窗"
volume: "音量"
masterVolume: "主音量"
+notUseSound: "静音"
+useSoundOnlyWhenActive: "仅在 Misskey 活跃时输出声音"
details: "详情"
chooseEmoji: "选择表情符号"
unableToProcess: "操作无法完成"
@@ -563,10 +578,14 @@ output: "输出"
script: "脚本"
disablePagesScript: "禁用页面脚本"
updateRemoteUser: "更新远程用户信息"
+unsetUserAvatar: "清除头像"
+unsetUserAvatarConfirm: "要清除头像吗?"
+unsetUserBanner: "清除横幅"
+unsetUserBannerConfirm: "要清除横幅吗?"
deleteAllFiles: "删除所有文件"
deleteAllFilesConfirm: "要删除所有文件吗?"
removeAllFollowing: "取消所有关注"
-removeAllFollowingDescription: "取消 {host} 的所有关注者。当服务器不再存在时执行。"
+removeAllFollowingDescription: "取消来自 {host} 的所有关注者。当服务器不再存在时执行。"
userSuspended: "该用户已被冻结。"
userSilenced: "该用户已被禁言。"
yourAccountSuspendedTitle: "账户已被冻结"
@@ -613,6 +632,7 @@ medium: "中"
small: "小"
generateAccessToken: "生成访问令牌"
permission: "权限"
+adminPermission: "管理员权限"
enableAll: "启用全部"
disableAll: "禁用全部"
tokenRequested: "允许访问账户"
@@ -634,6 +654,7 @@ smtpSecure: "在 SMTP 连接中使用隐式 SSL / TLS"
smtpSecureInfo: "使用 STARTTLS 时关闭。"
testEmail: "邮件发送测试"
wordMute: "文字屏蔽"
+hardWordMute: "屏蔽关键词"
regexpError: "正则表达式错误"
regexpErrorDescription: "{tab} 屏蔽文字的第 {line} 行的正则表达式有错误:"
instanceMute: "被屏蔽的服务器"
@@ -655,6 +676,7 @@ useGlobalSettingDesc: "启用时,将使用账户通知设置。关闭时,则
other: "其他"
regenerateLoginToken: "重新生成登录令牌"
regenerateLoginTokenDescription: "重新生成用于登录的内部令牌。通常您不需要这样做。重新生成后,您将在所有设备上登出。"
+theKeywordWhenSearchingForCustomEmoji: "这将是搜素自定义表情符号时的关键词。"
setMultipleBySeparatingWithSpace: "您可以使用空格分隔多个项目。"
fileIdOrUrl: "文件 ID 或者 URL"
behavior: "行为"
@@ -867,8 +889,8 @@ makeReactionsPublicDescription: "将您发表过的回应设置成公开可见
classic: "经典"
muteThread: "屏蔽帖子列表"
unmuteThread: "取消屏蔽帖子列表"
-ffVisibility: "关注关系的可见范围"
-ffVisibilityDescription: "您可以设置您的关注/关注者信息的公开范围"
+followingVisibility: "关注的人的公开范围"
+followersVisibility: "关注者的公开范围"
continueThread: "查看更多帖子"
deleteAccountConfirm: "将要删除账户。是否确认?"
incorrectPassword: "密码错误"
@@ -952,7 +974,7 @@ unsubscribePushNotification: "停用推送通知消息"
pushNotificationAlreadySubscribed: "推送通知消息已启用"
pushNotificationNotSupported: "浏览器或服务器不支持推送通知消息"
sendPushNotificationReadMessage: "删除已读推送通知消息"
-sendPushNotificationReadMessageCaption: "“{emptyPushNotificationMessage}”的通知消息将会显示。您终端设备的电池消耗可能会增加。"
+sendPushNotificationReadMessageCaption: "您终端设备的电池消耗可能会增加。"
windowMaximize: "最大化"
windowMinimize: "最小化"
windowRestore: "还原"
@@ -969,6 +991,7 @@ neverShow: "不再显示"
remindMeLater: "稍后提醒我"
didYouLikeMisskey: "您喜欢 Misskey 吗?"
pleaseDonate: "Misskey 是 {host} 所使用的免费软件。为了今后也能够维持 Misskey 的开发,请在有余力的情况下进行捐助!"
+correspondingSourceIsAvailable: "对应的源代码可在{anchor}找到"
roles: "角色"
role: "角色"
noRole: "角色不存在"
@@ -978,6 +1001,7 @@ assign: "分配"
unassign: "取消分配"
color: "颜色"
manageCustomEmojis: "管理自定义表情符号"
+manageAvatarDecorations: "管理头像挂件"
youCannotCreateAnymore: "抱歉,您无法再创建更多了。"
cannotPerformTemporary: "暂时不可用"
cannotPerformTemporaryDescription: "因操作过于频繁,暂时不可用,请稍后再试。"
@@ -1018,6 +1042,11 @@ resetPasswordConfirm: "确定重置密码?"
sensitiveWords: "敏感词"
sensitiveWordsDescription: "将包含设置词的帖子的可见范围设置为首页。可以通过用换行符分隔来设置多个。"
sensitiveWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。"
+prohibitedWords: "禁用词"
+prohibitedWordsDescription: "发布包含设定词汇的帖子时将出错。可用换行设定多个关键字"
+prohibitedWordsDescription2: "AND 条件用空格分隔,正则表达式用斜线包裹。"
+hiddenTags: "隐藏标签"
+hiddenTagsDescription: "设定的标签将不会在时间线上显示。可使用换行来设置多个标签。"
notesSearchNotAvailable: "帖子检索不可用"
license: "许可信息"
unfavoriteConfirm: "确定要取消收藏吗?"
@@ -1030,9 +1059,12 @@ enableChartsForRemoteUser: "生成远程用户的图表"
enableChartsForFederatedInstances: "生成远程服务器的图表"
showClipButtonInNoteFooter: "在贴文下方显示便签按钮"
reactionsDisplaySize: "回应显示大小"
+limitWidthOfReaction: "限制回应的最大宽度,并将其缩小显示"
noteIdOrUrl: "帖子 ID 或 URL"
video: "视频"
videos: "视频"
+audio: "音频"
+audioFiles: "音频"
dataSaver: "省流量模式"
accountMigration: "账户迁移"
accountMoved: "此用户已迁移账户"
@@ -1085,7 +1117,7 @@ branding: "品牌"
enableServerMachineStats: "公开服务器硬件统计信息"
enableIdenticonGeneration: "启用生成用户 Identicon"
turnOffToImprovePerformance: "关闭该选项可以提高性能。"
-createInviteCode: "发行邀请码"
+createInviteCode: "生成邀请码"
createWithOptions: "使用选项来创建"
createCount: "发行数"
inviteCodeCreated: "已创建邀请码"
@@ -1097,7 +1129,7 @@ noExpirationDate: "不设置有效日期"
inviteCodeUsedAt: "邀请码被使用的日期和时间"
registeredUserUsingInviteCode: "使用了邀请码的用户"
waitingForMailAuth: "等待验证电子邮件"
-inviteCodeCreator: "发行邀请码的用户"
+inviteCodeCreator: "生成邀请码的用户"
usedAt: "使用时间"
unused: "未使用"
used: "已使用"
@@ -1128,19 +1160,114 @@ showRenotes: "显示转帖"
edited: "已编辑"
notificationRecieveConfig: "通知接收设置"
mutualFollow: "互相关注"
+followingOrFollower: "关注中或关注者"
fileAttachedOnly: "仅限媒体"
-showRepliesToOthersInTimeline: "在时间线上显示给其他人的回复"
-hideRepliesToOthersInTimeline: "在时间线上隐藏给其他人的回复"
+showRepliesToOthersInTimeline: "在时间线中包含给别人的回复"
+hideRepliesToOthersInTimeline: "在时间线中隐藏给别人的回复"
+showRepliesToOthersInTimelineAll: "在时间线中包含现在关注的所有人的回复"
+hideRepliesToOthersInTimelineAll: "在时间线中隐藏现在关注的所有人的回复"
+confirmShowRepliesAll: "此操作不可撤销。确认要在时间线中包含现在关注的所有人的回复吗?"
+confirmHideRepliesAll: "此操作不可撤销。确认要在时间线中隐藏现在关注的所有人的回复吗?"
+externalServices: "外部服务"
+sourceCode: "源代码"
+sourceCodeIsNotYetProvided: "还未提供源代码。要解决此问题请联系管理员。"
+repositoryUrl: "仓库地址"
+repositoryUrlDescription: "若源代码所在的仓库是公开的,请填入对应的 URL。若是按原样使用 Misskey(并未追加或者修改代码)的情况请填入 https://github.com/misskey-dev/misskey。"
+repositoryUrlOrTarballRequired: "若仓库并未公开,则需要提供 tarball 作为替代。详情请看 .config/example.yml。"
+feedback: "反馈"
+feedbackUrl: "反馈地址"
+impressum: "运营商信息"
+impressumUrl: "运营商信息地址"
+impressumDescription: "德国等国家和地区有义务展示此类信息(Impressum)。"
+privacyPolicy: "隐私政策"
+privacyPolicyUrl: "隐私政策地址"
+tosAndPrivacyPolicy: "服务条款及隐私政策"
+avatarDecorations: "头像挂件"
+attach: "佩戴"
+detach: "卸下"
+detachAll: "全部卸下"
+angle: "角度"
flip: "翻转"
+showAvatarDecorations: "显示头像挂件"
+releaseToRefresh: "松开以刷新"
+refreshing: "刷新中"
+pullDownToRefresh: "下拉以刷新"
+disableStreamingTimeline: "禁止实时更新时间线"
+useGroupedNotifications: "分组显示通知"
+signupPendingError: "确认电子邮件时出现错误。链接可能已过期。"
+cwNotationRequired: "在启用「隐藏内容」时必须输入注释"
+doReaction: "回应"
+code: "代码"
+reloadRequiredToApplySettings: "需要重新载入来使设置生效"
+remainingN: "剩余:{n}"
+overwriteContentConfirm: "将覆盖现有内容。确定吗?"
+seasonalScreenEffect: "应景的画面效果"
+decorate: "装饰"
+addMfmFunction: "添加装饰"
+enableQuickAddMfmFunction: "显示高级 MFM 选择器"
+bubbleGame: "泡泡游戏"
+sfx: "音效"
+soundWillBePlayed: "声音将会播放"
+showReplay: "观看回放"
+replay: "重播"
+replaying: "重播中"
+endReplay: "结束回放"
+copyReplayData: "复制回放数据"
+ranking: "排行榜"
+lastNDays: "最近 {n} 天"
+backToTitle: "返回标题"
+hemisphere: "居住地区"
+withSensitive: "显示包含敏感媒体的帖子"
+userSaysSomethingSensitive: "含 {name} 敏感文件的帖子"
+enableHorizontalSwipe: "滑动切换标签页"
+loading: "读取中"
+surrender: "取消"
+gameRetry: "重试"
+_bubbleGame:
+ howToPlay: "游戏说明"
+ hold: "抓住"
+ _score:
+ score: "得分"
+ scoreYen: "赚到的钱"
+ highScore: "最高分"
+ maxChain: "最高连击数"
+ yen: "{yen} 日元"
+ estimatedQty: "约 {qty} 个"
+ _howToPlay:
+ section1: "对准位置将Emoji投入盒子。"
+ section2: "相同的Emoji相互接触合成后会得到新的Emoji,以此获得分数。"
+ section3: "如果Emoji从箱子中溢出游戏将会结束。在防止Emoji溢出的同时,不断合成新的Emoji,来获取更高的分数吧!"
+abuseReportCategory: "举报类型"
+selectCategory: "选择类别"
+reportComplete: "举报完成"
+blockThisUser: "屏蔽此用户"
+muteThisUser: "静音此用户"
+_abuseReportCategory:
+ nsfw: "含有敏感内容的帖子"
+ spam: "垃圾信息"
+ explicit: "包含暴力或攻击性内容的帖子"
+ phishing: "网络钓鱼或欺诈行为"
+ personalInfoLeak: "本人或他人个人信息泄露"
+ selfHarm: "自杀或自残等生命安全问题"
+ criticalBreach: "严重的协议违反"
+ otherBreach: "其他协议违反"
+ violationRights: "侵犯权利或冒充(本人)"
+ violationRightsOther: "侵犯他人权利"
+ notLike: "不喜欢此人"
+ other: "其他"
_announcement:
forExistingUsers: "仅限现有用户"
forExistingUsersDescription: "若启用,该公告将仅对创建此公告时存在的用户可见。 如果禁用,则在创建此公告后注册的用户也可以看到该公告。"
needConfirmationToRead: "需要确认才能标记为已读"
needConfirmationToReadDescription: "若启用,则会在标记已读时会显示确认对话框。此外,它也会不受批量已读操作的影响。"
end: "结束公告"
- tooManyActiveAnnouncementDescription: "若有大量活动公告,可能会造成用户体验可能下降。请考虑归档已完成的公告。"
+ tooManyActiveAnnouncementDescription: "若有大量活动公告,可能会造成用户体验下降。请考虑归档已完成的公告。"
readConfirmTitle: "标记为已读?"
readConfirmText: "阅读“{title}”的内容并将其标记为已读。"
+ shouldNotBeUsedToPresentPermanentInfo: "我们建议使用公告来发布临时性的流动信息而不是固定的常规信息,因为这可能损害用户体验,尤其是对于新用户而言。"
+ dialogAnnouncementUxWarn: "同时存在 2 个或以上的对话框公告极有可能对用户体验产生负面的影响,建议谨慎使用。"
+ silence: "不发送通知"
+ silenceDescription: "开启后,此条公告将不会发送通知,也不强制用户阅读。"
_initialAccountSetting:
accountCreated: "账户创建完成了!"
letsStartAccountSetup: "来进行帐户的初始设置吧。"
@@ -1153,19 +1280,91 @@ _initialAccountSetting:
pushNotificationDescription: "启用推送通知的话,就可以在设备上接收来自 {name} 的通知了。"
initialAccountSettingCompleted: "初始设定已经完成了!"
haveFun: "希望 {name} 在这里玩得开心!"
+ youCanContinueTutorial: "您可以继续了解 {name}(Misskey) 的使用教程,也可以在此停止教程并立即开始使用它。\n"
+ startTutorial: "开始教学"
skipAreYouSure: "要跳过初始设置吗?"
laterAreYouSure: "要稍后再进行初始设定吗?"
+_initialTutorial:
+ launchTutorial: "观看教学"
+ title: "教学"
+ wellDone: "做得好"
+ skipAreYouSure: "是否退出教学?"
+ _landing:
+ title: "欢迎来到教学"
+ description: "在这里,您可以查看 Misskey 的基本使用方法和功能。"
+ _note:
+ title: "什么是帖子?"
+ description: "在 Misskey 上发表的文章称为「帖子」。帖子在时间线上按照时间顺序排列,并实时更新。"
+ reply: "用来回复帖子。可以对回复进行回复,从而形成一串对话。"
+ renote: "用来将帖子共享到自己的时间线上。也可以加上自己的文字然后引用它。"
+ reaction: "用来添加回应。详细信息将在下一页进行说明。"
+ menu: "用来进行例如显示帖子详情、复制链接等各种各样的操作。"
+ _reaction:
+ title: "什么是回应?"
+ description: "您可以在帖子中添加“回应”。 您可以使用反应轻松地表达点“赞”所无法传达的细微差别。"
+ letsTryReacting: "回应可以通过点击帖子中的「+」按钮来添加。试着给这个示例帖子添加一个回应!"
+ reactToContinue: "添加一个回应来继续"
+ reactNotification: "当您的帖子被某人添加了回应时,将实时收到通知。"
+ reactDone: "通过按下「ー」按钮,可以取消已经添加的回应"
+ _timeline:
+ title: "时间线的运作方式"
+ description1: "Misskey 根据使用方式提供了多个时间线(根据服务器的设定,可能有一些被禁用)。"
+ home: "可以查看您关注的账户的帖子。"
+ local: "可以查看这个服务器上所有用户发表的帖子。"
+ social: "将同时显示首页时间线和本地时间线的内容。"
+ global: "可以查看所有已联合的服务器上的帖子。"
+ description2: "可以随时在屏幕顶部在每个时间线之间切换。"
+ description3: "另外,还有列表时间线和频道时间线。请参阅{link}了解更多详细信息。"
+ _postNote:
+ title: "帖子发布设置"
+ description1: "在 Misskey 发布帖子时,您可以设置各种选项。发帖窗口看起来是这样的。\n"
+ _visibility:
+ description: "您可以限制谁可以看到您的帖子。"
+ public: "向所有用户公开。\n"
+ home: "仅在首页时间线上发布。 关注者、从个人资料页查看过来的用户、以及通过转帖也能被别的用户看见。"
+ followers: "仅对关注者可见。 除了您自己之外,没有人可以转贴,并且只有您的关注者可以查看它。\n"
+ direct: "它将仅向指定用户公开,并且他们也会收到通知。 您可以使用它来代替私信。\n"
+ doNotSendConfidencialOnDirect1: "发送敏感信息时请注意。\n"
+ doNotSendConfidencialOnDirect2: "目标服务器的管理员可以看到发布的内容,因此如果您向不受信任的服务器上的用户发送私信,则在处理敏感信息时需要小心。"
+ localOnly: "不将帖子推送到其它服务器。 无论上述公开范围如何,其它服务器的用户将无法看到附加了此设定的帖子。\n"
+ _cw:
+ title: "隐藏内容 (CW)\n"
+ description: "显示「注解」里的内容而不是正文。点击「查看更多」将会把正文显示出来。"
+ _exampleNote:
+ cw: "深夜报复社会"
+ note: "茨了带巧克力的甜甜圈🍩😋"
+ useCases: "用于服务器条款所规定的帖子,或对剧透内容和敏感内容进行自主规制。"
+ _howToMakeAttachmentsSensitive:
+ title: "如何将附件标注为敏感内容?"
+ description: "对于服务器方针所要求要求的,又或者不适合直接展示的附件,请添加「敏感」标记。\n"
+ tryThisFile: "试试看,将附加到此窗口的图像标注为敏感!"
+ _exampleNote:
+ note: "拆纳豆包装时出错了…"
+ method: "要标注附件为敏感内容,请单击该文件以打开菜单,然后单击“标记为敏感内容”。"
+ sensitiveSucceeded: "附加文件时,请遵循服务器的条款来设置正确敏感设定。\n"
+ doItToContinue: "将图像标记为敏感后才能够继续"
+ _done:
+ title: "恭喜您,已经完成了教程🎉\n"
+ description: "这里介绍的只是其中一小部分的功能。 要了解更多有关如何使用 Misskey 的更多信息,请访问 {link}。"
+_timelineDescription:
+ home: "首页时间线可以查看您关注的账户的帖子。"
+ local: "本地时间线可以查看这个服务器上所有用户发表的帖子。"
+ social: "社交时间线将同时显示首页时间线和本地时间线的内容。"
+ global: "全局时间线可以查看所有已联合的服务器上的帖子。"
_serverRules:
description: "在新用户注册前显示服务器的简单规则。推荐显示服务条款的主要内容。"
_serverSettings:
iconUrl: "图标 URL"
appIconDescription: "指定当 {host} 显示为 app 时的图标。"
- appIconUsageExample: "例如:作为书签添加到 PWA 或手机主屏幕的时候"
+ appIconUsageExample: "如作为书签添加到 PWA 或手机主屏幕时"
appIconStyleRecommendation: "因为有可能会被裁切为圆形或者圆角矩形,建议使用边缘带有留白背景的图标。"
appIconResolutionMustBe: "分辨率必须为 {resolution}。"
- manifestJsonOverride: "覆盖 mainfest.json"
+ manifestJsonOverride: "覆盖 manifest.json"
shortName: "简称"
shortNameDescription: "如果服务器的正式名称很长,可以用简称或者別名来替代。"
+ fanoutTimelineDescription: "当启用时,可显著提高获取各种时间线时的性能,并减轻数据库的负荷。但是相对的 Redis 的内存使用量将会增加。如果服务器的内存不是很大,又或者运行不稳定的话可以把它关掉。"
+ fanoutTimelineDbFallback: "回退到数据库"
+ fanoutTimelineDbFallbackDescription: "当启用时,若时间线未被缓存,则将额外查询数据库。禁用该功能可通过不执行回退处理进一步减少服务器负载,但会限制可检索的时间线范围。"
_accountMigration:
moveFrom: "从别的账号迁移到此账户"
moveFromSub: "为另一个账户建立别名"
@@ -1392,7 +1591,7 @@ _achievements:
description: "点了这里"
_justPlainLucky:
title: "超高校级的幸运"
- description: "每 10 秒有 0.01 的概率自动获得"
+ description: "每 10 秒有 0.005% 的概率自动获得"
_setNameToSyuilo:
title: "像神一样呐"
description: "将名称设定为 syuilo"
@@ -1423,6 +1622,15 @@ _achievements:
_smashTestNotificationButton:
title: "过度测试"
description: "短时间内连续测试通知"
+ _tutorialCompleted:
+ title: "Misskey 初学者课程 结业证书"
+ description: "完成了教学"
+ _bubbleGameExplodingHead:
+ title: "🤯"
+ description: "你合成出了游戏里最大的Emoji"
+ _bubbleGameDoubleExplodingHead:
+ title: "两个🤯"
+ description: "你合成出了2个游戏里最大的Emoji"
_role:
new: "创建角色"
edit: "编辑角色"
@@ -1433,7 +1641,9 @@ _role:
assignTarget: "授权对象"
descriptionOfAssignTarget: "手动指手动选择谁被包括在这个角色中。\n符合条件指设置条件以自动包括符合条件的用户。"
manual: "手动"
+ manualRoles: "手动角色"
conditional: "符合条件"
+ conditionalRoles: "条件角色"
condition: "条件"
isConditionalRole: "这是一个条件控制的角色。"
isPublic: "角色公开"
@@ -1461,11 +1671,13 @@ _role:
gtlAvailable: "查看全局时间线"
ltlAvailable: "查看本地时间线"
canPublicNote: "允许公开发帖"
+ mentionMax: "帖子内最多提及数"
canInvite: "发放服务器邀请码"
- inviteLimit: "可发行邀请码的数量"
+ inviteLimit: "可生成邀请码的数量"
inviteLimitCycle: "邀请码的发行间隔"
inviteExpirationTime: "邀请码的有效日期"
canManageCustomEmojis: "管理自定义表情符号"
+ canManageAvatarDecorations: "管理头像挂件"
driveCapacity: "网盘容量"
alwaysMarkNsfw: "总是将文件标记为 NSFW"
pinMax: "帖子置顶数量限制"
@@ -1480,7 +1692,10 @@ _role:
descriptionOfRateLimitFactor: "值越小限制越少,值越大限制越多。"
canHideAds: "可以隐藏广告"
canSearchNotes: "是否可以搜索帖子"
+ canUseTranslator: "使用翻译功能"
+ avatarDecorationLimit: "可添加头像挂件的最大个数"
_condition:
+ roleAssignedTo: "已分配给手动角色"
isLocal: "是本地用户"
isRemote: "是远程用户"
createdLessThan: "账户创建时间少于"
@@ -1508,6 +1723,7 @@ _emailUnavailable:
disposable: "不是永久可用的地址"
mx: "邮件服务器不正确"
smtp: "邮件服务器没有响应"
+ banned: "无法使用此邮件地址注册"
_ffVisibility:
public: "公开"
followers: "只有关注你的用户能看到"
@@ -1528,6 +1744,10 @@ _ad:
reduceFrequencyOfThisAd: "减少此广告的频率"
hide: "不显示"
timezoneinfo: "星期几是由服务器的时区所指定的。"
+ adsSettings: "广告设置"
+ notesPerOneAd: "在实时更新时间线中插入广告的间隔(帖子个数)"
+ setZeroToDisable: "设为 0 将不在实时更新时间线中投放广告"
+ adsTooClose: "广告投放时间间隔过短将可能显著损害用户体验。"
_forgotPassword:
enterEmail: "请输入您设置的电子邮箱地址,密码重置链接将发送至该邮箱上。"
ifNoEmail: "如果您没有设置电子邮件地址,请联系管理员。"
@@ -1567,8 +1787,8 @@ _preferencesBackups:
invalidFile: "无效的的文件格式。"
_registry:
scope: "范围"
- key: "主要"
- keys: "主要"
+ key: "键"
+ keys: "键"
domain: "域"
createKey: "创建键"
_aboutMisskey:
@@ -1576,10 +1796,13 @@ _aboutMisskey:
contributors: "主要贡献者"
allContributors: "全体贡献者"
source: "源代码"
+ original: "原版"
+ thisIsModifiedVersion: "{name}正在使用修改后的 Misskey。"
translation: "翻译 Misskey"
donate: "赞助 Misskey"
morePatrons: "还有很多其它的人也在支持我们,非常感谢🥰"
patrons: "支持者"
+ projectMembers: "项目成员"
_displayOfSensitiveMedia:
respect: "隐藏敏感媒体"
ignore: "显示敏感媒体"
@@ -1604,6 +1827,7 @@ _channel:
notesCount: "有 {n} 个帖子"
nameAndDescription: "名称与描述"
nameOnly: "仅名称"
+ allowRenoteToExternal: "允许在频道外转帖及引用"
_menuDisplay:
sideFull: "横向"
sideIcon: "横向(图标)"
@@ -1695,6 +1919,14 @@ _sfx:
notification: "通知"
antenna: "天线接收"
channel: "频道通知"
+ reaction: "选择回应时"
+_soundSettings:
+ driveFile: "使用网盘内的音频"
+ driveFileWarn: "选择网盘上的文件"
+ driveFileTypeWarn: "不支持此文件"
+ driveFileTypeWarnDescription: "请选择音频文件"
+ driveFileDurationWarn: "音频过长"
+ driveFileDurationWarnDescription: "使用长音频可能会影响 Misskey 的使用。即使这样也要继续吗?"
_ago:
future: "未来"
justNow: "最近"
@@ -1706,6 +1938,14 @@ _ago:
monthsAgo: "{n} 月前"
yearsAgo: "{n} 年前"
invalid: "没有"
+_timeIn:
+ seconds: "{n}秒后"
+ minutes: "{n} 分后"
+ hours: "{n} 小时后"
+ days: "{n}天后"
+ weeks: "{n} 周后"
+ months: "{n} 月后"
+ years: "{n} 年后"
_time:
second: "秒"
minute: "分"
@@ -1777,6 +2017,55 @@ _permissions:
"write:flash": "编辑 Play"
"read:flash-likes": "查看 Play 的点赞"
"write:flash-likes": "编辑 Play 的点赞列表"
+ "read:admin:abuse-user-reports": "查看来自用户的举报"
+ "write:admin:delete-account": "删除用户账户"
+ "write:admin:delete-all-files-of-a-user": "删除用户所有的文件"
+ "read:admin:index-stats": "查看数据库索引相关的信息"
+ "read:admin:table-stats": "查看数据库表相关的信息"
+ "read:admin:user-ips": "查看用户 IP 地址"
+ "read:admin:meta": "查看实例的元数据"
+ "write:admin:reset-password": "重置用户密码"
+ "write:admin:resolve-abuse-user-report": "将来自用户的报告标记为「已解决」"
+ "write:admin:send-email": "发送邮件"
+ "read:admin:server-info": "查看服务器信息"
+ "read:admin:show-moderation-log": "查看管理日志"
+ "read:admin:show-user": "查看用户的非公开信息"
+ "read:admin:show-users": "查看用户的非公开信息"
+ "write:admin:suspend-user": "冻结用户"
+ "write:admin:unset-user-avatar": "删除用户头像"
+ "write:admin:unset-user-banner": "删除用户横幅"
+ "write:admin:unsuspend-user": "解除用户冻结"
+ "write:admin:meta": "编辑实例元数据"
+ "write:admin:user-note": "编辑管理笔记"
+ "write:admin:roles": "编辑角色"
+ "read:admin:roles": "查看角色"
+ "write:admin:relays": "编辑中继"
+ "read:admin:relays": "查看中继"
+ "write:admin:invite-codes": "编辑邀请码"
+ "read:admin:invite-codes": "查看邀请码"
+ "write:admin:announcements": "编辑公告"
+ "read:admin:announcements": "查看公告"
+ "write:admin:avatar-decorations": "编辑头像挂件"
+ "read:admin:avatar-decorations": "查看头像挂件"
+ "write:admin:federation": "编辑联合相关信息"
+ "write:admin:account": "编辑用户账户"
+ "read:admin:account": "查看用户相关情报"
+ "write:admin:emoji": "编辑表情文字"
+ "read:admin:emoji": "查看表情文字"
+ "write:admin:queue": "编辑作业队列"
+ "read:admin:queue": "查看作业队列相关情报"
+ "write:admin:promo": "运营推广说明"
+ "write:admin:drive": "编辑用户网盘"
+ "read:admin:drive": "查看用户网盘相关情报"
+ "read:admin:stream": "使用管理员用的 Websocket API"
+ "write:admin:ad": "编辑广告"
+ "read:admin:ad": "查看广告"
+ "write:invite-codes": "生成邀请码"
+ "read:invite-codes": "获取已发行的邀请码"
+ "write:clip-favorite": "编辑便签的点赞"
+ "read:clip-favorite": "查看便签的点赞"
+ "read:federation": "查看联合相关信息"
+ "write:report-abuse": "举报用户"
_auth:
shareAccessTitle: "应用程序授权许可"
shareAccess: "您要授权允许 “{name}” 访问您的帐户吗?"
@@ -1831,6 +2120,7 @@ _widgets:
_userList:
chooseList: "选择列表"
clicker: "点击器"
+ birthdayFollowings: "今天是他们的生日"
_cw:
hide: "隐藏"
show: "查看更多"
@@ -1893,15 +2183,18 @@ _profile:
changeAvatar: "修改头像"
changeBanner: "修改横幅"
verifiedLinkDescription: "如果将内容设置为 URL,当链接所指向的网页内包含自己的个人资料链接时,可以显示一个已验证图标。"
+ avatarDecorationMax: "最多可添加 {max} 个挂件"
_exportOrImport:
allNotes: "所有帖子"
favoritedNotes: "收藏的帖子"
+ clips: "便签"
followingList: "关注中"
muteList: "屏蔽"
blockingList: "拉黑"
userLists: "列表"
excludeMutingUsers: "排除屏蔽用户"
excludeInactiveUsers: "排除不活跃用户"
+ withReplies: "在时间线中包含导入用户的回复"
_charts:
federation: "联合"
apRequest: "请求"
@@ -2013,12 +2306,17 @@ _notification:
pollEnded: "问卷调查结果已生成。"
newNote: "新的帖子"
unreadAntennaNote: "天线 {name}"
+ roleAssigned: "授予的角色"
emptyPushNotificationMessage: "推送通知已更新"
achievementEarned: "获得成就"
testNotification: "测试通知"
checkNotificationBehavior: "检查通知显示"
sendTestNotification: "发送测试通知"
notificationWillBeDisplayedLikeThis: "通知将会这样表示"
+ reactedBySomeUsers: "{n} 人回应了"
+ renotedBySomeUsers: "{n} 人转发了"
+ followedBySomeUsers: "被 {n} 人关注"
+ flushNotification: "重置通知历史"
_types:
all: "全部"
note: "用户的新帖子"
@@ -2031,6 +2329,7 @@ _notification:
pollEnded: "问卷调查结束"
receiveFollowRequest: "收到关注请求"
followRequestAccepted: "关注请求已通过"
+ roleAssigned: "授予的角色"
achievementEarned: "取得的成就"
app: "关联应用的通知"
_actions:
@@ -2113,13 +2412,129 @@ _moderationLogTypes:
deleteGlobalAnnouncement: "删除全体通知"
deleteUserAnnouncement: "删除用户通知"
resetPassword: "重置密码"
+ suspendRemoteInstance: "停止远程服务器"
+ unsuspendRemoteInstance: "恢复远程服务器"
+ updateRemoteInstanceNote: "更新远程服务器的管理笔记"
markSensitiveDriveFile: "标记网盘文件为敏感媒体"
unmarkSensitiveDriveFile: "取消标记网盘文件为敏感媒体"
resolveAbuseReport: "处理举报"
- createInvitation: "发行邀请码"
+ createInvitation: "生成邀请码"
createAd: "创建了广告"
deleteAd: "删除了广告"
updateAd: "更新了广告"
+ createAvatarDecoration: "新建头像挂件"
+ updateAvatarDecoration: "更新头像挂件"
+ deleteAvatarDecoration: "删除头像挂件"
+ unsetUserAvatar: "清除用户头像"
+ unsetUserBanner: "清除用户横幅"
_fileViewer:
+ title: "文件信息"
+ type: "文件类型"
+ size: "文件大小"
url: "URL"
uploadedAt: "添加日期"
+ attachedNotes: "附加到的帖子"
+ thisPageCanBeSeenFromTheAuthor: "此页只能被该文件的上传者查看。"
+_externalResourceInstaller:
+ title: "从外部站点安装"
+ checkVendorBeforeInstall: "请在安装前确保来源可靠"
+ _plugin:
+ title: "要安装此插件吗?"
+ metaTitle: "插件信息"
+ _theme:
+ title: "要安装此主题吗?"
+ metaTitle: "主题信息"
+ _meta:
+ base: "基本配色方案"
+ _vendorInfo:
+ title: "来源信息"
+ endpoint: "参考端点"
+ hashVerify: "确认文件完整性"
+ _errors:
+ _invalidParams:
+ title: "缺少参数"
+ description: "缺少从外部站点获取数据所需的信息。请检查 URL。"
+ _resourceTypeNotSupported:
+ title: "不支持此外部资源"
+ description: "不支持从此外部站点获取的资源类型。请联系站点管理员。"
+ _failedToFetch:
+ title: "获取数据失败"
+ fetchErrorDescription: "与外部站点的通信失败。 如果重试后问题仍然存在,请联系站点管理员。"
+ parseErrorDescription: "无法读取从外部站点取得的数据。请联系站点管理员。"
+ _hashUnmatched:
+ title: "无法获取正确数据"
+ description: "无法验证数据的完整性。安全起见,无法继续安装。请联系站点管理员。"
+ _pluginParseFailed:
+ title: "AiScript 错误"
+ description: "虽然取得了数据,但是由于 AiScript 解析时出现错误,无法读取数据。请联系插件的作者。可在 Javascript 控制台查看错误详情。"
+ _pluginInstallFailed:
+ title: "插件安装失败"
+ description: "安装插件时出现错误。请再试一次。可在 Javascript 控制台查看错误详情。"
+ _themeParseFailed:
+ title: "主题解析错误"
+ description: "虽然取得了主题文件,但是由于解析时出现错误,无法加载主题。请联系主题的作者。可在 Javascript 控制台查看错误详情。"
+ _themeInstallFailed:
+ title: "安装主题失败"
+ description: "安装主题时出错。请再试一次。可在 Javascript 控制台查看错误详情。"
+_dataSaver:
+ _media:
+ title: "加载媒体"
+ description: "防止自动加载图像和视频。 点击隐藏的图像/视频即可加载它们。\n"
+ _avatar:
+ title: "头像"
+ description: "停止播放头像的动画。 由于动画图片的文件大小可能比普通图像大,这可以进一步减少数据流量。"
+ _urlPreview:
+ title: "URL预览缩略图\n"
+ description: "将不再加载 URL 预览缩略图。"
+ _code:
+ title: "代码高亮"
+ description: "如果使用了代码高亮标记,例如在 MFM 中,则在点击之前不会加载。 代码高亮要求加载每种高亮语言的定义文件,由于这些文件不再自动加载,因此有望减少数据传输量。"
+_hemisphere:
+ N: "北半球"
+ S: "南半球"
+ caption: "在某些客户端设置中用来确定季节"
+_reversi:
+ reversi: "黑白棋"
+ gameSettings: "对局设置"
+ blackOrWhite: "先手/后手"
+ blackIs: "{name}执黑(先手)"
+ rules: "规则"
+ thisGameIsStartedSoon: "对局即将开始"
+ waitingForOther: "等待对手准备"
+ waitingForMe: "等待你的准备"
+ waitingBoth: "请准备"
+ ready: "准备就绪"
+ cancelReady: "重新准备"
+ opponentTurn: "对手的回合"
+ myTurn: "你的回合"
+ turnOf: "{name}的回合"
+ pastTurnOf: "{name}的回合"
+ surrender: "认输"
+ surrendered: "已认输"
+ timeout: "超时"
+ drawn: "平局"
+ won: "{name}获胜"
+ black: "黑"
+ white: "白"
+ total: "总计"
+ turnCount: "第{count}回合"
+ myGames: "我的对局"
+ allGames: "所有对局"
+ ended: "结束"
+ playing: "对局中"
+ canPutEverywhere: "无限制放置模式"
+ timeLimitForEachTurn: "1回合的时间限制"
+ freeMatch: "自由匹配"
+ lookingForPlayer: "正在寻找对手"
+ gameCanceled: "对局被取消了"
+ shareToTlTheGameWhenStart: "开始时在时间线发布对局"
+ iStartedAGame: "对局开始!#MisskeyReversi"
+ opponentHasSettingsChanged: "对手更改了设定"
+ allowIrregularRules: "允许非常规规则(完全自由)"
+ disallowIrregularRules: "禁止非常规规则"
+ showBoardLabels: "显示行号和列号"
+ useAvatarAsStone: "用头像作为棋子"
+_offlineScreen:
+ title: "离线——无法连接到服务器"
+ header: "无法连接到服务器"
+
diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml
index ad0741693..5cdecc10a 100644
--- a/locales/zh-TW.yml
+++ b/locales/zh-TW.yml
@@ -66,7 +66,7 @@ showMore: "載入更多"
showLess: "關閉"
youGotNewFollower: "您有新的追隨者"
receiveFollowRequest: "您有新的追隨請求"
-followRequestAccepted: "追隨請求已接受"
+followRequestAccepted: "追隨請求已被接受"
mention: "提及"
mentions: "提及"
directNotes: "私訊"
@@ -91,7 +91,7 @@ manageLists: "管理清單"
error: "錯誤"
somethingHappened: "發生錯誤"
retry: "重試"
-pageLoadError: "載入頁面失敗"
+pageLoadError: "無法載入頁面。"
pageLoadErrorDescription: "這通常是網路錯誤或瀏覽器快取殘留而引起的。請先清除瀏覽器快取,稍後再重試。"
serverIsDead: "伺服器沒有回應。請稍等片刻再試。"
youShouldUpgradeClient: "請重新載入以使用新版客戶端顯示此頁面。"
@@ -121,10 +121,16 @@ sensitive: "敏感內容"
add: "新增"
reaction: "反應"
reactions: "反應"
-reactionSetting: "在選擇器中顯示反應"
+emojiPicker: "表情符號選擇器"
+pinnedEmojisForReactionSettingDescription: "選擇反應時可以設定要固定顯示在頂端的表情符號"
+pinnedEmojisSettingDescription: "輸入表情符號時可以設定要固定顯示在頂端的表情符號"
+emojiPickerDisplay: "顯示表情符號選擇器"
+overwriteFromPinnedEmojisForReaction: "從反應複寫設定"
+overwriteFromPinnedEmojis: "從一般複寫設定"
reactionSettingDescription2: "拖動以交換,點擊以刪除,按下「+」以新增。"
rememberNoteVisibility: "記住貼文可見性"
attachCancel: "移除附件"
+deleteFile: "刪除檔案"
markAsSensitive: "標記為敏感內容"
unmarkAsSensitive: "取消標記為敏感內容"
enterFileName: "請輸入檔案名稱"
@@ -261,6 +267,7 @@ removed: "已刪除"
removeAreYouSure: "確定要刪掉「{x}」嗎?"
deleteAreYouSure: "確定要刪掉「{x}」嗎?"
resetAreYouSure: "確定要重設嗎?"
+areYouSure: "是否確定?"
saved: "已儲存"
messaging: "聊天"
upload: "上傳"
@@ -292,13 +299,13 @@ birthday: "生日"
yearsOld: "{age} 歲"
registeredDate: "註冊日期"
location: "位置"
-theme: "外觀主題"
-themeForLightMode: "在淺色模式下使用的主題"
-themeForDarkMode: "在深色模式下使用的主題"
+theme: "佈景主題"
+themeForLightMode: "在淺色模式下使用的佈景主題"
+themeForDarkMode: "在深色模式下使用的佈景主題"
light: "淺色"
dark: "深色"
-lightThemes: "淺色主題"
-darkThemes: "深色主題"
+lightThemes: "淺色佈景主題"
+darkThemes: "深色佈景主題"
syncDeviceDarkMode: "與設備的深色模式同步"
drive: "雲端硬碟"
fileName: "檔案名稱"
@@ -311,6 +318,7 @@ folderName: "資料夾名稱"
createFolder: "新增資料夾"
renameFolder: "重新命名資料夾"
deleteFolder: "刪除資料夾"
+folder: "資料夾"
addFile: "加入附件"
emptyDrive: "雲端硬碟為空"
emptyFolder: "資料夾為空"
@@ -372,6 +380,11 @@ hcaptcha: "hCaptcha"
enableHcaptcha: "啟用 hCaptcha"
hcaptchaSiteKey: "網站金鑰"
hcaptchaSecretKey: "金鑰"
+mcaptcha: "mCaptcha"
+enableMcaptcha: "啟用 mCaptcha"
+mcaptchaSiteKey: "網站金鑰"
+mcaptchaSecretKey: "金鑰"
+mcaptchaInstanceUrl: "mCaptcha 的實例網址"
recaptcha: "reCAPTCHA"
enableRecaptcha: "啟用 reCAPTCHA"
recaptchaSiteKey: "網站金鑰"
@@ -437,7 +450,6 @@ share: "分享"
notFound: "查無項目"
notFoundDescription: "查無此頁"
uploadFolder: "預設上傳資料夾"
-cacheClear: "清除快取"
markAsReadAllNotifications: "標記所有通知為已讀"
markAsReadAllUnreadNotes: "標記所有貼文為已讀"
markAsReadAllTalkMessages: "標記所有訊息為已讀"
@@ -544,6 +556,8 @@ showInPage: "在頁面中顯示"
popout: "彈出式視窗"
volume: "音量"
masterVolume: "主音量"
+notUseSound: "關閉音效"
+useSoundOnlyWhenActive: "瀏覽器在前景運作時,Misskey 才會發出音效"
details: "詳細資訊"
chooseEmoji: "選擇您的表情符號"
unableToProcess: "操作無法完成"
@@ -564,6 +578,10 @@ output: "輸出"
script: "腳本"
disablePagesScript: "停用頁面的 AiScript 腳本"
updateRemoteUser: "更新遠端使用者資訊"
+unsetUserAvatar: "移除使用者的大頭貼"
+unsetUserAvatarConfirm: "確定要移除使用者的大頭貼嗎?"
+unsetUserBanner: "移除使用者的橫幅圖像"
+unsetUserBannerConfirm: "確定要移除使用者的橫幅圖像嗎?"
deleteAllFiles: "刪除所有檔案"
deleteAllFilesConfirm: "要刪除所有檔案嗎?"
removeAllFollowing: "解除所有追隨"
@@ -580,21 +598,21 @@ menu: "選單"
divider: "分隔線"
addItem: "新增項目"
rearrange: "排序方式"
-relays: "中繼"
-addRelay: "新增中繼"
+relays: "中繼器"
+addRelay: "新增中繼器"
inboxUrl: "收件夾URL"
-addedRelays: "已加入的中繼"
+addedRelays: "已加入的中繼器"
serviceworkerInfo: "如要使用推播通知,需要啟用此選項並設定金鑰。"
deletedNote: "已刪除的貼文"
-invisibleNote: "私密的貼文"
+invisibleNote: "私人貼文"
enableInfiniteScroll: "啟用自動滾動頁面模式"
visibility: "可見性"
-poll: "投票"
+poll: "票選活動"
useCw: "隱藏內容"
enablePlayer: "開啟播放器"
disablePlayer: "關閉播放器"
expandTweet: "展開推文"
-themeEditor: "主題編輯器"
+themeEditor: "佈景主題編輯器"
description: "描述"
describeFile: "新增標題"
enterFileDescription: "輸入標題"
@@ -614,17 +632,18 @@ medium: "中"
small: "小"
generateAccessToken: "發行存取權杖"
permission: "權限"
+adminPermission: "管理員權限"
enableAll: "啟用全部"
disableAll: "停用全部"
tokenRequested: "允許存取帳戶"
pluginTokenRequestedDescription: "此外掛將擁有在此設定的權限。"
notificationType: "通知形式"
edit: "編輯"
-emailServer: "電郵伺服器"
-enableEmail: "啟用發送電郵功能"
-emailConfigInfo: "用於確認電郵地址及密碼重置"
+emailServer: "電子郵件伺服器"
+enableEmail: "啟用發送電子郵件功能"
+emailConfigInfo: "用於確認電子郵件地址及密碼重置"
email: "電子郵件"
-emailAddress: "電郵地址"
+emailAddress: "電子郵件位址"
smtpConfig: "SMTP 伺服器設定"
smtpHost: "主機"
smtpPort: "埠"
@@ -635,6 +654,7 @@ smtpSecure: "在 SMTP 連接中使用隱式 SSL/TLS"
smtpSecureInfo: "使用 STARTTLS 時關閉。"
testEmail: "測試郵件發送"
wordMute: "被靜音的文字"
+hardWordMute: "硬文字靜音"
regexpError: "正規表達式錯誤"
regexpErrorDescription: "{tab} 靜音文字的第 {line} 行的正規表達式有錯誤:"
instanceMute: "被靜音的實例"
@@ -656,6 +676,7 @@ useGlobalSettingDesc: "啟用時,將使用帳戶通知設定。停用時,則
other: "其他"
regenerateLoginToken: "重新產生登入權杖"
regenerateLoginTokenDescription: "重新產生用於登入的內部權杖。一般情況下是不需要這樣做的。重新產生後,所有裝置將會被登出。"
+theKeywordWhenSearchingForCustomEmoji: "這是搜尋自訂表情符號時的關鍵字"
setMultipleBySeparatingWithSpace: "您可以使用空格分隔多個項目。"
fileIdOrUrl: "檔案 ID 或 URL"
behavior: "行為"
@@ -669,7 +690,7 @@ abuseReported: "檢舉完成。感謝您的報告。"
reporter: "檢舉者"
reporteeOrigin: "檢舉來源"
reporterOrigin: "檢舉者來源"
-forwardReport: "將報告轉送給遠端實例"
+forwardReport: "將報告轉送給遠端伺服器"
forwardReportIsAnonymous: "在遠端實例上看不到您的資訊,顯示的報告者是匿名的系统帳戶。"
send: "發送"
abuseMarkAsResolved: "處理完畢"
@@ -677,7 +698,7 @@ openInNewTab: "在新分頁中開啟"
openInSideView: "在側欄中開啟"
defaultNavigationBehaviour: "預設導航"
editTheseSettingsMayBreakAccount: "修改這些設定可能會毀損您的帳戶"
-instanceTicker: "貼文的實例來源"
+instanceTicker: "貼文的伺服器資訊"
waitingFor: "等待{x}"
random: "隨機"
system: "系統"
@@ -718,7 +739,7 @@ disableShowingAnimatedImages: "不播放動態圖檔"
highlightSensitiveMedia: "強調敏感標記"
verificationEmailSent: "已發送驗證電子郵件。請點擊進入電子郵件中的鏈接完成驗證。"
notSet: "未設定"
-emailVerified: "已成功驗證您的電郵"
+emailVerified: "已成功驗證您的電子郵件地址"
noteFavoritesCount: "我的最愛貼文的數目"
pageLikesCount: "頁面被按讚次數"
pageLikedCount: "頁面被按讚次數"
@@ -770,11 +791,11 @@ capacity: "容量"
inUse: "已使用"
editCode: "編輯代碼"
apply: "套用"
-receiveAnnouncementFromInstance: "接收由本實例發出的電郵通知"
+receiveAnnouncementFromInstance: "接收來自伺服器的通知"
emailNotification: "郵件通知"
publish: "發布"
inChannelSearch: "頻道内搜尋"
-useReactionPickerForContextMenu: "點擊右鍵開啟反應工具欄"
+useReactionPickerForContextMenu: "點擊右鍵開啟反應選擇器"
typingUsers: "{users}輸入中"
jumpToSpecifiedDate: "跳轉到特定日期"
showingPastTimeline: "顯示過往的時間軸"
@@ -798,7 +819,7 @@ active: "最近活躍"
offline: "離線"
notRecommended: "不推薦"
botProtection: "Bot 防護"
-instanceBlocking: "已封鎖的實例"
+instanceBlocking: "已封鎖或禁言的伺服器"
selectAccount: "選擇帳戶"
switchAccount: "切換帳戶"
enabled: "已啟用"
@@ -831,7 +852,7 @@ previewNoteText: "預覽文本"
customCss: "自定義 CSS"
customCssWarn: "這個設定必須由具備相關知識的人員操作,不當的設定可能導致客戶端無法正常使用。"
global: "全域"
-squareAvatars: "頭像以方形顯示"
+squareAvatars: "大頭貼以方形顯示"
sent: "發送"
received: "收取"
searchResult: "搜尋結果"
@@ -868,8 +889,8 @@ makeReactionsPublicDescription: "將您做過的反應設為公開可見。"
classic: "經典"
muteThread: "將貼文串設為靜音"
unmuteThread: "將貼文串的靜音解除"
-ffVisibility: "連繫的可見性"
-ffVisibilityDescription: "您可以設定追隨或追隨者資訊的公開範圍"
+followingVisibility: "追隨中的可見性"
+followersVisibility: "追隨者的可見性"
continueThread: "查看更多貼文"
deleteAccountConfirm: "將要刪除帳戶。是否確定?"
incorrectPassword: "密碼錯誤。"
@@ -882,13 +903,13 @@ overridedDeviceKind: "裝置類型"
smartphone: "智慧型手機"
tablet: "平板"
auto: "自動"
-themeColor: "主題顏色"
+themeColor: "佈景主題顏色"
size: "大小"
numberOfColumn: "列數"
searchByGoogle: "搜尋"
-instanceDefaultLightTheme: "實例預設的淺色主題"
-instanceDefaultDarkTheme: "實例預設的深色主題"
-instanceDefaultThemeDescription: "輸入物件形式的主題代碼"
+instanceDefaultLightTheme: "實例預設的淺色佈景主題"
+instanceDefaultDarkTheme: "實例預設的深色佈景主題"
+instanceDefaultThemeDescription: "輸入物件形式的佈景主題代碼"
mutePeriod: "靜音的期限"
period: "期限"
indefinitely: "無期限"
@@ -941,8 +962,8 @@ cannotUploadBecauseNoFreeSpace: "由於雲端硬碟沒有可用空間,因此
cannotUploadBecauseExceedsFileSizeLimit: "由於超過了檔案大小的限制,無法上傳。"
beta: "測試版"
enableAutoSensitive: "自動 NSFW 判定"
-enableAutoSensitiveDescription: "如果可用,它將使用機器學習技術判斷檔案是否需要標記為敏感。即使關閉此功能,也可能會依實例規則而自動啟用。"
-activeEmailValidationDescription: "積極驗證使用者的電郵地址,以判斷它是否可以通訊。關閉此選項代表只會檢查地址是否符合格式。"
+enableAutoSensitiveDescription: "如果可行,它將使用機器學習技術判斷檔案是否需要標記為敏感。即使關閉此功能,也可能會依伺服器規則而自動啟用。"
+activeEmailValidationDescription: "主動地驗證使用者的電子郵件地址,以確定是否是一次性地址以及是否可以真正與其進行通訊。關閉時,僅檢查格式是否正確。"
navbar: "導覽列"
shuffle: "隨機"
account: "帳戶"
@@ -951,7 +972,7 @@ pushNotification: "推播通知"
subscribePushNotification: "啟用推播通知"
unsubscribePushNotification: "停用推播通知"
pushNotificationAlreadySubscribed: "推播通知啟用中"
-pushNotificationNotSupported: "瀏覽器或實例不支援推播通知"
+pushNotificationNotSupported: "瀏覽器或伺服器不支援推播通知"
sendPushNotificationReadMessage: "如果已閱讀通知與訊息,就刪除推播通知"
sendPushNotificationReadMessageCaption: "「{emptyPushNotificationMessage}」通知將立刻顯示。可能會更消耗裝置電池。"
windowMaximize: "最大化"
@@ -970,6 +991,7 @@ neverShow: "不再顯示"
remindMeLater: "以後再說"
didYouLikeMisskey: "您喜歡 Misskey 嗎?"
pleaseDonate: "Misskey 是由 {host} 使用的免費軟體。請贊助我們,讓開發得以持續!"
+correspondingSourceIsAvailable: "對應的原始碼可以在 {anchor} 處找到。"
roles: "角色"
role: "角色"
noRole: "沒有角色"
@@ -1020,6 +1042,11 @@ resetPasswordConfirm: "重設密碼?"
sensitiveWords: "敏感詞"
sensitiveWordsDescription: "將含有設定詞彙的貼文可見性設為發送至首頁。可以用換行來進行複數的設定。"
sensitiveWordsDescription2: "空格代表「以及」(AND),斜線包圍關鍵字代表使用正規表達式。"
+prohibitedWords: "禁語"
+prohibitedWordsDescription: "當要發布包含禁語的貼文時,會出現錯誤。可以用換行分隔來設定多個禁語。"
+prohibitedWordsDescription2: "空格代表「以及」(AND),斜線包圍關鍵字代表使用正規表達式。"
+hiddenTags: "隱藏標籤"
+hiddenTagsDescription: "設定的標籤不會在趨勢中顯示,換行可以設定多個標籤。"
notesSearchNotAvailable: "無法使用搜尋貼文功能。"
license: "授權"
unfavoriteConfirm: "要取消收錄我的最愛嗎?"
@@ -1032,9 +1059,12 @@ enableChartsForRemoteUser: "生成遠端使用者的圖表"
enableChartsForFederatedInstances: "生成遠端伺服器的圖表"
showClipButtonInNoteFooter: "新增摘錄按鈕至貼文"
reactionsDisplaySize: "反應的顯示尺寸"
+limitWidthOfReaction: "限制反應的最大寬度,並縮小顯示尺寸。"
noteIdOrUrl: "貼文ID或URL"
video: "影片"
videos: "影片"
+audio: "音效"
+audioFiles: "音效檔案"
dataSaver: "數據節省模式"
accountMigration: "遷移帳戶"
accountMoved: "這個使用者已遷移至新的帳戶:"
@@ -1130,6 +1160,7 @@ showRenotes: "顯示其他人的轉發貼文"
edited: "已編輯"
notificationRecieveConfig: "接受通知的設定"
mutualFollow: "互相追隨"
+followingOrFollower: "追隨中或追隨者"
fileAttachedOnly: "顯示包含附件的貼文"
showRepliesToOthersInTimeline: "顯示給其他人的回覆"
hideRepliesToOthersInTimeline: "在時間軸上隱藏給其他人的回覆"
@@ -1138,6 +1169,13 @@ hideRepliesToOthersInTimelineAll: "在時間軸不包含追隨中所有人的回
confirmShowRepliesAll: "進行此操作後無法復原。您真的希望時間軸「包含」您目前追隨的所有人的回覆嗎?"
confirmHideRepliesAll: "進行此操作後無法復原。您真的希望時間軸「不包含」您目前追隨的所有人的回覆嗎?"
externalServices: "外部服務"
+sourceCode: "原始碼"
+sourceCodeIsNotYetProvided: "尚未提供原始碼,請洽詢管理員解決這個問題。"
+repositoryUrl: "儲存庫 URL"
+repositoryUrlDescription: "如果存在可公開取得原始碼的儲存庫,請輸入其 URL。 如果您按原樣使用 Misskey(不對原始碼進行任何更改),請輸入 https://github.com/misskey-dev/misskey。"
+repositoryUrlOrTarballRequired: "如果儲存庫不是公開的,則必須提供 tarball。 詳細資訊請參閱 .config/example.yml。"
+feedback: "意見回饋"
+feedbackUrl: "意見回饋 URL"
impressum: "營運者資訊"
impressumUrl: "營運者資訊網址"
impressumDescription: "在德國與部份地區必須要明確顯示營運者資訊。"
@@ -1147,6 +1185,7 @@ tosAndPrivacyPolicy: "服務條款和隱私政策"
avatarDecorations: "頭像裝飾"
attach: "裝上"
detach: "取下"
+detachAll: "移除所有裝飾"
angle: "角度"
flip: "翻轉"
showAvatarDecorations: "顯示頭像裝飾"
@@ -1158,6 +1197,47 @@ useGroupedNotifications: "分組顯示通知訊息"
signupPendingError: "驗證您的電子郵件地址時出現問題。連結可能已過期。"
cwNotationRequired: "如果開啟「隱藏內容」,則需要註解說明。"
doReaction: "做出反應"
+code: "程式碼"
+reloadRequiredToApplySettings: "需要重新載入頁面設定才能生效。"
+remainingN: "剩餘:{n}"
+overwriteContentConfirm: "確定要覆蓋目前的內容嗎?"
+seasonalScreenEffect: "隨季節變換畫面的呈現"
+decorate: "設置頭像裝飾"
+addMfmFunction: "插入MFM功能語法"
+enableQuickAddMfmFunction: "顯示高級 MFM 選擇器"
+bubbleGame: "氣泡遊戲"
+sfx: "音效"
+soundWillBePlayed: "將播放音效"
+showReplay: "觀看重播"
+replay: "重播"
+replaying: "重播中"
+endReplay: "退出重播"
+copyReplayData: "複製重播資料"
+ranking: "排行榜"
+lastNDays: "過去 {n} 天"
+backToTitle: "回到遊戲標題頁"
+hemisphere: "您居住的地區"
+withSensitive: "顯示包含敏感檔案的貼文"
+userSaysSomethingSensitive: "包含 {name} 敏感檔案的貼文"
+enableHorizontalSwipe: "滑動切換時間軸"
+loading: "載入中"
+surrender: "退出"
+gameRetry: "再試一次"
+_bubbleGame:
+ howToPlay: "玩法說明"
+ hold: "保留"
+ _score:
+ score: "分數"
+ scoreYen: "賺取的金額"
+ highScore: "最高分"
+ maxChain: "最大結合數"
+ yen: "{yen} 日圓"
+ estimatedQty: "{qty}個"
+ scoreSweets: "飯糰 {onigiriQtyWithUnit}"
+ _howToPlay:
+ section1: "調整位置並將物體放入盒子中。"
+ section2: "當相同類型的物體黏在一起時,它們會變成不同的物體,您就會得到分數。"
+ section3: "如果物體從盒子裡溢出,遊戲就結束了。透過融合物體而不溢出盒子來獲得高分!"
_announcement:
forExistingUsers: "僅限既有的使用者"
forExistingUsersDescription: "啟用代表僅向現存使用者顯示;停用代表張貼後註冊的新使用者也會看到。"
@@ -1167,7 +1247,7 @@ _announcement:
tooManyActiveAnnouncementDescription: "有過多公告可能會影響使用者體驗。請考慮歸檔已結束的公告。"
readConfirmTitle: "標記為已讀嗎?"
readConfirmText: "閱讀「{title}」的內容並標記為已讀。"
- shouldNotBeUsedToPresentPermanentInfo: "由於可能會破壞使用者體驗,尤其是對於新使用者而言,我們建議使用公告來發布有時效性的資訊而不是固定不變的資訊。"
+ shouldNotBeUsedToPresentPermanentInfo: "為了避免損害新用戶的使用體驗,建議使用公告來發布即時性的訊息,而不是用於固定不變的資訊。"
dialogAnnouncementUxWarn: "如果同時有 2 個以上對話方塊形式的公告存在,對於使用者體驗很可能會有不良的影響,因此建議謹慎使用。"
silence: "不發送通知"
silenceDescription: "啟用此選項後,將不會發送此公告的通知,並且無需將其標記為已讀。"
@@ -1194,7 +1274,7 @@ _initialTutorial:
skipAreYouSure: "結束教學模式?"
_landing:
title: "歡迎使用本教學課程"
- description: "在這裡您可以查看Misskey的基本使用方法和功能。"
+ description: "在這裡您可以查看 Misskey 的基本使用方法和功能。"
_note:
title: "什麼是貼文?"
description: "在Misskey上發布的內容稱為「貼文」。貼文在時間軸上按時間順序排列,並即時更新。"
@@ -1476,7 +1556,7 @@ _achievements:
description: "首頁時間軸在一分鐘內出現超過二十篇貼文"
_viewInstanceChart:
title: "分析師"
- description: "顯示了實例的圖表"
+ description: "顯示了伺服器的圖表"
_outputHelloWorldOnScratchpad:
title: "Hello, world!"
description: "在 AiScript 控制臺輸出了「hello world」"
@@ -1528,17 +1608,26 @@ _achievements:
_tutorialCompleted:
title: "Misskey新手講座 結業證書"
description: "已完成教學課程"
+ _bubbleGameExplodingHead:
+ title: "🤯"
+ description: "氣泡遊戲中最大的物體出現了"
+ _bubbleGameDoubleExplodingHead:
+ title: "雙重🤯"
+ description: "氣泡遊戲中最大的物體同時出現了兩個"
+ flavor: "這樣大小的便當盒,用 🤯 🤯 稍微裝滿一些吧"
_role:
new: "建立角色"
edit: "編輯角色"
name: "角色名稱"
description: "角色描述 "
permission: "角色的權限"
- descriptionOfPermission: "審查員執行與審查相關的基本操作。\n管理員能變更實例的全部設定"
+ descriptionOfPermission: "審查員執行與審查相關的基本操作。\n管理員能變更伺服器的全部設定。"
assignTarget: "指派目標"
descriptionOfAssignTarget: "手動是以手動管理這個角色包含的人員。\n符合條件是設定條件以自動包含符合條件的使用者。"
manual: "手動"
+ manualRoles: "手動角色"
conditional: "符合條件"
+ conditionalRoles: "有條件的角色"
condition: "條件"
isConditionalRole: "這是條件角色。"
isPublic: "角色為公開"
@@ -1548,7 +1637,7 @@ _role:
baseRole: "基本角色"
useBaseValue: "使用基本角色的值"
chooseRoleToAssign: "選擇要指派的角色"
- iconUrl: "圖示的URL"
+ iconUrl: "圖示的 URL"
asBadge: "顯示為徽章"
descriptionOfAsBadge: "開啟的話,角色圖示會顯示在使用者名稱旁邊。"
isExplorable: "讓使用者更容易找到您"
@@ -1566,7 +1655,8 @@ _role:
gtlAvailable: "瀏覽全域時間軸"
ltlAvailable: "瀏覽本地時間軸"
canPublicNote: "允許公開貼文"
- canInvite: "發行實例邀請碼"
+ mentionMax: "貼文內的最大提及數"
+ canInvite: "發行伺服器邀請碼"
inviteLimit: "可建立邀請碼的數量"
inviteLimitCycle: "邀請碼的發放間隔"
inviteExpirationTime: "邀請碼的有效日期"
@@ -1587,7 +1677,9 @@ _role:
canHideAds: "不顯示廣告"
canSearchNotes: "可否搜尋貼文"
canUseTranslator: "使用翻譯功能"
+ avatarDecorationLimit: "頭像裝飾的最大設置量"
_condition:
+ roleAssignedTo: "手動指派角色完成"
isLocal: "本地使用者"
isRemote: "遠端使用者"
createdLessThan: "帳戶加入時間不超過"
@@ -1615,6 +1707,7 @@ _emailUnavailable:
disposable: "不是永久可用的地址"
mx: "郵件伺服器不正確"
smtp: "郵件伺服器沒有應答"
+ banned: "無法使用此電子郵件地址註冊"
_ffVisibility:
public: "公開"
followers: "只有關注您的使用者能看到"
@@ -1642,7 +1735,7 @@ _ad:
_forgotPassword:
enterEmail: "請輸入您的帳戶註冊的電子郵件地址。 密碼重置連結將被發送到該電子郵件地址。"
ifNoEmail: "如果您還沒有註冊您的電子郵件地址,請聯繫管理員。 "
- contactAdmin: "此實例不支持電子郵件,請聯繫您的管理員重置您的密碼。 "
+ contactAdmin: "本伺服器不支援電子郵件,請聯繫您的管理員重置您的密碼。 "
_gallery:
my: "我的貼文"
liked: "喜歡的貼文"
@@ -1687,6 +1780,8 @@ _aboutMisskey:
contributors: "主要貢獻者"
allContributors: "全體貢獻人員"
source: "原始碼"
+ original: "原始"
+ thisIsModifiedVersion: "{name} 使用原始 Misskey 的修改版本。"
translation: "翻譯 Misskey"
donate: "贊助 Misskey"
morePatrons: "還有許許多多幫助我們的其他人,非常感謝你們。 🥰"
@@ -1729,20 +1824,20 @@ _wordMute:
_instanceMute:
instanceMuteDescription: "包括對被靜音伺服器上的使用者的回覆,被設定的伺服器上所有貼文及轉發都會被靜音。"
instanceMuteDescription2: "設定時以換行進行分隔"
- title: "將隱藏被設定的實例貼文。"
- heading: "將實例靜音"
+ title: "將隱藏被設定的伺服器貼文。"
+ heading: "將伺服器靜音"
_theme:
- explore: "取得佈景主題"
+ explore: "探索佈景主題"
install: "安裝佈景主題"
- manage: "佈景主題管理員"
- code: "主題代碼"
+ manage: "管理佈景主題"
+ code: "佈景主題代碼"
description: "描述"
installed: "{name}已安裝"
- installedThemes: "已經安裝的主題"
- builtinThemes: "標準主題"
- alreadyInstalled: "此主題已經安裝"
- invalid: "主題格式錯誤"
- make: "製作主題"
+ installedThemes: "已經安裝的佈景主題"
+ builtinThemes: "標準佈景主題"
+ alreadyInstalled: "已安裝此佈景主題"
+ invalid: "佈景主題格式錯誤"
+ make: "製作佈景主題"
base: "基於"
addConstant: "添加常數"
constant: "常數"
@@ -1759,7 +1854,7 @@ _theme:
darken: "暗度"
lighten: "亮度"
inputConstantName: "請輸入常數名稱"
- importInfo: "您可以在此貼上主題代碼,將其匯入編輯器中"
+ importInfo: "您可以在此貼上佈景主題代碼,將其匯入編輯器中"
deleteConstantConfirm: "確定要刪除常數{const}嗎?"
keys:
accent: "重點色彩"
@@ -1808,6 +1903,14 @@ _sfx:
notification: "通知"
antenna: "天線接收"
channel: "頻道通知"
+ reaction: "選擇反應時"
+_soundSettings:
+ driveFile: "使用雲端硬碟的音效檔案"
+ driveFileWarn: "請選擇雲端硬碟中的檔案"
+ driveFileTypeWarn: "不支援此檔案"
+ driveFileTypeWarnDescription: "請選擇音效檔案"
+ driveFileDurationWarn: "音效太長了"
+ driveFileDurationWarnDescription: "使用長音效檔可能會影響 Misskey 的使用體驗。仍要使用此檔案嗎?"
_ago:
future: "未來"
justNow: "剛剛"
@@ -1890,14 +1993,63 @@ _permissions:
"write:user-groups": "編輯使用者群組"
"read:channels": "已查看的頻道"
"write:channels": "編輯頻道"
- "read:gallery": "瀏覽圖庫"
- "write:gallery": "操作圖庫"
- "read:gallery-likes": "讀取喜歡的圖片"
- "write:gallery-likes": "操作喜歡的圖片"
+ "read:gallery": "瀏覽相簿"
+ "write:gallery": "編輯相簿"
+ "read:gallery-likes": "瀏覽相簿的讚"
+ "write:gallery-likes": "編輯相簿的讚"
"read:flash": "檢視 Play"
"write:flash": "編輯 Play"
"read:flash-likes": "檢視 Play 的讚"
"write:flash-likes": "編輯 Play 的讚"
+ "read:admin:abuse-user-reports": "查看來自使用者的檢舉"
+ "write:admin:delete-account": "刪除使用者帳戶"
+ "write:admin:delete-all-files-of-a-user": "刪除使用者的所有檔案"
+ "read:admin:index-stats": "查看資料庫索引的相關資訊"
+ "read:admin:table-stats": "查看資料庫表格的相關資訊"
+ "read:admin:user-ips": "查看使用者的 IP 位址"
+ "read:admin:meta": "查看實例的元資料"
+ "write:admin:reset-password": "重設使用者的密碼"
+ "write:admin:resolve-abuse-user-report": "解決來自使用者的檢舉"
+ "write:admin:send-email": "發送郵件"
+ "read:admin:server-info": "查看伺服器的資訊"
+ "read:admin:show-moderation-log": "查看審查紀錄"
+ "read:admin:show-user": "查看使用者的私密資訊"
+ "read:admin:show-users": "查看使用者的私密資訊"
+ "write:admin:suspend-user": "凍結使用者"
+ "write:admin:unset-user-avatar": "刪除使用者的頭像"
+ "write:admin:unset-user-banner": "刪除使用者的橫幅"
+ "write:admin:unsuspend-user": "解除凍結使用者"
+ "write:admin:meta": "編輯實例的元資料"
+ "write:admin:user-note": "編輯審查筆記"
+ "write:admin:roles": "編輯角色"
+ "read:admin:roles": "查看角色"
+ "write:admin:relays": "編輯中繼器"
+ "read:admin:relays": "查看中繼器"
+ "write:admin:invite-codes": "編輯邀請碼"
+ "read:admin:invite-codes": "查看邀請碼"
+ "write:admin:announcements": "編輯公告"
+ "read:admin:announcements": "查看公告"
+ "write:admin:avatar-decorations": "編輯頭像裝飾"
+ "read:admin:avatar-decorations": "查看頭像裝飾"
+ "write:admin:federation": "編輯站台聯邦的相關資訊"
+ "write:admin:account": "編輯使用者帳戶"
+ "read:admin:account": "查看使用者的相關資訊"
+ "write:admin:emoji": "編輯表情符號"
+ "read:admin:emoji": "查看表情符號"
+ "write:admin:queue": "編輯工作佇列"
+ "read:admin:queue": "查看工作佇列的相關資訊"
+ "write:admin:promo": "編輯推廣貼文"
+ "write:admin:drive": "編輯使用者的雲端硬碟"
+ "read:admin:drive": "查看使用者雲端硬碟的相關資訊"
+ "read:admin:stream": "使用管理員的 Websocket API"
+ "write:admin:ad": "編輯廣告"
+ "read:admin:ad": "查看廣告"
+ "write:invite-codes": "建立邀請碼"
+ "read:invite-codes": "取得邀請碼"
+ "write:clip-favorite": "編輯摘錄的讚"
+ "read:clip-favorite": "查看摘錄的讚"
+ "read:federation": "查看站台聯邦的相關資訊"
+ "write:report-abuse": "檢舉違規行為"
_auth:
shareAccessTitle: "應用程式的存取權限"
shareAccess: "要授權「“{name}”」存取您的帳戶嗎?"
@@ -1924,7 +2076,7 @@ _weekday:
saturday: "週六"
_widgets:
profile: "個人檔案"
- instanceInfo: "實例資訊"
+ instanceInfo: "伺服器資訊"
memo: "備忘錄"
notifications: "通知"
timeline: "時間軸"
@@ -1938,7 +2090,7 @@ _widgets:
digitalClock: "電子時鐘"
unixClock: "UNIX 時間"
federation: "聯邦宇宙"
- instanceCloud: "實例雲"
+ instanceCloud: "伺服器雲"
postForm: "發文視窗"
slideshow: "幻燈片"
button: "按鈕"
@@ -1952,6 +2104,7 @@ _widgets:
_userList:
chooseList: "選擇清單"
clicker: "點擊器"
+ birthdayFollowings: "今天生日的使用者"
_cw:
hide: "隱藏"
show: "顯示內容"
@@ -1961,7 +2114,7 @@ _poll:
noOnlyOneChoice: "需要至少兩個選項。"
choiceN: "選項 {n}"
noMore: "沒辦法再添加選項了"
- canMultipleVote: "可以多次投票"
+ canMultipleVote: "允許複選"
expiration: "期限"
infinite: "無期限"
at: "結束時間"
@@ -1970,7 +2123,7 @@ _poll:
deadlineTime: "小時"
duration: "時長"
votesCount: "{n} 票"
- totalVotes: "合共 {n} 票"
+ totalVotes: "合計 {n} 票"
vote: "投票"
showResult: "顯示結果"
voted: "已投票"
@@ -1989,7 +2142,7 @@ _visibility:
specified: "指定使用者"
specifiedDescription: "僅發布至指定使用者"
disableFederation: "停用聯邦"
- disableFederationDescription: "不要傳遞給其他實例"
+ disableFederationDescription: "不發送到其他伺服器"
_postForm:
replyPlaceholder: "回覆此貼文..."
quotePlaceholder: "引用此貼文..."
@@ -2014,9 +2167,11 @@ _profile:
changeAvatar: "更換大頭貼"
changeBanner: "變更橫幅圖像"
verifiedLinkDescription: "如果輸入包含您個人資料的網站 URL,欄位旁邊將出現驗證圖示。"
+ avatarDecorationMax: "最多可以設置 {max} 個裝飾。"
_exportOrImport:
allNotes: "所有貼文"
favoritedNotes: "「我的最愛」貼文"
+ clips: "摘錄"
followingList: "追隨中"
muteList: "靜音"
blockingList: "封鎖"
@@ -2028,7 +2183,7 @@ _charts:
federation: "聯邦宇宙"
apRequest: "請求"
usersIncDec: "使用者增減"
- usersTotal: "使用者合共"
+ usersTotal: "使用者總數"
activeUsers: "活躍使用者"
notesIncDec: "貼文増減"
localNotesIncDec: "本地貼文増減"
@@ -2135,6 +2290,7 @@ _notification:
pollEnded: "問卷調查已產生結果"
newNote: "新的貼文"
unreadAntennaNote: "天線 {name}"
+ roleAssigned: "已授予角色"
emptyPushNotificationMessage: "推送通知已更新"
achievementEarned: "獲得成就"
testNotification: "通知測試"
@@ -2144,6 +2300,7 @@ _notification:
reactedBySomeUsers: "{n}人做出了反應"
renotedBySomeUsers: "{n}人做了轉發"
followedBySomeUsers: "被{n}人追隨了"
+ flushNotification: "重置通知歷史紀錄"
_types:
all: "全部 "
note: "使用者的最新貼文"
@@ -2156,6 +2313,7 @@ _notification:
pollEnded: "問卷調查結束"
receiveFollowRequest: "已收到追隨請求"
followRequestAccepted: "追隨請求已接受"
+ roleAssigned: "已授予角色"
achievementEarned: "獲得成就"
app: "應用程式通知"
_actions:
@@ -2228,7 +2386,7 @@ _moderationLogTypes:
updateCustomEmoji: "更新自訂表情符號"
deleteCustomEmoji: "刪除自訂表情符號"
updateServerSettings: "更新伺服器設定"
- updateUserNote: "更新管理筆記"
+ updateUserNote: "更新了使用者的管理筆記"
deleteDriveFile: "刪除檔案"
deleteNote: "刪除貼文"
createGlobalAnnouncement: "建立全網通知"
@@ -2240,6 +2398,7 @@ _moderationLogTypes:
resetPassword: "重設密碼"
suspendRemoteInstance: "封鎖遠端伺服器"
unsuspendRemoteInstance: "解除封鎖遠端伺服器"
+ updateRemoteInstanceNote: "更新了遠端伺服器的管理筆記"
markSensitiveDriveFile: "標記為敏感檔案"
unmarkSensitiveDriveFile: "撤銷標記為敏感檔案"
resolveAbuseReport: "解決檢舉"
@@ -2250,6 +2409,8 @@ _moderationLogTypes:
createAvatarDecoration: "建立頭像裝飾"
updateAvatarDecoration: "更新頭像裝飾"
deleteAvatarDecoration: "刪除頭像裝飾"
+ unsetUserAvatar: "移除使用者的大頭貼"
+ unsetUserBanner: "移除使用者的橫幅圖像"
_fileViewer:
title: "檔案詳細資訊"
type: "檔案類型 "
@@ -2265,8 +2426,8 @@ _externalResourceInstaller:
title: "要安裝此外掛嘛?"
metaTitle: "外掛資訊"
_theme:
- title: "要安裝此外觀主題嘛?"
- metaTitle: "外觀主題資訊"
+ title: "要安裝此佈景主題嗎?"
+ metaTitle: "佈景主題資訊"
_meta:
base: "基本配色方案"
_vendorInfo:
@@ -2294,8 +2455,73 @@ _externalResourceInstaller:
title: "外掛安裝失敗"
description: "安裝插件時出現問題。請再試一次。請參閱 Javascript 控制台以取得錯誤詳細資訊。"
_themeParseFailed:
- title: "外觀主題解析錯誤"
- description: "已取得資料但解析外觀主題時發生錯誤,導致無法載入。請聯絡主題作者。請檢查 Javascript 控制台以取得錯誤詳細資訊。"
+ title: "佈景主題解析錯誤"
+ description: "已取得資料但解析佈景主題時發生錯誤,導致無法載入。請聯絡佈景主題的作者。請檢查 Javascript 控制台以取得錯誤詳細資訊。"
_themeInstallFailed:
- title: "無法安裝外觀主題"
- description: "安裝外觀主題時出現問題。請再試一次。請參閱 Javascript 控制台以取得錯誤詳細資訊。"
+ title: "無法安裝佈景主題"
+ description: "安裝佈景主題時出現問題。請再試一次。請參閱 Javascript 控制台以取得錯誤詳細資訊。"
+_dataSaver:
+ _media:
+ title: "載入媒體檔案"
+ description: "防止自動載入圖片和影片。點擊隱藏的圖片/影片即可載入。"
+ _avatar:
+ title: "大頭貼"
+ description: "停止顯示大頭貼的動畫。由於動畫圖片的檔案大小可能比普通圖片大,這可以進一步減少資料流量。"
+ _urlPreview:
+ title: "網址預覽縮圖"
+ description: "將不再自動載入網址預覽縮圖。"
+ _code:
+ title: "程式碼突出顯示"
+ description: "如果使用了 MFM 的程式碼突顯標記,則在點擊之前不會載入。程式碼突顯要求加載每種程式語言的突顯定義檔案,但由於這些檔案不再自動載入,因此有望減少資料流量。"
+_hemisphere:
+ N: "北半球"
+ S: "南半球"
+ caption: "在某些客戶端的設定中,用於判斷季節。"
+_reversi:
+ reversi: "黑白棋"
+ gameSettings: "對弈設定"
+ chooseBoard: "選擇棋盤"
+ blackOrWhite: "先手/後手"
+ blackIs: "{name} 為黑棋(先攻)"
+ rules: "規則"
+ thisGameIsStartedSoon: "對弈即將開始"
+ waitingForOther: "等待對手準備就緒"
+ waitingForMe: "等待您準備就緒"
+ waitingBoth: "請準備"
+ ready: "準備就緒"
+ cancelReady: "重新準備"
+ opponentTurn: "對手的回合"
+ myTurn: "您的回合"
+ turnOf: "{name} 的回合"
+ pastTurnOf: "{name} 的回合"
+ surrender: "認輸"
+ surrendered: "對手認輸"
+ timeout: "時間到"
+ drawn: "平手"
+ won: "{name} 獲勝"
+ black: "黑"
+ white: "白"
+ total: "合計"
+ turnCount: "{count} 回合"
+ myGames: "我的對弈"
+ allGames: "所有對弈"
+ ended: "已結束"
+ playing: "正在對弈"
+ isLlotheo: "子較少的一方為勝(顛倒規則)"
+ loopedMap: "循環棋盤"
+ canPutEverywhere: "隨意置放模式"
+ timeLimitForEachTurn: "每回合的時間限制"
+ freeMatch: "自由對戰"
+ lookingForPlayer: "正在搜尋對手"
+ gameCanceled: "對弈已被取消"
+ shareToTlTheGameWhenStart: "在遊戲開始時將對弈資訊發布到時間軸"
+ iStartedAGame: "對弈開始了! #MisskeyReversi"
+ opponentHasSettingsChanged: "對手更改了設定"
+ allowIrregularRules: "允許異常規則(完全自由)"
+ disallowIrregularRules: "不允許異常規則"
+ showBoardLabels: "在棋盤上顯示行、列號"
+ useAvatarAsStone: "用大頭貼當作棋子"
+_offlineScreen:
+ title: "離線-無法連接伺服器"
+ header: "無法連接伺服器"
+
diff --git a/misskey-assets b/misskey-assets
deleted file mode 160000
index 0179793ec..000000000
--- a/misskey-assets
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 0179793ec891856d6f37a3be16ba4c22f67a81b5
diff --git a/package.json b/package.json
index f51861401..f531b2f10 100644
--- a/package.json
+++ b/package.json
@@ -1,16 +1,19 @@
{
"name": "misskey",
- "version": "2023.11.1",
+ "version": "2024.3.1-io.1c",
"codename": "nasubi",
"repository": {
"type": "git",
- "url": "https://github.com/misskey-dev/misskey.git"
+ "url": "https://github.com/MisskeyIO/misskey.git"
},
- "packageManager": "pnpm@8.10.5",
+ "packageManager": "pnpm@8.15.4",
"workspaces": [
"packages/frontend",
"packages/backend",
- "packages/sw"
+ "packages/sw",
+ "packages/misskey-js",
+ "packages/misskey-reversi",
+ "packages/misskey-bubble-game"
],
"private": true,
"scripts": {
@@ -18,15 +21,18 @@
"build-assets": "node ./scripts/build-assets.mjs",
"build": "pnpm build-pre && pnpm -r build && pnpm build-assets",
"build-storybook": "pnpm --filter frontend build-storybook",
+ "build-misskey-js-with-types": "pnpm build-pre && pnpm --filter backend... --filter=!misskey-js build && pnpm --filter backend generate-api-json && ncp packages/backend/built/api.json packages/misskey-js/generator/api.json && pnpm --filter misskey-js update-autogen-code && pnpm --filter misskey-js build && pnpm --filter misskey-js api",
"start": "pnpm check:connect && cd packages/backend && node ./built/boot/entry.js",
+ "start:docker": "pnpm check:connect && cd packages/backend && exec node ./built/boot/entry.js",
"start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/entry.js",
"init": "pnpm migrate",
"migrate": "cd packages/backend && pnpm migrate",
"revert": "cd packages/backend && pnpm revert",
"check:connect": "cd packages/backend && pnpm check:connect",
"migrateandstart": "pnpm migrate && pnpm start",
+ "migrateandstart:docker": "pnpm migrate && exec pnpm start:docker",
"watch": "pnpm dev",
- "dev": "node ./scripts/dev.mjs",
+ "dev": "node scripts/dev.mjs",
"lint": "pnpm -r lint",
"cy:open": "pnpm cypress open --browser --e2e --config-file=cypress.config.ts",
"cy:run": "pnpm cypress run",
@@ -40,26 +46,29 @@
"cleanall": "pnpm clean-all"
},
"resolutions": {
- "chokidar": "3.5.3",
- "lodash": "4.17.21"
+ "@tensorflow/tfjs-core": "4.17.0",
+ "chokidar": "3.6.0",
+ "lodash": "4.17.21",
+ "sharp": "0.33.2"
},
"dependencies": {
+ "cssnano": "6.1.0",
"execa": "8.0.1",
- "cssnano": "6.0.1",
"js-yaml": "4.1.0",
- "postcss": "8.4.31",
- "terser": "5.24.0",
- "typescript": "5.3.2"
+ "postcss": "8.4.35",
+ "terser": "5.29.2",
+ "typescript": "5.4.2"
},
"devDependencies": {
- "@typescript-eslint/eslint-plugin": "6.11.0",
- "@typescript-eslint/parser": "6.11.0",
+ "@typescript-eslint/eslint-plugin": "7.2.0",
+ "@typescript-eslint/parser": "7.2.0",
"cross-env": "7.0.3",
- "cypress": "13.5.1",
- "eslint": "8.53.0",
+ "cypress": "13.7.0",
+ "eslint": "8.57.0",
+ "ncp": "2.0.0",
"start-server-and-test": "2.0.3"
},
"optionalDependencies": {
- "@tensorflow/tfjs-core": "4.4.0"
+ "@tensorflow/tfjs-core": "4.17.0"
}
}
diff --git a/packages/backend/.swcrc b/packages/backend/.swcrc
index d9f047b6a..0504a2d38 100644
--- a/packages/backend/.swcrc
+++ b/packages/backend/.swcrc
@@ -11,7 +11,7 @@
"decoratorMetadata": true
},
"experimental": {
- "keepImportAttributes": true
+ "keepImportAssertions": true
},
"baseUrl": "src",
"paths": {
diff --git a/packages/backend/check_connect.js b/packages/backend/check_connect.js
index ea988a7f6..d88e649c0 100644
--- a/packages/backend/check_connect.js
+++ b/packages/backend/check_connect.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/generate_api_json.js b/packages/backend/generate_api_json.js
index 5819c60a5..602ced1d7 100644
--- a/packages/backend/generate_api_json.js
+++ b/packages/backend/generate_api_json.js
@@ -1,8 +1,13 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
import { loadConfig } from './built/config.js'
import { genOpenapiSpec } from './built/server/api/openapi/gen-spec.js'
import { writeFileSync } from "node:fs";
const config = loadConfig();
-const spec = genOpenapiSpec(config);
+const spec = genOpenapiSpec(config, true);
-writeFileSync('./built/api.json', JSON.stringify(spec), 'utf-8');
\ No newline at end of file
+writeFileSync('./built/api.json', JSON.stringify(spec), 'utf-8');
diff --git a/packages/backend/jest.config.cjs b/packages/backend/jest.config.cjs
index 97d777c86..5a4aa4e15 100644
--- a/packages/backend/jest.config.cjs
+++ b/packages/backend/jest.config.cjs
@@ -160,7 +160,6 @@ module.exports = {
testMatch: [
"/test/unit/**/*.ts",
"/src/**/*.test.ts",
- "/test/e2e/**/*.ts",
],
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
diff --git a/packages/backend/jest.config.e2e.cjs b/packages/backend/jest.config.e2e.cjs
new file mode 100644
index 000000000..4502da47d
--- /dev/null
+++ b/packages/backend/jest.config.e2e.cjs
@@ -0,0 +1,15 @@
+/*
+* For a detailed explanation regarding each configuration property and type check, visit:
+* https://jestjs.io/docs/en/configuration.html
+*/
+
+const base = require('./jest.config.cjs')
+
+module.exports = {
+ ...base,
+ globalSetup: "/built-test/entry.js",
+ setupFilesAfterEnv: ["/test/jest.setup.ts"],
+ testMatch: [
+ "/test/e2e/**/*.ts",
+ ],
+};
diff --git a/packages/backend/jest.config.unit.cjs b/packages/backend/jest.config.unit.cjs
new file mode 100644
index 000000000..aa5992936
--- /dev/null
+++ b/packages/backend/jest.config.unit.cjs
@@ -0,0 +1,14 @@
+/*
+* For a detailed explanation regarding each configuration property and type check, visit:
+* https://jestjs.io/docs/en/configuration.html
+*/
+
+const base = require('./jest.config.cjs')
+
+module.exports = {
+ ...base,
+ testMatch: [
+ "/test/unit/**/*.ts",
+ "/src/**/*.test.ts",
+ ],
+};
diff --git a/packages/backend/migration/1000000000000-Init.js b/packages/backend/migration/1000000000000-Init.js
index 6f04b52ae..c06885fd4 100644
--- a/packages/backend/migration/1000000000000-Init.js
+++ b/packages/backend/migration/1000000000000-Init.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1556348509290-Pages.js b/packages/backend/migration/1556348509290-Pages.js
index 05d801227..c7542e808 100644
--- a/packages/backend/migration/1556348509290-Pages.js
+++ b/packages/backend/migration/1556348509290-Pages.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1556746559567-UserProfile.js b/packages/backend/migration/1556746559567-UserProfile.js
index 7cc1ba008..13ff6ce6b 100644
--- a/packages/backend/migration/1556746559567-UserProfile.js
+++ b/packages/backend/migration/1556746559567-UserProfile.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1557476068003-PinnedUsers.js b/packages/backend/migration/1557476068003-PinnedUsers.js
index 12f0b8fc6..f2f1deae2 100644
--- a/packages/backend/migration/1557476068003-PinnedUsers.js
+++ b/packages/backend/migration/1557476068003-PinnedUsers.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1557761316509-AddSomeUrls.js b/packages/backend/migration/1557761316509-AddSomeUrls.js
index 244f64f8e..eaf78b85b 100644
--- a/packages/backend/migration/1557761316509-AddSomeUrls.js
+++ b/packages/backend/migration/1557761316509-AddSomeUrls.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1557932705754-ObjectStorageSetting.js b/packages/backend/migration/1557932705754-ObjectStorageSetting.js
index 736dcafaa..0e1ef321a 100644
--- a/packages/backend/migration/1557932705754-ObjectStorageSetting.js
+++ b/packages/backend/migration/1557932705754-ObjectStorageSetting.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1558072954435-PageLike.js b/packages/backend/migration/1558072954435-PageLike.js
index d9502a6e0..a08f68a0e 100644
--- a/packages/backend/migration/1558072954435-PageLike.js
+++ b/packages/backend/migration/1558072954435-PageLike.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1558103093633-UserGroup.js b/packages/backend/migration/1558103093633-UserGroup.js
index b3cc6eb94..f762dc237 100644
--- a/packages/backend/migration/1558103093633-UserGroup.js
+++ b/packages/backend/migration/1558103093633-UserGroup.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1558257926829-UserGroupInvite.js b/packages/backend/migration/1558257926829-UserGroupInvite.js
index a87173cdf..853b52d17 100644
--- a/packages/backend/migration/1558257926829-UserGroupInvite.js
+++ b/packages/backend/migration/1558257926829-UserGroupInvite.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1558266512381-UserListJoining.js b/packages/backend/migration/1558266512381-UserListJoining.js
index bc94b7f42..e161d52f1 100644
--- a/packages/backend/migration/1558266512381-UserListJoining.js
+++ b/packages/backend/migration/1558266512381-UserListJoining.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1561706992953-webauthn.js b/packages/backend/migration/1561706992953-webauthn.js
index fa9b1188c..4c81035ff 100644
--- a/packages/backend/migration/1561706992953-webauthn.js
+++ b/packages/backend/migration/1561706992953-webauthn.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1561873850023-ChartIndexes.js b/packages/backend/migration/1561873850023-ChartIndexes.js
index c7e93ba7b..3f190ce14 100644
--- a/packages/backend/migration/1561873850023-ChartIndexes.js
+++ b/packages/backend/migration/1561873850023-ChartIndexes.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1562422242907-PasswordLessLogin.js b/packages/backend/migration/1562422242907-PasswordLessLogin.js
index 3df3a6f5f..4c0fbbbc9 100644
--- a/packages/backend/migration/1562422242907-PasswordLessLogin.js
+++ b/packages/backend/migration/1562422242907-PasswordLessLogin.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1562444565093-PinnedPage.js b/packages/backend/migration/1562444565093-PinnedPage.js
index 329d49bbe..89639399f 100644
--- a/packages/backend/migration/1562444565093-PinnedPage.js
+++ b/packages/backend/migration/1562444565093-PinnedPage.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1562448332510-PageTitleHideOption.js b/packages/backend/migration/1562448332510-PageTitleHideOption.js
index e41db0809..70d54aa77 100644
--- a/packages/backend/migration/1562448332510-PageTitleHideOption.js
+++ b/packages/backend/migration/1562448332510-PageTitleHideOption.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1562869971568-ModerationLog.js b/packages/backend/migration/1562869971568-ModerationLog.js
index 2eb3015d5..3dd9b22ed 100644
--- a/packages/backend/migration/1562869971568-ModerationLog.js
+++ b/packages/backend/migration/1562869971568-ModerationLog.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1563757595828-UsedUsername.js b/packages/backend/migration/1563757595828-UsedUsername.js
index 91d9d36b9..258e5abab 100644
--- a/packages/backend/migration/1563757595828-UsedUsername.js
+++ b/packages/backend/migration/1563757595828-UsedUsername.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1565634203341-room.js b/packages/backend/migration/1565634203341-room.js
index c2e5fca86..04c9749c1 100644
--- a/packages/backend/migration/1565634203341-room.js
+++ b/packages/backend/migration/1565634203341-room.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1571220798684-CustomEmojiCategory.js b/packages/backend/migration/1571220798684-CustomEmojiCategory.js
index f211af67b..1fc78a65f 100644
--- a/packages/backend/migration/1571220798684-CustomEmojiCategory.js
+++ b/packages/backend/migration/1571220798684-CustomEmojiCategory.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1572760203493-nodeinfo.js b/packages/backend/migration/1572760203493-nodeinfo.js
index c281b0b2d..ea7a67bc3 100644
--- a/packages/backend/migration/1572760203493-nodeinfo.js
+++ b/packages/backend/migration/1572760203493-nodeinfo.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1576269851876-TalkFederationId.js b/packages/backend/migration/1576269851876-TalkFederationId.js
index 045f9ddb0..c49c716e7 100644
--- a/packages/backend/migration/1576269851876-TalkFederationId.js
+++ b/packages/backend/migration/1576269851876-TalkFederationId.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1576869585998-ProxyRemoteFiles.js b/packages/backend/migration/1576869585998-ProxyRemoteFiles.js
index 0dde1ae70..192dbe348 100644
--- a/packages/backend/migration/1576869585998-ProxyRemoteFiles.js
+++ b/packages/backend/migration/1576869585998-ProxyRemoteFiles.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1579267006611-v12.js b/packages/backend/migration/1579267006611-v12.js
index 86f9da7e7..9267be563 100644
--- a/packages/backend/migration/1579267006611-v12.js
+++ b/packages/backend/migration/1579267006611-v12.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1579270193251-v12-2.js b/packages/backend/migration/1579270193251-v12-2.js
index 2593aca57..e2ca9709e 100644
--- a/packages/backend/migration/1579270193251-v12-2.js
+++ b/packages/backend/migration/1579270193251-v12-2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1579282808087-v12-3.js b/packages/backend/migration/1579282808087-v12-3.js
index a816b2e82..4098f041c 100644
--- a/packages/backend/migration/1579282808087-v12-3.js
+++ b/packages/backend/migration/1579282808087-v12-3.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1579544426412-v12-4.js b/packages/backend/migration/1579544426412-v12-4.js
index 600dc270a..1153993f3 100644
--- a/packages/backend/migration/1579544426412-v12-4.js
+++ b/packages/backend/migration/1579544426412-v12-4.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1579977526288-v12-5.js b/packages/backend/migration/1579977526288-v12-5.js
index 73f334334..d9e1b48bb 100644
--- a/packages/backend/migration/1579977526288-v12-5.js
+++ b/packages/backend/migration/1579977526288-v12-5.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1579993013959-v12-6.js b/packages/backend/migration/1579993013959-v12-6.js
index 5009e0aa8..9c249422a 100644
--- a/packages/backend/migration/1579993013959-v12-6.js
+++ b/packages/backend/migration/1579993013959-v12-6.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1580069531114-v12-7.js b/packages/backend/migration/1580069531114-v12-7.js
index ff943ffa6..ceee6b203 100644
--- a/packages/backend/migration/1580069531114-v12-7.js
+++ b/packages/backend/migration/1580069531114-v12-7.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1580148575182-v12-8.js b/packages/backend/migration/1580148575182-v12-8.js
index 20b77b391..6841dcc38 100644
--- a/packages/backend/migration/1580148575182-v12-8.js
+++ b/packages/backend/migration/1580148575182-v12-8.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1580154400017-v12-9.js b/packages/backend/migration/1580154400017-v12-9.js
index f78dc4745..c01d8089d 100644
--- a/packages/backend/migration/1580154400017-v12-9.js
+++ b/packages/backend/migration/1580154400017-v12-9.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1580276619901-v12-10.js b/packages/backend/migration/1580276619901-v12-10.js
index 09fa27ae8..be6e467fa 100644
--- a/packages/backend/migration/1580276619901-v12-10.js
+++ b/packages/backend/migration/1580276619901-v12-10.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1580331224276-v12-11.js b/packages/backend/migration/1580331224276-v12-11.js
index f118c3493..af817a8c8 100644
--- a/packages/backend/migration/1580331224276-v12-11.js
+++ b/packages/backend/migration/1580331224276-v12-11.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1580508795118-v12-12.js b/packages/backend/migration/1580508795118-v12-12.js
index 4fba933a0..4bd855f7a 100644
--- a/packages/backend/migration/1580508795118-v12-12.js
+++ b/packages/backend/migration/1580508795118-v12-12.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1580543501339-v12-13.js b/packages/backend/migration/1580543501339-v12-13.js
index 934451630..be76c0216 100644
--- a/packages/backend/migration/1580543501339-v12-13.js
+++ b/packages/backend/migration/1580543501339-v12-13.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1580864313253-v12-14.js b/packages/backend/migration/1580864313253-v12-14.js
index 5034492a7..f8891a2b6 100644
--- a/packages/backend/migration/1580864313253-v12-14.js
+++ b/packages/backend/migration/1580864313253-v12-14.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1581526429287-user-group-invitation.js b/packages/backend/migration/1581526429287-user-group-invitation.js
index fc8181380..51703e2ba 100644
--- a/packages/backend/migration/1581526429287-user-group-invitation.js
+++ b/packages/backend/migration/1581526429287-user-group-invitation.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1581695816408-user-group-antenna.js b/packages/backend/migration/1581695816408-user-group-antenna.js
index 8a212c092..e6791ba1a 100644
--- a/packages/backend/migration/1581695816408-user-group-antenna.js
+++ b/packages/backend/migration/1581695816408-user-group-antenna.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1581708415836-drive-user-folder-id-index.js b/packages/backend/migration/1581708415836-drive-user-folder-id-index.js
index 6594078db..28ce4cc14 100644
--- a/packages/backend/migration/1581708415836-drive-user-folder-id-index.js
+++ b/packages/backend/migration/1581708415836-drive-user-folder-id-index.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1581979837262-promo.js b/packages/backend/migration/1581979837262-promo.js
index 585564a40..707c85fcb 100644
--- a/packages/backend/migration/1581979837262-promo.js
+++ b/packages/backend/migration/1581979837262-promo.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1582019042083-featured-injecttion.js b/packages/backend/migration/1582019042083-featured-injecttion.js
index d27000627..f308f0a45 100644
--- a/packages/backend/migration/1582019042083-featured-injecttion.js
+++ b/packages/backend/migration/1582019042083-featured-injecttion.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1582210532752-antenna-exclude.js b/packages/backend/migration/1582210532752-antenna-exclude.js
index 12eee2364..9b87e3ff3 100644
--- a/packages/backend/migration/1582210532752-antenna-exclude.js
+++ b/packages/backend/migration/1582210532752-antenna-exclude.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1582875306439-note-reaction-length.js b/packages/backend/migration/1582875306439-note-reaction-length.js
index a4413c953..e801d1ac4 100644
--- a/packages/backend/migration/1582875306439-note-reaction-length.js
+++ b/packages/backend/migration/1582875306439-note-reaction-length.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1585361548360-miauth.js b/packages/backend/migration/1585361548360-miauth.js
index d073fa3d2..d5932c608 100644
--- a/packages/backend/migration/1585361548360-miauth.js
+++ b/packages/backend/migration/1585361548360-miauth.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1585385921215-custom-notification.js b/packages/backend/migration/1585385921215-custom-notification.js
index a3336e0ec..35303b99e 100644
--- a/packages/backend/migration/1585385921215-custom-notification.js
+++ b/packages/backend/migration/1585385921215-custom-notification.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1585772678853-ap-url.js b/packages/backend/migration/1585772678853-ap-url.js
index f67f5a454..f978fc80b 100644
--- a/packages/backend/migration/1585772678853-ap-url.js
+++ b/packages/backend/migration/1585772678853-ap-url.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1586624197029-AddObjectStorageUseProxy.js b/packages/backend/migration/1586624197029-AddObjectStorageUseProxy.js
index 16f7599b8..fde8629bb 100644
--- a/packages/backend/migration/1586624197029-AddObjectStorageUseProxy.js
+++ b/packages/backend/migration/1586624197029-AddObjectStorageUseProxy.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1586641139527-remote-reaction.js b/packages/backend/migration/1586641139527-remote-reaction.js
index 666bb42ca..3e907af5f 100644
--- a/packages/backend/migration/1586641139527-remote-reaction.js
+++ b/packages/backend/migration/1586641139527-remote-reaction.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1586708940386-pageAiScript.js b/packages/backend/migration/1586708940386-pageAiScript.js
index 3d0d0ab91..ce5007cea 100644
--- a/packages/backend/migration/1586708940386-pageAiScript.js
+++ b/packages/backend/migration/1586708940386-pageAiScript.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1588044505511-hCaptcha.js b/packages/backend/migration/1588044505511-hCaptcha.js
index 22cc6672c..aeacb653b 100644
--- a/packages/backend/migration/1588044505511-hCaptcha.js
+++ b/packages/backend/migration/1588044505511-hCaptcha.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1589023282116-pubRelay.js b/packages/backend/migration/1589023282116-pubRelay.js
index ed010699e..8739adb73 100644
--- a/packages/backend/migration/1589023282116-pubRelay.js
+++ b/packages/backend/migration/1589023282116-pubRelay.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1595075960584-blurhash.js b/packages/backend/migration/1595075960584-blurhash.js
index 967676531..9752625cd 100644
--- a/packages/backend/migration/1595075960584-blurhash.js
+++ b/packages/backend/migration/1595075960584-blurhash.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1595077605646-blurhash-for-avatar-banner.js b/packages/backend/migration/1595077605646-blurhash-for-avatar-banner.js
index 7df079ac0..fdff8c633 100644
--- a/packages/backend/migration/1595077605646-blurhash-for-avatar-banner.js
+++ b/packages/backend/migration/1595077605646-blurhash-for-avatar-banner.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1595676934834-instance-icon-url.js b/packages/backend/migration/1595676934834-instance-icon-url.js
index 6bccff082..5f834064c 100644
--- a/packages/backend/migration/1595676934834-instance-icon-url.js
+++ b/packages/backend/migration/1595676934834-instance-icon-url.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1595771249699-word-mute.js b/packages/backend/migration/1595771249699-word-mute.js
index cfd0a5ccc..f4fa1227e 100644
--- a/packages/backend/migration/1595771249699-word-mute.js
+++ b/packages/backend/migration/1595771249699-word-mute.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1595782306083-word-mute2.js b/packages/backend/migration/1595782306083-word-mute2.js
index 64acf2b72..3c2062ec0 100644
--- a/packages/backend/migration/1595782306083-word-mute2.js
+++ b/packages/backend/migration/1595782306083-word-mute2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1596548170836-channel.js b/packages/backend/migration/1596548170836-channel.js
index a26991d4d..ee6753a47 100644
--- a/packages/backend/migration/1596548170836-channel.js
+++ b/packages/backend/migration/1596548170836-channel.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1596786425167-channel2.js b/packages/backend/migration/1596786425167-channel2.js
index 4e87b11bb..9e6ead437 100644
--- a/packages/backend/migration/1596786425167-channel2.js
+++ b/packages/backend/migration/1596786425167-channel2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1597230137744-objectStorageSetPublicRead.js b/packages/backend/migration/1597230137744-objectStorageSetPublicRead.js
index 93e6f186d..bc32d4a05 100644
--- a/packages/backend/migration/1597230137744-objectStorageSetPublicRead.js
+++ b/packages/backend/migration/1597230137744-objectStorageSetPublicRead.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1597236229720-IncludingNotificationTypes.js b/packages/backend/migration/1597236229720-IncludingNotificationTypes.js
index bda702d99..99686bd70 100644
--- a/packages/backend/migration/1597236229720-IncludingNotificationTypes.js
+++ b/packages/backend/migration/1597236229720-IncludingNotificationTypes.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1597385880794-add-sensitive-index.js b/packages/backend/migration/1597385880794-add-sensitive-index.js
index ffb94895d..a67810880 100644
--- a/packages/backend/migration/1597385880794-add-sensitive-index.js
+++ b/packages/backend/migration/1597385880794-add-sensitive-index.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1597459042300-channel-unread.js b/packages/backend/migration/1597459042300-channel-unread.js
index 5b94d8296..ced9b5265 100644
--- a/packages/backend/migration/1597459042300-channel-unread.js
+++ b/packages/backend/migration/1597459042300-channel-unread.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1597893996136-ChannelNoteIdDescIndex.js b/packages/backend/migration/1597893996136-ChannelNoteIdDescIndex.js
index 543e51140..ca4eba385 100644
--- a/packages/backend/migration/1597893996136-ChannelNoteIdDescIndex.js
+++ b/packages/backend/migration/1597893996136-ChannelNoteIdDescIndex.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1600353287890-mutingNotificationTypes.js b/packages/backend/migration/1600353287890-mutingNotificationTypes.js
index 4e0b8ad6e..0996aa21f 100644
--- a/packages/backend/migration/1600353287890-mutingNotificationTypes.js
+++ b/packages/backend/migration/1600353287890-mutingNotificationTypes.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1603094348345-refine-abuse-user-report.js b/packages/backend/migration/1603094348345-refine-abuse-user-report.js
index 4e052e07c..354915b16 100644
--- a/packages/backend/migration/1603094348345-refine-abuse-user-report.js
+++ b/packages/backend/migration/1603094348345-refine-abuse-user-report.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1603095701770-refine-abuse-user-report2.js b/packages/backend/migration/1603095701770-refine-abuse-user-report2.js
index 2eb205c6e..75dd3513b 100644
--- a/packages/backend/migration/1603095701770-refine-abuse-user-report2.js
+++ b/packages/backend/migration/1603095701770-refine-abuse-user-report2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1603776877564-instance-theme-color.js b/packages/backend/migration/1603776877564-instance-theme-color.js
index 5f83bc14e..c8ab89ab5 100644
--- a/packages/backend/migration/1603776877564-instance-theme-color.js
+++ b/packages/backend/migration/1603776877564-instance-theme-color.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1603781553011-instance-favicon.js b/packages/backend/migration/1603781553011-instance-favicon.js
index 758b86408..7d793d4f1 100644
--- a/packages/backend/migration/1603781553011-instance-favicon.js
+++ b/packages/backend/migration/1603781553011-instance-favicon.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1604821689616-delete-auto-watch.js b/packages/backend/migration/1604821689616-delete-auto-watch.js
index 917ef5b10..816087703 100644
--- a/packages/backend/migration/1604821689616-delete-auto-watch.js
+++ b/packages/backend/migration/1604821689616-delete-auto-watch.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1605408848373-clip-description.js b/packages/backend/migration/1605408848373-clip-description.js
index fedc603b3..77a218791 100644
--- a/packages/backend/migration/1605408848373-clip-description.js
+++ b/packages/backend/migration/1605408848373-clip-description.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1605408971051-comments.js b/packages/backend/migration/1605408971051-comments.js
index 8ab16859d..494bfb795 100644
--- a/packages/backend/migration/1605408971051-comments.js
+++ b/packages/backend/migration/1605408971051-comments.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1605585339718-instance-pinned-pages.js b/packages/backend/migration/1605585339718-instance-pinned-pages.js
index e6f3c2a78..15a0cecd1 100644
--- a/packages/backend/migration/1605585339718-instance-pinned-pages.js
+++ b/packages/backend/migration/1605585339718-instance-pinned-pages.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1605965516823-instance-images.js b/packages/backend/migration/1605965516823-instance-images.js
index 848b53f1b..9cc2eb403 100644
--- a/packages/backend/migration/1605965516823-instance-images.js
+++ b/packages/backend/migration/1605965516823-instance-images.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1606191203881-no-crawle.js b/packages/backend/migration/1606191203881-no-crawle.js
index 5c878f5a2..af04566ea 100644
--- a/packages/backend/migration/1606191203881-no-crawle.js
+++ b/packages/backend/migration/1606191203881-no-crawle.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1607151207216-instance-pinned-clip.js b/packages/backend/migration/1607151207216-instance-pinned-clip.js
index 67db39fed..f85c3d42d 100644
--- a/packages/backend/migration/1607151207216-instance-pinned-clip.js
+++ b/packages/backend/migration/1607151207216-instance-pinned-clip.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1607353487793-isExplorable.js b/packages/backend/migration/1607353487793-isExplorable.js
index 95ee07e91..e07fe6c30 100644
--- a/packages/backend/migration/1607353487793-isExplorable.js
+++ b/packages/backend/migration/1607353487793-isExplorable.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1610277136869-registry.js b/packages/backend/migration/1610277136869-registry.js
index c5fe2c5a6..1a10f2359 100644
--- a/packages/backend/migration/1610277136869-registry.js
+++ b/packages/backend/migration/1610277136869-registry.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1610277585759-registry2.js b/packages/backend/migration/1610277585759-registry2.js
index f734a235b..46e56279f 100644
--- a/packages/backend/migration/1610277585759-registry2.js
+++ b/packages/backend/migration/1610277585759-registry2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1610283021566-registry3.js b/packages/backend/migration/1610283021566-registry3.js
index c94546c73..402040f38 100644
--- a/packages/backend/migration/1610283021566-registry3.js
+++ b/packages/backend/migration/1610283021566-registry3.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1611354329133-followersUri.js b/packages/backend/migration/1611354329133-followersUri.js
index 7e5f8c309..15abb2a9d 100644
--- a/packages/backend/migration/1611354329133-followersUri.js
+++ b/packages/backend/migration/1611354329133-followersUri.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1611397665007-gallery.js b/packages/backend/migration/1611397665007-gallery.js
index cd5c39cc1..cbd2b62c5 100644
--- a/packages/backend/migration/1611397665007-gallery.js
+++ b/packages/backend/migration/1611397665007-gallery.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1611547387175-objectStorageS3ForcePathStyle.js b/packages/backend/migration/1611547387175-objectStorageS3ForcePathStyle.js
index c0b1da1e5..c5440b7a4 100644
--- a/packages/backend/migration/1611547387175-objectStorageS3ForcePathStyle.js
+++ b/packages/backend/migration/1611547387175-objectStorageS3ForcePathStyle.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1612619156584-announcement-email.js b/packages/backend/migration/1612619156584-announcement-email.js
index f8277725f..ddacab322 100644
--- a/packages/backend/migration/1612619156584-announcement-email.js
+++ b/packages/backend/migration/1612619156584-announcement-email.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1613155914446-emailNotificationTypes.js b/packages/backend/migration/1613155914446-emailNotificationTypes.js
index 3afe491e4..d34ba7e82 100644
--- a/packages/backend/migration/1613155914446-emailNotificationTypes.js
+++ b/packages/backend/migration/1613155914446-emailNotificationTypes.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1613181457597-user-lang.js b/packages/backend/migration/1613181457597-user-lang.js
index 33e363477..6ef524595 100644
--- a/packages/backend/migration/1613181457597-user-lang.js
+++ b/packages/backend/migration/1613181457597-user-lang.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1613503367223-use-bigint-for-driveUsage.js b/packages/backend/migration/1613503367223-use-bigint-for-driveUsage.js
index 9c75c0ae5..8529ea324 100644
--- a/packages/backend/migration/1613503367223-use-bigint-for-driveUsage.js
+++ b/packages/backend/migration/1613503367223-use-bigint-for-driveUsage.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1615965918224-chart-v2.js b/packages/backend/migration/1615965918224-chart-v2.js
index 2c0cacd1d..deecde722 100644
--- a/packages/backend/migration/1615965918224-chart-v2.js
+++ b/packages/backend/migration/1615965918224-chart-v2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1615966519402-chart-v2-2.js b/packages/backend/migration/1615966519402-chart-v2-2.js
index 8d6ebf6a8..7842a2710 100644
--- a/packages/backend/migration/1615966519402-chart-v2-2.js
+++ b/packages/backend/migration/1615966519402-chart-v2-2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1618637372000-user-last-active-date.js b/packages/backend/migration/1618637372000-user-last-active-date.js
index 8b4652898..7caf179fa 100644
--- a/packages/backend/migration/1618637372000-user-last-active-date.js
+++ b/packages/backend/migration/1618637372000-user-last-active-date.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1618639857000-user-hide-online-status.js b/packages/backend/migration/1618639857000-user-hide-online-status.js
index 1f19a7ebb..201296274 100644
--- a/packages/backend/migration/1618639857000-user-hide-online-status.js
+++ b/packages/backend/migration/1618639857000-user-hide-online-status.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1619942102890-password-reset.js b/packages/backend/migration/1619942102890-password-reset.js
index 989801177..7784da2bc 100644
--- a/packages/backend/migration/1619942102890-password-reset.js
+++ b/packages/backend/migration/1619942102890-password-reset.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1620019354680-ad.js b/packages/backend/migration/1620019354680-ad.js
index 1ae66d71f..7630ed01a 100644
--- a/packages/backend/migration/1620019354680-ad.js
+++ b/packages/backend/migration/1620019354680-ad.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1620364649428-ad2.js b/packages/backend/migration/1620364649428-ad2.js
index b9b26be07..795918568 100644
--- a/packages/backend/migration/1620364649428-ad2.js
+++ b/packages/backend/migration/1620364649428-ad2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1621479946000-add-note-indexes.js b/packages/backend/migration/1621479946000-add-note-indexes.js
index 299c1f6c0..f72bf8211 100644
--- a/packages/backend/migration/1621479946000-add-note-indexes.js
+++ b/packages/backend/migration/1621479946000-add-note-indexes.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1622679304522-user-profile-description-length.js b/packages/backend/migration/1622679304522-user-profile-description-length.js
index 988456fe7..7324175b4 100644
--- a/packages/backend/migration/1622679304522-user-profile-description-length.js
+++ b/packages/backend/migration/1622679304522-user-profile-description-length.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1622681548499-log-message-length.js b/packages/backend/migration/1622681548499-log-message-length.js
index e1fa22c88..b4d8d497e 100644
--- a/packages/backend/migration/1622681548499-log-message-length.js
+++ b/packages/backend/migration/1622681548499-log-message-length.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1626509500668-fix-remote-file-proxy.js b/packages/backend/migration/1626509500668-fix-remote-file-proxy.js
index 906e49cab..9145247ab 100644
--- a/packages/backend/migration/1626509500668-fix-remote-file-proxy.js
+++ b/packages/backend/migration/1626509500668-fix-remote-file-proxy.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1629004542760-chart-reindex.js b/packages/backend/migration/1629004542760-chart-reindex.js
index f1d08ecfe..072cdec3c 100644
--- a/packages/backend/migration/1629004542760-chart-reindex.js
+++ b/packages/backend/migration/1629004542760-chart-reindex.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1629024377804-deepl-integration.js b/packages/backend/migration/1629024377804-deepl-integration.js
index 465f1bcca..5889196f1 100644
--- a/packages/backend/migration/1629024377804-deepl-integration.js
+++ b/packages/backend/migration/1629024377804-deepl-integration.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1629288472000-fix-channel-userId.js b/packages/backend/migration/1629288472000-fix-channel-userId.js
index 9f946ad55..d7907d05b 100644
--- a/packages/backend/migration/1629288472000-fix-channel-userId.js
+++ b/packages/backend/migration/1629288472000-fix-channel-userId.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1629512953000-user-is-deleted.js b/packages/backend/migration/1629512953000-user-is-deleted.js
index 78bbd8bbe..94165e466 100644
--- a/packages/backend/migration/1629512953000-user-is-deleted.js
+++ b/packages/backend/migration/1629512953000-user-is-deleted.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1629778475000-deepl-integration2.js b/packages/backend/migration/1629778475000-deepl-integration2.js
index b719dcf57..a54daf8fb 100644
--- a/packages/backend/migration/1629778475000-deepl-integration2.js
+++ b/packages/backend/migration/1629778475000-deepl-integration2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1629833361000-AddShowTLReplies.js b/packages/backend/migration/1629833361000-AddShowTLReplies.js
index 00aef6aeb..b80e2ef67 100644
--- a/packages/backend/migration/1629833361000-AddShowTLReplies.js
+++ b/packages/backend/migration/1629833361000-AddShowTLReplies.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1629968054000_userInstanceBlocks.js b/packages/backend/migration/1629968054000_userInstanceBlocks.js
index e8168e372..e88fa8aec 100644
--- a/packages/backend/migration/1629968054000_userInstanceBlocks.js
+++ b/packages/backend/migration/1629968054000_userInstanceBlocks.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1633068642000-email-required-for-signup.js b/packages/backend/migration/1633068642000-email-required-for-signup.js
index 230227d36..d23db2052 100644
--- a/packages/backend/migration/1633068642000-email-required-for-signup.js
+++ b/packages/backend/migration/1633068642000-email-required-for-signup.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1633071909016-user-pending.js b/packages/backend/migration/1633071909016-user-pending.js
index f0d037967..db0f2fde1 100644
--- a/packages/backend/migration/1633071909016-user-pending.js
+++ b/packages/backend/migration/1633071909016-user-pending.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1634486652000-user-public-reactions.js b/packages/backend/migration/1634486652000-user-public-reactions.js
index 09870c79c..ce1818886 100644
--- a/packages/backend/migration/1634486652000-user-public-reactions.js
+++ b/packages/backend/migration/1634486652000-user-public-reactions.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1634902659689-delete-log.js b/packages/backend/migration/1634902659689-delete-log.js
index e4e625536..2e2267f9f 100644
--- a/packages/backend/migration/1634902659689-delete-log.js
+++ b/packages/backend/migration/1634902659689-delete-log.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1635500777168-note-thread-mute.js b/packages/backend/migration/1635500777168-note-thread-mute.js
index 9f376c479..d5fca5959 100644
--- a/packages/backend/migration/1635500777168-note-thread-mute.js
+++ b/packages/backend/migration/1635500777168-note-thread-mute.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1636197624383-ff-visibility.js b/packages/backend/migration/1636197624383-ff-visibility.js
index aa089d42a..27faae1c9 100644
--- a/packages/backend/migration/1636197624383-ff-visibility.js
+++ b/packages/backend/migration/1636197624383-ff-visibility.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1636697408073-remove-via-mobile.js b/packages/backend/migration/1636697408073-remove-via-mobile.js
index c014ceb92..81f0b6344 100644
--- a/packages/backend/migration/1636697408073-remove-via-mobile.js
+++ b/packages/backend/migration/1636697408073-remove-via-mobile.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1637320813000-forwarded-report.js b/packages/backend/migration/1637320813000-forwarded-report.js
index 0d1f48beb..8125468aa 100644
--- a/packages/backend/migration/1637320813000-forwarded-report.js
+++ b/packages/backend/migration/1637320813000-forwarded-report.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1639325650583-chart-v3.js b/packages/backend/migration/1639325650583-chart-v3.js
index e6209e2b7..225547639 100644
--- a/packages/backend/migration/1639325650583-chart-v3.js
+++ b/packages/backend/migration/1639325650583-chart-v3.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1642611822809-emoji-url.js b/packages/backend/migration/1642611822809-emoji-url.js
index 212fc957a..421614b40 100644
--- a/packages/backend/migration/1642611822809-emoji-url.js
+++ b/packages/backend/migration/1642611822809-emoji-url.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1642613870898-drive-file-webpublic-type.js b/packages/backend/migration/1642613870898-drive-file-webpublic-type.js
index e50770fff..e61a3fc49 100644
--- a/packages/backend/migration/1642613870898-drive-file-webpublic-type.js
+++ b/packages/backend/migration/1642613870898-drive-file-webpublic-type.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1643963705770-chart-v4.js b/packages/backend/migration/1643963705770-chart-v4.js
index af0bd18e5..77355cd7f 100644
--- a/packages/backend/migration/1643963705770-chart-v4.js
+++ b/packages/backend/migration/1643963705770-chart-v4.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1643966656277-chart-v5.js b/packages/backend/migration/1643966656277-chart-v5.js
index b3389a653..54e4705e5 100644
--- a/packages/backend/migration/1643966656277-chart-v5.js
+++ b/packages/backend/migration/1643966656277-chart-v5.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1643967331284-chart-v6.js b/packages/backend/migration/1643967331284-chart-v6.js
index 1197bdd71..aa64bc9fa 100644
--- a/packages/backend/migration/1643967331284-chart-v6.js
+++ b/packages/backend/migration/1643967331284-chart-v6.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1644010796173-convert-hard-mutes.js b/packages/backend/migration/1644010796173-convert-hard-mutes.js
index 1a5316ac0..9aec21b5f 100644
--- a/packages/backend/migration/1644010796173-convert-hard-mutes.js
+++ b/packages/backend/migration/1644010796173-convert-hard-mutes.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1644058404077-chart-v7.js b/packages/backend/migration/1644058404077-chart-v7.js
index a850d5f48..a09fff1bc 100644
--- a/packages/backend/migration/1644058404077-chart-v7.js
+++ b/packages/backend/migration/1644058404077-chart-v7.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1644059847460-chart-v8.js b/packages/backend/migration/1644059847460-chart-v8.js
index 2e20159ba..43b95926b 100644
--- a/packages/backend/migration/1644059847460-chart-v8.js
+++ b/packages/backend/migration/1644059847460-chart-v8.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1644060125705-chart-v9.js b/packages/backend/migration/1644060125705-chart-v9.js
index d1d9469ea..dc99f3c8f 100644
--- a/packages/backend/migration/1644060125705-chart-v9.js
+++ b/packages/backend/migration/1644060125705-chart-v9.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1644073149413-chart-v10.js b/packages/backend/migration/1644073149413-chart-v10.js
index 466ae5983..4d3623572 100644
--- a/packages/backend/migration/1644073149413-chart-v10.js
+++ b/packages/backend/migration/1644073149413-chart-v10.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1644095659741-chart-v11.js b/packages/backend/migration/1644095659741-chart-v11.js
index 5c98e25d8..80bacbf71 100644
--- a/packages/backend/migration/1644095659741-chart-v11.js
+++ b/packages/backend/migration/1644095659741-chart-v11.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1644328606241-chart-v12.js b/packages/backend/migration/1644328606241-chart-v12.js
index 2a7272fd2..15c0dd904 100644
--- a/packages/backend/migration/1644328606241-chart-v12.js
+++ b/packages/backend/migration/1644328606241-chart-v12.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1644331238153-chart-v13.js b/packages/backend/migration/1644331238153-chart-v13.js
index 7e33b0a8e..0c2db66f2 100644
--- a/packages/backend/migration/1644331238153-chart-v13.js
+++ b/packages/backend/migration/1644331238153-chart-v13.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1644344266289-chart-v14.js b/packages/backend/migration/1644344266289-chart-v14.js
index 2050d5459..0f4688ab7 100644
--- a/packages/backend/migration/1644344266289-chart-v14.js
+++ b/packages/backend/migration/1644344266289-chart-v14.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1644395759931-instance-theme-color.js b/packages/backend/migration/1644395759931-instance-theme-color.js
index ac842e4fe..fd7356e68 100644
--- a/packages/backend/migration/1644395759931-instance-theme-color.js
+++ b/packages/backend/migration/1644395759931-instance-theme-color.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1644481657998-chart-v15.js b/packages/backend/migration/1644481657998-chart-v15.js
index ad5589df8..964bea3d0 100644
--- a/packages/backend/migration/1644481657998-chart-v15.js
+++ b/packages/backend/migration/1644481657998-chart-v15.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1644551208096-following-indexes.js b/packages/backend/migration/1644551208096-following-indexes.js
index 795b8e900..8d1d4890d 100644
--- a/packages/backend/migration/1644551208096-following-indexes.js
+++ b/packages/backend/migration/1644551208096-following-indexes.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1645340161439-remove-max-note-text-length.js b/packages/backend/migration/1645340161439-remove-max-note-text-length.js
index 84eaeddfa..1cf6b0801 100644
--- a/packages/backend/migration/1645340161439-remove-max-note-text-length.js
+++ b/packages/backend/migration/1645340161439-remove-max-note-text-length.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1645599900873-federation-chart-pubsub.js b/packages/backend/migration/1645599900873-federation-chart-pubsub.js
index 4f9f501cc..3042c8ecd 100644
--- a/packages/backend/migration/1645599900873-federation-chart-pubsub.js
+++ b/packages/backend/migration/1645599900873-federation-chart-pubsub.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1646143552768-instance-default-theme.js b/packages/backend/migration/1646143552768-instance-default-theme.js
index 353291630..8f0755e3a 100644
--- a/packages/backend/migration/1646143552768-instance-default-theme.js
+++ b/packages/backend/migration/1646143552768-instance-default-theme.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1646387162108-mute-expires-at.js b/packages/backend/migration/1646387162108-mute-expires-at.js
index 868f5c87e..412db1488 100644
--- a/packages/backend/migration/1646387162108-mute-expires-at.js
+++ b/packages/backend/migration/1646387162108-mute-expires-at.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1646549089451-poll-ended-notification.js b/packages/backend/migration/1646549089451-poll-ended-notification.js
index fa7327ff9..6c481c6ac 100644
--- a/packages/backend/migration/1646549089451-poll-ended-notification.js
+++ b/packages/backend/migration/1646549089451-poll-ended-notification.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1646633030285-chart-federation-active.js b/packages/backend/migration/1646633030285-chart-federation-active.js
index b9863746a..13d54c318 100644
--- a/packages/backend/migration/1646633030285-chart-federation-active.js
+++ b/packages/backend/migration/1646633030285-chart-federation-active.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1646655454495-remove-instance-drive-columns.js b/packages/backend/migration/1646655454495-remove-instance-drive-columns.js
index 8fd96ed4c..04d6fce88 100644
--- a/packages/backend/migration/1646655454495-remove-instance-drive-columns.js
+++ b/packages/backend/migration/1646655454495-remove-instance-drive-columns.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1646732390560-chart-federation-active-sub-pub.js b/packages/backend/migration/1646732390560-chart-federation-active-sub-pub.js
index 1b28d012a..289b929ad 100644
--- a/packages/backend/migration/1646732390560-chart-federation-active-sub-pub.js
+++ b/packages/backend/migration/1646732390560-chart-federation-active-sub-pub.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1648548247382-webhook.js b/packages/backend/migration/1648548247382-webhook.js
index fc2a69191..f31d3c5bb 100644
--- a/packages/backend/migration/1648548247382-webhook.js
+++ b/packages/backend/migration/1648548247382-webhook.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1648816172177-webhook-2.js b/packages/backend/migration/1648816172177-webhook-2.js
index a7bccff82..4d1b293b2 100644
--- a/packages/backend/migration/1648816172177-webhook-2.js
+++ b/packages/backend/migration/1648816172177-webhook-2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1651224615271-foreign-key.js b/packages/backend/migration/1651224615271-foreign-key.js
index 12e464632..fa51bb5e3 100644
--- a/packages/backend/migration/1651224615271-foreign-key.js
+++ b/packages/backend/migration/1651224615271-foreign-key.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1652859567549-uniform-themecolor.js b/packages/backend/migration/1652859567549-uniform-themecolor.js
index 422e63dfe..754e08982 100644
--- a/packages/backend/migration/1652859567549-uniform-themecolor.js
+++ b/packages/backend/migration/1652859567549-uniform-themecolor.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1655368940105-nsfw-detection.js b/packages/backend/migration/1655368940105-nsfw-detection.js
index ad37ff6f8..d2d0d0011 100644
--- a/packages/backend/migration/1655368940105-nsfw-detection.js
+++ b/packages/backend/migration/1655368940105-nsfw-detection.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1655371960534-nsfw-detection-2.js b/packages/backend/migration/1655371960534-nsfw-detection-2.js
index e6cc26617..e5adbddca 100644
--- a/packages/backend/migration/1655371960534-nsfw-detection-2.js
+++ b/packages/backend/migration/1655371960534-nsfw-detection-2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1655388169582-nsfw-detection-3.js b/packages/backend/migration/1655388169582-nsfw-detection-3.js
index 40362cc20..12fc28132 100644
--- a/packages/backend/migration/1655388169582-nsfw-detection-3.js
+++ b/packages/backend/migration/1655388169582-nsfw-detection-3.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1655393015659-nsfw-detection-4.js b/packages/backend/migration/1655393015659-nsfw-detection-4.js
index d74fe9c92..39fb17567 100644
--- a/packages/backend/migration/1655393015659-nsfw-detection-4.js
+++ b/packages/backend/migration/1655393015659-nsfw-detection-4.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1655813815729-driveCapacityOverrideMb.js b/packages/backend/migration/1655813815729-driveCapacityOverrideMb.js
index 7e97f9dc7..e64c8c1b8 100644
--- a/packages/backend/migration/1655813815729-driveCapacityOverrideMb.js
+++ b/packages/backend/migration/1655813815729-driveCapacityOverrideMb.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1655918165614-user-ip.js b/packages/backend/migration/1655918165614-user-ip.js
index ccb3ceb49..668c6d909 100644
--- a/packages/backend/migration/1655918165614-user-ip.js
+++ b/packages/backend/migration/1655918165614-user-ip.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1656122560740-file-ip.js b/packages/backend/migration/1656122560740-file-ip.js
index dc02df0e6..e5efaf3d9 100644
--- a/packages/backend/migration/1656122560740-file-ip.js
+++ b/packages/backend/migration/1656122560740-file-ip.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1656251734807-nsfw-detection-5.js b/packages/backend/migration/1656251734807-nsfw-detection-5.js
index 06da9251b..9b36bd76e 100644
--- a/packages/backend/migration/1656251734807-nsfw-detection-5.js
+++ b/packages/backend/migration/1656251734807-nsfw-detection-5.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1656328812281-ip-2.js b/packages/backend/migration/1656328812281-ip-2.js
index 1b53e697d..39fcd1d83 100644
--- a/packages/backend/migration/1656328812281-ip-2.js
+++ b/packages/backend/migration/1656328812281-ip-2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1656408772602-nsfw-detection-6.js b/packages/backend/migration/1656408772602-nsfw-detection-6.js
index 0adc8bb79..efadd22e5 100644
--- a/packages/backend/migration/1656408772602-nsfw-detection-6.js
+++ b/packages/backend/migration/1656408772602-nsfw-detection-6.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1656772790599-user-moderation-note.js b/packages/backend/migration/1656772790599-user-moderation-note.js
index 63a993851..ef2f0f652 100644
--- a/packages/backend/migration/1656772790599-user-moderation-note.js
+++ b/packages/backend/migration/1656772790599-user-moderation-note.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1657346559800-active-email-validation.js b/packages/backend/migration/1657346559800-active-email-validation.js
index 44b1f3f4f..e8d5b29cd 100644
--- a/packages/backend/migration/1657346559800-active-email-validation.js
+++ b/packages/backend/migration/1657346559800-active-email-validation.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1664694635394-turnstile.js b/packages/backend/migration/1664694635394-turnstile.js
index 3ec6da913..a9baf4c65 100644
--- a/packages/backend/migration/1664694635394-turnstile.js
+++ b/packages/backend/migration/1664694635394-turnstile.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1665091090561-add-renote-muting.js b/packages/backend/migration/1665091090561-add-renote-muting.js
index a22d7037f..574857251 100644
--- a/packages/backend/migration/1665091090561-add-renote-muting.js
+++ b/packages/backend/migration/1665091090561-add-renote-muting.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1669138716634-whetherPushNotifyToSendReadMessage.js b/packages/backend/migration/1669138716634-whetherPushNotifyToSendReadMessage.js
index a317468ac..431241897 100644
--- a/packages/backend/migration/1669138716634-whetherPushNotifyToSendReadMessage.js
+++ b/packages/backend/migration/1669138716634-whetherPushNotifyToSendReadMessage.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1671924750884-RetentionAggregation.js b/packages/backend/migration/1671924750884-RetentionAggregation.js
index 5057bf106..67079bb7a 100644
--- a/packages/backend/migration/1671924750884-RetentionAggregation.js
+++ b/packages/backend/migration/1671924750884-RetentionAggregation.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1671926422832-RetentionAggregation2.js b/packages/backend/migration/1671926422832-RetentionAggregation2.js
index 665e24d72..f26e0f7d2 100644
--- a/packages/backend/migration/1671926422832-RetentionAggregation2.js
+++ b/packages/backend/migration/1671926422832-RetentionAggregation2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1672562400597-PerUserPvChart.js b/packages/backend/migration/1672562400597-PerUserPvChart.js
index 1fbe1eb14..844f665a8 100644
--- a/packages/backend/migration/1672562400597-PerUserPvChart.js
+++ b/packages/backend/migration/1672562400597-PerUserPvChart.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1672703171386-remove-latestRequestSentAt.js b/packages/backend/migration/1672703171386-remove-latestRequestSentAt.js
index f053e5c20..fa73fc897 100644
--- a/packages/backend/migration/1672703171386-remove-latestRequestSentAt.js
+++ b/packages/backend/migration/1672703171386-remove-latestRequestSentAt.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1672704017999-remove-lastCommunicatedAt.js b/packages/backend/migration/1672704017999-remove-lastCommunicatedAt.js
index b71f7e130..abf209162 100644
--- a/packages/backend/migration/1672704017999-remove-lastCommunicatedAt.js
+++ b/packages/backend/migration/1672704017999-remove-lastCommunicatedAt.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1672704136584-remove-latestStatus.js b/packages/backend/migration/1672704136584-remove-latestStatus.js
index f08ed96a4..d75344c05 100644
--- a/packages/backend/migration/1672704136584-remove-latestStatus.js
+++ b/packages/backend/migration/1672704136584-remove-latestStatus.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1672822262496-Flash.js b/packages/backend/migration/1672822262496-Flash.js
index e45055b3c..fd3f77d89 100644
--- a/packages/backend/migration/1672822262496-Flash.js
+++ b/packages/backend/migration/1672822262496-Flash.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1673336077243-PollChoiceLength.js b/packages/backend/migration/1673336077243-PollChoiceLength.js
index 8c4a5007e..7bd65149d 100644
--- a/packages/backend/migration/1673336077243-PollChoiceLength.js
+++ b/packages/backend/migration/1673336077243-PollChoiceLength.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1673500412259-Role.js b/packages/backend/migration/1673500412259-Role.js
index 2bf6a7f4e..6bfb31e08 100644
--- a/packages/backend/migration/1673500412259-Role.js
+++ b/packages/backend/migration/1673500412259-Role.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1673515526953-RoleColor.js b/packages/backend/migration/1673515526953-RoleColor.js
index 693dcfb0b..b856e4183 100644
--- a/packages/backend/migration/1673515526953-RoleColor.js
+++ b/packages/backend/migration/1673515526953-RoleColor.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1673522856499-RoleIroiro.js b/packages/backend/migration/1673522856499-RoleIroiro.js
index 10a6eef16..40635e50d 100644
--- a/packages/backend/migration/1673522856499-RoleIroiro.js
+++ b/packages/backend/migration/1673522856499-RoleIroiro.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1673524604156-RoleLastUsedAt.js b/packages/backend/migration/1673524604156-RoleLastUsedAt.js
index 5bbd0c39a..3bbb8000d 100644
--- a/packages/backend/migration/1673524604156-RoleLastUsedAt.js
+++ b/packages/backend/migration/1673524604156-RoleLastUsedAt.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1673570377815-RoleConditional.js b/packages/backend/migration/1673570377815-RoleConditional.js
index d2b25d121..354fd6c66 100644
--- a/packages/backend/migration/1673570377815-RoleConditional.js
+++ b/packages/backend/migration/1673570377815-RoleConditional.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1673575973645-MetaClean.js b/packages/backend/migration/1673575973645-MetaClean.js
index 7671785d9..684d62e8e 100644
--- a/packages/backend/migration/1673575973645-MetaClean.js
+++ b/packages/backend/migration/1673575973645-MetaClean.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1673783015567-Policies.js b/packages/backend/migration/1673783015567-Policies.js
index 4f76752c9..867430662 100644
--- a/packages/backend/migration/1673783015567-Policies.js
+++ b/packages/backend/migration/1673783015567-Policies.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1673812883772-firstRetrievedAt.js b/packages/backend/migration/1673812883772-firstRetrievedAt.js
index 82990e30b..4111cc4ad 100644
--- a/packages/backend/migration/1673812883772-firstRetrievedAt.js
+++ b/packages/backend/migration/1673812883772-firstRetrievedAt.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1674086433654-flashScriptLength.js b/packages/backend/migration/1674086433654-flashScriptLength.js
index 996fe8c69..cdfb812ba 100644
--- a/packages/backend/migration/1674086433654-flashScriptLength.js
+++ b/packages/backend/migration/1674086433654-flashScriptLength.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1674118260469-achievement.js b/packages/backend/migration/1674118260469-achievement.js
index 5d79dc669..072cf81ec 100644
--- a/packages/backend/migration/1674118260469-achievement.js
+++ b/packages/backend/migration/1674118260469-achievement.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1674255666603-loggedInDates.js b/packages/backend/migration/1674255666603-loggedInDates.js
index a6cf4b400..a2a217da9 100644
--- a/packages/backend/migration/1674255666603-loggedInDates.js
+++ b/packages/backend/migration/1674255666603-loggedInDates.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1675053125067-fixforeignkeyreports.js b/packages/backend/migration/1675053125067-fixforeignkeyreports.js
index d24dc5ec5..2ca383f56 100644
--- a/packages/backend/migration/1675053125067-fixforeignkeyreports.js
+++ b/packages/backend/migration/1675053125067-fixforeignkeyreports.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1675404035646-cleanup.js b/packages/backend/migration/1675404035646-cleanup.js
index c4e4332bb..5cd5f5534 100644
--- a/packages/backend/migration/1675404035646-cleanup.js
+++ b/packages/backend/migration/1675404035646-cleanup.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1675557528704-role-icon-badge.js b/packages/backend/migration/1675557528704-role-icon-badge.js
index ee39c07a5..48684075d 100644
--- a/packages/backend/migration/1675557528704-role-icon-badge.js
+++ b/packages/backend/migration/1675557528704-role-icon-badge.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1676434944993-drop-group.js b/packages/backend/migration/1676434944993-drop-group.js
index 1db2d5818..2df8a2d78 100644
--- a/packages/backend/migration/1676434944993-drop-group.js
+++ b/packages/backend/migration/1676434944993-drop-group.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1676438468213-ad3.js b/packages/backend/migration/1676438468213-ad3.js
index 8347f56b9..83ca5828e 100644
--- a/packages/backend/migration/1676438468213-ad3.js
+++ b/packages/backend/migration/1676438468213-ad3.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1677054292210-ad4.js b/packages/backend/migration/1677054292210-ad4.js
index 037e21059..11c42dd35 100644
--- a/packages/backend/migration/1677054292210-ad4.js
+++ b/packages/backend/migration/1677054292210-ad4.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1677570181236-role-assignment-expires-at.js b/packages/backend/migration/1677570181236-role-assignment-expires-at.js
index e44bca1d2..6fe32ffeb 100644
--- a/packages/backend/migration/1677570181236-role-assignment-expires-at.js
+++ b/packages/backend/migration/1677570181236-role-assignment-expires-at.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1678164627293-per-note-reaction-acceptance.js b/packages/backend/migration/1678164627293-per-note-reaction-acceptance.js
index c85aafbd4..44c807499 100644
--- a/packages/backend/migration/1678164627293-per-note-reaction-acceptance.js
+++ b/packages/backend/migration/1678164627293-per-note-reaction-acceptance.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1678426061773-tweak-varchar-length.js b/packages/backend/migration/1678426061773-tweak-varchar-length.js
index 2541f99a1..74c4fd671 100644
--- a/packages/backend/migration/1678426061773-tweak-varchar-length.js
+++ b/packages/backend/migration/1678426061773-tweak-varchar-length.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1678427401214-remove-unused.js b/packages/backend/migration/1678427401214-remove-unused.js
index 59f42da08..e398b3700 100644
--- a/packages/backend/migration/1678427401214-remove-unused.js
+++ b/packages/backend/migration/1678427401214-remove-unused.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1678602320354-role-display-order.js b/packages/backend/migration/1678602320354-role-display-order.js
index 0ab7b0c3e..d3cc9792c 100644
--- a/packages/backend/migration/1678602320354-role-display-order.js
+++ b/packages/backend/migration/1678602320354-role-display-order.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1678694614599-sensitive-words.js b/packages/backend/migration/1678694614599-sensitive-words.js
index 5f69424ec..13361f597 100644
--- a/packages/backend/migration/1678694614599-sensitive-words.js
+++ b/packages/backend/migration/1678694614599-sensitive-words.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1678869617549-retention-date-key.js b/packages/backend/migration/1678869617549-retention-date-key.js
index 55bf6248e..1b995385b 100644
--- a/packages/backend/migration/1678869617549-retention-date-key.js
+++ b/packages/backend/migration/1678869617549-retention-date-key.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1678945242650-add-props-for-custom-emoji.js b/packages/backend/migration/1678945242650-add-props-for-custom-emoji.js
index 0054e78f8..5d1218be1 100644
--- a/packages/backend/migration/1678945242650-add-props-for-custom-emoji.js
+++ b/packages/backend/migration/1678945242650-add-props-for-custom-emoji.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1678953978856-clip-favorite.js b/packages/backend/migration/1678953978856-clip-favorite.js
index 13145497b..9d706c4da 100644
--- a/packages/backend/migration/1678953978856-clip-favorite.js
+++ b/packages/backend/migration/1678953978856-clip-favorite.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1679309757174-antenna-active.js b/packages/backend/migration/1679309757174-antenna-active.js
index 0b2bcc69f..dadea25a7 100644
--- a/packages/backend/migration/1679309757174-antenna-active.js
+++ b/packages/backend/migration/1679309757174-antenna-active.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1679639483253-enableChartsForRemoteUser.js b/packages/backend/migration/1679639483253-enableChartsForRemoteUser.js
index 68576064f..f2a13100e 100644
--- a/packages/backend/migration/1679639483253-enableChartsForRemoteUser.js
+++ b/packages/backend/migration/1679639483253-enableChartsForRemoteUser.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1679651580149-cleanup.js b/packages/backend/migration/1679651580149-cleanup.js
index 7049891cf..efee339c4 100644
--- a/packages/backend/migration/1679651580149-cleanup.js
+++ b/packages/backend/migration/1679651580149-cleanup.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1679652081809-enableChartsForFederatedInstances.js b/packages/backend/migration/1679652081809-enableChartsForFederatedInstances.js
index f3a07cbd1..67be10e6f 100644
--- a/packages/backend/migration/1679652081809-enableChartsForFederatedInstances.js
+++ b/packages/backend/migration/1679652081809-enableChartsForFederatedInstances.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1680228513388-channelFavorite.js b/packages/backend/migration/1680228513388-channelFavorite.js
index 58eb7359f..866173305 100644
--- a/packages/backend/migration/1680228513388-channelFavorite.js
+++ b/packages/backend/migration/1680228513388-channelFavorite.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1680238118084-channelNotePining.js b/packages/backend/migration/1680238118084-channelNotePining.js
index f1f192d7b..78bafc023 100644
--- a/packages/backend/migration/1680238118084-channelNotePining.js
+++ b/packages/backend/migration/1680238118084-channelNotePining.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1680491187535-cleanup.js b/packages/backend/migration/1680491187535-cleanup.js
index 006b403bd..f0b1bccda 100644
--- a/packages/backend/migration/1680491187535-cleanup.js
+++ b/packages/backend/migration/1680491187535-cleanup.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1680582195041-cleanup.js b/packages/backend/migration/1680582195041-cleanup.js
index 7d941be8c..83d04b618 100644
--- a/packages/backend/migration/1680582195041-cleanup.js
+++ b/packages/backend/migration/1680582195041-cleanup.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1680702787050-UserMemo.js b/packages/backend/migration/1680702787050-UserMemo.js
index 104d66ce2..3f7afe865 100644
--- a/packages/backend/migration/1680702787050-UserMemo.js
+++ b/packages/backend/migration/1680702787050-UserMemo.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1680775031481-avatar-url-and-banner-url.js b/packages/backend/migration/1680775031481-avatar-url-and-banner-url.js
index c613ee511..49295e70e 100644
--- a/packages/backend/migration/1680775031481-avatar-url-and-banner-url.js
+++ b/packages/backend/migration/1680775031481-avatar-url-and-banner-url.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1680931179228-account-move.js b/packages/backend/migration/1680931179228-account-move.js
index 203d838f5..a8b5e4df6 100644
--- a/packages/backend/migration/1680931179228-account-move.js
+++ b/packages/backend/migration/1680931179228-account-move.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1681400427971-serverRules.js b/packages/backend/migration/1681400427971-serverRules.js
index 70a74ebff..176783b50 100644
--- a/packages/backend/migration/1681400427971-serverRules.js
+++ b/packages/backend/migration/1681400427971-serverRules.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1681870960239-RoleTLSetting.js b/packages/backend/migration/1681870960239-RoleTLSetting.js
index 07b9bc4e3..2999051a3 100644
--- a/packages/backend/migration/1681870960239-RoleTLSetting.js
+++ b/packages/backend/migration/1681870960239-RoleTLSetting.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1682190963894-movedAt.js b/packages/backend/migration/1682190963894-movedAt.js
index cc33da874..852cf5896 100644
--- a/packages/backend/migration/1682190963894-movedAt.js
+++ b/packages/backend/migration/1682190963894-movedAt.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1682754135458-preservedUsernames.js b/packages/backend/migration/1682754135458-preservedUsernames.js
index 61723e4ab..8aae3c205 100644
--- a/packages/backend/migration/1682754135458-preservedUsernames.js
+++ b/packages/backend/migration/1682754135458-preservedUsernames.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1682985520254-channelColor.js b/packages/backend/migration/1682985520254-channelColor.js
index 43f1f4833..3c7f3101a 100644
--- a/packages/backend/migration/1682985520254-channelColor.js
+++ b/packages/backend/migration/1682985520254-channelColor.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1683328299359-channelArchive.js b/packages/backend/migration/1683328299359-channelArchive.js
index 759dcbfda..10a87246d 100644
--- a/packages/backend/migration/1683328299359-channelArchive.js
+++ b/packages/backend/migration/1683328299359-channelArchive.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1683682889948-prevent-ai-larning.js b/packages/backend/migration/1683682889948-prevent-ai-larning.js
index 1dc3eec21..167c9f71d 100644
--- a/packages/backend/migration/1683682889948-prevent-ai-larning.js
+++ b/packages/backend/migration/1683682889948-prevent-ai-larning.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1683683083083-public-reactions-default-true.js b/packages/backend/migration/1683683083083-public-reactions-default-true.js
index 32cbe33b2..f416e5ffa 100644
--- a/packages/backend/migration/1683683083083-public-reactions-default-true.js
+++ b/packages/backend/migration/1683683083083-public-reactions-default-true.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1683789676867-fix-typo.js b/packages/backend/migration/1683789676867-fix-typo.js
index 5cd686e2f..d647d20e6 100644
--- a/packages/backend/migration/1683789676867-fix-typo.js
+++ b/packages/backend/migration/1683789676867-fix-typo.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1683847157541-UserList.js b/packages/backend/migration/1683847157541-UserList.js
index f9e79a43a..14a52d64f 100644
--- a/packages/backend/migration/1683847157541-UserList.js
+++ b/packages/backend/migration/1683847157541-UserList.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1683869758873-UserListFavorites.js b/packages/backend/migration/1683869758873-UserListFavorites.js
index aef4597a7..aae405684 100644
--- a/packages/backend/migration/1683869758873-UserListFavorites.js
+++ b/packages/backend/migration/1683869758873-UserListFavorites.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1684206886988-remove-showTimelineReplies.js b/packages/backend/migration/1684206886988-remove-showTimelineReplies.js
index a0798f85c..398f9f080 100644
--- a/packages/backend/migration/1684206886988-remove-showTimelineReplies.js
+++ b/packages/backend/migration/1684206886988-remove-showTimelineReplies.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1684386446061-emoji-improve.js b/packages/backend/migration/1684386446061-emoji-improve.js
index 7bded84cc..e7e94769b 100644
--- a/packages/backend/migration/1684386446061-emoji-improve.js
+++ b/packages/backend/migration/1684386446061-emoji-improve.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1685973839966-errorImageUrl.js b/packages/backend/migration/1685973839966-errorImageUrl.js
index c4a1567b9..ca685ef08 100644
--- a/packages/backend/migration/1685973839966-errorImageUrl.js
+++ b/packages/backend/migration/1685973839966-errorImageUrl.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1686908762393-AbuseReportResolver.js b/packages/backend/migration/1686908762393-AbuseReportResolver.js
new file mode 100644
index 000000000..94698736d
--- /dev/null
+++ b/packages/backend/migration/1686908762393-AbuseReportResolver.js
@@ -0,0 +1,24 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class AbuseReportResolver1686908762393 {
+ name = 'AbuseReportResolver1686908762393'
+
+ async up(queryRunner) {
+ await queryRunner.query(`CREATE TYPE "public"."abuse_report_resolver_expiresat_enum" AS ENUM('1hour', '12hours', '1day', '1week', '1month', '3months', '6months', '1year', 'indefinitely')`);
+ await queryRunner.query(`CREATE TABLE "abuse_report_resolver" ("id" character varying(32) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL, "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL, "name" character varying(256) NOT NULL, "targetUserPattern" character varying(1024), "reporterPattern" character varying(1024), "reportContentPattern" character varying(1024), "expirationDate" TIMESTAMP WITH TIME ZONE, "expiresAt" "public"."abuse_report_resolver_expiresat_enum" NOT NULL, "forward" boolean NOT NULL, CONSTRAINT "PK_093500bf1bb38880d38b1bb41dc" PRIMARY KEY ("id")); COMMENT ON COLUMN "abuse_report_resolver"."createdAt" IS 'The created date of AbuseReportResolver'; COMMENT ON COLUMN "abuse_report_resolver"."updatedAt" IS 'The updated date of AbuseReportResolver'; COMMENT ON COLUMN "abuse_report_resolver"."expirationDate" IS 'The expiration date of AbuseReportResolver'`);
+ await queryRunner.query(`CREATE INDEX "IDX_fdd74ab625ed0f6a30c47b00e0" ON "abuse_report_resolver" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_d90c2c0e555b1eb2e4f19c9ad4" ON "abuse_report_resolver" ("updatedAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_e83a32a146021c72ba9bde6675" ON "abuse_report_resolver" ("expirationDate") `);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`DROP INDEX "public"."IDX_e83a32a146021c72ba9bde6675"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_d90c2c0e555b1eb2e4f19c9ad4"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_fdd74ab625ed0f6a30c47b00e0"`);
+ await queryRunner.query(`DROP TABLE "abuse_report_resolver"`);
+ await queryRunner.query(`DROP TYPE "public"."abuse_report_resolver_expiresat_enum"`);
+ }
+}
diff --git a/packages/backend/migration/1688280713783-add-meta-options.js b/packages/backend/migration/1688280713783-add-meta-options.js
index ade8378c0..77d193492 100644
--- a/packages/backend/migration/1688280713783-add-meta-options.js
+++ b/packages/backend/migration/1688280713783-add-meta-options.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1688647797135-userannouncement.js b/packages/backend/migration/1688647797135-userannouncement.js
new file mode 100644
index 000000000..c472f40db
--- /dev/null
+++ b/packages/backend/migration/1688647797135-userannouncement.js
@@ -0,0 +1,20 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class Userannouncement1688647797135 {
+ name = 'Userannouncement1688647797135'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "announcement" ADD COLUMN "userId" character varying(32)`);
+ await queryRunner.query(`ALTER TABLE "announcement" ADD COLUMN "closeDuration" integer NOT NULL DEFAULT 0`);
+ await queryRunner.query(`CREATE INDEX "IDX_fd25dfe3da37df1715f11ba6ec" ON "announcement" ("userId") `);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`DROP INDEX "public"."IDX_fd25dfe3da37df1715f11ba6ec"`);
+ await queryRunner.query(`ALTER TABLE "announcement" DROP COLUMN "userId"`);
+ await queryRunner.query(`ALTER TABLE "announcement" DROP COLUMN "closeDuration"`);
+ }
+}
diff --git a/packages/backend/migration/1688720440658-refactor-invite-system.js b/packages/backend/migration/1688720440658-refactor-invite-system.js
index 20f178612..ea192a195 100644
--- a/packages/backend/migration/1688720440658-refactor-invite-system.js
+++ b/packages/backend/migration/1688720440658-refactor-invite-system.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1688880985544-add-index-to-relations.js b/packages/backend/migration/1688880985544-add-index-to-relations.js
index 6daac2032..c18903641 100644
--- a/packages/backend/migration/1688880985544-add-index-to-relations.js
+++ b/packages/backend/migration/1688880985544-add-index-to-relations.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1689102832143-nsfw-cache.js b/packages/backend/migration/1689102832143-nsfw-cache.js
index 419588296..90d453418 100644
--- a/packages/backend/migration/1689102832143-nsfw-cache.js
+++ b/packages/backend/migration/1689102832143-nsfw-cache.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1689325027964-UserBlacklistAnntena.js b/packages/backend/migration/1689325027964-UserBlacklistAnntena.js
index ce246b20f..2dc777449 100644
--- a/packages/backend/migration/1689325027964-UserBlacklistAnntena.js
+++ b/packages/backend/migration/1689325027964-UserBlacklistAnntena.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class UserBlacklistAnntena1689325027964 {
name = 'UserBlacklistAnntena1689325027964'
diff --git a/packages/backend/migration/1690417561185-fix-renote-muting.js b/packages/backend/migration/1690417561185-fix-renote-muting.js
index 14150b036..d9604ca26 100644
--- a/packages/backend/migration/1690417561185-fix-renote-muting.js
+++ b/packages/backend/migration/1690417561185-fix-renote-muting.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class FixRenoteMuting1690417561185 {
name = 'FixRenoteMuting1690417561185'
diff --git a/packages/backend/migration/1690417561186-ChangeCacheRemoteFilesDefault.js b/packages/backend/migration/1690417561186-ChangeCacheRemoteFilesDefault.js
index 7eda5debe..9bccdb3bb 100644
--- a/packages/backend/migration/1690417561186-ChangeCacheRemoteFilesDefault.js
+++ b/packages/backend/migration/1690417561186-ChangeCacheRemoteFilesDefault.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class ChangeCacheRemoteFilesDefault1690417561186 {
name = 'ChangeCacheRemoteFilesDefault1690417561186'
diff --git a/packages/backend/migration/1690417561187-Fix.js b/packages/backend/migration/1690417561187-Fix.js
index e780e66d7..7f1d62d68 100644
--- a/packages/backend/migration/1690417561187-Fix.js
+++ b/packages/backend/migration/1690417561187-Fix.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class Fix1690417561187 {
name = 'Fix1690417561187'
diff --git a/packages/backend/migration/1690463372775-announcement-display-order.js b/packages/backend/migration/1690463372775-announcement-display-order.js
new file mode 100644
index 000000000..8c6c6211d
--- /dev/null
+++ b/packages/backend/migration/1690463372775-announcement-display-order.js
@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class AnnouncementDisplayOrder1690463372775 {
+ name = 'AnnouncementDisplayOrder1690463372775'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "announcement" ADD "displayOrder" integer NOT NULL DEFAULT '0'`);
+ await queryRunner.query(`CREATE INDEX "IDX_b64d293ca4bef21e91963054b0" ON "announcement" ("displayOrder") `);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`DROP INDEX "public"."IDX_b64d293ca4bef21e91963054b0"`);
+ await queryRunner.query(`ALTER TABLE "announcement" DROP COLUMN "displayOrder"`);
+ }
+}
diff --git a/packages/backend/migration/1690569881926-user-2fa-backup-codes.js b/packages/backend/migration/1690569881926-user-2fa-backup-codes.js
index 2049df8ea..a3ef8dcf0 100644
--- a/packages/backend/migration/1690569881926-user-2fa-backup-codes.js
+++ b/packages/backend/migration/1690569881926-user-2fa-backup-codes.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class User2faBackupCodes1690569881926 {
name = 'User2faBackupCodes1690569881926'
diff --git a/packages/backend/migration/1690782653311-SensitiveChannel.js b/packages/backend/migration/1690782653311-SensitiveChannel.js
index e76dda518..afec1a215 100644
--- a/packages/backend/migration/1690782653311-SensitiveChannel.js
+++ b/packages/backend/migration/1690782653311-SensitiveChannel.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1690796169261-play-visibility.js b/packages/backend/migration/1690796169261-play-visibility.js
index c57fa7a10..5e5843bfe 100644
--- a/packages/backend/migration/1690796169261-play-visibility.js
+++ b/packages/backend/migration/1690796169261-play-visibility.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1691317808362-customemoji-restricted-roles.js b/packages/backend/migration/1691317808362-customemoji-restricted-roles.js
new file mode 100644
index 000000000..d09d5e9b1
--- /dev/null
+++ b/packages/backend/migration/1691317808362-customemoji-restricted-roles.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class CustomemojiRestrictedRoles1691317808362 {
+ name = 'CustomemojiRestrictedRoles1691317808362'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "emoji" ADD "roleIdsThatCanNotBeUsedThisEmojiAsReaction" character varying(128) array NOT NULL DEFAULT '{}'`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "roleIdsThatCanNotBeUsedThisEmojiAsReaction"`);
+ }
+}
diff --git a/packages/backend/migration/1691649257651-refine-announcement.js b/packages/backend/migration/1691649257651-refine-announcement.js
index d8d63f310..5bdb17592 100644
--- a/packages/backend/migration/1691649257651-refine-announcement.js
+++ b/packages/backend/migration/1691649257651-refine-announcement.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class RefineAnnouncement1691649257651 {
name = 'RefineAnnouncement1691649257651'
@@ -6,19 +11,19 @@ export class RefineAnnouncement1691649257651 {
await queryRunner.query(`ALTER TABLE "announcement" ADD "needConfirmationToRead" boolean NOT NULL DEFAULT false`);
await queryRunner.query(`ALTER TABLE "announcement" ADD "isActive" boolean NOT NULL DEFAULT true`);
await queryRunner.query(`ALTER TABLE "announcement" ADD "forExistingUsers" boolean NOT NULL DEFAULT false`);
- await queryRunner.query(`ALTER TABLE "announcement" ADD "userId" character varying(32)`);
+ // await queryRunner.query(`ALTER TABLE "announcement" ADD "userId" character varying(32)`);
await queryRunner.query(`CREATE INDEX "IDX_bc1afcc8ef7e9400cdc3c0a87e" ON "announcement" ("isActive") `);
await queryRunner.query(`CREATE INDEX "IDX_da795d3a83187e8832005ba19d" ON "announcement" ("forExistingUsers") `);
- await queryRunner.query(`CREATE INDEX "IDX_fd25dfe3da37df1715f11ba6ec" ON "announcement" ("userId") `);
- await queryRunner.query(`ALTER TABLE "announcement" ADD CONSTRAINT "FK_fd25dfe3da37df1715f11ba6ec8" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
+ // await queryRunner.query(`CREATE INDEX "IDX_fd25dfe3da37df1715f11ba6ec" ON "announcement" ("userId") `);
+ // await queryRunner.query(`ALTER TABLE "announcement" ADD CONSTRAINT "FK_fd25dfe3da37df1715f11ba6ec8" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
async down(queryRunner) {
- await queryRunner.query(`ALTER TABLE "announcement" DROP CONSTRAINT "FK_fd25dfe3da37df1715f11ba6ec8"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_fd25dfe3da37df1715f11ba6ec"`);
+ // await queryRunner.query(`ALTER TABLE "announcement" DROP CONSTRAINT "FK_fd25dfe3da37df1715f11ba6ec8"`);
+ // await queryRunner.query(`DROP INDEX "public"."IDX_fd25dfe3da37df1715f11ba6ec"`);
await queryRunner.query(`DROP INDEX "public"."IDX_da795d3a83187e8832005ba19d"`);
await queryRunner.query(`DROP INDEX "public"."IDX_bc1afcc8ef7e9400cdc3c0a87e"`);
- await queryRunner.query(`ALTER TABLE "announcement" DROP COLUMN "userId"`);
+ // await queryRunner.query(`ALTER TABLE "announcement" DROP COLUMN "userId"`);
await queryRunner.query(`ALTER TABLE "announcement" DROP COLUMN "forExistingUsers"`);
await queryRunner.query(`ALTER TABLE "announcement" DROP COLUMN "isActive"`);
await queryRunner.query(`ALTER TABLE "announcement" DROP COLUMN "needConfirmationToRead"`);
diff --git a/packages/backend/migration/1691657412740-refine-announcement-2.js b/packages/backend/migration/1691657412740-refine-announcement-2.js
index 8791f99f4..67edf1965 100644
--- a/packages/backend/migration/1691657412740-refine-announcement-2.js
+++ b/packages/backend/migration/1691657412740-refine-announcement-2.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class RefineAnnouncement21691657412740 {
name = 'RefineAnnouncement21691657412740'
diff --git a/packages/backend/migration/1691959191872-passkey-support.js b/packages/backend/migration/1691959191872-passkey-support.js
index 55b571d60..1da9bdb36 100644
--- a/packages/backend/migration/1691959191872-passkey-support.js
+++ b/packages/backend/migration/1691959191872-passkey-support.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1694850832075-server-icons-and-manifest.js b/packages/backend/migration/1694850832075-server-icons-and-manifest.js
index 1bd8979d9..235bf0574 100644
--- a/packages/backend/migration/1694850832075-server-icons-and-manifest.js
+++ b/packages/backend/migration/1694850832075-server-icons-and-manifest.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1694915420864-clipped-count.js b/packages/backend/migration/1694915420864-clipped-count.js
index 1ad8e04ce..6d70aaecf 100644
--- a/packages/backend/migration/1694915420864-clipped-count.js
+++ b/packages/backend/migration/1694915420864-clipped-count.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1695260774117-verified-links.js b/packages/backend/migration/1695260774117-verified-links.js
index 18e0571d8..64c8a9ad8 100644
--- a/packages/backend/migration/1695260774117-verified-links.js
+++ b/packages/backend/migration/1695260774117-verified-links.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class VerifiedLinks1695260774117 {
name = 'VerifiedLinks1695260774117'
diff --git a/packages/backend/migration/1695288787870-following-notify.js b/packages/backend/migration/1695288787870-following-notify.js
index e7e2194b1..b3f78d5f2 100644
--- a/packages/backend/migration/1695288787870-following-notify.js
+++ b/packages/backend/migration/1695288787870-following-notify.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class FollowingNotify1695288787870 {
name = 'FollowingNotify1695288787870'
diff --git a/packages/backend/migration/1695440131671-short-name.js b/packages/backend/migration/1695440131671-short-name.js
index 2c37297fc..fdc256caf 100644
--- a/packages/backend/migration/1695440131671-short-name.js
+++ b/packages/backend/migration/1695440131671-short-name.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class ShortName1695440131671 {
name = 'ShortName1695440131671'
diff --git a/packages/backend/migration/1695605508898-mutingNotificationTypes.js b/packages/backend/migration/1695605508898-mutingNotificationTypes.js
index 8c0e52a2f..67d424314 100644
--- a/packages/backend/migration/1695605508898-mutingNotificationTypes.js
+++ b/packages/backend/migration/1695605508898-mutingNotificationTypes.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class MutingNotificationTypes1695605508898 {
name = 'MutingNotificationTypes1695605508898'
diff --git a/packages/backend/migration/1695901659683-note-updated-at.js b/packages/backend/migration/1695901659683-note-updated-at.js
index d8a151a1f..e828fb1a6 100644
--- a/packages/backend/migration/1695901659683-note-updated-at.js
+++ b/packages/backend/migration/1695901659683-note-updated-at.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class NoteUpdatedAt1695901659683 {
name = 'NoteUpdatedAt1695901659683'
diff --git a/packages/backend/migration/1695944637565-notificationRecieveConfig.js b/packages/backend/migration/1695944637565-notificationRecieveConfig.js
index 42d3dce5d..04a40993c 100644
--- a/packages/backend/migration/1695944637565-notificationRecieveConfig.js
+++ b/packages/backend/migration/1695944637565-notificationRecieveConfig.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1696003580220-AddSomeUrls.js b/packages/backend/migration/1696003580220-AddSomeUrls.js
index 683aa5eee..213e39e7a 100644
--- a/packages/backend/migration/1696003580220-AddSomeUrls.js
+++ b/packages/backend/migration/1696003580220-AddSomeUrls.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1696222183852-withReplies.js b/packages/backend/migration/1696222183852-withReplies.js
index 9f65d5f6a..84a5511d1 100644
--- a/packages/backend/migration/1696222183852-withReplies.js
+++ b/packages/backend/migration/1696222183852-withReplies.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1696323464251-user-list-membership.js b/packages/backend/migration/1696323464251-user-list-membership.js
index 7534040c4..dc1d438dd 100644
--- a/packages/backend/migration/1696323464251-user-list-membership.js
+++ b/packages/backend/migration/1696323464251-user-list-membership.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class UserListMembership1696323464251 {
name = 'UserListMembership1696323464251'
diff --git a/packages/backend/migration/1696331570827-hibernation.js b/packages/backend/migration/1696331570827-hibernation.js
index 119d35913..1487ece77 100644
--- a/packages/backend/migration/1696331570827-hibernation.js
+++ b/packages/backend/migration/1696331570827-hibernation.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class Hibernation1696331570827 {
name = 'Hibernation1696331570827'
diff --git a/packages/backend/migration/1696332072038-clean.js b/packages/backend/migration/1696332072038-clean.js
index 97dba655f..92a6810d6 100644
--- a/packages/backend/migration/1696332072038-clean.js
+++ b/packages/backend/migration/1696332072038-clean.js
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
export class Clean1696332072038 {
name = 'Clean1696332072038'
diff --git a/packages/backend/migration/1696373953614-meta-cache-settings.js b/packages/backend/migration/1696373953614-meta-cache-settings.js
index f994b76ef..cbbe471d4 100644
--- a/packages/backend/migration/1696373953614-meta-cache-settings.js
+++ b/packages/backend/migration/1696373953614-meta-cache-settings.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1696388600237-revert-note-edit.js b/packages/backend/migration/1696388600237-revert-note-edit.js
index 83bc552c3..d353c851d 100644
--- a/packages/backend/migration/1696388600237-revert-note-edit.js
+++ b/packages/backend/migration/1696388600237-revert-note-edit.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1696405744672-clean-up.js b/packages/backend/migration/1696405744672-clean-up.js
index 5ec89b08f..4e1ee6cd6 100644
--- a/packages/backend/migration/1696405744672-clean-up.js
+++ b/packages/backend/migration/1696405744672-clean-up.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1696569742153-clean-up.js b/packages/backend/migration/1696569742153-clean-up.js
index de48fab5a..b7c981bab 100644
--- a/packages/backend/migration/1696569742153-clean-up.js
+++ b/packages/backend/migration/1696569742153-clean-up.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1696581429196-clean-up.js b/packages/backend/migration/1696581429196-clean-up.js
index da69b4e9d..b6723f343 100644
--- a/packages/backend/migration/1696581429196-clean-up.js
+++ b/packages/backend/migration/1696581429196-clean-up.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1696743032098-AdsOnStream.js b/packages/backend/migration/1696743032098-AdsOnStream.js
index c86ee8488..43b9f83e6 100644
--- a/packages/backend/migration/1696743032098-AdsOnStream.js
+++ b/packages/backend/migration/1696743032098-AdsOnStream.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1696807733453-userListUserId.js b/packages/backend/migration/1696807733453-userListUserId.js
index e897da035..b57350175 100644
--- a/packages/backend/migration/1696807733453-userListUserId.js
+++ b/packages/backend/migration/1696807733453-userListUserId.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1696808725134-userListUserId-2.js b/packages/backend/migration/1696808725134-userListUserId-2.js
index 5bcb5aedc..cc504e761 100644
--- a/packages/backend/migration/1696808725134-userListUserId-2.js
+++ b/packages/backend/migration/1696808725134-userListUserId-2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1697247230117-InstanceSilence.js b/packages/backend/migration/1697247230117-InstanceSilence.js
index 5fdbca3b2..309d81708 100644
--- a/packages/backend/migration/1697247230117-InstanceSilence.js
+++ b/packages/backend/migration/1697247230117-InstanceSilence.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1697420555911-deleteCreatedAt.js b/packages/backend/migration/1697420555911-deleteCreatedAt.js
deleted file mode 100644
index 958d61a34..000000000
--- a/packages/backend/migration/1697420555911-deleteCreatedAt.js
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
- * SPDX-License-Identifier: AGPL-3.0-only
- */
-
-export class DeleteCreatedAt1697420555911 {
- name = 'DeleteCreatedAt1697420555911'
-
- async up(queryRunner) {
- await queryRunner.query(`DROP INDEX "public"."IDX_02878d441ceae15ce060b73daf"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_c8dfad3b72196dd1d6b5db168a"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_e11e649824a45d8ed01d597fd9"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_db2098070b2b5a523c58181f74"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_048a757923ed8b157e9895da53"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_1129c2ef687fc272df040bafaa"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_118ec703e596086fc4515acb39"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_b9a354f7941c1e779f3b33aea6"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_71cb7b435b7c0d4843317e7e16"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_11e71f2511589dcc8a4d3214f9"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_735a5544f9249d412255f47f95"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_582f8fab771a9040a12961f3e7"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_8f1a239bd077c8864a20c62c2c"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_f86d57fbca33c7a4e6897490cc"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_d1259a2c2b7bb413ff449e8711"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_fbb4297c927a9b85e9cefa2eb1"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_0fb627e1c2f753262a74f0562d"`);
- await queryRunner.query(`DROP INDEX "public"."IDX_149d2e44785707548c82999b01"`);
- await queryRunner.query(`ALTER TABLE "drive_folder" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "drive_file" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "user" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "app" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "access_token" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "ad" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "announcement" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "announcement_read" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "user_list" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "antenna" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "auth_session" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "blocking" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "channel" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "channel_following" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "channel_favorite" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "clip" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "clip_favorite" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "following" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "follow_request" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "gallery_post" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "gallery_like" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "moderation_log" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "muting" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "renote_muting" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "note_favorite" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "note_reaction" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "note_thread_muting" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "page" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "page_like" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "password_reset_request" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "poll_vote" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "promo_read" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "registration_ticket" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "registry_item" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "signin" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "sw_subscription" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "user_list_favorite" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "user_list_membership" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "user_note_pining" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "user_pending" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "webhook" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "role" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "role_assignment" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "flash" DROP COLUMN "createdAt"`);
- await queryRunner.query(`ALTER TABLE "flash_like" DROP COLUMN "createdAt"`);
- }
-
- async down(queryRunner) {
- await queryRunner.query(`ALTER TABLE "flash_like" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "flash" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "role_assignment" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "role" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "webhook" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "user_pending" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "user_note_pining" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "user_list_membership" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "user_list_favorite" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "sw_subscription" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "signin" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "registry_item" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "registration_ticket" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "promo_read" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "poll_vote" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "password_reset_request" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "page_like" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "page" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "note_thread_muting" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "note_reaction" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "note_favorite" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "renote_muting" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "muting" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "moderation_log" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "gallery_like" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "gallery_post" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "follow_request" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "following" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "clip_favorite" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "note" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "clip" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "channel_favorite" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "channel_following" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "channel" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "blocking" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "auth_session" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "antenna" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "user_list" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "announcement_read" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "announcement" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "ad" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "access_token" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "app" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "user" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "drive_file" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`ALTER TABLE "drive_folder" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL`);
- await queryRunner.query(`CREATE INDEX "IDX_149d2e44785707548c82999b01" ON "flash" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_0fb627e1c2f753262a74f0562d" ON "poll_vote" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_fbb4297c927a9b85e9cefa2eb1" ON "page" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_d1259a2c2b7bb413ff449e8711" ON "renote_muting" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_f86d57fbca33c7a4e6897490cc" ON "muting" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_8f1a239bd077c8864a20c62c2c" ON "gallery_post" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_582f8fab771a9040a12961f3e7" ON "following" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_735a5544f9249d412255f47f95" ON "channel_favorite" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_11e71f2511589dcc8a4d3214f9" ON "channel_following" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_71cb7b435b7c0d4843317e7e16" ON "channel" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_b9a354f7941c1e779f3b33aea6" ON "blocking" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_118ec703e596086fc4515acb39" ON "announcement" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_1129c2ef687fc272df040bafaa" ON "ad" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_048a757923ed8b157e9895da53" ON "app" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_db2098070b2b5a523c58181f74" ON "abuse_user_report" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_e11e649824a45d8ed01d597fd9" ON "user" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_c8dfad3b72196dd1d6b5db168a" ON "drive_file" ("createdAt") `);
- await queryRunner.query(`CREATE INDEX "IDX_02878d441ceae15ce060b73daf" ON "drive_folder" ("createdAt") `);
- }
-}
diff --git a/packages/backend/migration/1697436246389-antenna-localOnly.js b/packages/backend/migration/1697436246389-antenna-localOnly.js
index 022867329..d7c0ca651 100644
--- a/packages/backend/migration/1697436246389-antenna-localOnly.js
+++ b/packages/backend/migration/1697436246389-antenna-localOnly.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1697441463087-FollowRequestWithReplies.js b/packages/backend/migration/1697441463087-FollowRequestWithReplies.js
index 214c6f668..58b61aff6 100644
--- a/packages/backend/migration/1697441463087-FollowRequestWithReplies.js
+++ b/packages/backend/migration/1697441463087-FollowRequestWithReplies.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1697673894459-note-reactionAndUserPairCache.js b/packages/backend/migration/1697673894459-note-reactionAndUserPairCache.js
index fe0ea282d..fab07fd3f 100644
--- a/packages/backend/migration/1697673894459-note-reactionAndUserPairCache.js
+++ b/packages/backend/migration/1697673894459-note-reactionAndUserPairCache.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1697847397844-avatar-decoration.js b/packages/backend/migration/1697847397844-avatar-decoration.js
index 1f2213974..32ee47e96 100644
--- a/packages/backend/migration/1697847397844-avatar-decoration.js
+++ b/packages/backend/migration/1697847397844-avatar-decoration.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1697941908548-avatar-decoration2.js b/packages/backend/migration/1697941908548-avatar-decoration2.js
index 9d15c1c3d..58344e2bb 100644
--- a/packages/backend/migration/1697941908548-avatar-decoration2.js
+++ b/packages/backend/migration/1697941908548-avatar-decoration2.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1698041201306-enable-ftt.js b/packages/backend/migration/1698041201306-enable-ftt.js
index 6769ed53b..c67dda6f5 100644
--- a/packages/backend/migration/1698041201306-enable-ftt.js
+++ b/packages/backend/migration/1698041201306-enable-ftt.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1698840138000-add-allow-renote-to-external.js b/packages/backend/migration/1698840138000-add-allow-renote-to-external.js
index 0edf29884..8ce35b0f6 100644
--- a/packages/backend/migration/1698840138000-add-allow-renote-to-external.js
+++ b/packages/backend/migration/1698840138000-add-allow-renote-to-external.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1699141698112-announcement-silence.js b/packages/backend/migration/1699141698112-announcement-silence.js
index eef9b076f..f462d30b5 100644
--- a/packages/backend/migration/1699141698112-announcement-silence.js
+++ b/packages/backend/migration/1699141698112-announcement-silence.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1699284486293-urlPreviewDenyList.js b/packages/backend/migration/1699284486293-urlPreviewDenyList.js
new file mode 100644
index 000000000..bfa1881de
--- /dev/null
+++ b/packages/backend/migration/1699284486293-urlPreviewDenyList.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class UrlPreviewDenyList1699284486293 {
+ name = 'UrlPreviewDenyList1699284486293'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" ADD "urlPreviewDenyList" character varying(3072) array NOT NULL DEFAULT '{}'`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "urlPreviewDenyList"`);
+ }
+}
diff --git a/packages/backend/migration/1700096812223-enableFanoutTimelineDbFallback.js b/packages/backend/migration/1700096812223-enableFanoutTimelineDbFallback.js
index 94fa58898..2ab93624c 100644
--- a/packages/backend/migration/1700096812223-enableFanoutTimelineDbFallback.js
+++ b/packages/backend/migration/1700096812223-enableFanoutTimelineDbFallback.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1700303245007-supportVerifyMailApi.js b/packages/backend/migration/1700303245007-supportVerifyMailApi.js
index 3ac59ec37..58ff7a69c 100644
--- a/packages/backend/migration/1700303245007-supportVerifyMailApi.js
+++ b/packages/backend/migration/1700303245007-supportVerifyMailApi.js
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/migration/1700383825690-hard-mute.js b/packages/backend/migration/1700383825690-hard-mute.js
new file mode 100644
index 000000000..809308022
--- /dev/null
+++ b/packages/backend/migration/1700383825690-hard-mute.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class HardMute1700383825690 {
+ name = 'HardMute1700383825690'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "user_profile" ADD "hardMutedWords" jsonb NOT NULL DEFAULT '[]'`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "hardMutedWords"`);
+ }
+}
diff --git a/packages/backend/migration/1700415938358-createdAt-default.js b/packages/backend/migration/1700415938358-createdAt-default.js
new file mode 100644
index 000000000..458788612
--- /dev/null
+++ b/packages/backend/migration/1700415938358-createdAt-default.js
@@ -0,0 +1,222 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class CreatedAtDefault1700415938358 {
+ name = 'CreatedAtDefault1700415938358'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "avatar_decoration" ADD "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "avatar_decoration"."createdAt" IS 'The created date of the AvatarDecoration.'`);
+ await queryRunner.query(`COMMENT ON COLUMN "abuse_report_resolver"."createdAt" IS 'The created date of the AbuseReportResolver.'`);
+ await queryRunner.query(`ALTER TABLE "abuse_report_resolver" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "drive_folder" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "drive_file" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "user" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "abuse_user_report" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "app" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "ad" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "announcement" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "announcement_read" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "user_list" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "antenna" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "auth_session" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "blocking" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "channel" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "channel_following" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "channel_favorite" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "clip" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "note" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "clip_favorite"."createdAt" IS 'The created date of the ClipFavorite.'`);
+ await queryRunner.query(`ALTER TABLE "clip_favorite" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "following" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "follow_request" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "gallery_post" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "gallery_like"."createdAt" IS 'The created date of the GalleryLike.'`);
+ await queryRunner.query(`ALTER TABLE "gallery_like" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "preservedUsernames" SET DEFAULT '{ "admin", "administrator", "root", "system", "maintainer", "host", "mod", "moderator", "owner", "superuser", "staff", "auth", "i", "me", "everyone", "all", "mention", "mentions", "example", "user", "users", "account", "accounts", "official", "help", "helps", "support", "supports", "info", "information", "informations", "announce", "announces", "announcement", "announcements", "notice", "notification", "notifications", "dev", "developer", "developers", "tech", "misskey" }'`);
+ await queryRunner.query(`ALTER TABLE "moderation_log" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "muting" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "renote_muting"."createdAt" IS 'The created date of the RenoteMuting.'`);
+ await queryRunner.query(`ALTER TABLE "renote_muting" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "note_favorite" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "note_reaction" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "note_thread_muting"."createdAt" IS 'The created date of the NoteThreadMuting.'`);
+ await queryRunner.query(`ALTER TABLE "note_thread_muting" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "page" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "page_like"."createdAt" IS 'The created date of the PageLike.'`);
+ await queryRunner.query(`ALTER TABLE "page_like" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "password_reset_request"."createdAt" IS 'The created date of the PasswordResetRequest.'`);
+ await queryRunner.query(`ALTER TABLE "password_reset_request" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "poll_vote" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "promo_read" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "registration_ticket"."createdAt" IS 'The created date of the RegistrationTicket.'`);
+ await queryRunner.query(`ALTER TABLE "registration_ticket" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "registry_item" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "signin" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "sw_subscription"."createdAt" IS 'The created date of the SwSubscriptipnpon.'`);
+ await queryRunner.query(`ALTER TABLE "sw_subscription" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "used_username"."createdAt" IS 'The created date of the UsedUsername.'`);
+ await queryRunner.query(`ALTER TABLE "used_username" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "user_ip"."createdAt" IS 'The created date of the UserIp.'`);
+ await queryRunner.query(`ALTER TABLE "user_ip" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "user_list_favorite"."createdAt" IS 'The created date of the UserListFavorite.'`);
+ await queryRunner.query(`ALTER TABLE "user_list_favorite" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "user_list_membership" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "user_note_pining"."createdAt" IS 'The created date of the UserNotePining.'`);
+ await queryRunner.query(`ALTER TABLE "user_note_pining" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "user_pending"."createdAt" IS 'The created date of the UserPending.'`);
+ await queryRunner.query(`ALTER TABLE "user_pending" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "webhook"."createdAt" IS 'The created date of the Webhook.'`);
+ await queryRunner.query(`ALTER TABLE "webhook" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`COMMENT ON COLUMN "retention_aggregation"."createdAt" IS 'The created date of the GalleryPost.'`);
+ await queryRunner.query(`ALTER TABLE "retention_aggregation" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "role" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "role_assignment" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "flash" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`ALTER TABLE "flash" ALTER COLUMN "visibility" SET NOT NULL`);
+ await queryRunner.query(`COMMENT ON COLUMN "flash_like"."createdAt" IS 'The created date of the FlashLike.'`);
+ await queryRunner.query(`ALTER TABLE "flash_like" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ await queryRunner.query(`CREATE INDEX "IDX_f9b40730606162a441c7acb3e5" ON "access_token" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_cbca0122587e5a757ea0e584f0" ON "announcement_read" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_1383c050b99ba7deb995207afe" ON "user_list" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_9425d976c9cf6d47d2b9956344" ON "antenna" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_a3aca00bb7f8d79408edfefe67" ON "avatar_decoration" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_407e3e07747e5cebb916e77914" ON "auth_session" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_823073a0f1f5d44ef83917e0c4" ON "clip" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_e7c0567f5261063592f022e9b5" ON "note" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_94af6cc88a484caf0cd53bfec9" ON "clip_favorite" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_9a20428737dfc7c515fc31c9bc" ON "follow_request" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_3712d1129515e88dedc7c0ca9b" ON "gallery_like" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_1c32fad73f120e11702982f713" ON "moderation_log" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_b7a97c1435dfa03ab42ab7ec92" ON "note_favorite" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_01f4581f114e0ebd2bbb876f0b" ON "note_reaction" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_51fe96e68f335de120a5f8974b" ON "note_thread_muting" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_b72859eb6173fd2e176aad3fbc" ON "page_like" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_0123b5cc155383f3d380170774" ON "password_reset_request" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_65a0babf63cec88aaa804332a0" ON "promo_read" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_0bf1bd10114284dc984d900c8b" ON "registration_ticket" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_0ff7393a15d37079be4e1f2bd5" ON "registry_item" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_68e9b8637a5b186f242d81e41a" ON "signin" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_8781b31c9b1e5c6c0b1cf904c0" ON "sw_subscription" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_4ac8a879384f3fc210bbaa21bc" ON "used_username" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_e15e78ed889553e314336e4952" ON "user_ip" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_970ffee983708c114a0c289903" ON "user_list_favorite" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_d6d398ea7c0d187aa9a91c4ad0" ON "user_list_membership" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_61347f72791a48bfaa9244eb05" ON "user_note_pining" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_e9181436b1294069148b5ba491" ON "user_pending" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_7ad27f46c9449fe9d6fbb4c79c" ON "webhook" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_3c39bd046f5e69d37f0e4fe768" ON "role" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_fe3eb6be723a95c6b7ce539a4f" ON "role_assignment" ("createdAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_89523d5c47dc3fcc0bd6793f18" ON "flash_like" ("createdAt") `);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`DROP INDEX "public"."IDX_89523d5c47dc3fcc0bd6793f18"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_fe3eb6be723a95c6b7ce539a4f"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_3c39bd046f5e69d37f0e4fe768"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_7ad27f46c9449fe9d6fbb4c79c"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_e9181436b1294069148b5ba491"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_61347f72791a48bfaa9244eb05"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_d6d398ea7c0d187aa9a91c4ad0"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_970ffee983708c114a0c289903"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_e15e78ed889553e314336e4952"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_4ac8a879384f3fc210bbaa21bc"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_8781b31c9b1e5c6c0b1cf904c0"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_68e9b8637a5b186f242d81e41a"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_0ff7393a15d37079be4e1f2bd5"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_0bf1bd10114284dc984d900c8b"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_65a0babf63cec88aaa804332a0"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_0123b5cc155383f3d380170774"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_b72859eb6173fd2e176aad3fbc"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_51fe96e68f335de120a5f8974b"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_01f4581f114e0ebd2bbb876f0b"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_b7a97c1435dfa03ab42ab7ec92"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_1c32fad73f120e11702982f713"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_3712d1129515e88dedc7c0ca9b"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_9a20428737dfc7c515fc31c9bc"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_94af6cc88a484caf0cd53bfec9"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_e7c0567f5261063592f022e9b5"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_823073a0f1f5d44ef83917e0c4"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_407e3e07747e5cebb916e77914"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_a3aca00bb7f8d79408edfefe67"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_9425d976c9cf6d47d2b9956344"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_1383c050b99ba7deb995207afe"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_cbca0122587e5a757ea0e584f0"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_f9b40730606162a441c7acb3e5"`);
+ await queryRunner.query(`ALTER TABLE "flash_like" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "flash_like"."createdAt" IS NULL`);
+ await queryRunner.query(`ALTER TABLE "flash" ALTER COLUMN "visibility" DROP NOT NULL`);
+ await queryRunner.query(`ALTER TABLE "flash" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "role_assignment" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "role" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "retention_aggregation" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "retention_aggregation"."createdAt" IS 'The created date of the Note.'`);
+ await queryRunner.query(`ALTER TABLE "webhook" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "webhook"."createdAt" IS 'The created date of the Antenna.'`);
+ await queryRunner.query(`ALTER TABLE "user_pending" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "user_pending"."createdAt" IS NULL`);
+ await queryRunner.query(`ALTER TABLE "user_note_pining" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "user_note_pining"."createdAt" IS 'The created date of the UserNotePinings.'`);
+ await queryRunner.query(`ALTER TABLE "user_list_membership" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "user_list_favorite" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "user_list_favorite"."createdAt" IS NULL`);
+ await queryRunner.query(`ALTER TABLE "user_ip" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "user_ip"."createdAt" IS NULL`);
+ await queryRunner.query(`ALTER TABLE "used_username" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "used_username"."createdAt" IS NULL`);
+ await queryRunner.query(`ALTER TABLE "sw_subscription" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "sw_subscription"."createdAt" IS NULL`);
+ await queryRunner.query(`ALTER TABLE "signin" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "registry_item" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "registration_ticket" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "registration_ticket"."createdAt" IS NULL`);
+ await queryRunner.query(`ALTER TABLE "promo_read" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "poll_vote" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "password_reset_request" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "password_reset_request"."createdAt" IS NULL`);
+ await queryRunner.query(`ALTER TABLE "page_like" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "page_like"."createdAt" IS NULL`);
+ await queryRunner.query(`ALTER TABLE "page" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "note_thread_muting" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "note_thread_muting"."createdAt" IS NULL`);
+ await queryRunner.query(`ALTER TABLE "note_reaction" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "note_favorite" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "renote_muting" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "renote_muting"."createdAt" IS 'The created date of the Muting.'`);
+ await queryRunner.query(`ALTER TABLE "muting" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "moderation_log" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "preservedUsernames" SET DEFAULT '{admin,administrator,root,system,maintainer,host,mod,moderator,owner,superuser,staff,auth,i,me,everyone,all,mention,mentions,example,user,users,account,accounts,official,help,helps,support,supports,info,information,informations,announce,announces,announcement,announcements,notice,notification,notifications,dev,developer,developers,tech,misskey}'`);
+ await queryRunner.query(`ALTER TABLE "gallery_like" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "gallery_like"."createdAt" IS NULL`);
+ await queryRunner.query(`ALTER TABLE "gallery_post" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "follow_request" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "following" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "clip_favorite" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "clip_favorite"."createdAt" IS NULL`);
+ await queryRunner.query(`ALTER TABLE "note" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "clip" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "channel_favorite" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "channel_following" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "channel" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "blocking" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "auth_session" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "antenna" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "user_list" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "announcement_read" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "announcement" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "ad" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "access_token" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "app" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "abuse_user_report" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "user" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "drive_file" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "drive_folder" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "abuse_report_resolver" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ await queryRunner.query(`COMMENT ON COLUMN "abuse_report_resolver"."createdAt" IS 'The created date of AbuseReportResolver'`);
+ await queryRunner.query(`COMMENT ON COLUMN "avatar_decoration"."createdAt" IS 'The created date of the AvatarDecoration.'`);
+ await queryRunner.query(`ALTER TABLE "avatar_decoration" DROP COLUMN "createdAt"`);
+ }
+}
diff --git a/packages/backend/migration/1700880703631-revert-hard-mute.js b/packages/backend/migration/1700880703631-revert-hard-mute.js
new file mode 100644
index 000000000..df9017f78
--- /dev/null
+++ b/packages/backend/migration/1700880703631-revert-hard-mute.js
@@ -0,0 +1,35 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class RevertHardMute1700880703631 {
+ name = 'RevertHardMute1700880703631';
+
+ async up(queryRunner) {
+ // migrate hardMutedWords to mutedWords
+ await queryRunner.query(`
+ update "user_profile"
+ set "mutedWords" = (
+ select jsonb_agg(elem order by ord)
+ from (
+ select elem, ord
+ from (
+ select elem, row_number() over () as ord
+ from jsonb_array_elements("mutedWords") as elem
+ ) as muted
+ union
+ select elem, 1000000 + row_number() over ()
+ from jsonb_array_elements("hardMutedWords") as elem
+ where elem not in (select jsonb_array_elements("mutedWords"))
+ ) as combined
+ )
+ where "hardMutedWords" <> '[]'
+ `);
+ await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "hardMutedWords"`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "user_profile" ADD "hardMutedWords" jsonb NOT NULL DEFAULT '[]'`);
+ }
+}
diff --git a/packages/backend/migration/1700902349231-add-bday-index.js b/packages/backend/migration/1700902349231-add-bday-index.js
new file mode 100644
index 000000000..c58165c70
--- /dev/null
+++ b/packages/backend/migration/1700902349231-add-bday-index.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class AddBdayIndex1700902349231 {
+ name = 'AddBdayIndex1700902349231'
+
+ async up(queryRunner) {
+ await queryRunner.query(`CREATE INDEX "IDX_de22cd2b445eee31ae51cdbe99" ON "user_profile" (SUBSTR("birthday", 6, 5))`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`DROP INDEX "public"."IDX_de22cd2b445eee31ae51cdbe99"`);
+ }
+}
diff --git a/packages/backend/migration/1702718871541-ffVisibility.js b/packages/backend/migration/1702718871541-ffVisibility.js
new file mode 100644
index 000000000..164af00f2
--- /dev/null
+++ b/packages/backend/migration/1702718871541-ffVisibility.js
@@ -0,0 +1,37 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class ffVisibility1702718871541 {
+ constructor() {
+ this.name = 'ffVisibility1702718871541';
+ }
+ async up(queryRunner) {
+ await queryRunner.query(`CREATE TYPE "public"."user_profile_followingvisibility_enum" AS ENUM('public', 'followers', 'private')`);
+ await queryRunner.query(`CREATE CAST ("public"."user_profile_ffvisibility_enum" AS "public"."user_profile_followingvisibility_enum") WITH INOUT AS ASSIGNMENT`);
+ await queryRunner.query(`CREATE TYPE "public"."user_profile_followersVisibility_enum" AS ENUM('public', 'followers', 'private')`);
+ await queryRunner.query(`CREATE CAST ("public"."user_profile_ffvisibility_enum" AS "public"."user_profile_followersVisibility_enum") WITH INOUT AS ASSIGNMENT`);
+ await queryRunner.query(`ALTER TABLE "user_profile" ADD "followingVisibility" "public"."user_profile_followingvisibility_enum" NOT NULL DEFAULT 'public'`);
+ await queryRunner.query(`ALTER TABLE "user_profile" ADD "followersVisibility" "public"."user_profile_followersVisibility_enum" NOT NULL DEFAULT 'public'`);
+ await queryRunner.query(`UPDATE "user_profile" SET "followingVisibility" = "ffVisibility"`);
+ await queryRunner.query(`UPDATE "user_profile" SET "followersVisibility" = "ffVisibility"`);
+ await queryRunner.query(`DROP CAST ("public"."user_profile_ffvisibility_enum" AS "public"."user_profile_followersVisibility_enum")`);
+ await queryRunner.query(`DROP CAST ("public"."user_profile_ffvisibility_enum" AS "public"."user_profile_followingvisibility_enum")`);
+ await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "ffVisibility"`);
+ await queryRunner.query(`DROP TYPE "public"."user_profile_ffvisibility_enum"`);
+ }
+ async down(queryRunner) {
+ await queryRunner.query(`CREATE TYPE "public"."user_profile_ffvisibility_enum" AS ENUM('public', 'followers', 'private')`);
+ await queryRunner.query(`ALTER TABLE "user_profile" ADD "ffVisibility" "public"."user_profile_ffvisibility_enum" NOT NULL DEFAULT 'public'`);
+
+ await queryRunner.query(`CREATE CAST ("public"."user_profile_followingvisibility_enum" AS "public"."user_profile_ffvisibility_enum") WITH INOUT AS ASSIGNMENT`);
+ await queryRunner.query(`UPDATE "user_profile" SET "ffVisibility" = "followingVisibility"`);
+ await queryRunner.query(`DROP CAST ("public"."user_profile_followingvisibility_enum" AS "public"."user_profile_ffvisibility_enum")`);
+
+ await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "followersVisibility"`);
+ await queryRunner.query(`ALTER TABLE "user_profile" DROP COLUMN "followingVisibility"`);
+ await queryRunner.query(`DROP TYPE "public"."user_profile_followersVisibility_enum"`);
+ await queryRunner.query(`DROP TYPE "public"."user_profile_followingvisibility_enum"`);
+ }
+}
diff --git a/packages/backend/migration/1703209889304-bannedEmailDomains.js b/packages/backend/migration/1703209889304-bannedEmailDomains.js
new file mode 100644
index 000000000..2fdd4e118
--- /dev/null
+++ b/packages/backend/migration/1703209889304-bannedEmailDomains.js
@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class bannedEmailDomains1703209889304 {
+ constructor() {
+ this.name = 'bannedEmailDomains1703209889304';
+ }
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" ADD "bannedEmailDomains" character varying(1024) array NOT NULL DEFAULT '{}'`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "bannedEmailDomains"`);
+ }
+}
diff --git a/packages/backend/migration/1703250468098-abuse-user-report-category.js b/packages/backend/migration/1703250468098-abuse-user-report-category.js
new file mode 100644
index 000000000..d6e754682
--- /dev/null
+++ b/packages/backend/migration/1703250468098-abuse-user-report-category.js
@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class AbuseUserReportCategory1703250468098 {
+ name = 'AbuseUserReportCategory1703250468098'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "abuse_user_report" ADD "category" character varying(20) NOT NULL DEFAULT 'other'`);
+ await queryRunner.query(`CREATE INDEX "IDX_5b9acc09094daeb8683e362778" ON "abuse_user_report" ("category") `);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`DROP INDEX "public"."IDX_5b9acc09094daeb8683e362778"`);
+ await queryRunner.query(`ALTER TABLE "abuse_user_report" DROP COLUMN "category"`);
+ }
+}
diff --git a/packages/backend/migration/1703658526000-supportTrueMailApi.js b/packages/backend/migration/1703658526000-supportTrueMailApi.js
new file mode 100644
index 000000000..fb62653e4
--- /dev/null
+++ b/packages/backend/migration/1703658526000-supportTrueMailApi.js
@@ -0,0 +1,20 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class SupportTrueMailApi1703658526000 {
+ name = 'SupportTrueMailApi1703658526000'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" ADD "truemailInstance" character varying(1024)`);
+ await queryRunner.query(`ALTER TABLE "meta" ADD "truemailAuthKey" character varying(1024)`);
+ await queryRunner.query(`ALTER TABLE "meta" ADD "enableTruemailApi" boolean NOT NULL DEFAULT false`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableTruemailApi"`);
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "truemailInstance"`);
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "truemailAuthKey"`);
+ }
+}
diff --git a/packages/backend/migration/1704373210054-support-mcaptcha.js b/packages/backend/migration/1704373210054-support-mcaptcha.js
new file mode 100644
index 000000000..50b4801e1
--- /dev/null
+++ b/packages/backend/migration/1704373210054-support-mcaptcha.js
@@ -0,0 +1,22 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class SupportMcaptcha1704373210054 {
+ name = 'SupportMcaptcha1704373210054'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" ADD "enableMcaptcha" boolean NOT NULL DEFAULT false`);
+ await queryRunner.query(`ALTER TABLE "meta" ADD "mcaptchaSitekey" character varying(1024)`);
+ await queryRunner.query(`ALTER TABLE "meta" ADD "mcaptchaSecretKey" character varying(1024)`);
+ await queryRunner.query(`ALTER TABLE "meta" ADD "mcaptchaInstanceUrl" character varying(1024)`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "mcaptchaInstanceUrl"`);
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "mcaptchaSecretKey"`);
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "mcaptchaSitekey"`);
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableMcaptcha"`);
+ }
+}
diff --git a/packages/backend/migration/1704622962215-sensitive-media-hosts.js b/packages/backend/migration/1704622962215-sensitive-media-hosts.js
new file mode 100644
index 000000000..5a9a616e9
--- /dev/null
+++ b/packages/backend/migration/1704622962215-sensitive-media-hosts.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class SensitiveMediaHosts1704622962215 {
+ name = 'SensitiveMediaHosts1704622962215'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" ADD "sensitiveMediaHosts" character varying(1024) array NOT NULL DEFAULT '{}'`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "sensitiveMediaHosts"`);
+ }
+}
diff --git a/packages/backend/migration/1704959805077-bubble-game-record.js b/packages/backend/migration/1704959805077-bubble-game-record.js
new file mode 100644
index 000000000..6c4d7ab1a
--- /dev/null
+++ b/packages/backend/migration/1704959805077-bubble-game-record.js
@@ -0,0 +1,24 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class BubbleGameRecord1704959805077 {
+ name = 'BubbleGameRecord1704959805077'
+
+ async up(queryRunner) {
+ await queryRunner.query(`CREATE TABLE "bubble_game_record" ("id" character varying(32) NOT NULL, "userId" character varying(32) NOT NULL, "seededAt" TIMESTAMP WITH TIME ZONE NOT NULL, "seed" character varying(1024) NOT NULL, "gameVersion" integer NOT NULL, "gameMode" character varying(128) NOT NULL, "score" integer NOT NULL, "logs" jsonb NOT NULL DEFAULT '[]', "isVerified" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_a75395fe404b392e2893b50d7ea" PRIMARY KEY ("id"))`);
+ await queryRunner.query(`CREATE INDEX "IDX_75276757070d21fdfaf4c05290" ON "bubble_game_record" ("userId") `);
+ await queryRunner.query(`CREATE INDEX "IDX_4ae7053179014915d1432d3f40" ON "bubble_game_record" ("seededAt") `);
+ await queryRunner.query(`CREATE INDEX "IDX_26d4ee490b5a487142d35466ee" ON "bubble_game_record" ("score") `);
+ await queryRunner.query(`ALTER TABLE "bubble_game_record" ADD CONSTRAINT "FK_75276757070d21fdfaf4c052909" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "bubble_game_record" DROP CONSTRAINT "FK_75276757070d21fdfaf4c052909"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_26d4ee490b5a487142d35466ee"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_4ae7053179014915d1432d3f40"`);
+ await queryRunner.query(`DROP INDEX "public"."IDX_75276757070d21fdfaf4c05290"`);
+ await queryRunner.query(`DROP TABLE "bubble_game_record"`);
+ }
+}
diff --git a/packages/backend/migration/1705222772858-optimize-note-index-for-array-column.js b/packages/backend/migration/1705222772858-optimize-note-index-for-array-column.js
new file mode 100644
index 000000000..27514887b
--- /dev/null
+++ b/packages/backend/migration/1705222772858-optimize-note-index-for-array-column.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class OptimizeNoteIndexForArrayColumns1705222772858 {
+ name = 'OptimizeNoteIndexForArrayColumns1705222772858'
+
+ async up(queryRunner) {
+ await queryRunner.query(`CREATE INDEX "IDX_NOTE_FILE_IDS" ON "note" using gin ("fileIds")`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`DROP INDEX "IDX_NOTE_FILE_IDS"`);
+ }
+}
diff --git a/packages/backend/migration/1705475608437-reversi.js b/packages/backend/migration/1705475608437-reversi.js
new file mode 100644
index 000000000..fa37a7aaf
--- /dev/null
+++ b/packages/backend/migration/1705475608437-reversi.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class Reversi1705475608437 {
+ name = 'Reversi1705475608437'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "reversi_game" ALTER COLUMN "createdAt" SET DEFAULT now()`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "reversi_game" ALTER COLUMN "createdAt" DROP DEFAULT`);
+ }
+}
diff --git a/packages/backend/migration/1705654039457-reversi-2.js b/packages/backend/migration/1705654039457-reversi-2.js
new file mode 100644
index 000000000..6685dca73
--- /dev/null
+++ b/packages/backend/migration/1705654039457-reversi-2.js
@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class Reversi21705654039457 {
+ name = 'Reversi21705654039457'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "reversi_game" RENAME COLUMN "user1Accepted" TO "user1Ready"`);
+ await queryRunner.query(`ALTER TABLE "reversi_game" RENAME COLUMN "user2Accepted" TO "user2Ready"`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "reversi_game" RENAME COLUMN "user1Ready" TO "user1Accepted"`);
+ await queryRunner.query(`ALTER TABLE "reversi_game" RENAME COLUMN "user2Ready" TO "user2Accepted"`);
+ }
+}
diff --git a/packages/backend/migration/1705793785675-reversi-3.js b/packages/backend/migration/1705793785675-reversi-3.js
new file mode 100644
index 000000000..94b1e4fac
--- /dev/null
+++ b/packages/backend/migration/1705793785675-reversi-3.js
@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class Reversi31705793785675 {
+ name = 'Reversi31705793785675'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "reversi_game" RENAME COLUMN "surrendered" TO "surrenderedUserId"`);
+ await queryRunner.query(`ALTER TABLE "reversi_game" ADD "timeoutUserId" character varying(32)`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "reversi_game" DROP COLUMN "timeoutUserId"`);
+ await queryRunner.query(`ALTER TABLE "reversi_game" RENAME COLUMN "surrenderedUserId" TO "surrendered"`);
+ }
+}
diff --git a/packages/backend/migration/1705794768153-reversi-4.js b/packages/backend/migration/1705794768153-reversi-4.js
new file mode 100644
index 000000000..95119cabb
--- /dev/null
+++ b/packages/backend/migration/1705794768153-reversi-4.js
@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class Reversi41705794768153 {
+ name = 'Reversi41705794768153'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "reversi_game" ADD "endedAt" TIMESTAMP WITH TIME ZONE`);
+ await queryRunner.query(`COMMENT ON COLUMN "reversi_game"."endedAt" IS 'The ended date of the ReversiGame.'`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`COMMENT ON COLUMN "reversi_game"."endedAt" IS 'The ended date of the ReversiGame.'`);
+ await queryRunner.query(`ALTER TABLE "reversi_game" DROP COLUMN "endedAt"`);
+ }
+}
diff --git a/packages/backend/migration/1705798904141-reversi-5.js b/packages/backend/migration/1705798904141-reversi-5.js
new file mode 100644
index 000000000..f1a1a42d4
--- /dev/null
+++ b/packages/backend/migration/1705798904141-reversi-5.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class Reversi51705798904141 {
+ name = 'Reversi51705798904141'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "reversi_game" ADD "timeLimitForEachTurn" smallint NOT NULL DEFAULT '90'`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "reversi_game" DROP COLUMN "timeLimitForEachTurn"`);
+ }
+}
diff --git a/packages/backend/migration/1706011243939-UserProfileBirthdayIndex.js b/packages/backend/migration/1706011243939-UserProfileBirthdayIndex.js
new file mode 100644
index 000000000..12bffb97d
--- /dev/null
+++ b/packages/backend/migration/1706011243939-UserProfileBirthdayIndex.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class UserProfileBirthdayIndex1706011243939 {
+ name = 'UserProfileBirthdayIndex1706011243939'
+
+ async up(queryRunner) {
+ await queryRunner.query(`CREATE INDEX "IDX_58699f75b9cf904f5f007909cb" ON "user_profile" ("birthday") `);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`DROP INDEX "public"."IDX_58699f75b9cf904f5f007909cb"`);
+ }
+}
diff --git a/packages/backend/migration/1706081039979-featured-games-channel.js b/packages/backend/migration/1706081039979-featured-games-channel.js
new file mode 100644
index 000000000..943ccf691
--- /dev/null
+++ b/packages/backend/migration/1706081039979-featured-games-channel.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class FeaturedGamesChannel1706081039979 {
+ name = 'FeaturedGamesChannel1706081039979'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" ADD "featuredGameChannels" character varying(1024) array NOT NULL DEFAULT '{}'`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "featuredGameChannels"`);
+ }
+}
diff --git a/packages/backend/migration/1706081514499-reversi-6.js b/packages/backend/migration/1706081514499-reversi-6.js
new file mode 100644
index 000000000..0d9e5cbbf
--- /dev/null
+++ b/packages/backend/migration/1706081514499-reversi-6.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class Reversi61706081514499 {
+ name = 'Reversi61706081514499'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "reversi_game" ADD "noIrregularRules" boolean NOT NULL DEFAULT false`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "reversi_game" DROP COLUMN "noIrregularRules"`);
+ }
+}
diff --git a/packages/backend/migration/1706723072096-emoji-more-fields.js b/packages/backend/migration/1706723072096-emoji-more-fields.js
new file mode 100644
index 000000000..19b47b9f3
--- /dev/null
+++ b/packages/backend/migration/1706723072096-emoji-more-fields.js
@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class EmojiMoreFields1706723072096 {
+ name = 'EmojiMoreFields1706723072096'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "emoji" ADD "requestedBy" character varying(1024)`);
+ await queryRunner.query(`ALTER TABLE "emoji" ADD "memo" character varying(8192) NOT NULL DEFAULT ''`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "memo"`);
+ await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "requestedBy"`);
+ }
+}
diff --git a/packages/backend/migration/1706791962000-fix-meta-disableRegistration.js b/packages/backend/migration/1706791962000-fix-meta-disableRegistration.js
new file mode 100644
index 000000000..1c45f3756
--- /dev/null
+++ b/packages/backend/migration/1706791962000-fix-meta-disableRegistration.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class FixMetaDisableRegistration1706791962000 {
+ name = 'FixMetaDisableRegistration1706791962000'
+
+ async up(queryRunner) {
+ await queryRunner.query(`alter table meta alter column "disableRegistration" set default true;`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`alter table meta alter column "disableRegistration" set default false;`);
+ }
+}
diff --git a/packages/backend/migration/1707429690000-prohibited-words.js b/packages/backend/migration/1707429690000-prohibited-words.js
new file mode 100644
index 000000000..44e96cb16
--- /dev/null
+++ b/packages/backend/migration/1707429690000-prohibited-words.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class prohibitedWords1707429690000 {
+ name = 'prohibitedWords1707429690000'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" ADD "prohibitedWords" character varying(1024) array NOT NULL DEFAULT '{}'`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "prohibitedWords"`);
+ }
+}
diff --git a/packages/backend/migration/1707697398681-indie-auth-client.js b/packages/backend/migration/1707697398681-indie-auth-client.js
new file mode 100644
index 000000000..fdbb646a3
--- /dev/null
+++ b/packages/backend/migration/1707697398681-indie-auth-client.js
@@ -0,0 +1,13 @@
+export class IndieAuthClient1707697398681 {
+ name = 'IndieAuthClient1707697398681'
+
+ async up(queryRunner) {
+ await queryRunner.query(`CREATE TABLE "indie_auth_client" ("id" character varying(512) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "name" character varying(256), "redirectUris" character varying(512) array NOT NULL DEFAULT '{}', CONSTRAINT "PK_9a604c83d4dadfa1eb92ee03399" PRIMARY KEY ("id"))`);
+ await queryRunner.query(`CREATE INDEX "IDX_434fcbfbe82b58a90898e557b7" ON "indie_auth_client" ("createdAt") `);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`DROP INDEX "public"."IDX_434fcbfbe82b58a90898e557b7"`);
+ await queryRunner.query(`DROP TABLE "indie_auth_client"`);
+ }
+}
diff --git a/packages/backend/migration/1707808106310-MakeRepositoryUrlNullable.js b/packages/backend/migration/1707808106310-MakeRepositoryUrlNullable.js
new file mode 100644
index 000000000..335b14976
--- /dev/null
+++ b/packages/backend/migration/1707808106310-MakeRepositoryUrlNullable.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class MakeRepositoryUrlNullable1707808106310 {
+ name = 'MakeRepositoryUrlNullable1707808106310'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "repositoryUrl" DROP NOT NULL`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "repositoryUrl" SET NOT NULL`);
+ }
+}
diff --git a/packages/backend/migration/1708266695091-repositoryUrl-from-syuilo-to-misskey-dev.js b/packages/backend/migration/1708266695091-repositoryUrl-from-syuilo-to-misskey-dev.js
new file mode 100644
index 000000000..e4dbaa16d
--- /dev/null
+++ b/packages/backend/migration/1708266695091-repositoryUrl-from-syuilo-to-misskey-dev.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class RepositoryUrlFromSyuiloToMisskeyDev1708266695091 {
+ name = 'RepositoryUrlFromSyuiloToMisskeyDev1708266695091'
+
+ async up(queryRunner) {
+ await queryRunner.query(`UPDATE "meta" SET "repositoryUrl" = 'https://github.com/misskey-dev/misskey' WHERE "repositoryUrl" = 'https://github.com/syuilo/misskey'`);
+ }
+
+ async down(queryRunner) {
+ // no valid down migration
+ }
+}
diff --git a/packages/backend/migration/1708399372194-per-instance-mod-note.js b/packages/backend/migration/1708399372194-per-instance-mod-note.js
new file mode 100644
index 000000000..339a4d7af
--- /dev/null
+++ b/packages/backend/migration/1708399372194-per-instance-mod-note.js
@@ -0,0 +1,16 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+export class PerInstanceModNote1708399372194 {
+ name = 'PerInstanceModNote1708399372194'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "instance" ADD "moderationNote" character varying(16384) NOT NULL DEFAULT ''`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "instance" DROP COLUMN "moderationNote"`);
+ }
+}
diff --git a/packages/backend/migration/1710667213868-single-sign-on.js b/packages/backend/migration/1710667213868-single-sign-on.js
new file mode 100644
index 000000000..0f2095549
--- /dev/null
+++ b/packages/backend/migration/1710667213868-single-sign-on.js
@@ -0,0 +1,21 @@
+export class SingleSignOn1710667213868 {
+ name = 'SingleSignOn1710667213868'
+
+ async up(queryRunner) {
+ await queryRunner.query(`DROP TABLE IF EXISTS "sso_service_provider"`);
+ await queryRunner.query(`DROP INDEX IF EXISTS "public"."IDX_86eee7fa4ae68e4a558dc50961"`);
+ await queryRunner.query(`DROP TYPE IF EXISTS "public"."sso_service_provider_binding_enum"`);
+ await queryRunner.query(`DROP TYPE IF EXISTS "public"."sso_service_provider_type_enum"`);
+ await queryRunner.query(`CREATE TYPE "public"."sso_service_provider_type_enum" AS ENUM('saml', 'jwt')`);
+ await queryRunner.query(`CREATE TYPE "public"."sso_service_provider_binding_enum" AS ENUM('post', 'redirect')`);
+ await queryRunner.query(`CREATE TABLE "sso_service_provider" ("id" character varying(36) NOT NULL, "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "name" character varying(256), "type" "public"."sso_service_provider_type_enum" NOT NULL, "issuer" character varying(512) NOT NULL, "audience" character varying(512) array NOT NULL DEFAULT '{}', "binding" "public"."sso_service_provider_binding_enum" NOT NULL, "acsUrl" character varying(512) NOT NULL, "publicKey" character varying(4096) NOT NULL, "privateKey" character varying(4096), "signatureAlgorithm" character varying(100) NOT NULL, "cipherAlgorithm" character varying(100), "wantAuthnRequestsSigned" boolean NOT NULL DEFAULT false, "wantAssertionsSigned" boolean NOT NULL DEFAULT true, CONSTRAINT "PK_0e5fff64534026e48e1c248991a" PRIMARY KEY ("id"))`);
+ await queryRunner.query(`CREATE INDEX "IDX_86eee7fa4ae68e4a558dc50961" ON "sso_service_provider" ("createdAt") `);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`DROP INDEX "public"."IDX_86eee7fa4ae68e4a558dc50961"`);
+ await queryRunner.query(`DROP TABLE "sso_service_provider"`);
+ await queryRunner.query(`DROP TYPE "public"."sso_service_provider_binding_enum"`);
+ await queryRunner.query(`DROP TYPE "public"."sso_service_provider_type_enum"`);
+ }
+}
diff --git a/packages/backend/package.json b/packages/backend/package.json
index 18c7818dc..83256149a 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -4,44 +4,51 @@
"private": true,
"type": "module",
"engines": {
- "node": ">=18.16.0"
+ "node": ">=20.10.0"
},
"scripts": {
"start": "node ./built/boot/entry.js",
- "start:test": "NODE_ENV=test node ./built/boot/entry.js",
+ "start:test": "cross-env NODE_ENV=test node ./built/boot/entry.js",
"migrate": "pnpm typeorm migration:run -d ormconfig.js",
"revert": "pnpm typeorm migration:revert -d ormconfig.js",
"check:connect": "node ./check_connect.js",
"build": "swc src -d built -D",
+ "build:test": "swc test-server -d built-test -D --config-file test-server/.swcrc",
"watch:swc": "swc src -d built -D -w",
"build:tsc": "tsc -p tsconfig.json && tsc-alias -p tsconfig.json",
"watch": "node watch.mjs",
- "typecheck": "tsc --noEmit",
+ "restart": "pnpm build && pnpm start",
+ "dev": "nodemon -w src -e ts,js,mjs,cjs,json --exec \"cross-env NODE_ENV=development pnpm run restart\"",
+ "typecheck": "tsc --noEmit && tsc -p test --noEmit",
"eslint": "eslint --quiet \"src/**/*.ts\"",
"lint": "pnpm typecheck && pnpm eslint",
- "jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit",
- "jest-and-coverage": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit",
+ "jest": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --config jest.config.unit.cjs",
+ "jest:e2e": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --forceExit --config jest.config.e2e.cjs",
+ "jest-and-coverage": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit --config jest.config.unit.cjs",
+ "jest-and-coverage:e2e": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --coverage --forceExit --config jest.config.e2e.cjs",
"jest-clear": "cross-env NODE_ENV=test node --experimental-vm-modules --experimental-import-meta-resolve node_modules/jest/bin/jest.js --clearCache",
"test": "pnpm jest",
+ "test:e2e": "pnpm build && pnpm build:test && pnpm jest:e2e",
"test-and-coverage": "pnpm jest-and-coverage",
- "generate-api-json": "node ./generate_api_json.js"
+ "test-and-coverage:e2e": "pnpm build && pnpm build:test && pnpm jest-and-coverage:e2e",
+ "generate-api-json": "pnpm build && node ./generate_api_json.js"
},
"optionalDependencies": {
"@swc/core-android-arm64": "1.3.11",
- "@swc/core-darwin-arm64": "1.3.56",
- "@swc/core-darwin-x64": "1.3.56",
+ "@swc/core-darwin-arm64": "1.3.107",
+ "@swc/core-darwin-x64": "1.3.107",
"@swc/core-freebsd-x64": "1.3.11",
- "@swc/core-linux-arm-gnueabihf": "1.3.56",
- "@swc/core-linux-arm64-gnu": "1.3.56",
- "@swc/core-linux-arm64-musl": "1.3.56",
- "@swc/core-linux-x64-gnu": "1.3.56",
- "@swc/core-linux-x64-musl": "1.3.56",
- "@swc/core-win32-arm64-msvc": "1.3.56",
- "@swc/core-win32-ia32-msvc": "1.3.56",
- "@swc/core-win32-x64-msvc": "1.3.56",
- "@tensorflow/tfjs": "4.4.0",
- "@tensorflow/tfjs-node": "4.4.0",
- "bufferutil": "4.0.7",
+ "@swc/core-linux-arm-gnueabihf": "1.3.107",
+ "@swc/core-linux-arm64-gnu": "1.3.107",
+ "@swc/core-linux-arm64-musl": "1.3.107",
+ "@swc/core-linux-x64-gnu": "1.3.107",
+ "@swc/core-linux-x64-musl": "1.3.107",
+ "@swc/core-win32-arm64-msvc": "1.3.107",
+ "@swc/core-win32-ia32-msvc": "1.3.107",
+ "@swc/core-win32-x64-msvc": "1.3.107",
+ "@tensorflow/tfjs": "4.17.0",
+ "@tensorflow/tfjs-node": "4.17.0",
+ "bufferutil": "4.0.8",
"slacc-android-arm-eabi": "0.0.10",
"slacc-android-arm64": "0.0.10",
"slacc-darwin-arm64": "0.0.10",
@@ -58,85 +65,97 @@
"utf-8-validate": "6.0.3"
},
"dependencies": {
- "@aws-sdk/client-s3": "3.412.0",
- "@aws-sdk/lib-storage": "3.412.0",
- "@bull-board/api": "5.9.1",
- "@bull-board/fastify": "5.9.1",
- "@bull-board/ui": "5.9.1",
- "@discordapp/twemoji": "14.1.2",
- "@fastify/accepts": "4.2.0",
- "@fastify/cookie": "9.2.0",
- "@fastify/cors": "8.4.1",
+ "@authenio/samlify-node-xmllint": "2.0.0",
+ "@aws-sdk/client-s3": "3.534.0",
+ "@aws-sdk/lib-storage": "3.534.0",
+ "@bull-board/api": "5.15.1",
+ "@bull-board/fastify": "5.15.1",
+ "@bull-board/ui": "5.15.1",
+ "@discordapp/twemoji": "15.0.2",
+ "@fastify/accepts": "4.3.0",
+ "@fastify/cookie": "9.3.1",
+ "@fastify/cors": "9.0.1",
"@fastify/express": "2.3.0",
- "@fastify/http-proxy": "9.3.0",
- "@fastify/multipart": "8.0.0",
- "@fastify/static": "6.12.0",
- "@fastify/view": "8.2.0",
- "@nestjs/common": "10.2.8",
- "@nestjs/core": "10.2.8",
- "@nestjs/testing": "10.2.8",
+ "@fastify/formbody": "7.4.0",
+ "@fastify/http-proxy": "9.4.0",
+ "@fastify/multipart": "8.1.0",
+ "@fastify/static": "7.0.1",
+ "@fastify/view": "9.0.0",
+ "@misskey-dev/sharp-read-bmp": "1.2.0",
+ "@misskey-dev/summaly": "5.0.3",
+ "@nestjs/common": "10.3.3",
+ "@nestjs/core": "10.3.3",
+ "@nestjs/testing": "10.3.3",
"@peertube/http-signature": "1.7.0",
- "@simplewebauthn/server": "8.3.5",
+ "@simplewebauthn/server": "9.0.3",
"@sinonjs/fake-timers": "11.2.2",
- "@smithy/node-http-handler": "2.1.5",
- "@swc/cli": "0.1.63",
- "@swc/core": "1.3.96",
+ "@smithy/node-http-handler": "2.5.0",
+ "@swc/cli": "0.1.65",
+ "@swc/core": "1.3.107",
+ "@twemoji/parser": "15.0.0",
"accepts": "1.3.8",
"ajv": "8.12.0",
"archiver": "6.0.1",
- "async-mutex": "0.4.0",
+ "async-mutex": "0.4.1",
"bcryptjs": "2.4.3",
"blurhash": "2.0.5",
"body-parser": "1.20.2",
- "bullmq": "4.13.3",
+ "bullmq": "5.4.2",
"cacheable-lookup": "7.0.0",
- "cbor": "9.0.1",
+ "cbor": "9.0.2",
"chalk": "5.3.0",
"chalk-template": "1.1.0",
- "chokidar": "3.5.3",
+ "chokidar": "3.6.0",
"cli-highlight": "2.1.11",
"color-convert": "2.0.1",
"content-disposition": "0.5.4",
- "date-fns": "2.30.0",
+ "date-fns": "3.4.0",
"deep-email-validator": "0.1.21",
- "fastify": "4.24.3",
+ "fastify": "4.26.2",
+ "fastify-http-errors-enhanced": "5.0.3",
"fastify-raw-body": "4.3.0",
"feed": "4.2.2",
- "file-type": "18.7.0",
+ "file-type": "19.0.0",
"fluent-ffmpeg": "2.1.2",
"form-data": "4.0.0",
- "got": "13.0.0",
+ "got": "14.2.1",
"happy-dom": "10.0.3",
"hpagent": "1.2.0",
- "http-link-header": "1.1.1",
+ "htmlescape": "1.1.1",
+ "http-link-header": "1.1.2",
"ioredis": "5.3.2",
"ip-cidr": "3.1.0",
"ipaddr.js": "2.1.0",
"is-svg": "5.0.0",
+ "jose": "5.2.3",
"js-yaml": "4.1.0",
- "jsdom": "22.1.0",
+ "jsdom": "23.2.0",
"json5": "2.2.3",
- "jsonld": "8.3.1",
- "jsrsasign": "10.8.6",
- "meilisearch": "0.35.0",
- "mfm-js": "0.23.3",
- "microformats-parser": "1.5.2",
+ "jsonld": "8.3.2",
+ "jsrsasign": "11.1.0",
+ "meilisearch": "0.38.0",
+ "mfm-js": "0.24.0",
+ "microformats-parser": "2.0.2",
"mime-types": "2.1.35",
"misskey-js": "workspace:*",
+ "misskey-reversi": "workspace:*",
"ms": "3.0.0-canary.1",
- "nanoid": "5.0.3",
+ "nanoid": "5.0.6",
"nested-property": "4.0.0",
"node-fetch": "3.3.2",
- "nodemailer": "6.9.7",
+ "node-forge": "1.3.1",
+ "nodemailer": "6.9.12",
"nsfwjs": "2.4.2",
"oauth": "0.10.0",
"oauth2orize": "1.12.0",
"oauth2orize-pkce": "0.1.2",
"os-utils": "0.0.14",
- "otpauth": "9.2.0",
+ "otpauth": "9.2.2",
"parse5": "7.1.2",
"pg": "8.11.3",
- "pkce-challenge": "4.0.1",
+ "pino": "8.19.0",
+ "pino-pretty": "10.3.1",
+ "pkce-challenge": "4.1.0",
"probe-image-size": "7.2.3",
"promise-limit": "2.7.0",
"pug": "3.0.2",
@@ -145,86 +164,89 @@
"qrcode": "1.5.3",
"random-seed": "0.3.0",
"ratelimiter": "3.4.1",
- "re2": "1.20.8",
+ "re2": "1.20.10",
"redis-lock": "0.1.4",
- "reflect-metadata": "0.1.13",
+ "reflect-metadata": "0.2.1",
"rename": "1.0.4",
"rss-parser": "3.13.0",
"rxjs": "7.8.1",
- "sanitize-html": "2.11.0",
+ "samlify": "2.8.11",
+ "sanitize-html": "2.12.1",
"secure-json-parse": "2.7.0",
- "sharp": "0.32.6",
- "sharp-read-bmp": "github:misskey-dev/sharp-read-bmp",
+ "sharp": "0.33.2",
"slacc": "0.0.10",
"strict-event-emitter-types": "2.0.0",
"stringz": "2.1.0",
- "summaly": "github:misskey-dev/summaly",
- "systeminformation": "5.21.17",
+ "systeminformation": "5.22.2",
"tinycolor2": "1.6.0",
- "tmp": "0.2.1",
+ "tmp": "0.2.3",
"tsc-alias": "1.8.8",
"tsconfig-paths": "4.2.0",
- "twemoji-parser": "14.0.0",
- "typeorm": "0.3.17",
- "typescript": "5.3.2",
+ "typeorm": "0.3.20",
+ "typescript": "5.4.2",
"ulid": "2.3.0",
"vary": "1.1.2",
- "web-push": "3.6.6",
- "ws": "8.14.2",
- "xev": "3.0.2"
+ "web-push": "3.6.7",
+ "ws": "8.16.0",
+ "xev": "3.0.2",
+ "xmlbuilder": "15.1.1"
},
"devDependencies": {
"@jest/globals": "29.7.0",
- "@simplewebauthn/typescript-types": "8.3.4",
- "@swc/jest": "0.2.29",
+ "@misskey-dev/eslint-plugin": "1.0.0",
+ "@nestjs/platform-express": "10.3.3",
+ "@simplewebauthn/types": "9.0.1",
+ "@swc/jest": "0.2.36",
"@types/accepts": "1.3.7",
- "@types/archiver": "6.0.1",
+ "@types/archiver": "6.0.2",
"@types/bcryptjs": "2.4.6",
"@types/body-parser": "1.19.5",
- "@types/cbor": "6.0.0",
"@types/color-convert": "2.0.3",
"@types/content-disposition": "0.5.8",
"@types/fluent-ffmpeg": "2.1.24",
+ "@types/htmlescape": "^1.1.3",
"@types/http-link-header": "1.0.5",
- "@types/jest": "29.5.8",
+ "@types/jest": "29.5.12",
"@types/js-yaml": "4.0.9",
- "@types/jsdom": "21.1.5",
- "@types/jsonld": "1.5.12",
- "@types/jsrsasign": "10.5.12",
+ "@types/jsdom": "21.1.6",
+ "@types/jsonld": "1.5.13",
+ "@types/jsrsasign": "10.5.13",
"@types/mime-types": "2.1.4",
"@types/ms": "0.7.34",
- "@types/node": "20.9.1",
- "@types/node-fetch": "3.0.3",
+ "@types/node": "20.11.27",
+ "@types/node-forge": "1.3.11",
"@types/nodemailer": "6.4.14",
"@types/oauth": "0.9.4",
- "@types/oauth2orize": "1.11.3",
+ "@types/oauth2orize": "1.11.4",
"@types/oauth2orize-pkce": "0.1.2",
- "@types/pg": "8.10.9",
- "@types/pug": "2.0.9",
- "@types/punycode": "2.1.2",
+ "@types/pg": "8.11.2",
+ "@types/pug": "2.0.10",
+ "@types/punycode": "2.1.4",
"@types/qrcode": "1.5.5",
"@types/random-seed": "0.3.5",
"@types/ratelimiter": "3.4.6",
"@types/rename": "1.0.7",
- "@types/sanitize-html": "2.9.4",
- "@types/semver": "7.5.5",
- "@types/sharp": "0.32.0",
+ "@types/sanitize-html": "2.11.0",
+ "@types/semver": "7.5.8",
"@types/simple-oauth2": "5.0.7",
"@types/sinonjs__fake-timers": "8.1.5",
"@types/tinycolor2": "1.4.6",
"@types/tmp": "0.2.6",
"@types/vary": "1.1.3",
"@types/web-push": "3.6.3",
- "@types/ws": "8.5.9",
- "@typescript-eslint/eslint-plugin": "6.11.0",
- "@typescript-eslint/parser": "6.11.0",
- "aws-sdk-client-mock": "3.0.0",
+ "@types/ws": "8.5.10",
+ "@typescript-eslint/eslint-plugin": "7.2.0",
+ "@typescript-eslint/parser": "7.2.0",
+ "aws-sdk-client-mock": "3.0.1",
"cross-env": "7.0.3",
- "eslint": "8.53.0",
- "eslint-plugin-import": "2.29.0",
+ "eslint": "8.57.0",
+ "eslint-plugin-import": "2.29.1",
"execa": "8.0.1",
+ "fkill": "^9.0.0",
"jest": "29.7.0",
"jest-mock": "29.7.0",
+ "nodemon": "3.1.0",
+ "pid-port": "1.0.0",
"simple-oauth2": "5.0.0"
}
}
diff --git a/packages/backend/src/@types/fastify.d.ts b/packages/backend/src/@types/fastify.d.ts
new file mode 100644
index 000000000..f63a90f94
--- /dev/null
+++ b/packages/backend/src/@types/fastify.d.ts
@@ -0,0 +1,14 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import FastifyReply from 'fastify';
+
+declare module 'fastify' {
+ interface FastifyReply {
+ cspNonce: {
+ script: string
+ }
+ }
+}
diff --git a/packages/backend/src/@types/hcaptcha.d.ts b/packages/backend/src/@types/hcaptcha.d.ts
index 43e67dd34..e11dda466 100644
--- a/packages/backend/src/@types/hcaptcha.d.ts
+++ b/packages/backend/src/@types/hcaptcha.d.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/@types/http-signature.d.ts b/packages/backend/src/@types/http-signature.d.ts
index 1f3b48aa5..75b62e55f 100644
--- a/packages/backend/src/@types/http-signature.d.ts
+++ b/packages/backend/src/@types/http-signature.d.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/@types/os-utils.d.ts b/packages/backend/src/@types/os-utils.d.ts
index 8c44232c1..8943edddd 100644
--- a/packages/backend/src/@types/os-utils.d.ts
+++ b/packages/backend/src/@types/os-utils.d.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/@types/package.json.d.ts b/packages/backend/src/@types/package.json.d.ts
index 197b4b6bf..52a2b356d 100644
--- a/packages/backend/src/@types/package.json.d.ts
+++ b/packages/backend/src/@types/package.json.d.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/@types/probe-image-size.d.ts b/packages/backend/src/@types/probe-image-size.d.ts
index 4d312cba3..538836475 100644
--- a/packages/backend/src/@types/probe-image-size.d.ts
+++ b/packages/backend/src/@types/probe-image-size.d.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/@types/redis-lock.d.ts b/packages/backend/src/@types/redis-lock.d.ts
index c607d600d..b037cde5e 100644
--- a/packages/backend/src/@types/redis-lock.d.ts
+++ b/packages/backend/src/@types/redis-lock.d.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/@types/samlify-xsd-schema-validator.d.ts b/packages/backend/src/@types/samlify-xsd-schema-validator.d.ts
new file mode 100644
index 000000000..19d7cb11b
--- /dev/null
+++ b/packages/backend/src/@types/samlify-xsd-schema-validator.d.ts
@@ -0,0 +1 @@
+declare module '@authenio/samlify-xsd-schema-validator';
diff --git a/packages/backend/src/GlobalModule.ts b/packages/backend/src/GlobalModule.ts
index 3e9d19f82..a09221e65 100644
--- a/packages/backend/src/GlobalModule.ts
+++ b/packages/backend/src/GlobalModule.ts
@@ -1,9 +1,9 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { setTimeout } from 'node:timers/promises';
+import process from 'node:process';
import { Global, Inject, Module } from '@nestjs/common';
import * as Redis from 'ioredis';
import { DataSource } from 'typeorm';
@@ -12,6 +12,7 @@ import { DI } from './di-symbols.js';
import { Config, loadConfig } from './config.js';
import { createPostgresDataSource } from './postgres.js';
import { RepositoryModule } from './models/RepositoryModule.js';
+import { allSettled } from './misc/promise-tracker.js';
import type { Provider, OnApplicationShutdown } from '@nestjs/common';
const $config: Provider = {
@@ -33,7 +34,7 @@ const $meilisearch: Provider = {
useFactory: (config: Config) => {
if (config.meilisearch) {
return new MeiliSearch({
- host: `${config.meilisearch.ssl ? 'https' : 'http' }://${config.meilisearch.host}:${config.meilisearch.port}`,
+ host: `${config.meilisearch.ssl ? 'https' : 'http'}://${config.meilisearch.host}:${config.meilisearch.port}`,
apiKey: config.meilisearch.apiKey,
});
} else {
@@ -46,7 +47,16 @@ const $meilisearch: Provider = {
const $redis: Provider = {
provide: DI.redis,
useFactory: (config: Config) => {
- return new Redis.Redis(config.redis);
+ return new Redis.Redis({
+ ...config.redis,
+ reconnectOnError: (err: Error) => {
+ if ( err.message.includes('READONLY')
+ || err.message.includes('ETIMEDOUT')
+ || err.message.includes('Command timed out')
+ ) return 2;
+ return 1;
+ },
+ });
},
inject: [DI.config],
};
@@ -54,7 +64,16 @@ const $redis: Provider = {
const $redisForPub: Provider = {
provide: DI.redisForPub,
useFactory: (config: Config) => {
- const redis = new Redis.Redis(config.redisForPubsub);
+ const redis = new Redis.Redis({
+ ...config.redisForPubsub,
+ reconnectOnError: (err: Error) => {
+ if ( err.message.includes('READONLY')
+ || err.message.includes('ETIMEDOUT')
+ || err.message.includes('Command timed out')
+ ) return 2;
+ return 1;
+ },
+ });
return redis;
},
inject: [DI.config],
@@ -63,7 +82,16 @@ const $redisForPub: Provider = {
const $redisForSub: Provider = {
provide: DI.redisForSub,
useFactory: (config: Config) => {
- const redis = new Redis.Redis(config.redisForPubsub);
+ const redis = new Redis.Redis({
+ ...config.redisForPubsub,
+ reconnectOnError: (err: Error) => {
+ if ( err.message.includes('READONLY')
+ || err.message.includes('ETIMEDOUT')
+ || err.message.includes('Command timed out')
+ ) return 2;
+ return 1;
+ },
+ });
redis.subscribe(config.host);
return redis;
},
@@ -73,7 +101,16 @@ const $redisForSub: Provider = {
const $redisForTimelines: Provider = {
provide: DI.redisForTimelines,
useFactory: (config: Config) => {
- return new Redis.Redis(config.redisForTimelines);
+ return new Redis.Redis({
+ ...config.redisForTimelines,
+ reconnectOnError: (err: Error) => {
+ if ( err.message.includes('READONLY')
+ || err.message.includes('ETIMEDOUT')
+ || err.message.includes('Command timed out')
+ ) return 2;
+ return 1;
+ },
+ });
},
inject: [DI.config],
};
@@ -91,17 +128,12 @@ export class GlobalModule implements OnApplicationShutdown {
@Inject(DI.redisForPub) private redisForPub: Redis.Redis,
@Inject(DI.redisForSub) private redisForSub: Redis.Redis,
@Inject(DI.redisForTimelines) private redisForTimelines: Redis.Redis,
- ) {}
+ ) { }
public async dispose(): Promise {
- if (process.env.NODE_ENV === 'test') {
- // XXX:
- // Shutting down the existing connections causes errors on Jest as
- // Misskey has asynchronous postgres/redis connections that are not
- // awaited.
- // Let's wait for some random time for them to finish.
- await setTimeout(5000);
- }
+ // Wait for all potential DB queries
+ await allSettled();
+ // And then disconnect from DB
await Promise.all([
this.db.destroy(),
this.redisClient.disconnect(),
@@ -113,5 +145,9 @@ export class GlobalModule implements OnApplicationShutdown {
async onApplicationShutdown(signal: string): Promise {
await this.dispose();
+ process.emitWarning('Misskey is shutting down', {
+ code: 'MISSKEY_SHUTDOWN',
+ detail: `Application received ${signal} signal`,
+ });
}
}
diff --git a/packages/backend/src/MainModule.ts b/packages/backend/src/MainModule.ts
index 90aba0cc9..f86a0be93 100644
--- a/packages/backend/src/MainModule.ts
+++ b/packages/backend/src/MainModule.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/NestLogger.ts b/packages/backend/src/NestLogger.ts
index e18e9e88a..80f1f7a02 100644
--- a/packages/backend/src/NestLogger.ts
+++ b/packages/backend/src/NestLogger.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/boot/common.ts b/packages/backend/src/boot/common.ts
index df10ab1e3..b2dc31050 100644
--- a/packages/backend/src/boot/common.ts
+++ b/packages/backend/src/boot/common.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -9,7 +9,6 @@ import { QueueProcessorService } from '@/queue/QueueProcessorService.js';
import { NestLogger } from '@/NestLogger.js';
import { QueueProcessorModule } from '@/queue/QueueProcessorModule.js';
import { QueueStatsService } from '@/daemons/QueueStatsService.js';
-import { ServerStatsService } from '@/daemons/ServerStatsService.js';
import { ServerService } from '@/server/ServerService.js';
import { MainModule } from '@/MainModule.js';
@@ -17,6 +16,7 @@ export async function server() {
const app = await NestFactory.createApplicationContext(MainModule, {
logger: new NestLogger(),
});
+ app.enableShutdownHooks();
const serverService = app.get(ServerService);
await serverService.launch();
@@ -24,7 +24,6 @@ export async function server() {
if (process.env.NODE_ENV !== 'test') {
app.get(ChartManagementService).start();
app.get(QueueStatsService).start();
- app.get(ServerStatsService).start();
}
return app;
@@ -34,6 +33,7 @@ export async function jobQueue() {
const jobQueue = await NestFactory.createApplicationContext(QueueProcessorModule, {
logger: new NestLogger(),
});
+ jobQueue.enableShutdownHooks();
jobQueue.get(QueueProcessorService).start();
jobQueue.get(ChartManagementService).start();
diff --git a/packages/backend/src/boot/entry.ts b/packages/backend/src/boot/entry.ts
index fc8fc2ffb..9acb89929 100644
--- a/packages/backend/src/boot/entry.ts
+++ b/packages/backend/src/boot/entry.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -9,6 +9,7 @@
import cluster from 'node:cluster';
import { EventEmitter } from 'node:events';
+import process from 'node:process';
import chalk from 'chalk';
import Xev from 'xev';
import Logger from '@/logger.js';
@@ -29,23 +30,38 @@ const ev = new Xev();
//#region Events
-// Listen new workers
-cluster.on('fork', worker => {
- clusterLogger.debug(`Process forked: [${worker.id}]`);
-});
+let isShuttingDown = false;
-// Listen online workers
-cluster.on('online', worker => {
- clusterLogger.debug(`Process is now online: [${worker.id}]`);
-});
+if (cluster.isPrimary && !envOption.disableClustering) {
+ // Listen new workers
+ cluster.on('fork', worker => {
+ clusterLogger.debug(`Process forked: [${worker.id}]`);
+ });
-// Listen for dying workers
-cluster.on('exit', worker => {
- // Replace the dead worker,
- // we're not sentimental
- clusterLogger.error(chalk.red(`[${worker.id}] died :(`));
- cluster.fork();
-});
+ // Listen online workers
+ cluster.on('online', worker => {
+ clusterLogger.debug(`Process is now online: [${worker.id}]`);
+ });
+
+ // Listen for dying workers
+ cluster.on('exit', (worker, code, signal) => {
+ // Replace the dead worker,
+ // we're not sentimental
+ clusterLogger.error(chalk.red(`[${worker.id}] died (${signal || code})`));
+ if (!isShuttingDown) cluster.fork();
+ else clusterLogger.info(chalk.yellow('Worker respawn disabled because of shutdown'));
+ });
+
+ process.on('SIGINT', () => {
+ logger.warn(chalk.yellow('Process received SIGINT'));
+ isShuttingDown = true;
+ });
+
+ process.on('SIGTERM', () => {
+ logger.warn(chalk.yellow('Process received SIGTERM'));
+ isShuttingDown = true;
+ });
+}
// Display detail of unhandled promise rejection
if (!envOption.quiet) {
@@ -55,14 +71,20 @@ if (!envOption.quiet) {
// Display detail of uncaught exception
process.on('uncaughtException', err => {
try {
- logger.error(err);
- console.trace(err);
+ logger.error(`Uncaught exception: ${err.message}`, { error: err });
} catch { }
});
// Dying away...
process.on('exit', code => {
- logger.info(`The process is going to exit with code ${code}`);
+ logger.warn(chalk.yellow(`The process is going to exit with code ${code}`));
+});
+
+process.on('warning', warning => {
+ if ((warning as never)['code'] !== 'MISSKEY_SHUTDOWN') return;
+ logger.warn(chalk.yellow(`${warning.message}: ${(warning as never)['detail']}`));
+ for (const id in cluster.workers) cluster.workers[id]?.process.kill('SIGTERM');
+ process.exit();
});
//#endregion
@@ -75,7 +97,7 @@ if (cluster.isPrimary || envOption.disableClustering) {
}
}
-if (cluster.isWorker || envOption.disableClustering) {
+if (cluster.isWorker) {
await workerMain();
}
diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts
index 623cc964a..b442e1aa4 100644
--- a/packages/backend/src/boot/master.ts
+++ b/packages/backend/src/boot/master.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -28,7 +28,7 @@ const bootLogger = logger.createSubLogger('boot', 'magenta', false);
const themeColor = chalk.hex('#86b300');
function greet() {
- if (!envOption.quiet) {
+ if (!envOption.quiet && !envOption.logJson) {
//#region Misskey logo
const v = `v${meta.version}`;
console.log(themeColor(' _____ _ _ '));
@@ -46,7 +46,7 @@ function greet() {
}
bootLogger.info('Welcome to Misskey!');
- bootLogger.info(`Misskey v${meta.version}`, null, true);
+ bootLogger.info(`Misskey v${meta.version}`, { version: meta.version, hostname: os.hostname(), pid: process.pid }, true);
}
/**
@@ -65,7 +65,7 @@ export async function masterMain() {
//await connectDb();
if (config.pidFile) fs.writeFileSync(config.pidFile, process.pid.toString());
} catch (e) {
- bootLogger.error('Fatal error occurred during initialization', null, true);
+ bootLogger.error('Fatal error occurred during initialization', { error: e }, true);
process.exit(1);
}
@@ -124,7 +124,7 @@ function loadConfigBoot(): Config {
config = loadConfig();
} catch (exception) {
if (typeof exception === 'string') {
- configLogger.error(exception);
+ configLogger.error(exception, null, true);
process.exit(1);
} else if ((exception as any).code === 'ENOENT') {
configLogger.error('Configuration file not found', null, true);
diff --git a/packages/backend/src/boot/worker.ts b/packages/backend/src/boot/worker.ts
index 0399c9fe5..d4a7cd56e 100644
--- a/packages/backend/src/boot/worker.ts
+++ b/packages/backend/src/boot/worker.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts
index 377a4d527..a7e32e116 100644
--- a/packages/backend/src/config.ts
+++ b/packages/backend/src/config.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -7,9 +7,10 @@ import * as fs from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, resolve } from 'node:path';
import * as yaml from 'js-yaml';
+import type * as Bull from 'bullmq';
import type { RedisOptions } from 'ioredis';
-type RedisOptionsSource = Partial & {
+export type RedisOptionsSource = Partial & {
host: string;
port: number;
family?: number;
@@ -47,6 +48,14 @@ type Source = {
redis: RedisOptionsSource;
redisForPubsub?: RedisOptionsSource;
redisForJobQueue?: RedisOptionsSource;
+ redisForSystemQueue?: RedisOptionsSource;
+ redisForEndedPollNotificationQueue?: RedisOptionsSource;
+ redisForDeliverQueue?: RedisOptionsSource;
+ redisForInboxQueue?: RedisOptionsSource;
+ redisForDbQueue?: RedisOptionsSource;
+ redisForRelationshipQueue?: RedisOptionsSource;
+ redisForObjectStorageQueue?: RedisOptionsSource;
+ redisForWebhookDeliverQueue?: RedisOptionsSource;
redisForTimelines?: RedisOptionsSource;
meilisearch?: {
host: string;
@@ -78,6 +87,8 @@ type Source = {
allowedPrivateNetworks?: string[];
+ contentSecurityPolicy?: string;
+
maxFileSize?: number;
clusterLimit?: number;
@@ -87,12 +98,14 @@ type Source = {
outgoingAddress?: string;
outgoingAddressFamily?: 'ipv4' | 'ipv6' | 'dual';
+ bullmqQueueOptions?: Partial;
+ bullmqWorkerOptions?: Partial;
deliverJobConcurrency?: number;
inboxJobConcurrency?: number;
- relashionshipJobConcurrency?: number;
+ relationshipJobConcurrency?: number;
deliverJobPerSec?: number;
inboxJobPerSec?: number;
- relashionshipJobPerSec?: number;
+ relationshipJobPerSec?: number;
deliverJobMaxAttempts?: number;
inboxJobMaxAttempts?: number;
@@ -158,17 +171,20 @@ export type Config = {
proxySmtp: string | undefined;
proxyBypassHosts: string[] | undefined;
allowedPrivateNetworks: string[] | undefined;
+ contentSecurityPolicy: string | undefined;
maxFileSize: number | undefined;
clusterLimit: number | undefined;
id: string;
outgoingAddress: string | undefined;
outgoingAddressFamily: 'ipv4' | 'ipv6' | 'dual' | undefined;
+ bullmqQueueOptions: Partial;
+ bullmqWorkerOptions: Partial;
deliverJobConcurrency: number | undefined;
inboxJobConcurrency: number | undefined;
- relashionshipJobConcurrency: number | undefined;
+ relationshipJobConcurrency: number | undefined;
deliverJobPerSec: number | undefined;
inboxJobPerSec: number | undefined;
- relashionshipJobPerSec: number | undefined;
+ relationshipJobPerSec: number | undefined;
deliverJobMaxAttempts: number | undefined;
inboxJobMaxAttempts: number | undefined;
proxyRemoteFiles: boolean | undefined;
@@ -191,7 +207,14 @@ export type Config = {
videoThumbnailGenerator: string | null;
redis: RedisOptions & RedisOptionsSource;
redisForPubsub: RedisOptions & RedisOptionsSource;
- redisForJobQueue: RedisOptions & RedisOptionsSource;
+ redisForSystemQueue: RedisOptions & RedisOptionsSource;
+ redisForEndedPollNotificationQueue: RedisOptions & RedisOptionsSource;
+ redisForDeliverQueue: RedisOptions & RedisOptionsSource;
+ redisForInboxQueue: RedisOptions & RedisOptionsSource;
+ redisForDbQueue: RedisOptions & RedisOptionsSource;
+ redisForRelationshipQueue: RedisOptions & RedisOptionsSource;
+ redisForObjectStorageQueue: RedisOptions & RedisOptionsSource;
+ redisForWebhookDeliverQueue: RedisOptions & RedisOptionsSource;
redisForTimelines: RedisOptions & RedisOptionsSource;
perChannelMaxNoteCacheCount: number;
perUserNotificationsMaxCount: number;
@@ -236,6 +259,7 @@ export function loadConfig(): Config {
: null;
const internalMediaProxy = `${scheme}://${host}/proxy`;
const redis = convertRedisOptions(config.redis, host);
+ const redisForJobQueue = config.redisForJobQueue ? convertRedisOptions(config.redisForJobQueue, host) : redis;
return {
version,
@@ -259,23 +283,33 @@ export function loadConfig(): Config {
s3: config.s3,
redis,
redisForPubsub: config.redisForPubsub ? convertRedisOptions(config.redisForPubsub, host) : redis,
- redisForJobQueue: config.redisForJobQueue ? convertRedisOptions(config.redisForJobQueue, host) : redis,
+ redisForSystemQueue: config.redisForSystemQueue ? convertRedisOptions(config.redisForSystemQueue, host) : redisForJobQueue,
+ redisForEndedPollNotificationQueue: config.redisForEndedPollNotificationQueue ? convertRedisOptions(config.redisForEndedPollNotificationQueue, host) : redisForJobQueue,
+ redisForDeliverQueue: config.redisForDeliverQueue ? convertRedisOptions(config.redisForDeliverQueue, host) : redisForJobQueue,
+ redisForInboxQueue: config.redisForInboxQueue ? convertRedisOptions(config.redisForInboxQueue, host) : redisForJobQueue,
+ redisForDbQueue: config.redisForDbQueue ? convertRedisOptions(config.redisForDbQueue, host) : redisForJobQueue,
+ redisForRelationshipQueue: config.redisForRelationshipQueue ? convertRedisOptions(config.redisForRelationshipQueue, host) : redisForJobQueue,
+ redisForObjectStorageQueue: config.redisForObjectStorageQueue ? convertRedisOptions(config.redisForObjectStorageQueue, host) : redisForJobQueue,
+ redisForWebhookDeliverQueue: config.redisForWebhookDeliverQueue ? convertRedisOptions(config.redisForWebhookDeliverQueue, host) : redisForJobQueue,
redisForTimelines: config.redisForTimelines ? convertRedisOptions(config.redisForTimelines, host) : redis,
id: config.id,
proxy: config.proxy,
proxySmtp: config.proxySmtp,
proxyBypassHosts: config.proxyBypassHosts,
allowedPrivateNetworks: config.allowedPrivateNetworks,
+ contentSecurityPolicy: config.contentSecurityPolicy,
maxFileSize: config.maxFileSize,
clusterLimit: config.clusterLimit,
outgoingAddress: config.outgoingAddress,
outgoingAddressFamily: config.outgoingAddressFamily,
+ bullmqQueueOptions: config.bullmqQueueOptions ?? {},
+ bullmqWorkerOptions: config.bullmqWorkerOptions ?? {},
deliverJobConcurrency: config.deliverJobConcurrency,
inboxJobConcurrency: config.inboxJobConcurrency,
- relashionshipJobConcurrency: config.relashionshipJobConcurrency,
+ relationshipJobConcurrency: config.relationshipJobConcurrency,
deliverJobPerSec: config.deliverJobPerSec,
inboxJobPerSec: config.inboxJobPerSec,
- relashionshipJobPerSec: config.relashionshipJobPerSec,
+ relationshipJobPerSec: config.relationshipJobPerSec,
deliverJobMaxAttempts: config.deliverJobMaxAttempts,
inboxJobMaxAttempts: config.inboxJobMaxAttempts,
proxyRemoteFiles: config.proxyRemoteFiles,
diff --git a/packages/backend/src/const.ts b/packages/backend/src/const.ts
index 716a8de38..a238f4973 100644
--- a/packages/backend/src/const.ts
+++ b/packages/backend/src/const.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/AccountMoveService.ts b/packages/backend/src/core/AccountMoveService.ts
index 350aa6ba2..6aa2fc2fe 100644
--- a/packages/backend/src/core/AccountMoveService.ts
+++ b/packages/backend/src/core/AccountMoveService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -8,6 +8,7 @@ import { IsNull, In, MoreThan, Not } from 'typeorm';
import { bindThis } from '@/decorators.js';
import { DI } from '@/di-symbols.js';
+import type { Config } from '@/config.js';
import type { MiLocalUser, MiRemoteUser, MiUser } from '@/models/User.js';
import type { BlockingsRepository, FollowingsRepository, InstancesRepository, MutingsRepository, UserListMembershipsRepository, UsersRepository } from '@/models/_.js';
import type { RelationshipJobData, ThinUser } from '@/queue/types.js';
@@ -20,7 +21,6 @@ import { ApPersonService } from '@/core/activitypub/models/ApPersonService.js';
import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
-import { CacheService } from '@/core/CacheService.js';
import { ProxyAccountService } from '@/core/ProxyAccountService.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
import { MetaService } from '@/core/MetaService.js';
@@ -60,7 +60,6 @@ export class AccountMoveService {
private instanceChart: InstanceChart,
private metaService: MetaService,
private relayService: RelayService,
- private cacheService: CacheService,
private queueService: QueueService,
) {
}
@@ -72,7 +71,6 @@ export class AccountMoveService {
*/
@bindThis
public async moveFromLocal(src: MiLocalUser, dst: MiLocalUser | MiRemoteUser): Promise {
- const srcUri = this.userEntityService.getUserUri(src);
const dstUri = this.userEntityService.getUserUri(dst);
// add movedToUri to indicate that the user has moved
@@ -84,7 +82,7 @@ export class AccountMoveService {
Object.assign(src, update);
// Update cache
- this.cacheService.uriPersonCache.set(srcUri, src);
+ this.globalEventService.publishInternalEvent('localUserUpdated', src);
const srcPerson = await this.apRendererService.renderPerson(src);
const updateAct = this.apRendererService.addContext(this.apRendererService.renderUpdate(srcPerson, src));
@@ -96,7 +94,7 @@ export class AccountMoveService {
await this.apDeliverManagerService.deliverToFollowers(src, moveAct);
// Publish meUpdated event
- const iObj = await this.userEntityService.pack(src.id, src, { detail: true, includeSecrets: true });
+ const iObj = await this.userEntityService.pack(src.id, src, { schema: 'MeDetailed', includeSecrets: true });
this.globalEventService.publishMainStream(src.id, 'meUpdated', iObj);
// Unfollow after 24 hours
diff --git a/packages/backend/src/core/AccountUpdateService.ts b/packages/backend/src/core/AccountUpdateService.ts
index 664700ea6..69a57b485 100644
--- a/packages/backend/src/core/AccountUpdateService.ts
+++ b/packages/backend/src/core/AccountUpdateService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/AchievementService.ts b/packages/backend/src/core/AchievementService.ts
index 88fc03385..4fc1193f3 100644
--- a/packages/backend/src/core/AchievementService.ts
+++ b/packages/backend/src/core/AchievementService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -87,6 +87,8 @@ export const ACHIEVEMENT_TYPES = [
'brainDiver',
'smashTestNotificationButton',
'tutorialCompleted',
+ 'bubbleGameExplodingHead',
+ 'bubbleGameDoubleExplodingHead',
] as const;
@Injectable()
diff --git a/packages/backend/src/core/AiService.ts b/packages/backend/src/core/AiService.ts
index 4e876495a..33b79be35 100644
--- a/packages/backend/src/core/AiService.ts
+++ b/packages/backend/src/core/AiService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -11,6 +11,8 @@ import * as nsfw from 'nsfwjs';
import si from 'systeminformation';
import { Mutex } from 'async-mutex';
import { bindThis } from '@/decorators.js';
+import type Logger from '@/logger.js';
+import { LoggerService } from '@/core/LoggerService.js';
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
@@ -20,11 +22,14 @@ let isSupportedCpu: undefined | boolean = undefined;
@Injectable()
export class AiService {
+ private logger: Logger;
private model: nsfw.NSFWJS;
private modelLoadMutex: Mutex = new Mutex();
constructor(
+ private loggerService: LoggerService,
) {
+ this.logger = this.loggerService.getLogger('ai');
}
@bindThis
@@ -36,7 +41,7 @@ export class AiService {
}
if (!isSupportedCpu) {
- console.error('This CPU cannot use TensorFlow.');
+ this.logger.error('This CPU cannot use TensorFlow.');
return null;
}
@@ -59,7 +64,7 @@ export class AiService {
image.dispose();
}
} catch (err) {
- console.error(err);
+ this.logger.error('Failed to detect sensitive', { error: err });
return null;
}
}
diff --git a/packages/backend/src/core/AnnouncementService.ts b/packages/backend/src/core/AnnouncementService.ts
index 8c348e595..102d256be 100644
--- a/packages/backend/src/core/AnnouncementService.ts
+++ b/packages/backend/src/core/AnnouncementService.ts
@@ -1,16 +1,19 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
-import { Brackets } from 'typeorm';
+import { Brackets, In } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { MiUser } from '@/models/User.js';
-import type { AnnouncementReadsRepository, AnnouncementsRepository, MiAnnouncement, MiAnnouncementRead, UsersRepository } from '@/models/_.js';
+import type { AnnouncementReadsRepository, AnnouncementsRepository, MiAnnouncement, UsersRepository } from '@/models/_.js';
+import { MiAnnouncementRead } from '@/models/_.js';
import { bindThis } from '@/decorators.js';
import { Packed } from '@/misc/json-schema.js';
import { IdService } from '@/core/IdService.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import { AnnouncementEntityService } from '@/core/entities/AnnouncementEntityService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
@@ -27,6 +30,8 @@ export class AnnouncementService {
private usersRepository: UsersRepository,
private idService: IdService,
+ private userEntityService: UserEntityService,
+ private announcementEntityService: AnnouncementEntityService,
private globalEventService: GlobalEventService,
private moderationLogService: ModerationLogService,
) {
@@ -40,13 +45,18 @@ export class AnnouncementService {
}
@bindThis
- public async getUnreadAnnouncements(user: MiUser): Promise {
- const readsQuery = this.announcementReadsRepository.createQueryBuilder('read')
- .select('read.announcementId')
- .where('read.userId = :userId', { userId: user.id });
+ public async getUnreadAnnouncements(user: MiUser): Promise[]> {
+ const q = this.announcementsRepository.createQueryBuilder('announcement');
+ q.leftJoinAndSelect(
+ MiAnnouncementRead,
+ 'read',
+ 'read."announcementId" = announcement.id AND read."userId" = :userId',
+ { userId: user.id },
+ );
- const q = this.announcementsRepository.createQueryBuilder('announcement')
- .where('announcement.isActive = true')
+ q
+ .where('read.id IS NULL')
+ .andWhere('announcement.isActive = true')
.andWhere('announcement.silence = false')
.andWhere(new Brackets(qb => {
qb.orWhere('announcement.userId = :userId', { userId: user.id });
@@ -55,12 +65,17 @@ export class AnnouncementService {
.andWhere(new Brackets(qb => {
qb.orWhere('announcement.forExistingUsers = false');
qb.orWhere('announcement.id > :userId', { userId: user.id });
- }))
- .andWhere(`announcement.id NOT IN (${ readsQuery.getQuery() })`);
+ }));
- q.setParameters(readsQuery.getParameters());
+ q.orderBy({
+ 'announcement."displayOrder"': 'DESC',
+ 'announcement.id': 'DESC',
+ });
- return q.getMany();
+ return this.announcementEntityService.packMany(
+ await q.getMany(),
+ user,
+ );
}
@bindThis
@@ -76,10 +91,12 @@ export class AnnouncementService {
forExistingUsers: values.forExistingUsers,
silence: values.silence,
needConfirmationToRead: values.needConfirmationToRead,
+ closeDuration: values.closeDuration,
+ displayOrder: values.displayOrder,
userId: values.userId,
}).then(x => this.announcementsRepository.findOneByOrFail(x.identifiers[0]));
- const packed = (await this.packMany([announcement]))[0];
+ const packed = (await this.announcementEntityService.packMany([announcement], null))[0];
if (values.userId) {
this.globalEventService.publishMainStream(values.userId, 'announcementCreated', {
@@ -115,10 +132,65 @@ export class AnnouncementService {
};
}
+ @bindThis
+ public async list(
+ userId: MiUser['id'] | null,
+ limit: number,
+ offset: number,
+ moderator: MiUser,
+ ): Promise<(MiAnnouncement & { userInfo: Packed<'UserLite'> | null, reads: number })[]> {
+ const query = this.announcementsRepository.createQueryBuilder('announcement');
+
+ if (userId) {
+ query.andWhere('announcement."userId" = :userId', { userId: userId });
+ } else {
+ query.andWhere('announcement."userId" IS NULL');
+ }
+
+ query.orderBy({
+ 'announcement."isActive"': 'DESC',
+ 'announcement.id': 'DESC',
+ });
+
+ const announcements = await query
+ .limit(limit)
+ .offset(offset)
+ .getMany();
+
+ const reads = new Map();
+
+ for (const announcement of announcements) {
+ reads.set(announcement, await this.announcementReadsRepository.countBy({
+ announcementId: announcement.id,
+ }));
+ }
+
+ const users = await this.usersRepository.findBy({
+ id: In(announcements.map(a => a.userId).filter(id => id != null)),
+ });
+ const packedUsers = await this.userEntityService.packMany(users, moderator, {
+ schema: 'UserLite'
+ });
+
+ return announcements.map(announcement => ({
+ ...announcement,
+ userInfo: packedUsers.find(u => u.id === announcement.userId) ?? null,
+ reads: reads.get(announcement) ?? 0,
+ }));
+ }
+
@bindThis
public async update(announcement: MiAnnouncement, values: Partial, moderator?: MiUser): Promise {
+ if (announcement.userId && announcement.userId !== values.userId) {
+ await this.announcementReadsRepository.delete({
+ announcementId: announcement.id,
+ userId: announcement.userId,
+ });
+ }
+
await this.announcementsRepository.update(announcement.id, {
updatedAt: new Date(),
+ isActive: values.isActive,
title: values.title,
text: values.text,
/* eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- 空の文字列の場合、nullを渡すようにするため */
@@ -126,9 +198,11 @@ export class AnnouncementService {
display: values.display,
icon: values.icon,
forExistingUsers: values.forExistingUsers,
- silence: values.silence,
needConfirmationToRead: values.needConfirmationToRead,
- isActive: values.isActive,
+ closeDuration: values.closeDuration,
+ displayOrder: values.displayOrder,
+ silence: values.silence,
+ userId: values.userId,
});
const after = await this.announcementsRepository.findOneByOrFail({ id: announcement.id });
@@ -156,6 +230,9 @@ export class AnnouncementService {
@bindThis
public async delete(announcement: MiAnnouncement, moderator?: MiUser): Promise {
+ await this.announcementReadsRepository.delete({
+ announcementId: announcement.id,
+ });
await this.announcementsRepository.delete(announcement.id);
if (moderator) {
@@ -177,6 +254,99 @@ export class AnnouncementService {
}
}
+ @bindThis
+ public async getAnnouncements(
+ me: MiUser | null,
+ limit: number,
+ offset: number,
+ isActive: boolean,
+ ): Promise[]> {
+ const query = this.announcementsRepository.createQueryBuilder('announcement');
+
+ if (me) {
+ query.leftJoin(
+ MiAnnouncementRead,
+ 'read',
+ 'read."announcementId" = announcement.id AND read."userId" = :userId',
+ { userId: me.id },
+ );
+ query.select([
+ 'announcement.*',
+ 'read.id IS NOT NULL as "isRead"',
+ ]);
+ query
+ .andWhere(
+ new Brackets((qb) => {
+ qb.orWhere('announcement."userId" = :userId', { userId: me.id });
+ qb.orWhere('announcement."userId" IS NULL');
+ }),
+ )
+ .andWhere(
+ new Brackets((qb) => {
+ qb.orWhere('announcement."forExistingUsers" = false');
+ qb.orWhere('announcement.id > :userId', { userId: me.id });
+ }),
+ );
+ } else {
+ query.select([
+ 'announcement.*',
+ 'NULL as "isRead"',
+ ]);
+ query.andWhere('announcement."userId" IS NULL');
+ query.andWhere('announcement."forExistingUsers" = false');
+ }
+
+ query.andWhere('announcement."isActive" = :isActive', {
+ isActive: isActive,
+ });
+
+ if (isActive) {
+ query.orderBy({
+ '"isRead"': 'ASC',
+ 'announcement."displayOrder"': 'DESC',
+ 'announcement.id': 'DESC',
+ });
+ } else {
+ query.orderBy({
+ 'announcement.id': 'DESC',
+ });
+ }
+
+ return this.announcementEntityService.packMany(
+ await query
+ .limit(limit)
+ .offset(offset)
+ .getRawMany(),
+ me,
+ );
+ }
+
+ @bindThis
+ public async countUnreadAnnouncements(user: MiUser): Promise {
+ const q = this.announcementsRepository.createQueryBuilder('announcement');
+ q.leftJoinAndSelect(
+ MiAnnouncementRead,
+ 'read',
+ 'read."announcementId" = announcement.id AND read."userId" = :userId',
+ { userId: user.id },
+ );
+
+ q
+ .where('read.id IS NULL')
+ .andWhere('announcement.isActive = true')
+ .andWhere('announcement.silence = false')
+ .andWhere(new Brackets(qb => {
+ qb.orWhere('announcement.userId = :userId', { userId: user.id });
+ qb.orWhere('announcement.userId IS NULL');
+ }))
+ .andWhere(new Brackets(qb => {
+ qb.orWhere('announcement.forExistingUsers = false');
+ qb.orWhere('announcement.id > :userId', { userId: user.id });
+ }));
+
+ return q.getCount();
+ }
+
@bindThis
public async read(user: MiUser, announcementId: MiAnnouncement['id']): Promise {
try {
@@ -189,33 +359,8 @@ export class AnnouncementService {
return;
}
- if ((await this.getUnreadAnnouncements(user)).length === 0) {
+ if ((await this.countUnreadAnnouncements(user)) === 0) {
this.globalEventService.publishMainStream(user.id, 'readAllAnnouncements');
}
}
-
- @bindThis
- public async packMany(
- announcements: MiAnnouncement[],
- me?: { id: MiUser['id'] } | null | undefined,
- options?: {
- reads?: MiAnnouncementRead[];
- },
- ): Promise[]> {
- const reads = me ? (options?.reads ?? await this.getReads(me.id)) : [];
- return announcements.map(announcement => ({
- id: announcement.id,
- createdAt: this.idService.parse(announcement.id).date.toISOString(),
- updatedAt: announcement.updatedAt?.toISOString() ?? null,
- text: announcement.text,
- title: announcement.title,
- imageUrl: announcement.imageUrl,
- icon: announcement.icon,
- display: announcement.display,
- needConfirmationToRead: announcement.needConfirmationToRead,
- silence: announcement.silence,
- forYou: announcement.userId === me?.id,
- isRead: reads.some(read => read.announcementId === announcement.id),
- }));
- }
}
diff --git a/packages/backend/src/core/AntennaService.ts b/packages/backend/src/core/AntennaService.ts
index 2815d2473..c148cf547 100644
--- a/packages/backend/src/core/AntennaService.ts
+++ b/packages/backend/src/core/AntennaService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -16,7 +16,8 @@ import type { AntennasRepository, UserListMembershipsRepository } from '@/models
import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js';
-import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
+import { FanoutTimelineService } from '@/core/FanoutTimelineService.js';
+import { RolePolicies, RoleService } from '@/core/RoleService.js';
import type { OnApplicationShutdown } from '@nestjs/common';
@Injectable()
@@ -39,7 +40,8 @@ export class AntennaService implements OnApplicationShutdown {
private utilityService: UtilityService,
private globalEventService: GlobalEventService,
- private funoutTimelineService: FunoutTimelineService,
+ private fanoutTimelineService: FanoutTimelineService,
+ private roleService: RoleService,
) {
this.antennasFetched = false;
this.antennas = [];
@@ -55,23 +57,32 @@ export class AntennaService implements OnApplicationShutdown {
const { type, body } = obj.message as GlobalEvents['internal']['payload'];
switch (type) {
case 'antennaCreated':
- this.antennas.push({
+ this.antennas.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい
...body,
+ createdAt: new Date(body.createdAt),
lastUsedAt: new Date(body.lastUsedAt),
+ user: null, // joinなカラムは通常取ってこないので
+ userList: null, // joinなカラムは通常取ってこないので
});
break;
case 'antennaUpdated': {
const idx = this.antennas.findIndex(a => a.id === body.id);
if (idx >= 0) {
- this.antennas[idx] = {
+ this.antennas[idx] = { // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい
...body,
+ createdAt: new Date(body.createdAt),
lastUsedAt: new Date(body.lastUsedAt),
+ user: null, // joinなカラムは通常取ってこないので
+ userList: null, // joinなカラムは通常取ってこないので
};
} else {
// サーバ起動時にactiveじゃなかった場合、リストに持っていないので追加する必要あり
- this.antennas.push({
+ this.antennas.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい
...body,
+ createdAt: new Date(body.createdAt),
lastUsedAt: new Date(body.lastUsedAt),
+ user: null, // joinなカラムは通常取ってこないので
+ userList: null, // joinなカラムは通常取ってこないので
});
}
}
@@ -93,8 +104,14 @@ export class AntennaService implements OnApplicationShutdown {
const redisPipeline = this.redisForTimelines.pipeline();
+ const policies = new Map((await Promise.allSettled(Array.from(new Set(matchedAntennas.map(antenna => antenna.userId))).map(async userId => [userId, await this.roleService.getUserPolicies(userId)] as const)))
+ .filter((result): result is PromiseFulfilledResult<[string, RolePolicies]> => result.status === 'fulfilled')
+ .map(result => result.value));
+
for (const antenna of matchedAntennas) {
- this.funoutTimelineService.push(`antennaTimeline:${antenna.id}`, note.id, 200, redisPipeline);
+ const { antennaNotesLimit } = policies.get(antenna.userId) ?? await this.roleService.getUserPolicies(antenna.userId);
+
+ this.fanoutTimelineService.push(`antennaTimeline:${antenna.id}`, note.id, antennaNotesLimit, redisPipeline);
this.globalEventService.publishAntennaStream(antenna.id, 'note', note);
}
diff --git a/packages/backend/src/core/AppLockService.ts b/packages/backend/src/core/AppLockService.ts
index 7a1293a6d..bd2749cb8 100644
--- a/packages/backend/src/core/AppLockService.ts
+++ b/packages/backend/src/core/AppLockService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/AvatarDecorationService.ts b/packages/backend/src/core/AvatarDecorationService.ts
index e97946f9d..21e31d79a 100644
--- a/packages/backend/src/core/AvatarDecorationService.ts
+++ b/packages/backend/src/core/AvatarDecorationService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/CacheService.ts b/packages/backend/src/core/CacheService.ts
index e1413342b..d008e7ec5 100644
--- a/packages/backend/src/core/CacheService.ts
+++ b/packages/backend/src/core/CacheService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -16,10 +16,10 @@ import type { OnApplicationShutdown } from '@nestjs/common';
@Injectable()
export class CacheService implements OnApplicationShutdown {
- public userByIdCache: MemoryKVCache;
- public localUserByNativeTokenCache: MemoryKVCache;
+ public userByIdCache: MemoryKVCache;
+ public localUserByNativeTokenCache: MemoryKVCache;
public localUserByIdCache: MemoryKVCache;
- public uriPersonCache: MemoryKVCache;
+ public uriPersonCache: MemoryKVCache;
public userProfileCache: RedisKVCache;
public userMutingsCache: RedisKVCache>;
public userBlockingCache: RedisKVCache>;
@@ -56,41 +56,10 @@ export class CacheService implements OnApplicationShutdown {
) {
//this.onMessage = this.onMessage.bind(this);
- const localUserByIdCache = new MemoryKVCache(1000 * 60 * 60 * 6 /* 6h */);
- this.localUserByIdCache = localUserByIdCache;
-
- // ローカルユーザーならlocalUserByIdCacheにデータを追加し、こちらにはid(文字列)だけを追加する
- const userByIdCache = new MemoryKVCache(1000 * 60 * 60 * 6 /* 6h */, {
- toMapConverter: user => {
- if (user.host === null) {
- localUserByIdCache.set(user.id, user as MiLocalUser);
- return user.id;
- }
-
- return user;
- },
- fromMapConverter: userOrId => typeof userOrId === 'string' ? localUserByIdCache.get(userOrId) : userOrId,
- });
- this.userByIdCache = userByIdCache;
-
- this.localUserByNativeTokenCache = new MemoryKVCache(Infinity, {
- toMapConverter: user => {
- if (user === null) return null;
-
- localUserByIdCache.set(user.id, user);
- return user.id;
- },
- fromMapConverter: id => id === null ? null : localUserByIdCache.get(id),
- });
- this.uriPersonCache = new MemoryKVCache(Infinity, {
- toMapConverter: user => {
- if (user === null) return null;
-
- userByIdCache.set(user.id, user);
- return user.id;
- },
- fromMapConverter: id => id === null ? null : userByIdCache.get(id),
- });
+ this.userByIdCache = new MemoryKVCache(Infinity);
+ this.localUserByNativeTokenCache = new MemoryKVCache(Infinity);
+ this.localUserByIdCache = new MemoryKVCache(Infinity);
+ this.uriPersonCache = new MemoryKVCache(Infinity);
this.userProfileCache = new RedisKVCache(this.redisClient, 'userProfile', {
lifetime: 1000 * 60 * 30, // 30m
@@ -159,17 +128,29 @@ export class CacheService implements OnApplicationShutdown {
const { type, body } = obj.message as GlobalEvents['internal']['payload'];
switch (type) {
case 'userChangeSuspendedState':
- case 'remoteUserUpdated': {
- const user = await this.usersRepository.findOneByOrFail({ id: body.id });
- this.userByIdCache.set(user.id, user);
- for (const [k, v] of this.uriPersonCache.cache.entries()) {
- if (v.value === user.id) {
- this.uriPersonCache.set(k, user);
+ case 'userChangeDeletedState':
+ case 'remoteUserUpdated':
+ case 'localUserUpdated': {
+ const user = await this.usersRepository.findOneBy({ id: body.id });
+ if (user == null) {
+ this.userByIdCache.delete(body.id);
+ this.localUserByIdCache.delete(body.id);
+ for (const [k, v] of this.uriPersonCache.cache.entries()) {
+ if (v.value?.id === body.id) {
+ this.uriPersonCache.delete(k);
+ }
+ }
+ } else {
+ this.userByIdCache.set(user.id, user);
+ for (const [k, v] of this.uriPersonCache.cache.entries()) {
+ if (v.value?.id === user.id) {
+ this.uriPersonCache.set(k, user);
+ }
+ }
+ if (this.userEntityService.isLocalUser(user)) {
+ this.localUserByNativeTokenCache.set(user.token!, user);
+ this.localUserByIdCache.set(user.id, user);
}
- }
- if (this.userEntityService.isLocalUser(user)) {
- this.localUserByNativeTokenCache.set(user.token!, user);
- this.localUserByIdCache.set(user.id, user);
}
break;
}
diff --git a/packages/backend/src/core/CaptchaService.ts b/packages/backend/src/core/CaptchaService.ts
index f64196f4f..f6b7955cd 100644
--- a/packages/backend/src/core/CaptchaService.ts
+++ b/packages/backend/src/core/CaptchaService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -73,6 +73,37 @@ export class CaptchaService {
}
}
+ // https://codeberg.org/Gusted/mCaptcha/src/branch/main/mcaptcha.go
+ @bindThis
+ public async verifyMcaptcha(secret: string, siteKey: string, instanceHost: string, response: string | null | undefined): Promise {
+ if (response == null) {
+ throw new Error('mcaptcha-failed: no response provided');
+ }
+
+ const endpointUrl = new URL('/api/v1/pow/siteverify', instanceHost);
+ const result = await this.httpRequestService.send(endpointUrl.toString(), {
+ method: 'POST',
+ body: JSON.stringify({
+ key: siteKey,
+ secret: secret,
+ token: response,
+ }),
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ });
+
+ if (result.status !== 200) {
+ throw new Error('mcaptcha-failed: mcaptcha didn\'t return 200 OK');
+ }
+
+ const resp = (await result.json()) as { valid: boolean };
+
+ if (!resp.valid) {
+ throw new Error('mcaptcha-request-failed');
+ }
+ }
+
@bindThis
public async verifyTurnstile(secret: string, response: string | null | undefined): Promise {
if (response == null) {
diff --git a/packages/backend/src/core/ChannelFollowingService.ts b/packages/backend/src/core/ChannelFollowingService.ts
index 75843b977..12251595e 100644
--- a/packages/backend/src/core/ChannelFollowingService.ts
+++ b/packages/backend/src/core/ChannelFollowingService.ts
@@ -1,3 +1,8 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
import { Inject, Injectable, OnModuleInit } from '@nestjs/common';
import Redis from 'ioredis';
import { DI } from '@/di-symbols.js';
diff --git a/packages/backend/src/core/ClipService.ts b/packages/backend/src/core/ClipService.ts
index e94f1eb53..bb8be26ce 100644
--- a/packages/backend/src/core/ClipService.ts
+++ b/packages/backend/src/core/ClipService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts
index 9fb29e0e6..042e11c45 100644
--- a/packages/backend/src/core/CoreModule.ts
+++ b/packages/backend/src/core/CoreModule.ts
@@ -1,9 +1,10 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Module } from '@nestjs/common';
+import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js';
import { AccountMoveService } from './AccountMoveService.js';
import { AccountUpdateService } from './AccountUpdateService.js';
import { AiService } from './AiService.js';
@@ -62,9 +63,10 @@ import { FileInfoService } from './FileInfoService.js';
import { SearchService } from './SearchService.js';
import { ClipService } from './ClipService.js';
import { FeaturedService } from './FeaturedService.js';
-import { FunoutTimelineService } from './FunoutTimelineService.js';
+import { FanoutTimelineService } from './FanoutTimelineService.js';
import { ChannelFollowingService } from './ChannelFollowingService.js';
import { RegistryApiService } from './RegistryApiService.js';
+import { ReversiService } from './ReversiService.js';
import { ChartLoggerService } from './chart/ChartLoggerService.js';
import FederationChart from './chart/charts/federation.js';
import NotesChart from './chart/charts/notes.js';
@@ -80,6 +82,7 @@ import PerUserDriveChart from './chart/charts/per-user-drive.js';
import ApRequestChart from './chart/charts/ap-request.js';
import { ChartManagementService } from './chart/ChartManagementService.js';
import { AbuseUserReportEntityService } from './entities/AbuseUserReportEntityService.js';
+import { AnnouncementEntityService } from './entities/AnnouncementEntityService.js';
import { AntennaEntityService } from './entities/AntennaEntityService.js';
import { AppEntityService } from './entities/AppEntityService.js';
import { AuthSessionEntityService } from './entities/AuthSessionEntityService.js';
@@ -111,6 +114,9 @@ import { UserListEntityService } from './entities/UserListEntityService.js';
import { FlashEntityService } from './entities/FlashEntityService.js';
import { FlashLikeEntityService } from './entities/FlashLikeEntityService.js';
import { RoleEntityService } from './entities/RoleEntityService.js';
+import { ReversiGameEntityService } from './entities/ReversiGameEntityService.js';
+import { MetaEntityService } from './entities/MetaEntityService.js';
+
import { ApAudienceService } from './activitypub/ApAudienceService.js';
import { ApDbResolverService } from './activitypub/ApDbResolverService.js';
import { ApDeliverManagerService } from './activitypub/ApDeliverManagerService.js';
@@ -194,9 +200,11 @@ const $FileInfoService: Provider = { provide: 'FileInfoService', useExisting: Fi
const $SearchService: Provider = { provide: 'SearchService', useExisting: SearchService };
const $ClipService: Provider = { provide: 'ClipService', useExisting: ClipService };
const $FeaturedService: Provider = { provide: 'FeaturedService', useExisting: FeaturedService };
-const $FunoutTimelineService: Provider = { provide: 'FunoutTimelineService', useExisting: FunoutTimelineService };
+const $FanoutTimelineService: Provider = { provide: 'FanoutTimelineService', useExisting: FanoutTimelineService };
+const $FanoutTimelineEndpointService: Provider = { provide: 'FanoutTimelineEndpointService', useExisting: FanoutTimelineEndpointService };
const $ChannelFollowingService: Provider = { provide: 'ChannelFollowingService', useExisting: ChannelFollowingService };
const $RegistryApiService: Provider = { provide: 'RegistryApiService', useExisting: RegistryApiService };
+const $ReversiService: Provider = { provide: 'ReversiService', useExisting: ReversiService };
const $ChartLoggerService: Provider = { provide: 'ChartLoggerService', useExisting: ChartLoggerService };
const $FederationChart: Provider = { provide: 'FederationChart', useExisting: FederationChart };
@@ -214,6 +222,7 @@ const $ApRequestChart: Provider = { provide: 'ApRequestChart', useExisting: ApRe
const $ChartManagementService: Provider = { provide: 'ChartManagementService', useExisting: ChartManagementService };
const $AbuseUserReportEntityService: Provider = { provide: 'AbuseUserReportEntityService', useExisting: AbuseUserReportEntityService };
+const $AnnouncementEntityService: Provider = { provide: 'AnnouncementEntityService', useExisting: AnnouncementEntityService };
const $AntennaEntityService: Provider = { provide: 'AntennaEntityService', useExisting: AntennaEntityService };
const $AppEntityService: Provider = { provide: 'AppEntityService', useExisting: AppEntityService };
const $AuthSessionEntityService: Provider = { provide: 'AuthSessionEntityService', useExisting: AuthSessionEntityService };
@@ -245,6 +254,8 @@ const $UserListEntityService: Provider = { provide: 'UserListEntityService', use
const $FlashEntityService: Provider = { provide: 'FlashEntityService', useExisting: FlashEntityService };
const $FlashLikeEntityService: Provider = { provide: 'FlashLikeEntityService', useExisting: FlashLikeEntityService };
const $RoleEntityService: Provider = { provide: 'RoleEntityService', useExisting: RoleEntityService };
+const $ReversiGameEntityService: Provider = { provide: 'ReversiGameEntityService', useExisting: ReversiGameEntityService };
+const $MetaEntityService: Provider = { provide: 'MetaEntityService', useExisting: MetaEntityService };
const $ApAudienceService: Provider = { provide: 'ApAudienceService', useExisting: ApAudienceService };
const $ApDbResolverService: Provider = { provide: 'ApDbResolverService', useExisting: ApDbResolverService };
@@ -330,9 +341,11 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
SearchService,
ClipService,
FeaturedService,
- FunoutTimelineService,
+ FanoutTimelineService,
+ FanoutTimelineEndpointService,
ChannelFollowingService,
RegistryApiService,
+ ReversiService,
ChartLoggerService,
FederationChart,
NotesChart,
@@ -348,6 +361,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ApRequestChart,
ChartManagementService,
AbuseUserReportEntityService,
+ AnnouncementEntityService,
AntennaEntityService,
AppEntityService,
AuthSessionEntityService,
@@ -379,6 +393,9 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
FlashEntityService,
FlashLikeEntityService,
RoleEntityService,
+ ReversiGameEntityService,
+ MetaEntityService,
+
ApAudienceService,
ApDbResolverService,
ApDeliverManagerService,
@@ -459,9 +476,11 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$SearchService,
$ClipService,
$FeaturedService,
- $FunoutTimelineService,
+ $FanoutTimelineService,
+ $FanoutTimelineEndpointService,
$ChannelFollowingService,
$RegistryApiService,
+ $ReversiService,
$ChartLoggerService,
$FederationChart,
$NotesChart,
@@ -477,6 +496,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$ApRequestChart,
$ChartManagementService,
$AbuseUserReportEntityService,
+ $AnnouncementEntityService,
$AntennaEntityService,
$AppEntityService,
$AuthSessionEntityService,
@@ -508,6 +528,9 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$FlashEntityService,
$FlashLikeEntityService,
$RoleEntityService,
+ $ReversiGameEntityService,
+ $MetaEntityService,
+
$ApAudienceService,
$ApDbResolverService,
$ApDeliverManagerService,
@@ -589,9 +612,11 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
SearchService,
ClipService,
FeaturedService,
- FunoutTimelineService,
+ FanoutTimelineService,
+ FanoutTimelineEndpointService,
ChannelFollowingService,
RegistryApiService,
+ ReversiService,
FederationChart,
NotesChart,
UsersChart,
@@ -606,6 +631,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
ApRequestChart,
ChartManagementService,
AbuseUserReportEntityService,
+ AnnouncementEntityService,
AntennaEntityService,
AppEntityService,
AuthSessionEntityService,
@@ -637,6 +663,9 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
FlashEntityService,
FlashLikeEntityService,
RoleEntityService,
+ ReversiGameEntityService,
+ MetaEntityService,
+
ApAudienceService,
ApDbResolverService,
ApDeliverManagerService,
@@ -717,9 +746,11 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$SearchService,
$ClipService,
$FeaturedService,
- $FunoutTimelineService,
+ $FanoutTimelineService,
+ $FanoutTimelineEndpointService,
$ChannelFollowingService,
$RegistryApiService,
+ $ReversiService,
$FederationChart,
$NotesChart,
$UsersChart,
@@ -734,6 +765,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$ApRequestChart,
$ChartManagementService,
$AbuseUserReportEntityService,
+ $AnnouncementEntityService,
$AntennaEntityService,
$AppEntityService,
$AuthSessionEntityService,
@@ -765,6 +797,9 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting
$FlashEntityService,
$FlashLikeEntityService,
$RoleEntityService,
+ $ReversiGameEntityService,
+ $MetaEntityService,
+
$ApAudienceService,
$ApDbResolverService,
$ApDeliverManagerService,
diff --git a/packages/backend/src/core/CreateSystemUserService.ts b/packages/backend/src/core/CreateSystemUserService.ts
index 6b475316f..11212bc12 100644
--- a/packages/backend/src/core/CreateSystemUserService.ts
+++ b/packages/backend/src/core/CreateSystemUserService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -38,7 +38,7 @@ export class CreateSystemUserService {
// Generate secret
const secret = generateNativeUserToken();
- const keyPair = await genRsaKeyPair();
+ const keyPair = await genRsaKeyPair(3072);
let account!: MiUser;
diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts
index 9a8267b46..2f64599a4 100644
--- a/packages/backend/src/core/CustomEmojiService.ts
+++ b/packages/backend/src/core/CustomEmojiService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -66,7 +66,10 @@ export class CustomEmojiService implements OnApplicationShutdown {
license: string | null;
isSensitive: boolean;
localOnly: boolean;
+ requestedBy: string | null;
+ memo: string | null;
roleIdsThatCanBeUsedThisEmojiAsReaction: MiRole['id'][];
+ roleIdsThatCanNotBeUsedThisEmojiAsReaction: MiRole['id'][];
}, moderator?: MiUser): Promise {
const emoji = await this.emojisRepository.insert({
id: this.idService.gen(),
@@ -81,7 +84,10 @@ export class CustomEmojiService implements OnApplicationShutdown {
license: data.license,
isSensitive: data.isSensitive,
localOnly: data.localOnly,
+ requestedBy: data.requestedBy,
+ memo: data.memo,
roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction,
+ roleIdsThatCanNotBeUsedThisEmojiAsReaction: data.roleIdsThatCanNotBeUsedThisEmojiAsReaction,
}).then(x => this.emojisRepository.findOneByOrFail(x.identifiers[0]));
if (data.host == null) {
@@ -111,7 +117,10 @@ export class CustomEmojiService implements OnApplicationShutdown {
license?: string | null;
isSensitive?: boolean;
localOnly?: boolean;
+ requestedBy?: string | null;
+ memo?: string | null;
roleIdsThatCanBeUsedThisEmojiAsReaction?: MiRole['id'][];
+ roleIdsThatCanNotBeUsedThisEmojiAsReaction?: MiRole['id'][];
}, moderator?: MiUser): Promise {
const emoji = await this.emojisRepository.findOneByOrFail({ id: id });
const sameNameEmoji = await this.emojisRepository.findOneBy({ name: data.name, host: IsNull() });
@@ -128,7 +137,10 @@ export class CustomEmojiService implements OnApplicationShutdown {
originalUrl: data.driveFile != null ? data.driveFile.url : undefined,
publicUrl: data.driveFile != null ? (data.driveFile.webpublicUrl ?? data.driveFile.url) : undefined,
type: data.driveFile != null ? (data.driveFile.webpublicType ?? data.driveFile.type) : undefined,
+ requestedBy: data.requestedBy ?? undefined,
+ memo: data.memo ?? undefined,
roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction ?? undefined,
+ roleIdsThatCanNotBeUsedThisEmojiAsReaction: data.roleIdsThatCanNotBeUsedThisEmojiAsReaction ?? undefined,
});
this.localEmojisCache.refresh();
@@ -385,7 +397,7 @@ export class CustomEmojiService implements OnApplicationShutdown {
*/
@bindThis
public checkDuplicate(name: string): Promise {
- return this.emojisRepository.exist({ where: { name, host: IsNull() } });
+ return this.emojisRepository.exists({ where: { name, host: IsNull() } });
}
@bindThis
@@ -393,6 +405,11 @@ export class CustomEmojiService implements OnApplicationShutdown {
return this.emojisRepository.findOneBy({ id });
}
+ @bindThis
+ public getEmojiByName(name: string): Promise {
+ return this.emojisRepository.findOneBy({ name, host: IsNull() });
+ }
+
@bindThis
public dispose(): void {
this.cache.dispose();
diff --git a/packages/backend/src/core/DeleteAccountService.ts b/packages/backend/src/core/DeleteAccountService.ts
index 570bd440e..385f54b42 100644
--- a/packages/backend/src/core/DeleteAccountService.ts
+++ b/packages/backend/src/core/DeleteAccountService.ts
@@ -1,43 +1,68 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
+import { bindThis } from '@/decorators.js';
+import { DI } from '@/di-symbols.js';
+import type Logger from '@/logger.js';
import type { UsersRepository } from '@/models/_.js';
+import type { MiUser } from '@/models/User.js';
+import { RoleService } from '@/core/RoleService.js';
import { QueueService } from '@/core/QueueService.js';
import { UserSuspendService } from '@/core/UserSuspendService.js';
-import { DI } from '@/di-symbols.js';
-import { bindThis } from '@/decorators.js';
+import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { LoggerService } from '@/core/LoggerService.js';
@Injectable()
export class DeleteAccountService {
+ public logger: Logger;
+
constructor(
@Inject(DI.usersRepository)
private usersRepository: UsersRepository,
- private userSuspendService: UserSuspendService,
+ private roleService: RoleService,
private queueService: QueueService,
+ private userSuspendService: UserSuspendService,
+ private globalEventService: GlobalEventService,
+ private loggerService: LoggerService,
) {
+ this.logger = this.loggerService.getLogger('delete-account');
}
@bindThis
- public async deleteAccount(user: {
- id: string;
- host: string | null;
- }): Promise {
+ public async deleteAccount(user: MiUser, soft: boolean, me: MiUser | null): Promise {
+ this.logger.warn(`Delete account requested by ${me ? me.id : 'remote'} for ${user.id} (soft: ${soft})`);
+
const _user = await this.usersRepository.findOneByOrFail({ id: user.id });
if (_user.isRoot) throw new Error('cannot delete a root account');
// 物理削除する前にDelete activityを送信する
- await this.userSuspendService.doPostSuspend(user).catch(e => {});
+ await this.userSuspendService.doPostSuspend(user).catch(err => this.logger.error(err));
this.queueService.createDeleteAccountJob(user, {
- soft: false,
+ force: me ? await this.roleService.isModerator(me) : false,
+ soft: soft,
});
await this.usersRepository.update(user.id, {
isDeleted: true,
});
+
+ this.globalEventService.publishInternalEvent('userChangeDeletedState', { id: user.id, isDeleted: true });
+ }
+
+ @bindThis
+ public async deleteAllDriveFiles(user: MiUser, me: MiUser | null): Promise {
+ this.logger.warn(`Delete all drive files requested by ${me ? me.id : 'remote'} for ${user.id}`);
+
+ await this.usersRepository.findOneByOrFail({ id: user.id });
+
+ this.queueService.createDeleteAccountJob(user, {
+ force: me ? await this.roleService.isModerator(me) : false,
+ onlyFiles: true,
+ });
}
}
diff --git a/packages/backend/src/core/DownloadService.ts b/packages/backend/src/core/DownloadService.ts
index 5474272b0..21ae798f9 100644
--- a/packages/backend/src/core/DownloadService.ts
+++ b/packages/backend/src/core/DownloadService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -145,7 +145,8 @@ export class DownloadService {
const parsedIp = ipaddr.parse(ip);
for (const net of this.config.allowedPrivateNetworks ?? []) {
- if (parsedIp.match(ipaddr.parseCIDR(net))) {
+ const cidr = ipaddr.parseCIDR(net);
+ if (cidr[0].kind() === parsedIp.kind() && parsedIp.match(ipaddr.parseCIDR(net))) {
return false;
}
}
diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts
index 0861ee3f9..2985d9c7a 100644
--- a/packages/backend/src/core/DriveService.ts
+++ b/packages/backend/src/core/DriveService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -7,7 +7,7 @@ import { randomUUID } from 'node:crypto';
import * as fs from 'node:fs';
import { Inject, Injectable } from '@nestjs/common';
import sharp from 'sharp';
-import { sharpBmp } from 'sharp-read-bmp';
+import { sharpBmp } from '@misskey-dev/sharp-read-bmp';
import { IsNull } from 'typeorm';
import { DeleteObjectCommandInput, PutObjectCommandInput, NoSuchKey } from '@aws-sdk/client-s3';
import { DI } from '@/di-symbols.js';
@@ -399,7 +399,7 @@ export class DriveService {
})
.catch(
err => {
- this.registerLogger.error(`Upload Failed: key = ${key}, filename = ${filename}`, err);
+ this.registerLogger.error(`Upload Failed: key = ${key}, filename = ${filename}`, { error: err });
},
);
}
@@ -455,15 +455,14 @@ export class DriveService {
}: AddFileArgs): Promise {
let skipNsfwCheck = false;
const instance = await this.metaService.fetch();
- const userRoleNSFW = user && (await this.roleService.getUserPolicies(user.id)).alwaysMarkNsfw;
- if (user == null) {
- skipNsfwCheck = true;
- } else if (userRoleNSFW) {
- skipNsfwCheck = true;
- }
- if (instance.sensitiveMediaDetection === 'none') skipNsfwCheck = true;
- if (user && instance.sensitiveMediaDetection === 'local' && this.userEntityService.isRemoteUser(user)) skipNsfwCheck = true;
- if (user && instance.sensitiveMediaDetection === 'remote' && this.userEntityService.isLocalUser(user)) skipNsfwCheck = true;
+ const policies = user && await this.roleService.getUserPolicies(user.id);
+ const userRoleNSFW = policies?.alwaysMarkNsfw;
+ skipNsfwCheck ||= user == null;
+ skipNsfwCheck ||= !!userRoleNSFW;
+ skipNsfwCheck ||= !!policies?.skipNsfwDetection;
+ skipNsfwCheck ||= instance.sensitiveMediaDetection === 'none';
+ skipNsfwCheck ||= !!(user && instance.sensitiveMediaDetection === 'local' && this.userEntityService.isRemoteUser(user));
+ skipNsfwCheck ||= !!(user && instance.sensitiveMediaDetection === 'remote' && this.userEntityService.isLocalUser(user));
const info = await this.fileInfoService.getFileInfo(path, {
skipSensitiveDetection: skipNsfwCheck,
@@ -507,11 +506,10 @@ export class DriveService {
this.registerLogger.debug(`ADD DRIVE FILE: user ${user?.id ?? 'not set'}, name ${detectedName}, tmp ${path}`);
//#region Check drive usage
- if (user && !isLink) {
+ if (user && policies && !isLink) {
const usage = await this.driveFileEntityService.calcDriveUsageOf(user);
const isLocalUser = this.userEntityService.isLocalUser(user);
- const policies = await this.roleService.getUserPolicies(user.id);
const driveCapacity = 1024 * 1024 * policies.driveCapacityMb;
this.registerLogger.debug('drive capacity override applied');
this.registerLogger.debug(`overrideCap: ${driveCapacity}bytes, usage: ${usage}bytes, u+s: ${usage + info.size}bytes`);
@@ -519,7 +517,7 @@ export class DriveService {
// If usage limit exceeded
if (driveCapacity < usage + info.size) {
if (isLocalUser) {
- throw new IdentifiableError('c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6', 'No free space.');
+ throw new IdentifiableError('c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6', 'No free space in drive.');
}
await this.expireOldFile(await this.usersRepository.findOneByOrFail({ id: user.id }) as MiRemoteUser, driveCapacity - info.size);
}
@@ -616,7 +614,7 @@ export class DriveService {
userId: user ? user.id : IsNull(),
}) as MiDriveFile;
} else {
- this.registerLogger.error(err as Error);
+ this.registerLogger.error(`failed to register ${file.uri}`, { error: err });
throw err;
}
}
@@ -627,7 +625,7 @@ export class DriveService {
this.registerLogger.succ(`drive file has been created ${file.id}`);
if (user) {
- this.driveFileEntityService.pack(file, { self: true }).then(packedFile => {
+ this.driveFileEntityService.pack(file, user, { self: true }).then(packedFile => {
// Publish driveFileCreated event
this.globalEventService.publishMainStream(user.id, 'driveFileCreated', packedFile);
this.globalEventService.publishDriveStream(user.id, 'fileCreated', packedFile);
@@ -651,7 +649,7 @@ export class DriveService {
public async updateFile(file: MiDriveFile, values: Partial, updater: MiUser) {
const alwaysMarkNsfw = (await this.roleService.getUserPolicies(file.userId)).alwaysMarkNsfw;
- if (values.name && !this.driveFileEntityService.validateFileName(file.name)) {
+ if (values.name != null && !this.driveFileEntityService.validateFileName(values.name)) {
throw new DriveService.InvalidFileNameError();
}
@@ -672,7 +670,7 @@ export class DriveService {
await this.driveFilesRepository.update(file.id, values);
- const fileObj = await this.driveFileEntityService.pack(file.id, { self: true });
+ const fileObj = await this.driveFileEntityService.pack(file.id, updater, { self: true });
// Publish fileUpdated event
if (file.userId) {
@@ -858,7 +856,7 @@ export class DriveService {
} catch (err) {
this.downloaderLogger.error(`Failed to create drive file: ${err}`, {
url: url,
- e: err,
+ error: err,
});
throw err;
} finally {
diff --git a/packages/backend/src/core/EmailService.ts b/packages/backend/src/core/EmailService.ts
index f31cec2b3..79e6ea4ef 100644
--- a/packages/backend/src/core/EmailService.ts
+++ b/packages/backend/src/core/EmailService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -7,8 +7,9 @@ import { URLSearchParams } from 'node:url';
import * as nodemailer from 'nodemailer';
import { Inject, Injectable } from '@nestjs/common';
import { validate as validateEmail } from 'deep-email-validator';
-import { SubOutputFormat } from 'deep-email-validator/dist/output/output.js';
+import Redis from 'ioredis';
import { MetaService } from '@/core/MetaService.js';
+import { UtilityService } from '@/core/UtilityService.js';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import type Logger from '@/logger.js';
@@ -16,29 +17,51 @@ import type { UserProfilesRepository } from '@/models/_.js';
import { LoggerService } from '@/core/LoggerService.js';
import { bindThis } from '@/decorators.js';
import { HttpRequestService } from '@/core/HttpRequestService.js';
+import { RedisKVCache } from '@/misc/cache.js';
@Injectable()
export class EmailService {
private logger: Logger;
+ private verifymailResponseCache: RedisKVCache<{
+ valid: boolean,
+ reason?: string | null,
+ }>;
+
constructor(
@Inject(DI.config)
private config: Config,
+ @Inject(DI.redis)
+ private redisClient: Redis.Redis,
+
@Inject(DI.userProfilesRepository)
private userProfilesRepository: UserProfilesRepository,
private metaService: MetaService,
private loggerService: LoggerService,
+ private utilityService: UtilityService,
private httpRequestService: HttpRequestService,
) {
this.logger = this.loggerService.getLogger('email');
+ this.verifymailResponseCache = new RedisKVCache<{
+ valid: boolean,
+ reason?: string | null,
+ }>(this.redisClient, 'verifymailResponse', {
+ lifetime: 1000 * 60 * 60 * 24 * 7, // 7d
+ memoryCacheLifetime: 1000 * 60 * 60 * 24 * 7, // 7d
+ fetcher: (key) => this.verifyMail(key),
+ toRedisConverter: (value) => JSON.stringify(value),
+ fromRedisConverter: (value) => JSON.parse(value),
+ });
}
@bindThis
public async sendEmail(to: string, subject: string, html: string, text: string) {
const meta = await this.metaService.fetch(true);
+ if (!meta.enableEmail) return;
+
const iconUrl = `${this.config.url}/static-assets/mi-white.png`;
const emailSettingUrl = `${this.config.url}/settings/email`;
@@ -147,7 +170,7 @@ export class EmailService {
this.logger.info(`Message sent: ${info.messageId}`);
} catch (err) {
- this.logger.error(err as Error);
+ this.logger.error('Failed to send email', { error: err });
throw err;
}
}
@@ -155,7 +178,7 @@ export class EmailService {
@bindThis
public async validateEmailForAccount(emailAddress: string): Promise<{
available: boolean;
- reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp';
+ reason: null | 'used' | 'format' | 'disposable' | 'mx' | 'smtp' | 'banned' | 'network' | 'blacklist';
}> {
const meta = await this.metaService.fetch();
@@ -164,45 +187,78 @@ export class EmailService {
email: emailAddress,
});
- const verifymailApi = meta.enableVerifymailApi && meta.verifymailAuthKey != null;
- let validated;
-
- if (meta.enableActiveEmailValidation && meta.verifymailAuthKey) {
- if (verifymailApi) {
- validated = await this.verifyMail(emailAddress, meta.verifymailAuthKey);
- } else {
- validated = meta.enableActiveEmailValidation ? await validateEmail({
- email: emailAddress,
- validateRegex: true,
- validateMx: true,
- validateTypo: false, // TLDを見ているみたいだけどclubとか弾かれるので
- validateDisposable: true, // 捨てアドかどうかチェック
- validateSMTP: false, // 日本だと25ポートが殆どのプロバイダーで塞がれていてタイムアウトになるので
- }) : { valid: true, reason: null };
- }
- } else {
- validated = { valid: true, reason: null };
+ if (exist !== 0) {
+ return {
+ available: false,
+ reason: 'used',
+ };
}
- const available = exist === 0 && validated.valid;
+ let validated: {
+ valid: boolean,
+ reason?: string | null,
+ } = { valid: true, reason: null };
+
+ if (meta.enableActiveEmailValidation) {
+ validated = await validateEmail({
+ email: emailAddress,
+ validateRegex: true,
+ validateMx: true,
+ validateTypo: false, // TLDを見ているみたいだけどclubとか弾かれるので
+ validateDisposable: true, // 捨てアドかどうかチェック
+ validateSMTP: false, // 日本だと25ポートが殆どのプロバイダーで塞がれていてタイムアウトになるので
+ });
+
+ if (validated.valid && meta.enableVerifymailApi && meta.verifymailAuthKey != null) {
+ const domain = emailAddress.split('@')[1];
+ validated = await this.verifymailResponseCache.fetch(domain);
+ }
+
+ if (validated.valid && meta.enableTruemailApi && meta.truemailInstance && meta.truemailAuthKey != null) {
+ validated = await this.trueMail(meta.truemailInstance, emailAddress, meta.truemailAuthKey);
+ }
+ }
+
+ if (!validated.valid) {
+ const formatReason: Record = {
+ regex: 'format',
+ disposable: 'disposable',
+ mx: 'mx',
+ smtp: 'smtp',
+ network: 'network',
+ blacklist: 'blacklist',
+ };
+
+ return {
+ available: false,
+ reason: validated.reason ? formatReason[validated.reason] ?? null : null,
+ };
+ }
+
+ const emailDomain: string = emailAddress.split('@')[1];
+ const isBanned = this.utilityService.isBlockedHost(meta.bannedEmailDomains, emailDomain);
+
+ if (isBanned) {
+ return {
+ available: false,
+ reason: 'banned',
+ };
+ }
return {
- available,
- reason: available ? null :
- exist !== 0 ? 'used' :
- validated.reason === 'regex' ? 'format' :
- validated.reason === 'disposable' ? 'disposable' :
- validated.reason === 'mx' ? 'mx' :
- validated.reason === 'smtp' ? 'smtp' :
- null,
+ available: true,
+ reason: null,
};
}
- private async verifyMail(emailAddress: string, verifymailAuthKey: string): Promise<{
+ private async verifyMail(domain: string): Promise<{
valid: boolean;
reason: 'used' | 'format' | 'disposable' | 'mx' | 'smtp' | null;
}> {
- const endpoint = 'https://verifymail.io/api/' + emailAddress + '?key=' + verifymailAuthKey;
+ const meta = await this.metaService.fetch();
+ if (meta.verifymailAuthKey == null) throw new Error('verifymailAuthKey is not set');
+
+ const endpoint = 'https://verifymail.io/api/' + domain + '?key=' + meta.verifymailAuthKey;
const res = await this.httpRequestService.send(endpoint, {
method: 'GET',
headers: {
@@ -211,7 +267,8 @@ export class EmailService {
},
});
- const json = (await res.json()) as {
+ const json = (await res.json()) as Partial<{
+ message: string;
block: boolean;
catch_all: boolean;
deliverable_email: boolean;
@@ -226,18 +283,13 @@ export class EmailService {
mx_priority: { [key: string]: number };
privacy: boolean;
related_domains: string[];
- };
+ }>;
- if (json.email_address === undefined) {
+ /* api error: when there is only one `message` attribute in the returned result */
+ if (Object.keys(json).length === 1 && Reflect.has(json, 'message')) {
return {
valid: false,
- reason: 'format',
- };
- }
- if (json.deliverable_email !== undefined && !json.deliverable_email) {
- return {
- valid: false,
- reason: 'smtp',
+ reason: null,
};
}
if (json.disposable) {
@@ -258,4 +310,68 @@ export class EmailService {
reason: null,
};
}
+
+ private async trueMail(truemailInstance: string, emailAddress: string, truemailAuthKey: string): Promise<{
+ valid: boolean;
+ reason: 'used' | 'format' | 'blacklist' | 'mx' | 'smtp' | 'network' | T | null;
+ }> {
+ const endpoint = truemailInstance + '?email=' + emailAddress;
+ try {
+ const res = await this.httpRequestService.send(endpoint, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ Accept: 'application/json',
+ Authorization: truemailAuthKey,
+ },
+ });
+
+ const json = (await res.json()) as {
+ email: string;
+ success: boolean;
+ error?: string;
+ errors?: {
+ list_match?: string;
+ regex?: string;
+ mx?: string;
+ smtp?: string;
+ } | null;
+ };
+
+ if (json.email === undefined || json.errors?.regex) {
+ return {
+ valid: false,
+ reason: 'format',
+ };
+ }
+ if (json.errors?.smtp) {
+ return {
+ valid: false,
+ reason: 'smtp',
+ };
+ }
+ if (json.errors?.mx) {
+ return {
+ valid: false,
+ reason: 'mx',
+ };
+ }
+ if (!json.success) {
+ return {
+ valid: false,
+ reason: json.errors?.list_match as T || 'blacklist',
+ };
+ }
+
+ return {
+ valid: true,
+ reason: null,
+ };
+ } catch (error) {
+ return {
+ valid: false,
+ reason: 'network',
+ };
+ }
+ }
}
diff --git a/packages/backend/src/core/FanoutTimelineEndpointService.ts b/packages/backend/src/core/FanoutTimelineEndpointService.ts
new file mode 100644
index 000000000..9c239b4df
--- /dev/null
+++ b/packages/backend/src/core/FanoutTimelineEndpointService.ts
@@ -0,0 +1,186 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import { DI } from '@/di-symbols.js';
+import { bindThis } from '@/decorators.js';
+import type { MiUser } from '@/models/User.js';
+import type { MiNote } from '@/models/Note.js';
+import { Packed } from '@/misc/json-schema.js';
+import type { NotesRepository } from '@/models/_.js';
+import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
+import { FanoutTimelineName, FanoutTimelineService } from '@/core/FanoutTimelineService.js';
+import { isUserRelated } from '@/misc/is-user-related.js';
+import { isPureRenote } from '@/misc/is-pure-renote.js';
+import { CacheService } from '@/core/CacheService.js';
+import { isReply } from '@/misc/is-reply.js';
+import { isInstanceMuted } from '@/misc/is-instance-muted.js';
+
+type TimelineOptions = {
+ untilId: string | null,
+ sinceId: string | null,
+ limit: number,
+ allowPartial: boolean,
+ me?: { id: MiUser['id'] } | undefined | null,
+ useDbFallback: boolean,
+ redisTimelines: FanoutTimelineName[],
+ noteFilter?: (note: MiNote) => boolean,
+ alwaysIncludeMyNotes?: boolean;
+ ignoreAuthorFromBlock?: boolean;
+ ignoreAuthorFromMute?: boolean;
+ excludeNoFiles?: boolean;
+ excludeReplies?: boolean;
+ excludePureRenotes: boolean;
+ dbFallback: (untilId: string | null, sinceId: string | null, limit: number) => Promise,
+};
+
+@Injectable()
+export class FanoutTimelineEndpointService {
+ constructor(
+ @Inject(DI.notesRepository)
+ private notesRepository: NotesRepository,
+
+ private noteEntityService: NoteEntityService,
+ private cacheService: CacheService,
+ private fanoutTimelineService: FanoutTimelineService,
+ ) {
+ }
+
+ @bindThis
+ async timeline(ps: TimelineOptions): Promise[]> {
+ return await this.noteEntityService.packMany(await this.getMiNotes(ps), ps.me);
+ }
+
+ @bindThis
+ private async getMiNotes(ps: TimelineOptions): Promise {
+ let noteIds: string[];
+ let shouldFallbackToDb = false;
+
+ // 呼び出し元と以下の処理をシンプルにするためにdbFallbackを置き換える
+ if (!ps.useDbFallback) ps.dbFallback = () => Promise.resolve([]);
+
+ const shouldPrepend = ps.sinceId && !ps.untilId;
+ const idCompare: (a: string, b: string) => number = shouldPrepend ? (a, b) => a < b ? -1 : 1 : (a, b) => a > b ? -1 : 1;
+
+ const redisResult = await this.fanoutTimelineService.getMulti(ps.redisTimelines, ps.untilId, ps.sinceId);
+
+ // TODO: いい感じにgetMulti内でソート済だからuniqするときにredisResultが全てソート済なのを利用して再ソートを避けたい
+ const redisResultIds = Array.from(new Set(redisResult.flat(1)));
+
+ redisResultIds.sort(idCompare);
+ noteIds = redisResultIds.slice(0, ps.limit);
+
+ shouldFallbackToDb = shouldFallbackToDb || (noteIds.length === 0);
+
+ if (!shouldFallbackToDb) {
+ let filter = ps.noteFilter ?? (_note => true);
+
+ if (ps.alwaysIncludeMyNotes && ps.me) {
+ const me = ps.me;
+ const parentFilter = filter;
+ filter = (note) => note.userId === me.id || parentFilter(note);
+ }
+
+ if (ps.excludeNoFiles) {
+ const parentFilter = filter;
+ filter = (note) => note.fileIds.length !== 0 && parentFilter(note);
+ }
+
+ if (ps.excludeReplies) {
+ const parentFilter = filter;
+ filter = (note) => !isReply(note, ps.me?.id) && parentFilter(note);
+ }
+
+ if (ps.excludePureRenotes) {
+ const parentFilter = filter;
+ filter = (note) => !isPureRenote(note) && parentFilter(note);
+ }
+
+ if (ps.me) {
+ const me = ps.me;
+ const [
+ userIdsWhoMeMuting,
+ userIdsWhoMeMutingRenotes,
+ userIdsWhoBlockingMe,
+ userMutedInstances,
+ ] = await Promise.all([
+ this.cacheService.userMutingsCache.fetch(ps.me.id),
+ this.cacheService.renoteMutingsCache.fetch(ps.me.id),
+ this.cacheService.userBlockedCache.fetch(ps.me.id),
+ this.cacheService.userProfileCache.fetch(me.id).then(p => new Set(p.mutedInstances)),
+ ]);
+
+ const parentFilter = filter;
+ filter = (note) => {
+ if (isUserRelated(note, userIdsWhoBlockingMe, ps.ignoreAuthorFromBlock)) return false;
+ if (isUserRelated(note, userIdsWhoMeMuting, ps.ignoreAuthorFromMute)) return false;
+ if (isPureRenote(note) && isUserRelated(note, userIdsWhoMeMutingRenotes, ps.ignoreAuthorFromMute)) return false;
+ if (isInstanceMuted(note, userMutedInstances)) return false;
+
+ return parentFilter(note);
+ };
+ }
+
+ const redisTimeline: MiNote[] = [];
+ let readFromRedis = 0;
+ let lastSuccessfulRate = 1; // rateをキャッシュする?
+
+ while ((redisResultIds.length - readFromRedis) !== 0) {
+ const remainingToRead = ps.limit - redisTimeline.length;
+
+ // DBからの取り直しを減らす初回と同じ割合以上で成功すると仮定するが、クエリの長さを考えて三倍まで
+ const countToGet = Math.ceil(remainingToRead * Math.min(1.1 / lastSuccessfulRate, 3));
+ noteIds = redisResultIds.slice(readFromRedis, readFromRedis + countToGet);
+
+ readFromRedis += noteIds.length;
+
+ const gotFromDb = await this.getAndFilterFromDb(noteIds, filter, idCompare);
+ redisTimeline.push(...gotFromDb);
+ lastSuccessfulRate = gotFromDb.length / noteIds.length;
+
+ if (ps.allowPartial ? redisTimeline.length !== 0 : redisTimeline.length >= ps.limit) {
+ // 十分Redisからとれた
+ const result = redisTimeline.slice(0, ps.limit);
+ if (shouldPrepend) result.reverse();
+ return result;
+ }
+ }
+
+ // まだ足りない分はDBにフォールバック
+ const remainingToRead = ps.limit - redisTimeline.length;
+ let dbUntil: string | null;
+ let dbSince: string | null;
+ if (shouldPrepend) {
+ redisTimeline.reverse();
+ dbUntil = ps.untilId;
+ dbSince = noteIds[noteIds.length - 1];
+ } else {
+ dbUntil = noteIds[noteIds.length - 1];
+ dbSince = ps.sinceId;
+ }
+ const gotFromDb = await ps.dbFallback(dbUntil, dbSince, remainingToRead);
+ return shouldPrepend ? [...gotFromDb, ...redisTimeline] : [...redisTimeline, ...gotFromDb];
+ }
+
+ return await ps.dbFallback(ps.untilId, ps.sinceId, ps.limit);
+ }
+
+ private async getAndFilterFromDb(noteIds: string[], noteFilter: (note: MiNote) => boolean, idCompare: (a: string, b: string) => number): Promise {
+ const query = this.notesRepository.createQueryBuilder('note')
+ .where('note.id IN (:...noteIds)', { noteIds: noteIds })
+ .innerJoinAndSelect('note.user', 'user')
+ .leftJoinAndSelect('note.reply', 'reply')
+ .leftJoinAndSelect('note.renote', 'renote')
+ .leftJoinAndSelect('reply.user', 'replyUser')
+ .leftJoinAndSelect('renote.user', 'renoteUser')
+ .leftJoinAndSelect('note.channel', 'channel');
+
+ const notes = (await query.getMany()).filter(noteFilter);
+
+ notes.sort((a, b) => idCompare(a.id, b.id));
+
+ return notes;
+ }
+}
diff --git a/packages/backend/src/core/FunoutTimelineService.ts b/packages/backend/src/core/FanoutTimelineService.ts
similarity index 61%
rename from packages/backend/src/core/FunoutTimelineService.ts
rename to packages/backend/src/core/FanoutTimelineService.ts
index c633c329e..013cbd0ac 100644
--- a/packages/backend/src/core/FunoutTimelineService.ts
+++ b/packages/backend/src/core/FanoutTimelineService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -9,8 +9,39 @@ import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js';
+export type FanoutTimelineName =
+ // home timeline
+ | `homeTimeline:${string}`
+ | `homeTimelineWithFiles:${string}` // only notes with files are included
+ // local timeline
+ | 'localTimeline' // replies are not included
+ | 'localTimelineWithFiles' // only non-reply notes with files are included
+ | 'localTimelineWithReplies' // only replies are included
+ | `localTimelineWithReplyTo:${string}` // Only replies to specific local user are included. Parameter is reply user id.
+
+ // antenna
+ | `antennaTimeline:${string}`
+
+ // user timeline
+ | `userTimeline:${string}` // replies are not included
+ | `userTimelineWithFiles:${string}` // only non-reply notes with files are included
+ | `userTimelineWithReplies:${string}` // only replies are included
+ | `userTimelineWithRepliesWithFiles:${string}`
+ | `userTimelineWithChannel:${string}` // only channel notes are included, replies are included
+ | `userTimelineWithChannelWithFiles:${string}`
+
+ // user list timelines
+ | `userListTimeline:${string}`
+ | `userListTimelineWithFiles:${string}` // only notes with files are included
+
+ // channel timelines
+ | `channelTimeline:${string}` // replies are included
+
+ // role timelines
+ | `roleTimeline:${string}` // any notes are included
+
@Injectable()
-export class FunoutTimelineService {
+export class FanoutTimelineService {
constructor(
@Inject(DI.redisForTimelines)
private redisForTimelines: Redis.Redis,
@@ -20,7 +51,7 @@ export class FunoutTimelineService {
}
@bindThis
- public push(tl: string, id: string, maxlen: number, pipeline: Redis.ChainableCommander) {
+ public push(tl: FanoutTimelineName, id: string, maxlen: number, pipeline: Redis.ChainableCommander) {
// リモートから遅れて届いた(もしくは後から追加された)投稿日時が古い投稿が追加されるとページネーション時に問題を引き起こすため、
// 3分以内に投稿されたものでない場合、Redisにある最古のIDより新しい場合のみ追加する
if (this.idService.parse(id).date.getTime() > Date.now() - 1000 * 60 * 3) {
@@ -41,7 +72,7 @@ export class FunoutTimelineService {
}
@bindThis
- public get(name: string, untilId?: string | null, sinceId?: string | null) {
+ public get(name: FanoutTimelineName, untilId?: string | null, sinceId?: string | null) {
if (untilId && sinceId) {
return this.redisForTimelines.lrange('list:' + name, 0, -1)
.then(ids => ids.filter(id => id < untilId && id > sinceId).sort((a, b) => a > b ? -1 : 1));
@@ -58,7 +89,7 @@ export class FunoutTimelineService {
}
@bindThis
- public getMulti(name: string[], untilId?: string | null, sinceId?: string | null): Promise {
+ public getMulti(name: FanoutTimelineName[], untilId?: string | null, sinceId?: string | null): Promise {
const pipeline = this.redisForTimelines.pipeline();
for (const n of name) {
pipeline.lrange('list:' + n, 0, -1);
@@ -79,7 +110,7 @@ export class FunoutTimelineService {
}
@bindThis
- public purge(name: string) {
+ public purge(name: FanoutTimelineName) {
return this.redisForTimelines.del('list:' + name);
}
}
diff --git a/packages/backend/src/core/FeaturedService.ts b/packages/backend/src/core/FeaturedService.ts
index 3af562df1..3dfa1508f 100644
--- a/packages/backend/src/core/FeaturedService.ts
+++ b/packages/backend/src/core/FeaturedService.ts
@@ -1,18 +1,21 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis';
-import type { MiNote, MiUser } from '@/models/_.js';
+import type { MiGalleryPost, MiNote, MiUser } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
const GLOBAL_NOTES_RANKING_WINDOW = 1000 * 60 * 60 * 24 * 3; // 3日ごと
+export const GALLERY_POSTS_RANKING_WINDOW = 1000 * 60 * 60 * 24 * 3; // 3日ごと
const PER_USER_NOTES_RANKING_WINDOW = 1000 * 60 * 60 * 24 * 7; // 1週間ごと
const HASHTAG_RANKING_WINDOW = 1000 * 60 * 60; // 1時間ごと
+const featuredEpoc = new Date('2023-01-01T00:00:00Z').getTime();
+
@Injectable()
export class FeaturedService {
constructor(
@@ -23,7 +26,7 @@ export class FeaturedService {
@bindThis
private getCurrentWindow(windowRange: number): number {
- const passed = new Date().getTime() - new Date(new Date().getFullYear(), 0, 1).getTime();
+ const passed = new Date().getTime() - featuredEpoc;
return Math.floor(passed / windowRange);
}
@@ -52,7 +55,7 @@ export class FeaturedService {
`${name}:${currentWindow}`, 0, threshold, 'WITHSCORES');
redisPipeline.zrevrange(
`${name}:${previousWindow}`, 0, threshold, 'WITHSCORES');
- const [currentRankingResult, previousRankingResult] = await redisPipeline.exec().then(result => result ? result.map(r => r[1] as string[]) : [[], []]);
+ const [currentRankingResult, previousRankingResult] = await redisPipeline.exec().then(result => result ? result.map(r => (r[1] ?? []) as string[]) : [[], []]);
const ranking = new Map();
for (let i = 0; i < currentRankingResult.length; i += 2) {
@@ -74,11 +77,27 @@ export class FeaturedService {
return Array.from(ranking.keys());
}
+ @bindThis
+ private async removeFromRanking(name: string, windowRange: number, element: string): Promise {
+ const currentWindow = this.getCurrentWindow(windowRange);
+ const previousWindow = currentWindow - 1;
+
+ const redisPipeline = this.redisClient.pipeline();
+ redisPipeline.zrem(`${name}:${currentWindow}`, element);
+ redisPipeline.zrem(`${name}:${previousWindow}`, element);
+ await redisPipeline.exec();
+ }
+
@bindThis
public updateGlobalNotesRanking(noteId: MiNote['id'], score = 1): Promise {
return this.updateRankingOf('featuredGlobalNotesRanking', GLOBAL_NOTES_RANKING_WINDOW, noteId, score);
}
+ @bindThis
+ public updateGalleryPostsRanking(galleryPostId: MiGalleryPost['id'], score = 1): Promise {
+ return this.updateRankingOf('featuredGalleryPostsRanking', GALLERY_POSTS_RANKING_WINDOW, galleryPostId, score);
+ }
+
@bindThis
public updateInChannelNotesRanking(channelId: MiNote['channelId'], noteId: MiNote['id'], score = 1): Promise {
return this.updateRankingOf(`featuredInChannelNotesRanking:${channelId}`, GLOBAL_NOTES_RANKING_WINDOW, noteId, score);
@@ -99,6 +118,11 @@ export class FeaturedService {
return this.getRankingOf('featuredGlobalNotesRanking', GLOBAL_NOTES_RANKING_WINDOW, threshold);
}
+ @bindThis
+ public getGalleryPostsRanking(threshold: number): Promise {
+ return this.getRankingOf('featuredGalleryPostsRanking', GALLERY_POSTS_RANKING_WINDOW, threshold);
+ }
+
@bindThis
public getInChannelNotesRanking(channelId: MiNote['channelId'], threshold: number): Promise {
return this.getRankingOf(`featuredInChannelNotesRanking:${channelId}`, GLOBAL_NOTES_RANKING_WINDOW, threshold);
@@ -113,4 +137,9 @@ export class FeaturedService {
public getHashtagsRanking(threshold: number): Promise {
return this.getRankingOf('featuredHashtagsRanking', HASHTAG_RANKING_WINDOW, threshold);
}
+
+ @bindThis
+ public removeHashtagsFromRanking(hashtag: string): Promise {
+ return this.removeFromRanking('featuredHashtagsRanking', HASHTAG_RANKING_WINDOW, hashtag);
+ }
}
diff --git a/packages/backend/src/core/FederatedInstanceService.ts b/packages/backend/src/core/FederatedInstanceService.ts
index e41f010e4..66db2067d 100644
--- a/packages/backend/src/core/FederatedInstanceService.ts
+++ b/packages/backend/src/core/FederatedInstanceService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/FetchInstanceMetadataService.ts b/packages/backend/src/core/FetchInstanceMetadataService.ts
index 682acef15..ffc17fee1 100644
--- a/packages/backend/src/core/FetchInstanceMetadataService.ts
+++ b/packages/backend/src/core/FetchInstanceMetadataService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -51,21 +51,23 @@ export class FetchInstanceMetadataService {
}
@bindThis
+ // public for test
public async tryLock(host: string): Promise {
- const mutex = await this.redisClient.set(`fetchInstanceMetadata:mutex:${host}`, '1', 'GET');
- return mutex !== '1';
+ const mutex = await this.redisClient.set(`fetchInstanceMetadata:mutex:${host}`, Date.now(), 'EX', 60 * 5, 'NX');
+ return mutex !== null;
}
@bindThis
- public unlock(host: string): Promise<'OK'> {
- return this.redisClient.set(`fetchInstanceMetadata:mutex:${host}`, '0');
+ // public for test
+ public unlock(host: string): Promise {
+ return this.redisClient.unlink(`fetchInstanceMetadata:mutex:${host}`);
}
@bindThis
public async fetchInstanceMetadata(instance: MiInstance, force = false): Promise {
const host = instance.host;
// Acquire mutex to ensure no parallel runs
- if (!await this.tryLock(host)) return;
+ if (!await this.tryLock(host) && !force) return;
try {
if (!force) {
const _instance = await this.federatedInstanceService.fetch(host);
@@ -116,7 +118,7 @@ export class FetchInstanceMetadataService {
this.logger.succ(`Successfuly updated metadata of ${instance.host}`);
} catch (e) {
- this.logger.error(`Failed to update metadata of ${instance.host}: ${e}`);
+ this.logger.error(`Failed to update metadata of ${instance.host}: ${e}`, { error: e });
} finally {
await this.unlock(host);
}
@@ -160,7 +162,7 @@ export class FetchInstanceMetadataService {
return info as NodeInfo;
} catch (err) {
- this.logger.error(`Failed to fetch nodeinfo of ${instance.host}: ${err}`);
+ this.logger.error(`Failed to fetch nodeinfo of ${instance.host}: ${err}`, { error: err });
throw err;
}
diff --git a/packages/backend/src/core/FileInfoService.ts b/packages/backend/src/core/FileInfoService.ts
index fdea59a8a..f3e93b9db 100644
--- a/packages/backend/src/core/FileInfoService.ts
+++ b/packages/backend/src/core/FileInfoService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -14,7 +14,7 @@ import FFmpeg from 'fluent-ffmpeg';
import isSvg from 'is-svg';
import probeImageSize from 'probe-image-size';
import { type predictionType } from 'nsfwjs';
-import sharp from 'sharp';
+import { sharpBmp } from '@misskey-dev/sharp-read-bmp';
import { encode } from 'blurhash';
import { createTempDir } from '@/misc/create-temp.js';
import { AiService } from '@/core/AiService.js';
@@ -122,7 +122,7 @@ export class FileInfoService {
'image/avif',
'image/svg+xml',
].includes(type.mime)) {
- blurhash = await this.getBlurhash(path).catch(e => {
+ blurhash = await this.getBlurhash(path, type.mime).catch(e => {
warnings.push(`getBlurhash failed: ${e}`);
return undefined;
});
@@ -407,25 +407,14 @@ export class FileInfoService {
* Calculate average color of image
*/
@bindThis
- private getBlurhash(path: string): Promise {
- return new Promise((resolve, reject) => {
- sharp(path)
- .raw()
- .ensureAlpha()
- .resize(64, 64, { fit: 'inside' })
- .toBuffer((err, buffer, info) => {
- if (err) return reject(err);
+ private async getBlurhash(path: string, type: string): Promise {
+ const sharp = await sharpBmp(path, type);
+ const { data, info } = await sharp
+ .raw()
+ .ensureAlpha()
+ .resize(64, 64, { fit: 'inside' })
+ .toBuffer({ resolveWithObject: true });
- let hash;
-
- try {
- hash = encode(new Uint8ClampedArray(buffer), info.width, info.height, 5, 5);
- } catch (e) {
- return reject(e);
- }
-
- resolve(hash);
- });
- });
+ return encode(new Uint8ClampedArray(data), info.width, info.height, 5, 5);
}
}
diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts
index d175f21f2..90efd63f3 100644
--- a/packages/backend/src/core/GlobalEventService.ts
+++ b/packages/backend/src/core/GlobalEventService.ts
@@ -1,10 +1,11 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis';
+import * as Reversi from 'misskey-reversi';
import type { MiChannel } from '@/models/Channel.js';
import type { MiUser } from '@/models/User.js';
import type { MiUserProfile } from '@/models/UserProfile.js';
@@ -18,7 +19,7 @@ import type { MiSignin } from '@/models/Signin.js';
import type { MiPage } from '@/models/Page.js';
import type { MiWebhook } from '@/models/Webhook.js';
import type { MiMeta } from '@/models/Meta.js';
-import { MiAvatarDecoration, MiRole, MiRoleAssignment } from '@/models/_.js';
+import { MiAvatarDecoration, MiReversiGame, MiRole, MiRoleAssignment } from '@/models/_.js';
import type { Packed } from '@/misc/json-schema.js';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
@@ -53,21 +54,22 @@ export interface MainEventTypes {
reply: Packed<'Note'>;
renote: Packed<'Note'>;
follow: Packed<'UserDetailedNotMe'>;
- followed: Packed<'User'>;
- unfollow: Packed<'User'>;
- meUpdated: Packed<'User'>;
+ followed: Packed<'UserLite'>;
+ unfollow: Packed<'UserDetailedNotMe'>;
+ meUpdated: Packed<'MeDetailed'>;
pageEvent: {
pageId: MiPage['id'];
event: string;
var: any;
userId: MiUser['id'];
- user: Packed<'User'>;
+ user: Packed<'UserDetailed'>;
};
urlUploadFinished: {
marker?: string | null;
file: Packed<'DriveFile'>;
};
readAllNotifications: undefined;
+ notificationFlushed: undefined;
unreadNotification: Packed<'Notification'>;
unreadMention: MiNote['id'];
readAllUnreadMentions: undefined;
@@ -91,7 +93,7 @@ export interface MainEventTypes {
};
driveFileCreated: Packed<'DriveFile'>;
readAntenna: MiAntenna;
- receiveFollowRequest: Packed<'User'>;
+ receiveFollowRequest: Packed<'UserLite'>;
announcementCreated: {
announcement: Packed<'Announcement'>;
};
@@ -139,8 +141,8 @@ type NoteStreamEventTypes = {
};
export interface UserListEventTypes {
- userAdded: Packed<'User'>;
- userRemoved: Packed<'User'>;
+ userAdded: Packed<'UserLite'>;
+ userRemoved: Packed<'UserLite'>;
}
export interface AntennaEventTypes {
@@ -159,6 +161,38 @@ export interface AdminEventTypes {
comment: string;
};
}
+
+export interface ReversiEventTypes {
+ matched: {
+ game: Packed<'ReversiGameDetailed'>;
+ };
+ invited: {
+ user: Packed<'User'>;
+ };
+}
+
+export interface ReversiGameEventTypes {
+ changeReadyStates: {
+ user1: boolean;
+ user2: boolean;
+ };
+ updateSettings: {
+ userId: MiUser['id'];
+ key: string;
+ value: any;
+ };
+ log: Reversi.Serializer.Log & { id: string | null };
+ started: {
+ game: Packed<'ReversiGameDetailed'>;
+ };
+ ended: {
+ winnerId: MiUser['id'] | null;
+ game: Packed<'ReversiGameDetailed'>;
+ };
+ canceled: {
+ userId: MiUser['id'];
+ };
+}
//#endregion
// 辞書(interface or type)から{ type, body }ユニオンを定義
@@ -176,8 +210,10 @@ type SerializedAll = {
export interface InternalEventTypes {
userChangeSuspendedState: { id: MiUser['id']; isSuspended: MiUser['isSuspended']; };
+ userChangeDeletedState: { id: MiUser['id']; isDeleted: MiUser['isDeleted']; };
userTokenRegenerated: { id: MiUser['id']; oldToken: string; newToken: string; };
remoteUserUpdated: { id: MiUser['id']; };
+ localUserUpdated: { id: MiUser['id']; };
follow: { followerId: MiUser['id']; followeeId: MiUser['id']; };
unfollow: { followerId: MiUser['id']; followeeId: MiUser['id']; };
blockingCreated: { blockerId: MiUser['id']; blockeeId: MiUser['id']; };
@@ -249,6 +285,14 @@ export type GlobalEvents = {
name: 'notesStream';
payload: Serialized>;
};
+ reversi: {
+ name: `reversiStream:${MiUser['id']}`;
+ payload: EventUnionFromDictionary>;
+ };
+ reversiGame: {
+ name: `reversiGameStream:${MiReversiGame['id']}`;
+ payload: EventUnionFromDictionary>;
+ };
};
// API event definitions
@@ -338,4 +382,14 @@ export class GlobalEventService {
public publishAdminStream(userId: MiUser['id'], type: K, value?: AdminEventTypes[K]): void {
this.publish(`adminStream:${userId}`, type, typeof value === 'undefined' ? null : value);
}
+
+ @bindThis
+ public publishReversiStream(userId: MiUser['id'], type: K, value?: ReversiEventTypes[K]): void {
+ this.publish(`reversiStream:${userId}`, type, typeof value === 'undefined' ? null : value);
+ }
+
+ @bindThis
+ public publishReversiGameStream(gameId: MiReversiGame['id'], type: K, value?: ReversiGameEventTypes[K]): void {
+ this.publish(`reversiGameStream:${gameId}`, type, typeof value === 'undefined' ? null : value);
+ }
}
diff --git a/packages/backend/src/core/HashtagService.ts b/packages/backend/src/core/HashtagService.ts
index d37899990..eb192ee6d 100644
--- a/packages/backend/src/core/HashtagService.ts
+++ b/packages/backend/src/core/HashtagService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -15,6 +15,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { bindThis } from '@/decorators.js';
import { FeaturedService } from '@/core/FeaturedService.js';
import { MetaService } from '@/core/MetaService.js';
+import { UtilityService } from '@/core/UtilityService.js';
@Injectable()
export class HashtagService {
@@ -29,6 +30,7 @@ export class HashtagService {
private featuredService: FeaturedService,
private idService: IdService,
private metaService: MetaService,
+ private utilityService: UtilityService,
) {
}
@@ -161,6 +163,7 @@ export class HashtagService {
const instance = await this.metaService.fetch();
const hiddenTags = instance.hiddenTags.map(t => normalizeForSearch(t));
if (hiddenTags.includes(hashtag)) return;
+ if (this.utilityService.isKeyWordIncluded(hashtag, instance.sensitiveWords)) return;
// YYYYMMDDHHmm (10分間隔)
const now = new Date();
diff --git a/packages/backend/src/core/HttpRequestService.ts b/packages/backend/src/core/HttpRequestService.ts
index 73bb3dc7e..3eb2a8089 100644
--- a/packages/backend/src/core/HttpRequestService.ts
+++ b/packages/backend/src/core/HttpRequestService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -14,9 +14,16 @@ import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { StatusError } from '@/misc/status-error.js';
import { bindThis } from '@/decorators.js';
+import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js';
+import type { IObject } from '@/core/activitypub/type.js';
import type { Response } from 'node-fetch';
import type { URL } from 'node:url';
+export type HttpRequestSendOptions = {
+ throwErrorWhenResponseNotOk: boolean;
+ validators?: ((res: Response) => void)[];
+};
+
@Injectable()
export class HttpRequestService {
/**
@@ -104,6 +111,23 @@ export class HttpRequestService {
}
}
+ @bindThis
+ public async getActivityJson(url: string): Promise {
+ const res = await this.send(url, {
+ method: 'GET',
+ headers: {
+ Accept: 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
+ },
+ timeout: 5000,
+ size: 1024 * 256,
+ }, {
+ throwErrorWhenResponseNotOk: true,
+ validators: [validateContentTypeSetAsActivityPub],
+ });
+
+ return await res.json() as IObject;
+ }
+
@bindThis
public async getJson(url: string, accept = 'application/json, */*', headers?: Record): Promise {
const res = await this.send(url, {
@@ -132,17 +156,20 @@ export class HttpRequestService {
}
@bindThis
- public async send(url: string, args: {
- method?: string,
- body?: string,
- headers?: Record,
- timeout?: number,
- size?: number,
- } = {}, extra: {
- throwErrorWhenResponseNotOk: boolean;
- } = {
- throwErrorWhenResponseNotOk: true,
- }): Promise {
+ public async send(
+ url: string,
+ args: {
+ method?: string,
+ body?: string,
+ headers?: Record,
+ timeout?: number,
+ size?: number,
+ } = {},
+ extra: HttpRequestSendOptions = {
+ throwErrorWhenResponseNotOk: true,
+ validators: [],
+ },
+ ): Promise {
const timeout = args.timeout ?? 5000;
const controller = new AbortController();
@@ -150,11 +177,14 @@ export class HttpRequestService {
controller.abort();
}, timeout);
- const res = await fetch(url, {
+ const bearcaps = url.startsWith('bear:?') ? this.parseBearcaps(url) : undefined;
+
+ const res = await fetch(bearcaps?.url ?? url, {
method: args.method ?? 'GET',
headers: {
'User-Agent': this.config.userAgent,
...(args.headers ?? {}),
+ ...(bearcaps?.token ? { Authorization: `Bearer ${bearcaps.token}` } : {}),
},
body: args.body,
size: args.size ?? 10 * 1024 * 1024,
@@ -166,6 +196,25 @@ export class HttpRequestService {
throw new StatusError(`${res.status} ${res.statusText}`, res.status, res.statusText);
}
+ if (res.ok) {
+ for (const validator of (extra.validators ?? [])) {
+ validator(res);
+ }
+ }
+
return res;
}
+
+ // Bearcaps https://docs.joinmastodon.org/spec/bearcaps/
+ // bear:?t=&u=https://example.com/foo'
+ // -> GET https://example.com/foo Authorization: Bearer
+ private parseBearcaps(url: string): { url: string, token: string | undefined } | undefined {
+ const params = new URLSearchParams(url.split('?')[1]);
+ if (!params.has('u')) return undefined;
+
+ return {
+ url: params.get('u')!,
+ token: params.get('t') ?? undefined,
+ };
+ }
}
diff --git a/packages/backend/src/core/IdService.ts b/packages/backend/src/core/IdService.ts
index c98b8ea6f..10df6ef26 100644
--- a/packages/backend/src/core/IdService.ts
+++ b/packages/backend/src/core/IdService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -7,11 +7,11 @@ import { Inject, Injectable } from '@nestjs/common';
import { ulid } from 'ulid';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
-import { genAid, parseAid } from '@/misc/id/aid.js';
-import { genAidx, parseAidx } from '@/misc/id/aidx.js';
-import { genMeid, parseMeid } from '@/misc/id/meid.js';
-import { genMeidg, parseMeidg } from '@/misc/id/meidg.js';
-import { genObjectId, parseObjectId } from '@/misc/id/object-id.js';
+import { genAid, isSafeAidT, parseAid } from '@/misc/id/aid.js';
+import { genAidx, isSafeAidxT, parseAidx } from '@/misc/id/aidx.js';
+import { genMeid, isSafeMeidT, parseMeid } from '@/misc/id/meid.js';
+import { genMeidg, isSafeMeidgT, parseMeidg } from '@/misc/id/meidg.js';
+import { genObjectId, isSafeObjectIdT, parseObjectId } from '@/misc/id/object-id.js';
import { bindThis } from '@/decorators.js';
import { parseUlid } from '@/misc/id/ulid.js';
@@ -26,6 +26,19 @@ export class IdService {
this.method = config.id.toLowerCase();
}
+ @bindThis
+ public isSafeT(t: number): boolean {
+ switch (this.method) {
+ case 'aid': return isSafeAidT(t);
+ case 'aidx': return isSafeAidxT(t);
+ case 'meid': return isSafeMeidT(t);
+ case 'meidg': return isSafeMeidgT(t);
+ case 'ulid': return t > 0;
+ case 'objectid': return isSafeObjectIdT(t);
+ default: throw new Error('unrecognized id generation method');
+ }
+ }
+
/**
* 時間を元にIDを生成します(省略時は現在日時)
* @param time 日時
diff --git a/packages/backend/src/core/ImageProcessingService.ts b/packages/backend/src/core/ImageProcessingService.ts
index 8e800eb8f..6f978b34c 100644
--- a/packages/backend/src/core/ImageProcessingService.ts
+++ b/packages/backend/src/core/ImageProcessingService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/InstanceActorService.ts b/packages/backend/src/core/InstanceActorService.ts
index b40fd4629..22c47297a 100644
--- a/packages/backend/src/core/InstanceActorService.ts
+++ b/packages/backend/src/core/InstanceActorService.ts
@@ -1,10 +1,10 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
-import { IsNull } from 'typeorm';
+import { IsNull, Not } from 'typeorm';
import type { MiLocalUser } from '@/models/User.js';
import type { UsersRepository } from '@/models/_.js';
import { MemorySingleCache } from '@/misc/cache.js';
@@ -27,6 +27,14 @@ export class InstanceActorService {
this.cache = new MemorySingleCache(Infinity);
}
+ @bindThis
+ public async realLocalUsersPresent(): Promise {
+ return await this.usersRepository.existsBy({
+ host: IsNull(),
+ username: Not(ACTOR_USERNAME),
+ });
+ }
+
@bindThis
public async getInstanceActor(): Promise {
const cached = this.cache.get();
diff --git a/packages/backend/src/core/InternalStorageService.ts b/packages/backend/src/core/InternalStorageService.ts
index 22129bb34..4fb8a93e4 100644
--- a/packages/backend/src/core/InternalStorageService.ts
+++ b/packages/backend/src/core/InternalStorageService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/LoggerService.ts b/packages/backend/src/core/LoggerService.ts
index 46b000ee6..a3d371a30 100644
--- a/packages/backend/src/core/LoggerService.ts
+++ b/packages/backend/src/core/LoggerService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -16,6 +16,6 @@ export class LoggerService {
@bindThis
public getLogger(domain: string, color?: KEYWORD | undefined, store?: boolean) {
- return new Logger(domain, color, store);
+ return new Logger(domain);
}
}
diff --git a/packages/backend/src/core/MetaService.ts b/packages/backend/src/core/MetaService.ts
index 508544dc0..ec630f804 100644
--- a/packages/backend/src/core/MetaService.ts
+++ b/packages/backend/src/core/MetaService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -11,6 +11,7 @@ import { MiMeta } from '@/models/Meta.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { bindThis } from '@/decorators.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js';
+import { FeaturedService } from '@/core/FeaturedService.js';
import type { OnApplicationShutdown } from '@nestjs/common';
@Injectable()
@@ -25,6 +26,7 @@ export class MetaService implements OnApplicationShutdown {
@Inject(DI.db)
private db: DataSource,
+ private featuredService: FeaturedService,
private globalEventService: GlobalEventService,
) {
//this.onMessage = this.onMessage.bind(this);
@@ -49,7 +51,10 @@ export class MetaService implements OnApplicationShutdown {
const { type, body } = obj.message as GlobalEvents['internal']['payload'];
switch (type) {
case 'metaUpdated': {
- this.cache = body;
+ this.cache = { // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい
+ ...body,
+ proxyAccount: null, // joinなカラムは通常取ってこないので
+ };
break;
}
default:
@@ -95,6 +100,8 @@ export class MetaService implements OnApplicationShutdown {
@bindThis
public async update(data: Partial): Promise {
+ let before: MiMeta | undefined;
+
const updated = await this.db.transaction(async transactionalEntityManager => {
const metas = await transactionalEntityManager.find(MiMeta, {
order: {
@@ -102,10 +109,10 @@ export class MetaService implements OnApplicationShutdown {
},
});
- const meta = metas[0];
+ before = metas[0];
- if (meta) {
- await transactionalEntityManager.update(MiMeta, meta.id, data);
+ if (before) {
+ await transactionalEntityManager.update(MiMeta, before.id, data);
const metas = await transactionalEntityManager.find(MiMeta, {
order: {
@@ -119,6 +126,21 @@ export class MetaService implements OnApplicationShutdown {
}
});
+ if (data.hiddenTags) {
+ process.nextTick(() => {
+ const hiddenTags = new Set(data.hiddenTags);
+ if (before) {
+ for (const previousHiddenTag of before.hiddenTags) {
+ hiddenTags.delete(previousHiddenTag);
+ }
+ }
+
+ for (const hiddenTag of hiddenTags) {
+ this.featuredService.removeHashtagsFromRanking(hiddenTag);
+ }
+ });
+ }
+
this.globalEventService.publishInternalEvent('metaUpdated', updated);
return updated;
diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts
index e74c62e1a..c62ee5a64 100644
--- a/packages/backend/src/core/MfmService.ts
+++ b/packages/backend/src/core/MfmService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -419,6 +419,10 @@ export class MfmService {
},
text: (node) => {
+ if (!node.props.text.match(/[\r\n]/)) {
+ return doc.createTextNode(node.props.text);
+ }
+
const el = doc.createElement('span');
const nodes = node.props.text.split(/\r\n|\r|\n/).map(x => doc.createTextNode(x));
diff --git a/packages/backend/src/core/ModerationLogService.ts b/packages/backend/src/core/ModerationLogService.ts
index 8b78d0204..6c155c9a6 100644
--- a/packages/backend/src/core/ModerationLogService.ts
+++ b/packages/backend/src/core/ModerationLogService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts
index ae1d88759..2889c7def 100644
--- a/packages/backend/src/core/NoteCreateService.ts
+++ b/packages/backend/src/core/NoteCreateService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -32,10 +32,12 @@ import { RelayService } from '@/core/RelayService.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
+import type Logger from '@/logger.js';
import NotesChart from '@/core/chart/charts/notes.js';
import PerUserNotesChart from '@/core/chart/charts/per-user-notes.js';
import InstanceChart from '@/core/chart/charts/instance.js';
import ActiveUsersChart from '@/core/chart/charts/active-users.js';
+import { LoggerService } from '@/core/LoggerService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { NotificationService } from '@/core/NotificationService.js';
import { WebhookService } from '@/core/WebhookService.js';
@@ -54,9 +56,13 @@ import { RoleService } from '@/core/RoleService.js';
import { MetaService } from '@/core/MetaService.js';
import { SearchService } from '@/core/SearchService.js';
import { FeaturedService } from '@/core/FeaturedService.js';
-import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
+import { FanoutTimelineService } from '@/core/FanoutTimelineService.js';
import { UtilityService } from '@/core/UtilityService.js';
import { UserBlockingService } from '@/core/UserBlockingService.js';
+import { isReply } from '@/misc/is-reply.js';
+import { trackPromise } from '@/misc/promise-tracker.js';
+import { isNotNull } from '@/misc/is-not-null.js';
+import { IdentifiableError } from '@/misc/identifiable-error.js';
type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
@@ -147,6 +153,7 @@ type Option = {
@Injectable()
export class NoteCreateService implements OnApplicationShutdown {
+ private logger: Logger;
#shutdownController = new AbortController();
constructor(
@@ -194,7 +201,7 @@ export class NoteCreateService implements OnApplicationShutdown {
private idService: IdService,
private globalEventService: GlobalEventService,
private queueService: QueueService,
- private funoutTimelineService: FunoutTimelineService,
+ private fanoutTimelineService: FanoutTimelineService,
private noteReadService: NoteReadService,
private notificationService: NotificationService,
private relayService: RelayService,
@@ -215,7 +222,10 @@ export class NoteCreateService implements OnApplicationShutdown {
private instanceChart: InstanceChart,
private utilityService: UtilityService,
private userBlockingService: UserBlockingService,
- ) { }
+ private loggerService: LoggerService,
+ ) {
+ this.logger = this.loggerService.getLogger('note:create');
+ }
@bindThis
public async create(user: {
@@ -249,16 +259,32 @@ export class NoteCreateService implements OnApplicationShutdown {
if (data.channel != null) data.localOnly = true;
const meta = await this.metaService.fetch();
+ const policies = await this.roleService.getUserPolicies(user.id);
if (data.visibility === 'public' && data.channel == null) {
const sensitiveWords = meta.sensitiveWords;
- if (this.isSensitive(data, sensitiveWords)) {
+ if (this.utilityService.isKeyWordIncluded(data.cw ?? data.text ?? '', sensitiveWords)) {
data.visibility = 'home';
- } else if ((await this.roleService.getUserPolicies(user.id)).canPublicNote === false) {
+ this.logger.warn('Visibility changed to home because sensitive words are included', { user: user.id, note: data });
+ } else if (policies.canPublicNote === false) {
data.visibility = 'home';
}
}
+ const hasProhibitedWords = await this.checkProhibitedWordsContain(
+ meta.prohibitedWords,
+ {
+ cw: data.cw,
+ text: data.text,
+ pollChoices: data.poll?.choices,
+ },
+ );
+
+ if (hasProhibitedWords) {
+ this.logger.error('Request rejected because prohibited words are included', { user: user.id, note: data });
+ throw new IdentifiableError('689ee33f-f97c-479a-ac49-1b9f8140af99', 'Notes including prohibited words are not allowed.');
+ }
+
const inSilencedInstance = this.utilityService.isSilencedHost(meta.silencedHosts, user.host);
if (data.visibility === 'public' && inSilencedInstance && user.host !== null) {
@@ -292,7 +318,7 @@ export class NoteCreateService implements OnApplicationShutdown {
}
// Check blocking
- if (data.renote && data.text == null && data.poll == null && (data.files == null || data.files.length === 0)) {
+ if (data.renote && !this.isQuote(data)) {
if (data.renote.userHost === null) {
if (data.renote.userId !== user.id) {
const blocked = await this.userBlockingService.checkBlocked(data.renote.userId, user.id);
@@ -323,6 +349,9 @@ export class NoteCreateService implements OnApplicationShutdown {
data.text = data.text.slice(0, DB_MAX_NOTE_TEXT_LENGTH);
}
data.text = data.text.trim();
+ if (data.text === '') {
+ data.text = null;
+ }
} else {
data.text = null;
}
@@ -348,6 +377,30 @@ export class NoteCreateService implements OnApplicationShutdown {
mentionedUsers = data.apMentions ?? await this.extractMentionedUsers(user, combinedTokens);
}
+ const willCauseNotification = mentionedUsers.some(u => u.host === null)
+ || (data.visibility === 'specified' && data.visibleUsers?.some(u => u.host === null))
+ || data.reply?.userHost === null || (this.isQuote(data) && data.renote?.userHost === null) || false;
+
+ if (process.env.MISSKEY_BLOCK_MENTIONS_FROM_UNFAMILIAR_REMOTE_USERS === 'true' && user.host !== null && willCauseNotification) {
+ const userEntity = await this.usersRepository.findOneBy({ id: user.id });
+ if ((userEntity?.followersCount ?? 0) === 0) {
+ this.logger.error('Request rejected because user has no local followers', { user: user.id, note: data });
+ throw new IdentifiableError('e11b3a16-f543-4885-8eb1-66cad131dbfd', 'Notes including mentions, replies, or renotes from remote users are not allowed until user has at least one local follower.');
+ }
+ }
+
+ if (policies.canInitiateConversation === false) {
+ if (
+ mentionedUsers.some(u => u.id !== user.id)
+ || (data.reply && data.reply.userId !== user.id)
+ || (data.visibility === 'specified' && data.visibleUsers?.some(u => u.id !== user.id))
+ || (this.isQuote(data) && data.renote.userId !== user.id)
+ ) {
+ this.logger.error('Request rejected because user has no permission to initiate conversation', { user: user.id, note: data });
+ throw new IdentifiableError('332dd91b-6a00-430a-ac39-620cf60ad34b', 'Notes including mentions, replies, or renotes are not allowed.');
+ }
+ }
+
tags = tags.filter(tag => Array.from(tag).length <= 128).splice(0, 32);
if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) {
@@ -368,6 +421,10 @@ export class NoteCreateService implements OnApplicationShutdown {
}
}
+ if (mentionedUsers.length > 0 && mentionedUsers.length > policies.mentionLimit) {
+ throw new IdentifiableError('9f466dab-c856-48cd-9e65-ff90ff750580', `Notes including mentions are limited to ${policies.mentionLimit} users.`);
+ }
+
const note = await this.insertNote(user, data, tags, emojis, mentionedUsers);
setImmediate('post created', { signal: this.#shutdownController.signal }).then(
@@ -382,6 +439,7 @@ export class NoteCreateService implements OnApplicationShutdown {
private async insertNote(user: { id: MiUser['id']; host: MiUser['host']; }, data: Option, tags: string[], emojis: string[], mentionedUsers: MinimumUser[]) {
const insert = new MiNote({
id: this.idService.gen(data.createdAt?.getTime()),
+ createdAt: data.createdAt!,
fileIds: data.files ? data.files.map(file => file.id) : [],
replyId: data.reply ? data.reply.id : null,
renoteId: data.renote ? data.renote.id : null,
@@ -469,7 +527,7 @@ export class NoteCreateService implements OnApplicationShutdown {
throw err;
}
- console.error(e);
+ this.logger.error(`Failed to create note: ${e}`, { error: e });
throw e;
}
@@ -598,7 +656,7 @@ export class NoteCreateService implements OnApplicationShutdown {
if (data.reply) {
// 通知
if (data.reply.userHost === null) {
- const isThreadMuted = await this.noteThreadMutingsRepository.exist({
+ const isThreadMuted = await this.noteThreadMutingsRepository.exists({
where: {
userId: data.reply.userId,
threadId: data.reply.threadId ?? data.reply.id,
@@ -621,7 +679,7 @@ export class NoteCreateService implements OnApplicationShutdown {
// If it is renote
if (data.renote) {
- const type = data.text ? 'quote' : 'renote';
+ const type = this.isQuote(data) ? 'quote' : 'renote';
// Notify
if (data.renote.userHost === null) {
@@ -675,7 +733,7 @@ export class NoteCreateService implements OnApplicationShutdown {
this.relayService.deliverToRelays(user, noteActivity);
}
- dm.execute();
+ trackPromise(dm.execute());
})();
}
//#endregion
@@ -704,28 +762,38 @@ export class NoteCreateService implements OnApplicationShutdown {
}
@bindThis
- private isSensitive(note: Option, sensitiveWord: string[]): boolean {
- if (sensitiveWord.length > 0) {
- const text = note.cw ?? note.text ?? '';
- if (text === '') return false;
- const matched = sensitiveWord.some(filter => {
- // represents RegExp
- const regexp = filter.match(/^\/(.+)\/(.*)$/);
- // This should never happen due to input sanitisation.
- if (!regexp) {
- const words = filter.split(' ');
- return words.every(keyword => text.includes(keyword));
- }
- try {
- return new RE2(regexp[1], regexp[2]).test(text);
- } catch (err) {
- // This should never happen due to input sanitisation.
- return false;
- }
- });
- if (matched) return true;
- }
- return false;
+ public async appendNoteVisibleUser(user: {
+ id: MiUser['id'];
+ username: MiUser['username'];
+ host: MiUser['host'];
+ isBot: MiUser['isBot'];
+ isCat: MiUser['isCat'];
+ }, note: MiNote, additionalUserId: MiLocalUser['id']) {
+ if (note.visibility !== 'specified') return;
+ if (note.visibleUserIds.includes(additionalUserId)) return;
+
+ const additionalUser = await this.usersRepository.findOneByOrFail({ id: additionalUserId, host: IsNull() });
+
+ // ノートのvisibleUserIdsを更新
+ await this.notesRepository.update(note.id, {
+ visibleUserIds: () => `array_append("visibleUserIds", '${additionalUser.id}')`,
+ });
+
+ // 新しい対象ユーザーにだけ処理が行われるようにする
+ note.visibleUserIds = [additionalUser.id];
+
+ // FanoutTimelineに追加
+ this.pushToTl(note, user);
+
+ // ストリームに流す
+ const noteObj = await this.noteEntityService.pack(note, null, { skipHide: true, withReactionAndUserPairCache: true });
+ this.globalEventService.publishNotesStream(noteObj);
+ }
+
+ @bindThis
+ private isQuote(note: Option): note is Option & { renote: MiNote } {
+ // sync with misc/is-quote.ts
+ return !!note.renote && (!!note.text || !!note.cw || (!!note.files && !!note.files.length) || !!note.poll);
}
@bindThis
@@ -756,7 +824,7 @@ export class NoteCreateService implements OnApplicationShutdown {
@bindThis
private async createMentionedEvents(mentionedUsers: MinimumUser[], note: MiNote, nm: NotificationManager) {
for (const u of mentionedUsers.filter(u => this.userEntityService.isLocalUser(u))) {
- const isThreadMuted = await this.noteThreadMutingsRepository.exist({
+ const isThreadMuted = await this.noteThreadMutingsRepository.exists({
where: {
userId: u.id,
threadId: note.threadId ?? note.id,
@@ -794,7 +862,7 @@ export class NoteCreateService implements OnApplicationShutdown {
private async renderNoteOrRenoteActivity(data: Option, note: MiNote) {
if (data.localOnly) return null;
- const content = data.renote && data.text == null && data.poll == null && (data.files == null || data.files.length === 0)
+ const content = data.renote && !this.isQuote(data)
? this.apRendererService.renderAnnounce(data.renote.uri ? data.renote.uri : `${this.config.url}/notes/${data.renote.id}`, note)
: this.apRendererService.renderCreate(await this.apRendererService.renderNote(note, false), note);
@@ -826,7 +894,7 @@ export class NoteCreateService implements OnApplicationShutdown {
const mentions = extractMentions(tokens);
let mentionedUsers = (await Promise.all(mentions.map(m =>
this.remoteUserResolveService.resolveUser(m.username, m.host ?? user.host).catch(() => null),
- ))).filter(x => x != null) as MiUser[];
+ ))).filter(isNotNull);
// Drop duplicate users
mentionedUsers = mentionedUsers.filter((u, i, self) =>
@@ -871,26 +939,27 @@ export class NoteCreateService implements OnApplicationShutdown {
// ダイレクトのとき、そのリストが対象外のユーザーの場合
if (
note.visibility === 'specified' &&
+ note.userId !== userListMembership.userListUserId &&
!note.visibleUserIds.some(v => v === userListMembership.userListUserId)
) continue;
// 「自分自身への返信 or そのリストの作成者への返信」のどちらでもない場合
- if (note.replyId && !(note.replyUserId === note.userId || note.replyUserId === userListMembership.userListUserId)) {
+ if (isReply(note, userListMembership.userListUserId)) {
if (!userListMembership.withReplies) continue;
}
- this.funoutTimelineService.push(`userListTimeline:${userListMembership.userListId}`, note.id, meta.perUserListTimelineCacheMax, r);
+ this.fanoutTimelineService.push(`userListTimeline:${userListMembership.userListId}`, note.id, meta.perUserListTimelineCacheMax, r);
if (note.fileIds.length > 0) {
- this.funoutTimelineService.push(`userListTimelineWithFiles:${userListMembership.userListId}`, note.id, meta.perUserListTimelineCacheMax / 2, r);
+ this.fanoutTimelineService.push(`userListTimelineWithFiles:${userListMembership.userListId}`, note.id, meta.perUserListTimelineCacheMax / 2, r);
}
}
if (note.channelId) {
- this.funoutTimelineService.push(`channelTimeline:${note.channelId}`, note.id, this.config.perChannelMaxNoteCacheCount, r);
+ this.fanoutTimelineService.push(`channelTimeline:${note.channelId}`, note.id, this.config.perChannelMaxNoteCacheCount, r);
- this.funoutTimelineService.push(`userTimelineWithChannel:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax : meta.perRemoteUserUserTimelineCacheMax, r);
+ this.fanoutTimelineService.push(`userTimelineWithChannel:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax : meta.perRemoteUserUserTimelineCacheMax, r);
if (note.fileIds.length > 0) {
- this.funoutTimelineService.push(`userTimelineWithChannelWithFiles:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax / 2 : meta.perRemoteUserUserTimelineCacheMax / 2, r);
+ this.fanoutTimelineService.push(`userTimelineWithChannelWithFiles:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax / 2 : meta.perRemoteUserUserTimelineCacheMax / 2, r);
}
const channelFollowings = await this.channelFollowingsRepository.find({
@@ -901,9 +970,9 @@ export class NoteCreateService implements OnApplicationShutdown {
});
for (const channelFollowing of channelFollowings) {
- this.funoutTimelineService.push(`homeTimeline:${channelFollowing.followerId}`, note.id, meta.perUserHomeTimelineCacheMax, r);
+ this.fanoutTimelineService.push(`homeTimeline:${channelFollowing.followerId}`, note.id, meta.perUserHomeTimelineCacheMax, r);
if (note.fileIds.length > 0) {
- this.funoutTimelineService.push(`homeTimelineWithFiles:${channelFollowing.followerId}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r);
+ this.fanoutTimelineService.push(`homeTimelineWithFiles:${channelFollowing.followerId}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r);
}
}
} else {
@@ -913,43 +982,46 @@ export class NoteCreateService implements OnApplicationShutdown {
if (note.visibility === 'specified' && !note.visibleUserIds.some(v => v === following.followerId)) continue;
// 「自分自身への返信 or そのフォロワーへの返信」のどちらでもない場合
- if (note.replyId && !(note.replyUserId === note.userId || note.replyUserId === following.followerId)) {
+ if (isReply(note, following.followerId)) {
if (!following.withReplies) continue;
}
- this.funoutTimelineService.push(`homeTimeline:${following.followerId}`, note.id, meta.perUserHomeTimelineCacheMax, r);
+ this.fanoutTimelineService.push(`homeTimeline:${following.followerId}`, note.id, meta.perUserHomeTimelineCacheMax, r);
if (note.fileIds.length > 0) {
- this.funoutTimelineService.push(`homeTimelineWithFiles:${following.followerId}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r);
+ this.fanoutTimelineService.push(`homeTimelineWithFiles:${following.followerId}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r);
}
}
if (note.visibility !== 'specified' || !note.visibleUserIds.some(v => v === user.id)) { // 自分自身のHTL
- this.funoutTimelineService.push(`homeTimeline:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax, r);
+ this.fanoutTimelineService.push(`homeTimeline:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax, r);
if (note.fileIds.length > 0) {
- this.funoutTimelineService.push(`homeTimelineWithFiles:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r);
+ this.fanoutTimelineService.push(`homeTimelineWithFiles:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r);
}
}
// 自分自身以外への返信
- if (note.replyId && note.replyUserId !== note.userId) {
- this.funoutTimelineService.push(`userTimelineWithReplies:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax : meta.perRemoteUserUserTimelineCacheMax, r);
+ if (isReply(note)) {
+ this.fanoutTimelineService.push(`userTimelineWithReplies:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax : meta.perRemoteUserUserTimelineCacheMax, r);
if (note.fileIds.length > 0) {
- this.funoutTimelineService.push(`userTimelineWithRepliesWithFiles:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax / 2 : meta.perRemoteUserUserTimelineCacheMax / 2, r);
+ this.fanoutTimelineService.push(`userTimelineWithRepliesWithFiles:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax / 2 : meta.perRemoteUserUserTimelineCacheMax / 2, r);
}
if (note.visibility === 'public' && note.userHost == null) {
- this.funoutTimelineService.push('localTimelineWithReplies', note.id, 300, r);
+ this.fanoutTimelineService.push('localTimelineWithReplies', note.id, 300, r);
+ if (note.replyUserHost == null) {
+ this.fanoutTimelineService.push(`localTimelineWithReplyTo:${note.replyUserId}`, note.id, 300 / 10, r);
+ }
}
} else {
- this.funoutTimelineService.push(`userTimeline:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax : meta.perRemoteUserUserTimelineCacheMax, r);
+ this.fanoutTimelineService.push(`userTimeline:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax : meta.perRemoteUserUserTimelineCacheMax, r);
if (note.fileIds.length > 0) {
- this.funoutTimelineService.push(`userTimelineWithFiles:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax / 2 : meta.perRemoteUserUserTimelineCacheMax / 2, r);
+ this.fanoutTimelineService.push(`userTimelineWithFiles:${user.id}`, note.id, note.userHost == null ? meta.perLocalUserUserTimelineCacheMax / 2 : meta.perRemoteUserUserTimelineCacheMax / 2, r);
}
if (note.visibility === 'public' && note.userHost == null) {
- this.funoutTimelineService.push('localTimeline', note.id, 1000, r);
+ this.fanoutTimelineService.push('localTimeline', note.id, 1000, r);
if (note.fileIds.length > 0) {
- this.funoutTimelineService.push('localTimelineWithFiles', note.id, 500, r);
+ this.fanoutTimelineService.push('localTimelineWithFiles', note.id, 500, r);
}
}
}
@@ -1002,6 +1074,13 @@ export class NoteCreateService implements OnApplicationShutdown {
}
}
+ public async checkProhibitedWordsContain(prohibitedWords: string[], content: Parameters[0]) {
+ return this.utilityService.isKeyWordIncluded(
+ this.utilityService.concatNoteContentsForKeyWordCheck(content),
+ prohibitedWords,
+ );
+ }
+
@bindThis
public dispose(): void {
this.#shutdownController.abort();
diff --git a/packages/backend/src/core/NoteDeleteService.ts b/packages/backend/src/core/NoteDeleteService.ts
index 632daf991..fdf843c3e 100644
--- a/packages/backend/src/core/NoteDeleteService.ts
+++ b/packages/backend/src/core/NoteDeleteService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/NotePiningService.ts b/packages/backend/src/core/NotePiningService.ts
index 52abb4c2a..d38b48b65 100644
--- a/packages/backend/src/core/NotePiningService.ts
+++ b/packages/backend/src/core/NotePiningService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -77,7 +77,7 @@ export class NotePiningService {
} as MiUserNotePining);
// Deliver to remote followers
- if (this.userEntityService.isLocalUser(user)) {
+ if (this.userEntityService.isLocalUser(user) && !note.localOnly && ['public', 'home'].includes(note.visibility)) {
this.deliverPinnedChange(user.id, note.id, true);
}
}
@@ -105,7 +105,7 @@ export class NotePiningService {
});
// Deliver to remote followers
- if (this.userEntityService.isLocalUser(user)) {
+ if (this.userEntityService.isLocalUser(user) && !note.localOnly && ['public', 'home'].includes(note.visibility)) {
this.deliverPinnedChange(user.id, noteId, false);
}
}
diff --git a/packages/backend/src/core/NoteReadService.ts b/packages/backend/src/core/NoteReadService.ts
index 03c1735e0..f15dcfd8a 100644
--- a/packages/backend/src/core/NoteReadService.ts
+++ b/packages/backend/src/core/NoteReadService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -14,6 +14,7 @@ import { IdService } from '@/core/IdService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import type { NoteUnreadsRepository, MutingsRepository, NoteThreadMutingsRepository } from '@/models/_.js';
import { bindThis } from '@/decorators.js';
+import { trackPromise } from '@/misc/promise-tracker.js';
@Injectable()
export class NoteReadService implements OnApplicationShutdown {
@@ -48,7 +49,7 @@ export class NoteReadService implements OnApplicationShutdown {
//#endregion
// スレッドミュート
- const isThreadMuted = await this.noteThreadMutingsRepository.exist({
+ const isThreadMuted = await this.noteThreadMutingsRepository.exists({
where: {
userId: userId,
threadId: note.threadId ?? note.id,
@@ -69,7 +70,7 @@ export class NoteReadService implements OnApplicationShutdown {
// 2秒経っても既読にならなかったら「未読の投稿がありますよ」イベントを発行する
setTimeout(2000, 'unread note', { signal: this.#shutdownController.signal }).then(async () => {
- const exist = await this.noteUnreadsRepository.exist({ where: { id: unread.id } });
+ const exist = await this.noteUnreadsRepository.exists({ where: { id: unread.id } });
if (!exist) return;
@@ -87,46 +88,43 @@ export class NoteReadService implements OnApplicationShutdown {
userId: MiUser['id'],
notes: (MiNote | Packed<'Note'>)[],
): Promise {
- const readMentions: (MiNote | Packed<'Note'>)[] = [];
- const readSpecifiedNotes: (MiNote | Packed<'Note'>)[] = [];
+ if (notes.length === 0) return;
- for (const note of notes) {
- if (note.mentions && note.mentions.includes(userId)) {
- readMentions.push(note);
- } else if (note.visibleUserIds && note.visibleUserIds.includes(userId)) {
- readSpecifiedNotes.push(note);
+ const noteIds = new Set(
+ notes.filter(note =>
+ (note.mentions?.includes(userId) ?? false) || (note.visibleUserIds?.includes(userId) ?? false)
+ ).map(note => note.id),
+ );
+
+ if (noteIds.size === 0) return;
+
+ // Remove the record
+ await this.noteUnreadsRepository.delete({
+ userId: userId,
+ noteId: In(Array.from(noteIds)),
+ });
+
+ // TODO: ↓まとめてクエリしたい
+
+ trackPromise(this.noteUnreadsRepository.countBy({
+ userId: userId,
+ isMentioned: true,
+ }).then(mentionsCount => {
+ if (mentionsCount === 0) {
+ // 全て既読になったイベントを発行
+ this.globalEventService.publishMainStream(userId, 'readAllUnreadMentions');
}
- }
+ }));
- if ((readMentions.length > 0) || (readSpecifiedNotes.length > 0)) {
- // Remove the record
- await this.noteUnreadsRepository.delete({
- userId: userId,
- noteId: In([...readMentions.map(n => n.id), ...readSpecifiedNotes.map(n => n.id)]),
- });
-
- // TODO: ↓まとめてクエリしたい
-
- this.noteUnreadsRepository.countBy({
- userId: userId,
- isMentioned: true,
- }).then(mentionsCount => {
- if (mentionsCount === 0) {
- // 全て既読になったイベントを発行
- this.globalEventService.publishMainStream(userId, 'readAllUnreadMentions');
- }
- });
-
- this.noteUnreadsRepository.countBy({
- userId: userId,
- isSpecified: true,
- }).then(specifiedCount => {
- if (specifiedCount === 0) {
- // 全て既読になったイベントを発行
- this.globalEventService.publishMainStream(userId, 'readAllUnreadSpecifiedNotes');
- }
- });
- }
+ trackPromise(this.noteUnreadsRepository.countBy({
+ userId: userId,
+ isSpecified: true,
+ }).then(specifiedCount => {
+ if (specifiedCount === 0) {
+ // 全て既読になったイベントを発行
+ this.globalEventService.publishMainStream(userId, 'readAllUnreadSpecifiedNotes');
+ }
+ }));
}
@bindThis
diff --git a/packages/backend/src/core/NotificationService.ts b/packages/backend/src/core/NotificationService.ts
index ad7be83e5..624e5dea4 100644
--- a/packages/backend/src/core/NotificationService.ts
+++ b/packages/backend/src/core/NotificationService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -20,6 +20,7 @@ import { CacheService } from '@/core/CacheService.js';
import type { Config } from '@/config.js';
import { UserListService } from '@/core/UserListService.js';
import type { FilterUnionByProperty } from '@/types.js';
+import { trackPromise } from '@/misc/promise-tracker.js';
@Injectable()
export class NotificationService implements OnApplicationShutdown {
@@ -74,7 +75,18 @@ export class NotificationService implements OnApplicationShutdown {
}
@bindThis
- public async createNotification(
+ public createNotification(
+ notifieeId: MiUser['id'],
+ type: T,
+ data: Omit, 'type' | 'id' | 'createdAt' | 'notifierId'>,
+ notifierId?: MiUser['id'] | null,
+ ) {
+ trackPromise(
+ this.#createNotificationInternal(notifieeId, type, data, notifierId),
+ );
+ }
+
+ async #createNotificationInternal(
notifieeId: MiUser['id'],
type: T,
data: Omit, 'type' | 'id' | 'createdAt' | 'notifierId'>,
@@ -110,6 +122,14 @@ export class NotificationService implements OnApplicationShutdown {
return null;
}
} else if (recieveConfig?.type === 'mutualFollow') {
+ const [isFollowing, isFollower] = await Promise.all([
+ this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => Object.hasOwn(followings, notifierId)),
+ this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => Object.hasOwn(followings, notifieeId)),
+ ]);
+ if (!(isFollowing && isFollower)) {
+ return null;
+ }
+ } else if (recieveConfig?.type === 'followingOrFollower') {
const [isFollowing, isFollower] = await Promise.all([
this.cacheService.userFollowingsCache.fetch(notifieeId).then(followings => Object.hasOwn(followings, notifierId)),
this.cacheService.userFollowingsCache.fetch(notifierId).then(followings => Object.hasOwn(followings, notifieeId)),
@@ -143,6 +163,8 @@ export class NotificationService implements OnApplicationShutdown {
const packed = await this.notificationEntityService.pack(notification, notifieeId, {});
+ if (packed == null) return null;
+
// Publish notification event
this.globalEventService.publishMainStream(notifieeId, 'notification', packed);
@@ -176,7 +198,7 @@ export class NotificationService implements OnApplicationShutdown {
const locale = locales[userProfile.lang ?? 'ja-JP'];
const i18n = new I18n(locale);
// TODO: render user information html
- sendEmail(userProfile.email, i18n.t('_email._follow.title'), `${follower.name} (@${Acct.toString(follower)})`, `${follower.name} (@${Acct.toString(follower)})`);
+ sendEmail(userProfile.email, i18n.ts._email._follow.title, `${follower.name} (@${Acct.toString(follower)})`, `${follower.name} (@${Acct.toString(follower)})`);
*/
}
@@ -188,10 +210,19 @@ export class NotificationService implements OnApplicationShutdown {
const locale = locales[userProfile.lang ?? 'ja-JP'];
const i18n = new I18n(locale);
// TODO: render user information html
- sendEmail(userProfile.email, i18n.t('_email._receiveFollowRequest.title'), `${follower.name} (@${Acct.toString(follower)})`, `${follower.name} (@${Acct.toString(follower)})`);
+ sendEmail(userProfile.email, i18n.ts._email._receiveFollowRequest.title, `${follower.name} (@${Acct.toString(follower)})`, `${follower.name} (@${Acct.toString(follower)})`);
*/
}
+ @bindThis
+ public async flushAllNotifications(userId: MiUser['id']) {
+ await Promise.all([
+ this.redisClient.del(`notificationTimeline:${userId}`),
+ this.redisClient.del(`latestReadNotification:${userId}`),
+ ]);
+ this.globalEventService.publishMainStream(userId, 'notificationFlushed');
+ }
+
@bindThis
public dispose(): void {
this.#shutdownController.abort();
diff --git a/packages/backend/src/core/PollService.ts b/packages/backend/src/core/PollService.ts
index 9e1b5ca78..9f6924b60 100644
--- a/packages/backend/src/core/PollService.ts
+++ b/packages/backend/src/core/PollService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -97,7 +97,7 @@ export class PollService {
if (note.localOnly) return;
const user = await this.usersRepository.findOneBy({ id: note.userId });
- if (user == null) throw new Error('note not found');
+ if (user == null) throw new Error('user not found');
if (this.userEntityService.isLocalUser(user)) {
const content = this.apRendererService.addContext(this.apRendererService.renderUpdate(await this.apRendererService.renderNote(note, false), user));
diff --git a/packages/backend/src/core/ProxyAccountService.ts b/packages/backend/src/core/ProxyAccountService.ts
index b1bc60701..71d663bf9 100644
--- a/packages/backend/src/core/ProxyAccountService.ts
+++ b/packages/backend/src/core/ProxyAccountService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/PushNotificationService.ts b/packages/backend/src/core/PushNotificationService.ts
index 40d1decee..3b706d985 100644
--- a/packages/backend/src/core/PushNotificationService.ts
+++ b/packages/backend/src/core/PushNotificationService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -115,12 +115,19 @@ export class PushNotificationService implements OnApplicationShutdown {
endpoint: subscription.endpoint,
auth: subscription.auth,
publickey: subscription.publickey,
+ }).then(() => {
+ this.refreshCache(userId);
});
}
});
}
}
+ @bindThis
+ public refreshCache(userId: string): void {
+ this.subscriptionsCache.refresh(userId);
+ }
+
@bindThis
public dispose(): void {
this.subscriptionsCache.dispose();
diff --git a/packages/backend/src/core/QueryService.ts b/packages/backend/src/core/QueryService.ts
index f006ed494..49df6d1fd 100644
--- a/packages/backend/src/core/QueryService.ts
+++ b/packages/backend/src/core/QueryService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -188,7 +188,7 @@ export class QueryService {
}
@bindThis
- public generateVisibilityQuery(q: SelectQueryBuilder, me?: { id: MiUser['id'] } | null): void {
+ public generateVisibilityQuery(q: SelectQueryBuilder, me: { id: MiUser['id'] } | null): void {
// This code must always be synchronized with the checks in Notes.isVisibleForMe.
if (me == null) {
q.andWhere(new Brackets(qb => {
@@ -212,8 +212,8 @@ export class QueryService {
// または 自分自身
.orWhere('note.userId = :meId')
// または 自分宛て
- .orWhere(':meId = ANY(note.visibleUserIds)')
- .orWhere(':meId = ANY(note.mentions)')
+ .orWhere(':meIdAsList <@ note.visibleUserIds')
+ .orWhere(':meIdAsList <@ note.mentions')
.orWhere(new Brackets(qb => {
qb
// または フォロワー宛ての投稿であり、
@@ -228,7 +228,7 @@ export class QueryService {
}));
}));
- q.setParameters({ meId: me.id });
+ q.setParameters({ meId: me.id, meIdAsList: [me.id] });
}
}
diff --git a/packages/backend/src/core/QueueModule.ts b/packages/backend/src/core/QueueModule.ts
index 4444dc978..1537deca6 100644
--- a/packages/backend/src/core/QueueModule.ts
+++ b/packages/backend/src/core/QueueModule.ts
@@ -1,14 +1,14 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { setTimeout } from 'node:timers/promises';
import { Inject, Module, OnApplicationShutdown } from '@nestjs/common';
import * as Bull from 'bullmq';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { QUEUE, baseQueueOptions } from '@/queue/const.js';
+import { allSettled } from '@/misc/promise-tracker.js';
import type { Provider } from '@nestjs/common';
import type { DeliverJobData, InboxJobData, EndedPollNotificationJobData, WebhookDeliverJobData, RelationshipJobData } from '../queue/types.js';
@@ -23,49 +23,49 @@ export type WebhookDeliverQueue = Bull.Queue;
const $system: Provider = {
provide: 'queue:system',
- useFactory: (config: Config) => new Bull.Queue(QUEUE.SYSTEM, baseQueueOptions(config, QUEUE.SYSTEM)),
+ useFactory: (config: Config) => new Bull.Queue(QUEUE.SYSTEM, baseQueueOptions(config.redisForSystemQueue, config.bullmqQueueOptions, QUEUE.SYSTEM)),
inject: [DI.config],
};
const $endedPollNotification: Provider = {
provide: 'queue:endedPollNotification',
- useFactory: (config: Config) => new Bull.Queue(QUEUE.ENDED_POLL_NOTIFICATION, baseQueueOptions(config, QUEUE.ENDED_POLL_NOTIFICATION)),
+ useFactory: (config: Config) => new Bull.Queue(QUEUE.ENDED_POLL_NOTIFICATION, baseQueueOptions(config.redisForEndedPollNotificationQueue, config.bullmqQueueOptions, QUEUE.ENDED_POLL_NOTIFICATION)),
inject: [DI.config],
};
const $deliver: Provider = {
provide: 'queue:deliver',
- useFactory: (config: Config) => new Bull.Queue(QUEUE.DELIVER, baseQueueOptions(config, QUEUE.DELIVER)),
+ useFactory: (config: Config) => new Bull.Queue(QUEUE.DELIVER, baseQueueOptions(config.redisForDeliverQueue, config.bullmqQueueOptions, QUEUE.DELIVER)),
inject: [DI.config],
};
const $inbox: Provider = {
provide: 'queue:inbox',
- useFactory: (config: Config) => new Bull.Queue(QUEUE.INBOX, baseQueueOptions(config, QUEUE.INBOX)),
+ useFactory: (config: Config) => new Bull.Queue(QUEUE.INBOX, baseQueueOptions(config.redisForInboxQueue, config.bullmqQueueOptions, QUEUE.INBOX)),
inject: [DI.config],
};
const $db: Provider = {
provide: 'queue:db',
- useFactory: (config: Config) => new Bull.Queue(QUEUE.DB, baseQueueOptions(config, QUEUE.DB)),
+ useFactory: (config: Config) => new Bull.Queue(QUEUE.DB, baseQueueOptions(config.redisForDbQueue, config.bullmqQueueOptions, QUEUE.DB)),
inject: [DI.config],
};
const $relationship: Provider = {
provide: 'queue:relationship',
- useFactory: (config: Config) => new Bull.Queue(QUEUE.RELATIONSHIP, baseQueueOptions(config, QUEUE.RELATIONSHIP)),
+ useFactory: (config: Config) => new Bull.Queue(QUEUE.RELATIONSHIP, baseQueueOptions(config.redisForRelationshipQueue, config.bullmqQueueOptions, QUEUE.RELATIONSHIP)),
inject: [DI.config],
};
const $objectStorage: Provider = {
provide: 'queue:objectStorage',
- useFactory: (config: Config) => new Bull.Queue(QUEUE.OBJECT_STORAGE, baseQueueOptions(config, QUEUE.OBJECT_STORAGE)),
+ useFactory: (config: Config) => new Bull.Queue(QUEUE.OBJECT_STORAGE, baseQueueOptions(config.redisForObjectStorageQueue, config.bullmqQueueOptions, QUEUE.OBJECT_STORAGE)),
inject: [DI.config],
};
const $webhookDeliver: Provider = {
provide: 'queue:webhookDeliver',
- useFactory: (config: Config) => new Bull.Queue(QUEUE.WEBHOOK_DELIVER, baseQueueOptions(config, QUEUE.WEBHOOK_DELIVER)),
+ useFactory: (config: Config) => new Bull.Queue(QUEUE.WEBHOOK_DELIVER, baseQueueOptions(config.redisForWebhookDeliverQueue, config.bullmqQueueOptions, QUEUE.WEBHOOK_DELIVER)),
inject: [DI.config],
};
@@ -106,14 +106,9 @@ export class QueueModule implements OnApplicationShutdown {
) {}
public async dispose(): Promise {
- if (process.env.NODE_ENV === 'test') {
- // XXX:
- // Shutting down the existing connections causes errors on Jest as
- // Misskey has asynchronous postgres/redis connections that are not
- // awaited.
- // Let's wait for some random time for them to finish.
- await setTimeout(5000);
- }
+ // Wait for all potential queue jobs
+ await allSettled();
+ // And then close all queues
await Promise.all([
this.systemQueue.close(),
this.endedPollNotificationQueue.close(),
diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts
index be378a899..7c92dd402 100644
--- a/packages/backend/src/core/QueueService.ts
+++ b/packages/backend/src/core/QueueService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -7,11 +7,13 @@ import { randomUUID } from 'node:crypto';
import { Inject, Injectable } from '@nestjs/common';
import type { IActivity } from '@/core/activitypub/type.js';
import type { MiDriveFile } from '@/models/DriveFile.js';
+import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js';
import type { MiWebhook, webhookEventTypes } from '@/models/Webhook.js';
import type { Config } from '@/config.js';
import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
import type { Antenna } from '@/server/api/endpoints/i/import-antennas.js';
+import { ApRequestCreator } from '@/core/activitypub/ApRequestService.js';
import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, RelationshipQueue, SystemQueue, WebhookDeliverQueue } from './QueueModule.js';
import type { DbJobData, DeliverJobData, RelationshipJobData, ThinUser } from '../queue/types.js';
import type httpSignature from '@peertube/http-signature';
@@ -74,11 +76,15 @@ export class QueueService {
if (content == null) return null;
if (to == null) return null;
+ const contentBody = JSON.stringify(content);
+ const digest = ApRequestCreator.createDigest(contentBody);
+
const data: DeliverJobData = {
user: {
id: user.id,
},
- content,
+ content: contentBody,
+ digest,
to,
isSharedInbox,
};
@@ -103,6 +109,8 @@ export class QueueService {
@bindThis
public async deliverMany(user: ThinUser, content: IActivity | null, inboxes: Map) {
if (content == null) return null;
+ const contentBody = JSON.stringify(content);
+ const digest = ApRequestCreator.createDigest(contentBody);
const opts = {
attempts: this.config.deliverJobMaxAttempts ?? 12,
@@ -117,10 +125,11 @@ export class QueueService {
name: d[0],
data: {
user,
- content,
+ content: contentBody,
+ digest,
to: d[0],
isSharedInbox: d[1],
- } as DeliverJobData,
+ },
opts,
})));
@@ -128,8 +137,9 @@ export class QueueService {
}
@bindThis
- public inbox(activity: IActivity, signature: httpSignature.IParsedSignature) {
+ public inbox(user: ThinUser | null, activity: IActivity, signature: httpSignature.IParsedSignature) {
const data = {
+ user: user ?? undefined,
activity: activity,
signature,
};
@@ -174,6 +184,16 @@ export class QueueService {
});
}
+ @bindThis
+ public createExportClipsJob(user: ThinUser) {
+ return this.dbQueue.add('exportClips', {
+ user: { id: user.id },
+ }, {
+ removeOnComplete: true,
+ removeOnFail: true,
+ });
+ }
+
@bindThis
public createExportFavoritesJob(user: ThinUser) {
return this.dbQueue.add('exportFavorites', {
@@ -332,16 +352,23 @@ export class QueueService {
}
@bindThis
- public createDeleteAccountJob(user: ThinUser, opts: { soft?: boolean; } = {}) {
+ public createDeleteAccountJob(user: ThinUser, opts: { soft?: boolean, force?: boolean, onlyFiles?: boolean } = {}) {
return this.dbQueue.add('deleteAccount', {
user: { id: user.id },
soft: opts.soft,
+ force: opts.force,
+ onlyFiles: opts.onlyFiles,
}, {
removeOnComplete: true,
removeOnFail: true,
});
}
+ @bindThis
+ public createReportAbuseJob(report: MiAbuseUserReport) {
+ return this.dbQueue.add('reportAbuse', report);
+ }
+
@bindThis
public createFollowJob(followings: { from: ThinUser, to: ThinUser, requestId?: string, silent?: boolean, withReplies?: boolean }[]) {
const jobs = followings.map(rel => this.generateRelationshipJobData('follow', rel));
diff --git a/packages/backend/src/core/ReactionService.ts b/packages/backend/src/core/ReactionService.ts
index 13fa3f8f3..e4aa0b983 100644
--- a/packages/backend/src/core/ReactionService.ts
+++ b/packages/backend/src/core/ReactionService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -28,13 +28,14 @@ import { UserBlockingService } from '@/core/UserBlockingService.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { RoleService } from '@/core/RoleService.js';
import { FeaturedService } from '@/core/FeaturedService.js';
+import { trackPromise } from '@/misc/promise-tracker.js';
-const FALLBACK = '❤';
+const FALLBACK = '\u2764';
const PER_NOTE_REACTION_USER_PAIR_CACHE_MAX = 16;
const legacies: Record = {
'like': '👍',
- 'love': '❤', // ここに記述する場合は異体字セレクタを入れない
+ 'love': '\u2764', // ハート、異体字セレクタを入れない
'laugh': '😆',
'hmm': '🤔',
'surprise': '😮',
@@ -107,7 +108,7 @@ export class ReactionService {
if (note.userId !== user.id) {
const blocked = await this.userBlockingService.checkBlocked(note.userId, user.id);
if (blocked) {
- throw new IdentifiableError('e70412a4-7197-4726-8e74-f3e0deb92aa7');
+ throw new IdentifiableError('e70412a4-7197-4726-8e74-f3e0deb92aa7', 'You are blocked by the user.');
}
}
@@ -119,7 +120,7 @@ export class ReactionService {
let reaction = _reaction ?? FALLBACK;
if (note.reactionAcceptance === 'likeOnly' || ((note.reactionAcceptance === 'likeOnlyForRemote' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote') && (user.host != null))) {
- reaction = '❤️';
+ reaction = '\u2764';
} else if (_reaction) {
const custom = reaction.match(isCustomEmojiRegexp);
if (custom) {
@@ -134,11 +135,14 @@ export class ReactionService {
});
if (emoji) {
- if (emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length === 0 || (await this.roleService.getUserRoles(user.id)).some(r => emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.includes(r.id))) {
+ if (
+ (emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length === 0 || (await this.roleService.getUserRoles(user.id)).some(r => emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.includes(r.id))) &&
+ (emoji.roleIdsThatCanNotBeUsedThisEmojiAsReaction.length === 0 || !(await this.roleService.getUserRoles(user.id)).some(r => emoji.roleIdsThatCanNotBeUsedThisEmojiAsReaction.includes(r.id)))
+ ) {
reaction = reacterHost ? `:${name}@${reacterHost}:` : `:${name}:`;
// センシティブ
- if ((note.reactionAcceptance === 'nonSensitiveOnly') && emoji.isSensitive) {
+ if ((note.reactionAcceptance === 'nonSensitiveOnly' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote') && emoji.isSensitive) {
reaction = FALLBACK;
}
} else {
@@ -155,6 +159,7 @@ export class ReactionService {
const record: MiNoteReaction = {
id: this.idService.gen(),
+ createdAt: new Date(),
noteId: note.id,
userId: user.id,
reaction,
@@ -176,7 +181,7 @@ export class ReactionService {
await this.noteReactionsRepository.insert(record);
} else {
// 同じリアクションがすでにされていたらエラー
- throw new IdentifiableError('51c42bb4-931a-456b-bff7-e5a8a70dd298');
+ throw new IdentifiableError('51c42bb4-931a-456b-bff7-e5a8a70dd298', 'You already reacted to this note with the same reaction.');
}
} else {
throw e;
@@ -269,7 +274,7 @@ export class ReactionService {
}
}
- dm.execute();
+ trackPromise(dm.execute());
}
//#endregion
}
@@ -283,14 +288,14 @@ export class ReactionService {
});
if (exist == null) {
- throw new IdentifiableError('60527ec9-b4cb-4a88-a6bd-32d3ad26817d', 'not reacted');
+ throw new IdentifiableError('60527ec9-b4cb-4a88-a6bd-32d3ad26817d', 'You have not reacted to this note.');
}
// Delete reaction
const result = await this.noteReactionsRepository.delete(exist.id);
if (result.affected !== 1) {
- throw new IdentifiableError('60527ec9-b4cb-4a88-a6bd-32d3ad26817d', 'not reacted');
+ throw new IdentifiableError('60527ec9-b4cb-4a88-a6bd-32d3ad26817d', 'You have not reacted to this note.');
}
// Decrement reactions count
@@ -317,40 +322,41 @@ export class ReactionService {
dm.addDirectRecipe(reactee as MiRemoteUser);
}
dm.addFollowersRecipe();
- dm.execute();
+ trackPromise(dm.execute());
}
//#endregion
}
+ /**
+ * 文字列タイプのレガシーな形式のリアクションを現在の形式に変換しつつ、
+ * データベース上には存在する「0個のリアクションがついている」という情報を削除する。
+ */
@bindThis
- public convertLegacyReactions(reactions: Record) {
- const _reactions = {} as Record;
+ public convertLegacyReactions(reactions: MiNote['reactions']): MiNote['reactions'] {
+ return Object.entries(reactions)
+ .filter(([, count]) => {
+ // `ReactionService.prototype.delete`ではリアクション削除時に、
+ // `MiNote['reactions']`のエントリの値をデクリメントしているが、
+ // デクリメントしているだけなのでエントリ自体は0を値として持つ形で残り続ける。
+ // そのため、この処理がなければ、「0個のリアクションがついている」ということになってしまう。
+ return count > 0;
+ })
+ .map(([reaction, count]) => {
+ // unchecked indexed access
+ const convertedReaction = legacies[reaction] as string | undefined;
- for (const reaction of Object.keys(reactions)) {
- if (reactions[reaction] <= 0) continue;
+ const key = this.decodeReaction(convertedReaction ?? reaction).reaction;
- if (Object.keys(legacies).includes(reaction)) {
- if (_reactions[legacies[reaction]]) {
- _reactions[legacies[reaction]] += reactions[reaction];
- } else {
- _reactions[legacies[reaction]] = reactions[reaction];
- }
- } else {
- if (_reactions[reaction]) {
- _reactions[reaction] += reactions[reaction];
- } else {
- _reactions[reaction] = reactions[reaction];
- }
- }
- }
+ return [key, count] as const;
+ })
+ .reduce((acc, [key, count]) => {
+ // unchecked indexed access
+ const prevCount = acc[key] as number | undefined;
- const _reactions2 = {} as Record;
+ acc[key] = (prevCount ?? 0) + count;
- for (const reaction of Object.keys(_reactions)) {
- _reactions2[this.decodeReaction(reaction).reaction] = _reactions[reaction];
- }
-
- return _reactions2;
+ return acc;
+ }, {});
}
@bindThis
diff --git a/packages/backend/src/core/RegistryApiService.ts b/packages/backend/src/core/RegistryApiService.ts
index d340c5e48..2c8877d8a 100644
--- a/packages/backend/src/core/RegistryApiService.ts
+++ b/packages/backend/src/core/RegistryApiService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/RelayService.ts b/packages/backend/src/core/RelayService.ts
index d40cd080c..e9dc9b57a 100644
--- a/packages/backend/src/core/RelayService.ts
+++ b/packages/backend/src/core/RelayService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/RemoteLoggerService.ts b/packages/backend/src/core/RemoteLoggerService.ts
index 5d13988ed..413b03bb5 100644
--- a/packages/backend/src/core/RemoteLoggerService.ts
+++ b/packages/backend/src/core/RemoteLoggerService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/RemoteUserResolveService.ts b/packages/backend/src/core/RemoteUserResolveService.ts
index 75c5f14aa..38f45a03a 100644
--- a/packages/backend/src/core/RemoteUserResolveService.ts
+++ b/packages/backend/src/core/RemoteUserResolveService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -74,7 +74,7 @@ export class RemoteUserResolveService {
if (user == null) {
const self = await this.resolveSelf(acctLower);
- if (self.href.startsWith(this.config.url)) {
+ if (new URL(self.href).origin === this.config.url) {
const local = this.apDbResolverService.parseUri(self.href);
if (local.local && local.type === 'users') {
// the LR points to local
@@ -145,7 +145,7 @@ export class RemoteUserResolveService {
private async resolveSelf(acctLower: string): Promise {
this.logger.info(`WebFinger for ${chalk.yellow(acctLower)}`);
const finger = await this.webfingerService.webfinger(acctLower).catch(err => {
- this.logger.error(`Failed to WebFinger for ${chalk.yellow(acctLower)}: ${ err.statusCode ?? err.message }`);
+ this.logger.error(`Failed to WebFinger for ${chalk.yellow(acctLower)}: ${ err.statusCode ?? err.message }`, { error: err });
throw new Error(`Failed to WebFinger for ${acctLower}: ${ err.statusCode ?? err.message }`);
});
const self = finger.links.find(link => link.rel != null && link.rel.toLowerCase() === 'self');
diff --git a/packages/backend/src/core/ReversiService.ts b/packages/backend/src/core/ReversiService.ts
new file mode 100644
index 000000000..bdebe3ed7
--- /dev/null
+++ b/packages/backend/src/core/ReversiService.ts
@@ -0,0 +1,607 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import * as Redis from 'ioredis';
+import { ModuleRef } from '@nestjs/core';
+import * as Reversi from 'misskey-reversi';
+import { LessThan, MoreThan } from 'typeorm';
+import type {
+ MiReversiGame,
+ ReversiGamesRepository,
+} from '@/models/_.js';
+import type { MiUser } from '@/models/User.js';
+import { DI } from '@/di-symbols.js';
+import { bindThis } from '@/decorators.js';
+import { CacheService } from '@/core/CacheService.js';
+import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { IdService } from '@/core/IdService.js';
+import { NotificationService } from '@/core/NotificationService.js';
+import { Serialized } from '@/types.js';
+import { ReversiGameEntityService } from './entities/ReversiGameEntityService.js';
+import type { OnModuleInit } from '@nestjs/common';
+
+const INVITATION_TIMEOUT_MS = 1000 * 20; // 20sec
+
+@Injectable()
+export class ReversiService implements OnModuleInit {
+ private notificationService: NotificationService;
+
+ constructor(
+ private moduleRef: ModuleRef,
+
+ @Inject(DI.redis)
+ private redisClient: Redis.Redis,
+
+ @Inject(DI.reversiGamesRepository)
+ private reversiGamesRepository: ReversiGamesRepository,
+
+ private cacheService: CacheService,
+ private userEntityService: UserEntityService,
+ private globalEventService: GlobalEventService,
+ private reversiGameEntityService: ReversiGameEntityService,
+ private idService: IdService,
+ ) {
+ }
+
+ async onModuleInit() {
+ this.notificationService = this.moduleRef.get(NotificationService.name);
+ }
+
+ @bindThis
+ private async cacheGame(game: MiReversiGame) {
+ await this.redisClient.setex(`reversi:game:cache:${game.id}`, 60 * 60, JSON.stringify(game));
+ }
+
+ @bindThis
+ private async deleteGameCache(gameId: MiReversiGame['id']) {
+ await this.redisClient.del(`reversi:game:cache:${gameId}`);
+ }
+
+ @bindThis
+ private getBakeProps(game: MiReversiGame) {
+ return {
+ startedAt: game.startedAt,
+ endedAt: game.endedAt,
+ // ゲームの途中からユーザーが変わることは無いので
+ //user1Id: game.user1Id,
+ //user2Id: game.user2Id,
+ user1Ready: game.user1Ready,
+ user2Ready: game.user2Ready,
+ black: game.black,
+ isStarted: game.isStarted,
+ isEnded: game.isEnded,
+ winnerId: game.winnerId,
+ surrenderedUserId: game.surrenderedUserId,
+ timeoutUserId: game.timeoutUserId,
+ isLlotheo: game.isLlotheo,
+ canPutEverywhere: game.canPutEverywhere,
+ loopedBoard: game.loopedBoard,
+ timeLimitForEachTurn: game.timeLimitForEachTurn,
+ logs: game.logs,
+ map: game.map,
+ bw: game.bw,
+ crc32: game.crc32,
+ noIrregularRules: game.noIrregularRules,
+ } satisfies Partial;
+ }
+
+ @bindThis
+ public async matchSpecificUser(me: MiUser, targetUser: MiUser, multiple = false): Promise {
+ if (targetUser.id === me.id) {
+ throw new Error('You cannot match yourself.');
+ }
+
+ if (!multiple) {
+ // 既にマッチしている対局が無いか探す(3分以内)
+ const games = await this.reversiGamesRepository.find({
+ where: [
+ { id: MoreThan(this.idService.gen(Date.now() - 1000 * 60 * 3)), user1Id: me.id, user2Id: targetUser.id, isStarted: false },
+ { id: MoreThan(this.idService.gen(Date.now() - 1000 * 60 * 3)), user1Id: targetUser.id, user2Id: me.id, isStarted: false },
+ ],
+ relations: ['user1', 'user2'],
+ order: { id: 'DESC' },
+ });
+ if (games.length > 0) {
+ return games[0];
+ }
+ }
+
+ //#region 相手から既に招待されてないか確認
+ const invitations = await this.redisClient.zrange(
+ `reversi:matchSpecific:${me.id}`,
+ Date.now() - INVITATION_TIMEOUT_MS,
+ '+inf',
+ 'BYSCORE');
+
+ if (invitations.includes(targetUser.id)) {
+ await this.redisClient.zrem(`reversi:matchSpecific:${me.id}`, targetUser.id);
+
+ const game = await this.matched(targetUser.id, me.id, {
+ noIrregularRules: false,
+ });
+
+ return game;
+ }
+ //#endregion
+
+ const redisPipeline = this.redisClient.pipeline();
+ redisPipeline.zadd(`reversi:matchSpecific:${targetUser.id}`, Date.now(), me.id);
+ redisPipeline.expire(`reversi:matchSpecific:${targetUser.id}`, 120, 'NX');
+ await redisPipeline.exec();
+
+ this.globalEventService.publishReversiStream(targetUser.id, 'invited', {
+ user: await this.userEntityService.pack(me, targetUser),
+ });
+
+ return null;
+ }
+
+ @bindThis
+ public async matchAnyUser(me: MiUser, options: { noIrregularRules: boolean }, multiple = false): Promise {
+ if (!multiple) {
+ // 既にマッチしている対局が無いか探す(3分以内)
+ const games = await this.reversiGamesRepository.find({
+ where: [
+ { id: MoreThan(this.idService.gen(Date.now() - 1000 * 60 * 3)), user1Id: me.id, isStarted: false },
+ { id: MoreThan(this.idService.gen(Date.now() - 1000 * 60 * 3)), user2Id: me.id, isStarted: false },
+ ],
+ relations: ['user1', 'user2'],
+ order: { id: 'DESC' },
+ });
+ if (games.length > 0) {
+ return games[0];
+ }
+ }
+
+ //#region まず自分宛ての招待を探す
+ const invitations = await this.redisClient.zrange(
+ `reversi:matchSpecific:${me.id}`,
+ Date.now() - INVITATION_TIMEOUT_MS,
+ '+inf',
+ 'BYSCORE');
+
+ if (invitations.length > 0) {
+ const invitorId = invitations[Math.floor(Math.random() * invitations.length)];
+ await this.redisClient.zrem(`reversi:matchSpecific:${me.id}`, invitorId);
+
+ const game = await this.matched(invitorId, me.id, {
+ noIrregularRules: false,
+ });
+
+ return game;
+ }
+ //#endregion
+
+ const matchings = await this.redisClient.zrange(
+ 'reversi:matchAny',
+ 0,
+ 2, // 自分自身のIDが入っている場合もあるので2つ取得
+ 'REV');
+
+ const items = matchings.filter(id => !id.startsWith(me.id));
+
+ if (items.length > 0) {
+ const [matchedUserId, option] = items[0].split(':');
+
+ await this.redisClient.zrem('reversi:matchAny',
+ me.id,
+ matchedUserId,
+ me.id + ':noIrregularRules',
+ matchedUserId + ':noIrregularRules');
+
+ const game = await this.matched(matchedUserId, me.id, {
+ noIrregularRules: options.noIrregularRules || option === 'noIrregularRules',
+ });
+
+ return game;
+ } else {
+ const redisPipeline = this.redisClient.pipeline();
+ if (options.noIrregularRules) {
+ redisPipeline.zadd('reversi:matchAny', Date.now(), me.id + ':noIrregularRules');
+ } else {
+ redisPipeline.zadd('reversi:matchAny', Date.now(), me.id);
+ }
+ redisPipeline.expire('reversi:matchAny', 15, 'NX');
+ await redisPipeline.exec();
+ return null;
+ }
+ }
+
+ @bindThis
+ public async matchSpecificUserCancel(user: MiUser, targetUserId: MiUser['id']) {
+ await this.redisClient.zrem(`reversi:matchSpecific:${targetUserId}`, user.id);
+ }
+
+ @bindThis
+ public async matchAnyUserCancel(user: MiUser) {
+ await this.redisClient.zrem('reversi:matchAny', user.id, user.id + ':noIrregularRules');
+ }
+
+ @bindThis
+ public async cleanOutdatedGames() {
+ await this.reversiGamesRepository.delete({
+ id: LessThan(this.idService.gen(Date.now() - 1000 * 60 * 10)),
+ isStarted: false,
+ });
+ }
+
+ @bindThis
+ public async gameReady(gameId: MiReversiGame['id'], user: MiUser, ready: boolean) {
+ const game = await this.get(gameId);
+ if (game == null) throw new Error('game not found');
+ if (game.isStarted) return;
+
+ let isBothReady = false;
+
+ if (game.user1Id === user.id) {
+ const updatedGame = {
+ ...game,
+ user1Ready: ready,
+ };
+ this.cacheGame(updatedGame);
+
+ this.globalEventService.publishReversiGameStream(game.id, 'changeReadyStates', {
+ user1: ready,
+ user2: updatedGame.user2Ready,
+ });
+
+ if (ready && updatedGame.user2Ready) isBothReady = true;
+ } else if (game.user2Id === user.id) {
+ const updatedGame = {
+ ...game,
+ user2Ready: ready,
+ };
+ this.cacheGame(updatedGame);
+
+ this.globalEventService.publishReversiGameStream(game.id, 'changeReadyStates', {
+ user1: updatedGame.user1Ready,
+ user2: ready,
+ });
+
+ if (ready && updatedGame.user1Ready) isBothReady = true;
+ } else {
+ return;
+ }
+
+ if (isBothReady) {
+ // 3秒後、両者readyならゲーム開始
+ setTimeout(async () => {
+ const freshGame = await this.get(game.id);
+ if (freshGame == null || freshGame.isStarted || freshGame.isEnded) return;
+ if (!freshGame.user1Ready || !freshGame.user2Ready) return;
+
+ this.startGame(freshGame);
+ }, 3000);
+ }
+ }
+
+ @bindThis
+ private async matched(parentId: MiUser['id'], childId: MiUser['id'], options: { noIrregularRules: boolean; }): Promise {
+ const game = await this.reversiGamesRepository.insert({
+ id: this.idService.gen(),
+ user1Id: parentId,
+ user2Id: childId,
+ user1Ready: false,
+ user2Ready: false,
+ isStarted: false,
+ isEnded: false,
+ logs: [],
+ map: Reversi.maps.eighteight.data,
+ bw: 'random',
+ isLlotheo: false,
+ noIrregularRules: options.noIrregularRules,
+ }).then(x => this.reversiGamesRepository.findOneOrFail({
+ where: { id: x.identifiers[0].id },
+ relations: ['user1', 'user2'],
+ }));
+ this.cacheGame(game);
+
+ const packed = await this.reversiGameEntityService.packDetail(game, null);
+ this.globalEventService.publishReversiStream(parentId, 'matched', { game: packed });
+
+ return game;
+ }
+
+ @bindThis
+ private async startGame(game: MiReversiGame) {
+ let bw: number;
+ if (game.bw === 'random') {
+ bw = Math.random() > 0.5 ? 1 : 2;
+ } else {
+ bw = parseInt(game.bw, 10);
+ }
+
+ const engine = new Reversi.Game(game.map, {
+ isLlotheo: game.isLlotheo,
+ canPutEverywhere: game.canPutEverywhere,
+ loopedBoard: game.loopedBoard,
+ });
+
+ const crc32 = engine.calcCrc32().toString();
+
+ const updatedGame = await this.reversiGamesRepository.createQueryBuilder().update()
+ .set({
+ ...this.getBakeProps(game),
+ startedAt: new Date(),
+ isStarted: true,
+ black: bw,
+ map: game.map,
+ crc32,
+ })
+ .where('id = :id', { id: game.id })
+ .returning('*')
+ .execute()
+ .then((response) => response.raw[0]);
+ // キャッシュ効率化のためにユーザー情報は再利用
+ updatedGame.user1 = game.user1;
+ updatedGame.user2 = game.user2;
+ this.cacheGame(updatedGame);
+
+ //#region 盤面に最初から石がないなどして始まった瞬間に勝敗が決定する場合があるのでその処理
+ if (engine.isEnded) {
+ let winnerId;
+ if (engine.winner === true) {
+ winnerId = bw === 1 ? updatedGame.user1Id : updatedGame.user2Id;
+ } else if (engine.winner === false) {
+ winnerId = bw === 1 ? updatedGame.user2Id : updatedGame.user1Id;
+ } else {
+ winnerId = null;
+ }
+
+ await this.endGame(updatedGame, winnerId, null);
+
+ return;
+ }
+ //#endregion
+
+ this.redisClient.setex(`reversi:game:turnTimer:${game.id}:1`, updatedGame.timeLimitForEachTurn, '');
+
+ this.globalEventService.publishReversiGameStream(game.id, 'started', {
+ game: await this.reversiGameEntityService.packDetail(updatedGame, null),
+ });
+ }
+
+ @bindThis
+ private async endGame(game: MiReversiGame, winnerId: MiUser['id'] | null, reason: 'surrender' | 'timeout' | null) {
+ const updatedGame = await this.reversiGamesRepository.createQueryBuilder().update()
+ .set({
+ ...this.getBakeProps(game),
+ isEnded: true,
+ endedAt: new Date(),
+ winnerId: winnerId,
+ surrenderedUserId: reason === 'surrender' ? (winnerId === game.user1Id ? game.user2Id : game.user1Id) : null,
+ timeoutUserId: reason === 'timeout' ? (winnerId === game.user1Id ? game.user2Id : game.user1Id) : null,
+ })
+ .where('id = :id', { id: game.id })
+ .returning('*')
+ .execute()
+ .then((response) => response.raw[0]);
+ // キャッシュ効率化のためにユーザー情報は再利用
+ updatedGame.user1 = game.user1;
+ updatedGame.user2 = game.user2;
+ this.cacheGame(updatedGame);
+
+ this.globalEventService.publishReversiGameStream(game.id, 'ended', {
+ winnerId: winnerId,
+ game: await this.reversiGameEntityService.packDetail(updatedGame, null),
+ });
+ }
+
+ @bindThis
+ public async getInvitations(user: MiUser): Promise {
+ const invitations = await this.redisClient.zrange(
+ `reversi:matchSpecific:${user.id}`,
+ Date.now() - INVITATION_TIMEOUT_MS,
+ '+inf',
+ 'BYSCORE');
+ return invitations;
+ }
+
+ @bindThis
+ public async updateSettings(gameId: MiReversiGame['id'], user: MiUser, key: string, value: any) {
+ const game = await this.get(gameId);
+ if (game == null) throw new Error('game not found');
+ if (game.isStarted) return;
+ if ((game.user1Id !== user.id) && (game.user2Id !== user.id)) return;
+ if ((game.user1Id === user.id) && game.user1Ready) return;
+ if ((game.user2Id === user.id) && game.user2Ready) return;
+
+ if (!['map', 'bw', 'isLlotheo', 'canPutEverywhere', 'loopedBoard', 'timeLimitForEachTurn'].includes(key)) return;
+
+ // TODO: より厳格なバリデーション
+
+ const updatedGame = {
+ ...game,
+ [key]: value,
+ };
+ this.cacheGame(updatedGame);
+
+ this.globalEventService.publishReversiGameStream(game.id, 'updateSettings', {
+ userId: user.id,
+ key: key,
+ value: value,
+ });
+ }
+
+ @bindThis
+ public async putStoneToGame(gameId: MiReversiGame['id'], user: MiUser, pos: number, id?: string | null) {
+ const game = await this.get(gameId);
+ if (game == null) throw new Error('game not found');
+ if (!game.isStarted) return;
+ if (game.isEnded) return;
+ if ((game.user1Id !== user.id) && (game.user2Id !== user.id)) return;
+
+ const myColor =
+ ((game.user1Id === user.id) && game.black === 1) || ((game.user2Id === user.id) && game.black === 2)
+ ? true
+ : false;
+
+ const engine = Reversi.Serializer.restoreGame({
+ map: game.map,
+ isLlotheo: game.isLlotheo,
+ canPutEverywhere: game.canPutEverywhere,
+ loopedBoard: game.loopedBoard,
+ logs: game.logs,
+ });
+
+ if (engine.turn !== myColor) return;
+ if (!engine.canPut(myColor, pos)) return;
+
+ engine.putStone(pos);
+
+ const logs = Reversi.Serializer.deserializeLogs(game.logs);
+
+ const log = {
+ time: Date.now(),
+ player: myColor,
+ operation: 'put',
+ pos,
+ } as const;
+
+ logs.push(log);
+
+ const serializeLogs = Reversi.Serializer.serializeLogs(logs);
+
+ const crc32 = engine.calcCrc32().toString();
+
+ const updatedGame = {
+ ...game,
+ crc32,
+ logs: serializeLogs,
+ };
+ this.cacheGame(updatedGame);
+
+ this.globalEventService.publishReversiGameStream(game.id, 'log', {
+ ...log,
+ id: id ?? null,
+ });
+
+ if (engine.isEnded) {
+ let winnerId;
+ if (engine.winner === true) {
+ winnerId = game.black === 1 ? game.user1Id : game.user2Id;
+ } else if (engine.winner === false) {
+ winnerId = game.black === 1 ? game.user2Id : game.user1Id;
+ } else {
+ winnerId = null;
+ }
+
+ await this.endGame(updatedGame, winnerId, null);
+ } else {
+ this.redisClient.setex(`reversi:game:turnTimer:${game.id}:${engine.turn ? '1' : '0'}`, updatedGame.timeLimitForEachTurn, '');
+ }
+ }
+
+ @bindThis
+ public async surrender(gameId: MiReversiGame['id'], user: MiUser) {
+ const game = await this.get(gameId);
+ if (game == null) throw new Error('game not found');
+ if (game.isEnded) return;
+ if ((game.user1Id !== user.id) && (game.user2Id !== user.id)) return;
+
+ const winnerId = game.user1Id === user.id ? game.user2Id : game.user1Id;
+
+ await this.endGame(game, winnerId, 'surrender');
+ }
+
+ @bindThis
+ public async checkTimeout(gameId: MiReversiGame['id']) {
+ const game = await this.get(gameId);
+ if (game == null) throw new Error('game not found');
+ if (game.isEnded) return;
+
+ const engine = Reversi.Serializer.restoreGame({
+ map: game.map,
+ isLlotheo: game.isLlotheo,
+ canPutEverywhere: game.canPutEverywhere,
+ loopedBoard: game.loopedBoard,
+ logs: game.logs,
+ });
+
+ if (engine.turn == null) return;
+
+ const timer = await this.redisClient.exists(`reversi:game:turnTimer:${game.id}:${engine.turn ? '1' : '0'}`);
+
+ if (timer === 0) {
+ const winnerId = engine.turn ? (game.black === 1 ? game.user2Id : game.user1Id) : (game.black === 1 ? game.user1Id : game.user2Id);
+
+ await this.endGame(game, winnerId, 'timeout');
+ }
+ }
+
+ @bindThis
+ public async cancelGame(gameId: MiReversiGame['id'], user: MiUser) {
+ const game = await this.get(gameId);
+ if (game == null) throw new Error('game not found');
+ if (game.isStarted) return;
+ if ((game.user1Id !== user.id) && (game.user2Id !== user.id)) return;
+
+ await this.reversiGamesRepository.delete(game.id);
+ this.deleteGameCache(game.id);
+
+ this.globalEventService.publishReversiGameStream(game.id, 'canceled', {
+ userId: user.id,
+ });
+ }
+
+ @bindThis
+ public async get(id: MiReversiGame['id']): Promise {
+ const cached = await this.redisClient.get(`reversi:game:cache:${id}`);
+ if (cached != null) {
+ // TODO: この辺りのデシリアライズ処理をどこか別のサービスに切り出したい
+ const parsed = JSON.parse(cached) as Serialized;
+ return {
+ ...parsed,
+ createdAt: new Date(parsed.createdAt),
+ startedAt: parsed.startedAt != null ? new Date(parsed.startedAt) : null,
+ endedAt: parsed.endedAt != null ? new Date(parsed.endedAt) : null,
+ user1: parsed.user1 != null ? {
+ ...parsed.user1,
+ avatar: null,
+ banner: null,
+ createdAt: new Date(parsed.user1.createdAt),
+ updatedAt: parsed.user1.updatedAt != null ? new Date(parsed.user1.updatedAt) : null,
+ lastActiveDate: parsed.user1.lastActiveDate != null ? new Date(parsed.user1.lastActiveDate) : null,
+ lastFetchedAt: parsed.user1.lastFetchedAt != null ? new Date(parsed.user1.lastFetchedAt) : null,
+ movedAt: parsed.user1.movedAt != null ? new Date(parsed.user1.movedAt) : null,
+ } : null,
+ user2: parsed.user2 != null ? {
+ ...parsed.user2,
+ avatar: null,
+ banner: null,
+ createdAt: new Date(parsed.user2.createdAt),
+ updatedAt: parsed.user2.updatedAt != null ? new Date(parsed.user2.updatedAt) : null,
+ lastActiveDate: parsed.user2.lastActiveDate != null ? new Date(parsed.user2.lastActiveDate) : null,
+ lastFetchedAt: parsed.user2.lastFetchedAt != null ? new Date(parsed.user2.lastFetchedAt) : null,
+ movedAt: parsed.user2.movedAt != null ? new Date(parsed.user2.movedAt) : null,
+ } : null,
+ };
+ } else {
+ const game = await this.reversiGamesRepository.findOne({
+ where: { id },
+ relations: ['user1', 'user2'],
+ });
+ if (game == null) return null;
+
+ this.cacheGame(game);
+
+ return game;
+ }
+ }
+
+ @bindThis
+ public async checkCrc(gameId: MiReversiGame['id'], crc32: string | number) {
+ const game = await this.get(gameId);
+ if (game == null) throw new Error('game not found');
+
+ if (crc32.toString() !== game.crc32) {
+ return game;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts
index 432887b3b..7607c711a 100644
--- a/packages/backend/src/core/RoleService.ts
+++ b/packages/backend/src/core/RoleService.ts
@@ -1,13 +1,21 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis';
import { In } from 'typeorm';
-import type { MiRole, MiRoleAssignment, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/_.js';
+import { ModuleRef } from '@nestjs/core';
+import type {
+ MiRole,
+ MiRoleAssignment,
+ RoleAssignmentsRepository,
+ RolesRepository,
+ UsersRepository,
+} from '@/models/_.js';
import { MemoryKVCache, MemorySingleCache } from '@/misc/cache.js';
+import { IdentifiableError } from '@/misc/identifiable-error.js';
import type { MiUser } from '@/models/User.js';
import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js';
@@ -16,17 +24,26 @@ import { CacheService } from '@/core/CacheService.js';
import type { RoleCondFormulaValue } from '@/models/Role.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js';
-import { IdService } from '@/core/IdService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { IdService } from '@/core/IdService.js';
import { ModerationLogService } from '@/core/ModerationLogService.js';
import type { Packed } from '@/misc/json-schema.js';
-import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
-import type { OnApplicationShutdown } from '@nestjs/common';
+import { FanoutTimelineService } from '@/core/FanoutTimelineService.js';
+import { NotificationService } from '@/core/NotificationService.js';
+import type { OnApplicationShutdown, OnModuleInit } from '@nestjs/common';
export type RolePolicies = {
gtlAvailable: boolean;
ltlAvailable: boolean;
canPublicNote: boolean;
+ canInitiateConversation: boolean;
+ canCreateContent: boolean;
+ canUpdateContent: boolean;
+ canDeleteContent: boolean;
+ canPurgeAccount: boolean;
+ canUpdateAvatar: boolean;
+ canUpdateBanner: boolean;
+ mentionLimit: number;
canInvite: boolean;
inviteLimit: number;
inviteLimitCycle: number;
@@ -35,11 +52,14 @@ export type RolePolicies = {
canManageAvatarDecorations: boolean;
canSearchNotes: boolean;
canUseTranslator: boolean;
+ canUseDriveFileInSoundSettings: boolean;
canHideAds: boolean;
driveCapacityMb: number;
alwaysMarkNsfw: boolean;
+ skipNsfwDetection: boolean;
pinLimit: number;
antennaLimit: number;
+ antennaNotesLimit: number;
wordMuteLimit: number;
webhookLimit: number;
clipLimit: number;
@@ -47,12 +67,21 @@ export type RolePolicies = {
userListLimit: number;
userEachUserListsLimit: number;
rateLimitFactor: number;
+ avatarDecorationLimit: number;
};
export const DEFAULT_POLICIES: RolePolicies = {
gtlAvailable: true,
ltlAvailable: true,
canPublicNote: true,
+ canInitiateConversation: true,
+ canCreateContent: true,
+ canUpdateContent: true,
+ canDeleteContent: true,
+ canPurgeAccount: true,
+ canUpdateAvatar: true,
+ canUpdateBanner: true,
+ mentionLimit: 20,
canInvite: false,
inviteLimit: 0,
inviteLimitCycle: 60 * 24 * 7,
@@ -61,11 +90,14 @@ export const DEFAULT_POLICIES: RolePolicies = {
canManageAvatarDecorations: false,
canSearchNotes: false,
canUseTranslator: true,
+ canUseDriveFileInSoundSettings: false,
canHideAds: false,
driveCapacityMb: 100,
alwaysMarkNsfw: false,
+ skipNsfwDetection: false,
pinLimit: 5,
antennaLimit: 5,
+ antennaNotesLimit: 200,
wordMuteLimit: 200,
webhookLimit: 3,
clipLimit: 10,
@@ -73,17 +105,18 @@ export const DEFAULT_POLICIES: RolePolicies = {
userListLimit: 10,
userEachUserListsLimit: 50,
rateLimitFactor: 1,
+ avatarDecorationLimit: 1,
};
@Injectable()
-export class RoleService implements OnApplicationShutdown {
+export class RoleService implements OnApplicationShutdown, OnModuleInit {
private rolesCache: MemorySingleCache;
private roleAssignmentByUserIdCache: MemoryKVCache;
-
- public static AlreadyAssignedError = class extends Error {};
- public static NotAssignedError = class extends Error {};
+ private notificationService: NotificationService;
constructor(
+ private moduleRef: ModuleRef,
+
@Inject(DI.redis)
private redisClient: Redis.Redis,
@@ -108,7 +141,7 @@ export class RoleService implements OnApplicationShutdown {
private globalEventService: GlobalEventService,
private idService: IdService,
private moderationLogService: ModerationLogService,
- private funoutTimelineService: FunoutTimelineService,
+ private fanoutTimelineService: FanoutTimelineService,
) {
//this.onMessage = this.onMessage.bind(this);
@@ -118,6 +151,10 @@ export class RoleService implements OnApplicationShutdown {
this.redisForSub.on('message', this.onMessage);
}
+ async onModuleInit() {
+ this.notificationService = this.moduleRef.get(NotificationService.name);
+ }
+
@bindThis
private async onMessage(_: string, data: string): Promise {
const obj = JSON.parse(data);
@@ -130,6 +167,7 @@ export class RoleService implements OnApplicationShutdown {
if (cached) {
cached.push({
...body,
+ createdAt: new Date(body.createdAt),
updatedAt: new Date(body.updatedAt),
lastUsedAt: new Date(body.lastUsedAt),
});
@@ -143,6 +181,7 @@ export class RoleService implements OnApplicationShutdown {
if (i > -1) {
cached[i] = {
...body,
+ createdAt: new Date(body.createdAt),
updatedAt: new Date(body.updatedAt),
lastUsedAt: new Date(body.lastUsedAt),
};
@@ -160,9 +199,12 @@ export class RoleService implements OnApplicationShutdown {
case 'userRoleAssigned': {
const cached = this.roleAssignmentByUserIdCache.get(body.userId);
if (cached) {
- cached.push({
+ cached.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい
...body,
+ createdAt: new Date(body.createdAt),
expiresAt: body.expiresAt ? new Date(body.expiresAt) : null,
+ user: null, // joinなカラムは通常取ってこないので
+ role: null, // joinなカラムは通常取ってこないので
});
}
break;
@@ -181,17 +223,20 @@ export class RoleService implements OnApplicationShutdown {
}
@bindThis
- private evalCond(user: MiUser, value: RoleCondFormulaValue): boolean {
+ private evalCond(user: MiUser, roles: MiRole[], value: RoleCondFormulaValue): boolean {
try {
switch (value.type) {
case 'and': {
- return value.values.every(v => this.evalCond(user, v));
+ return value.values.every(v => this.evalCond(user, roles, v));
}
case 'or': {
- return value.values.some(v => this.evalCond(user, v));
+ return value.values.some(v => this.evalCond(user, roles, v));
}
case 'not': {
- return !this.evalCond(user, value.value);
+ return !this.evalCond(user, roles, value.value);
+ }
+ case 'roleAssignedTo': {
+ return roles.some(r => r.id === value.roleId);
}
case 'isLocal': {
return this.userEntityService.isLocalUser(user);
@@ -253,7 +298,7 @@ export class RoleService implements OnApplicationShutdown {
const assigns = await this.getUserAssigns(userId);
const assignedRoles = roles.filter(r => assigns.map(x => x.roleId).includes(r.id));
const user = roles.some(r => r.target === 'conditional') ? await this.cacheService.findUserById(userId) : null;
- const matchedCondRoles = roles.filter(r => r.target === 'conditional' && this.evalCond(user!, r.condFormula));
+ const matchedCondRoles = roles.filter(r => r.target === 'conditional' && this.evalCond(user!, assignedRoles, r.condFormula));
return [...assignedRoles, ...matchedCondRoles];
}
@@ -266,13 +311,13 @@ export class RoleService implements OnApplicationShutdown {
let assigns = await this.roleAssignmentByUserIdCache.fetch(userId, () => this.roleAssignmentsRepository.findBy({ userId }));
// 期限切れのロールを除外
assigns = assigns.filter(a => a.expiresAt == null || (a.expiresAt.getTime() > now));
- const assignedRoleIds = assigns.map(x => x.roleId);
const roles = await this.rolesCache.fetch(() => this.rolesRepository.findBy({}));
- const assignedBadgeRoles = roles.filter(r => r.asBadge && assignedRoleIds.includes(r.id));
+ const assignedRoles = roles.filter(r => assigns.map(x => x.roleId).includes(r.id));
+ const assignedBadgeRoles = assignedRoles.filter(r => r.asBadge);
const badgeCondRoles = roles.filter(r => r.asBadge && (r.target === 'conditional'));
if (badgeCondRoles.length > 0) {
const user = roles.some(r => r.target === 'conditional') ? await this.cacheService.findUserById(userId) : null;
- const matchedBadgeCondRoles = badgeCondRoles.filter(r => this.evalCond(user!, r.condFormula));
+ const matchedBadgeCondRoles = badgeCondRoles.filter(r => this.evalCond(user!, assignedRoles, r.condFormula));
return [...assignedBadgeRoles, ...matchedBadgeCondRoles];
} else {
return assignedBadgeRoles;
@@ -306,6 +351,14 @@ export class RoleService implements OnApplicationShutdown {
gtlAvailable: calc('gtlAvailable', vs => vs.some(v => v === true)),
ltlAvailable: calc('ltlAvailable', vs => vs.some(v => v === true)),
canPublicNote: calc('canPublicNote', vs => vs.some(v => v === true)),
+ canInitiateConversation: calc('canInitiateConversation', vs => vs.some(v => v === true)),
+ canCreateContent: calc('canCreateContent', vs => vs.some(v => v === true)),
+ canUpdateContent: calc('canUpdateContent', vs => vs.some(v => v === true)),
+ canDeleteContent: calc('canDeleteContent', vs => vs.some(v => v === true)),
+ canPurgeAccount: calc('canPurgeAccount', vs => vs.some(v => v === true)),
+ canUpdateAvatar: calc('canUpdateAvatar', vs => vs.some(v => v === true)),
+ canUpdateBanner: calc('canUpdateBanner', vs => vs.some(v => v === true)),
+ mentionLimit: calc('mentionLimit', vs => Math.max(...vs)),
canInvite: calc('canInvite', vs => vs.some(v => v === true)),
inviteLimit: calc('inviteLimit', vs => Math.max(...vs)),
inviteLimitCycle: calc('inviteLimitCycle', vs => Math.max(...vs)),
@@ -314,11 +367,14 @@ export class RoleService implements OnApplicationShutdown {
canManageAvatarDecorations: calc('canManageAvatarDecorations', vs => vs.some(v => v === true)),
canSearchNotes: calc('canSearchNotes', vs => vs.some(v => v === true)),
canUseTranslator: calc('canUseTranslator', vs => vs.some(v => v === true)),
+ canUseDriveFileInSoundSettings: calc('canUseDriveFileInSoundSettings', vs => vs.some(v => v === true)),
canHideAds: calc('canHideAds', vs => vs.some(v => v === true)),
driveCapacityMb: calc('driveCapacityMb', vs => Math.max(...vs)),
alwaysMarkNsfw: calc('alwaysMarkNsfw', vs => vs.some(v => v === true)),
+ skipNsfwDetection: calc('skipNsfwDetection', vs => vs.some(v => v === true)),
pinLimit: calc('pinLimit', vs => Math.max(...vs)),
antennaLimit: calc('antennaLimit', vs => Math.max(...vs)),
+ antennaNotesLimit: calc('antennaNotesLimit', vs => Math.max(...vs)),
wordMuteLimit: calc('wordMuteLimit', vs => Math.max(...vs)),
webhookLimit: calc('webhookLimit', vs => Math.max(...vs)),
clipLimit: calc('clipLimit', vs => Math.max(...vs)),
@@ -326,6 +382,7 @@ export class RoleService implements OnApplicationShutdown {
userListLimit: calc('userListLimit', vs => Math.max(...vs)),
userEachUserListsLimit: calc('userEachUserListsLimit', vs => Math.max(...vs)),
rateLimitFactor: calc('rateLimitFactor', vs => Math.max(...vs)),
+ avatarDecorationLimit: calc('avatarDecorationLimit', vs => Math.max(...vs)),
};
}
@@ -395,35 +452,46 @@ export class RoleService implements OnApplicationShutdown {
const role = await this.rolesRepository.findOneByOrFail({ id: roleId });
- const existing = await this.roleAssignmentsRepository.findOneBy({
+ let existing = await this.roleAssignmentsRepository.findOneBy({
roleId: roleId,
userId: userId,
});
- if (existing) {
- if (existing.expiresAt && (existing.expiresAt.getTime() < now)) {
- await this.roleAssignmentsRepository.delete({
- roleId: roleId,
- userId: userId,
- });
- } else {
- throw new RoleService.AlreadyAssignedError();
- }
+ if (existing?.expiresAt && (existing.expiresAt.getTime() < now)) {
+ await this.roleAssignmentsRepository.delete({
+ roleId: roleId,
+ userId: userId,
+ });
+ existing = null;
}
- const created = await this.roleAssignmentsRepository.insert({
- id: this.idService.gen(now),
- expiresAt: expiresAt,
- roleId: roleId,
- userId: userId,
- }).then(x => this.roleAssignmentsRepository.findOneByOrFail(x.identifiers[0]));
+ if (!existing) {
+ const created = await this.roleAssignmentsRepository.insert({
+ id: this.idService.gen(now),
+ expiresAt: expiresAt,
+ roleId: roleId,
+ userId: userId,
+ }).then(x => this.roleAssignmentsRepository.findOneByOrFail(x.identifiers[0]));
+
+ this.globalEventService.publishInternalEvent('userRoleAssigned', created);
+
+ if (role.isPublic) {
+ this.notificationService.createNotification(userId, 'roleAssigned', {
+ roleId: roleId,
+ });
+ }
+ } else if (existing.expiresAt !== expiresAt) {
+ await this.roleAssignmentsRepository.update(existing.id, {
+ expiresAt: expiresAt,
+ });
+ } else {
+ throw new IdentifiableError('67d8689c-25c6-435f-8ced-631e4b81fce1', 'User is already assigned to this role.');
+ }
this.rolesRepository.update(roleId, {
lastUsedAt: new Date(),
});
- this.globalEventService.publishInternalEvent('userRoleAssigned', created);
-
if (moderator) {
const user = await this.usersRepository.findOneByOrFail({ id: userId });
this.moderationLogService.log(moderator, 'assignRole', {
@@ -441,15 +509,17 @@ export class RoleService implements OnApplicationShutdown {
public async unassign(userId: MiUser['id'], roleId: MiRole['id'], moderator?: MiUser): Promise {
const now = new Date();
- const existing = await this.roleAssignmentsRepository.findOneBy({ roleId, userId });
- if (existing == null) {
- throw new RoleService.NotAssignedError();
- } else if (existing.expiresAt && (existing.expiresAt.getTime() < now.getTime())) {
+ let existing = await this.roleAssignmentsRepository.findOneBy({ roleId, userId });
+ if (existing?.expiresAt && (existing.expiresAt.getTime() < now.getTime())) {
await this.roleAssignmentsRepository.delete({
roleId: roleId,
userId: userId,
});
- throw new RoleService.NotAssignedError();
+ existing = null;
+ }
+
+ if (!existing) {
+ throw new IdentifiableError('b9060ac7-5c94-4da4-9f55-2047c953df44', 'User was not assigned to this role.');
}
await this.roleAssignmentsRepository.delete(existing.id);
@@ -482,7 +552,7 @@ export class RoleService implements OnApplicationShutdown {
const redisPipeline = this.redisForTimelines.pipeline();
for (const role of roles) {
- this.funoutTimelineService.push(`roleTimeline:${role.id}`, note.id, 1000, redisPipeline);
+ this.fanoutTimelineService.push(`roleTimeline:${role.id}`, note.id, 1000, redisPipeline);
this.globalEventService.publishRoleTimelineStream(role.id, 'note', note);
}
diff --git a/packages/backend/src/core/S3Service.ts b/packages/backend/src/core/S3Service.ts
index 0a2037733..025f01e10 100644
--- a/packages/backend/src/core/S3Service.ts
+++ b/packages/backend/src/core/S3Service.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -10,10 +10,10 @@ import { Inject, Injectable } from '@nestjs/common';
import { DeleteObjectCommand, S3Client } from '@aws-sdk/client-s3';
import { Upload } from '@aws-sdk/lib-storage';
import { NodeHttpHandler, NodeHttpHandlerOptions } from '@smithy/node-http-handler';
+import { bindThis } from '@/decorators.js';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { HttpRequestService } from '@/core/HttpRequestService.js';
-import { bindThis } from '@/decorators.js';
import type { DeleteObjectCommandInput, PutObjectCommandInput } from '@aws-sdk/client-s3';
@Injectable()
diff --git a/packages/backend/src/core/SearchService.ts b/packages/backend/src/core/SearchService.ts
index b6d2bcabc..2e4329775 100644
--- a/packages/backend/src/core/SearchService.ts
+++ b/packages/backend/src/core/SearchService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -12,6 +12,8 @@ import { MiNote } from '@/models/Note.js';
import { MiUser } from '@/models/_.js';
import type { NotesRepository } from '@/models/_.js';
import { sqlLikeEscape } from '@/misc/sql-like-escape.js';
+import { isUserRelated } from '@/misc/is-user-related.js';
+import { CacheService } from '@/core/CacheService.js';
import { QueryService } from '@/core/QueryService.js';
import { IdService } from '@/core/IdService.js';
import type { Index, MeiliSearch } from 'meilisearch';
@@ -74,12 +76,13 @@ export class SearchService {
@Inject(DI.notesRepository)
private notesRepository: NotesRepository,
+ private cacheService: CacheService,
private queryService: QueryService,
private idService: IdService,
) {
if (meilisearch) {
this.meilisearchNoteIndex = meilisearch.index(`${config.meilisearch!.index}---notes`);
- this.meilisearchNoteIndex.updateSettings({
+ /*this.meilisearchNoteIndex.updateSettings({
searchableAttributes: [
'text',
'cw',
@@ -100,7 +103,7 @@ export class SearchService {
pagination: {
maxTotalHits: 10000,
},
- });
+ });*/
}
if (config.meilisearch?.scope) {
@@ -187,8 +190,19 @@ export class SearchService {
limit: pagination.limit,
});
if (res.hits.length === 0) return [];
- const notes = await this.notesRepository.findBy({
+ const [
+ userIdsWhoMeMuting,
+ userIdsWhoBlockingMe,
+ ] = me ? await Promise.all([
+ this.cacheService.userMutingsCache.fetch(me.id),
+ this.cacheService.userBlockedCache.fetch(me.id),
+ ]) : [new Set(), new Set()];
+ const notes = (await this.notesRepository.findBy({
id: In(res.hits.map(x => x.id)),
+ })).filter(note => {
+ if (me && isUserRelated(note, userIdsWhoBlockingMe)) return false;
+ if (me && isUserRelated(note, userIdsWhoMeMuting)) return false;
+ return true;
});
return notes.sort((a, b) => a.id > b.id ? -1 : 1);
} else {
diff --git a/packages/backend/src/core/SignupService.ts b/packages/backend/src/core/SignupService.ts
index b9e3ded46..72d06c3da 100644
--- a/packages/backend/src/core/SignupService.ts
+++ b/packages/backend/src/core/SignupService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -16,6 +16,7 @@ import { MiUserKeypair } from '@/models/UserKeypair.js';
import { MiUsedUsername } from '@/models/UsedUsername.js';
import generateUserToken from '@/misc/generate-native-user-token.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
+import { InstanceActorService } from '@/core/InstanceActorService.js';
import { bindThis } from '@/decorators.js';
import UsersChart from '@/core/chart/charts/users.js';
import { UtilityService } from '@/core/UtilityService.js';
@@ -37,6 +38,7 @@ export class SignupService {
private userEntityService: UserEntityService,
private idService: IdService,
private metaService: MetaService,
+ private instanceActorService: InstanceActorService,
private usersChart: UsersChart,
) {
}
@@ -72,16 +74,16 @@ export class SignupService {
const secret = generateUserToken();
// Check username duplication
- if (await this.usersRepository.exist({ where: { usernameLower: username.toLowerCase(), host: IsNull() } })) {
+ if (await this.usersRepository.exists({ where: { usernameLower: username.toLowerCase(), host: IsNull() } })) {
throw new Error('DUPLICATED_USERNAME');
}
// Check deleted username duplication
- if (await this.usedUsernamesRepository.exist({ where: { username: username.toLowerCase() } })) {
+ if (await this.usedUsernamesRepository.exists({ where: { username: username.toLowerCase() } })) {
throw new Error('USED_USERNAME');
}
- const isTheFirstUser = (await this.usersRepository.countBy({ host: IsNull() })) === 0;
+ const isTheFirstUser = !await this.instanceActorService.realLocalUsersPresent();
if (!opts.ignorePreservedUsernames && !isTheFirstUser) {
const instance = await this.metaService.fetch(true);
@@ -93,7 +95,7 @@ export class SignupService {
const keyPair = await new Promise((res, rej) =>
generateKeyPair('rsa', {
- modulusLength: 2048,
+ modulusLength: 3072,
publicKeyEncoding: {
type: 'spki',
format: 'pem',
diff --git a/packages/backend/src/core/UserAuthService.ts b/packages/backend/src/core/UserAuthService.ts
index ccf4dfc6b..14f298c51 100644
--- a/packages/backend/src/core/UserAuthService.ts
+++ b/packages/backend/src/core/UserAuthService.ts
@@ -1,16 +1,14 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
-import { QueryFailedError } from 'typeorm';
import * as OTPAuth from 'otpauth';
import { DI } from '@/di-symbols.js';
import type { MiUserProfile, UserProfilesRepository, UsersRepository } from '@/models/_.js';
import { bindThis } from '@/decorators.js';
-import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js';
-import type { MiLocalUser } from '@/models/User.js';
+import { IdentifiableError } from '@/misc/identifiable-error.js';
@Injectable()
export class UserAuthService {
@@ -38,7 +36,7 @@ export class UserAuthService {
});
if (delta === null) {
- throw new Error('authentication failed');
+ throw new IdentifiableError('7d0a7d85-206c-4d16-8cf3-8af92249a082', 'Two-factor authentication failed.');
}
}
}
diff --git a/packages/backend/src/core/UserBlockingService.ts b/packages/backend/src/core/UserBlockingService.ts
index 39b19325c..96f389b54 100644
--- a/packages/backend/src/core/UserBlockingService.ts
+++ b/packages/backend/src/core/UserBlockingService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -109,13 +109,13 @@ export class UserBlockingService implements OnModuleInit {
if (this.userEntityService.isLocalUser(followee)) {
this.userEntityService.pack(followee, followee, {
- detail: true,
+ schema: 'MeDetailed',
}).then(packed => this.globalEventService.publishMainStream(followee.id, 'meUpdated', packed));
}
if (this.userEntityService.isLocalUser(follower) && !silent) {
this.userEntityService.pack(followee, follower, {
- detail: true,
+ schema: 'UserDetailedNotMe',
}).then(async packed => {
this.globalEventService.publishMainStream(follower.id, 'unfollow', packed);
diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts
index bd7f29802..5949c70a5 100644
--- a/packages/backend/src/core/UserFollowingService.ts
+++ b/packages/backend/src/core/UserFollowingService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -13,7 +13,6 @@ import PerUserFollowingChart from '@/core/chart/charts/per-user-following.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { IdService } from '@/core/IdService.js';
import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js';
-import type { Packed } from '@/misc/json-schema.js';
import InstanceChart from '@/core/chart/charts/instance.js';
import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
import { WebhookService } from '@/core/WebhookService.js';
@@ -29,7 +28,8 @@ import { CacheService } from '@/core/CacheService.js';
import type { Config } from '@/config.js';
import { AccountMoveService } from '@/core/AccountMoveService.js';
import { UtilityService } from '@/core/UtilityService.js';
-import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
+import { FanoutTimelineService } from '@/core/FanoutTimelineService.js';
+import type { ThinUser } from '@/queue/types.js';
import Logger from '../logger.js';
const logger = new Logger('following/create');
@@ -84,7 +84,7 @@ export class UserFollowingService implements OnModuleInit {
private webhookService: WebhookService,
private apRendererService: ApRendererService,
private accountMoveService: AccountMoveService,
- private funoutTimelineService: FunoutTimelineService,
+ private fanoutTimelineService: FanoutTimelineService,
private perUserFollowingChart: PerUserFollowingChart,
private instanceChart: InstanceChart,
) {
@@ -94,21 +94,35 @@ export class UserFollowingService implements OnModuleInit {
this.userBlockingService = this.moduleRef.get('UserBlockingService');
}
+ @bindThis
+ public async deliverAccept(follower: MiRemoteUser, followee: MiPartialLocalUser, requestId?: string) {
+ const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee));
+ this.queueService.deliver(followee, content, follower.inbox, false);
+ }
+
@bindThis
public async follow(
- _follower: { id: MiUser['id'] },
- _followee: { id: MiUser['id'] },
+ _follower: ThinUser,
+ _followee: ThinUser,
{ requestId, silent = false, withReplies }: {
requestId?: string,
silent?: boolean,
withReplies?: boolean,
} = {},
): Promise {
+ /**
+ * 必ず最新のユーザー情報を取得する
+ */
const [follower, followee] = await Promise.all([
this.usersRepository.findOneByOrFail({ id: _follower.id }),
this.usersRepository.findOneByOrFail({ id: _followee.id }),
]) as [MiLocalUser | MiRemoteUser, MiLocalUser | MiRemoteUser];
+ if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isRemoteUser(followee)) {
+ // What?
+ throw new Error('Remote user cannot follow remote user.');
+ }
+
// check blocking
const [blocking, blocked] = await Promise.all([
this.userBlockingService.checkBlocked(follower.id, followee.id),
@@ -125,8 +139,26 @@ export class UserFollowingService implements OnModuleInit {
await this.userBlockingService.unblock(follower, followee);
} else {
// それ以外は単純に例外
- if (blocking) throw new IdentifiableError('710e8fb0-b8c3-4922-be49-d5d93d8e6a6e', 'blocking');
- if (blocked) throw new IdentifiableError('3338392a-f764-498d-8855-db939dcf8c48', 'blocked');
+ if (blocking) throw new IdentifiableError('710e8fb0-b8c3-4922-be49-d5d93d8e6a6e', 'You have blocked this user.');
+ if (blocked) throw new IdentifiableError('3338392a-f764-498d-8855-db939dcf8c48', 'You have been blocked by this user.');
+ }
+
+ if (await this.followingsRepository.exists({
+ where: {
+ followerId: follower.id,
+ followeeId: followee.id,
+ },
+ })) {
+ // すでにフォロー関係が存在している場合
+ if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
+ // リモート → ローカル: acceptを送り返しておしまい
+ this.deliverAccept(follower, followee, requestId);
+ return;
+ }
+ if (this.userEntityService.isLocalUser(follower)) {
+ // ローカル → リモート/ローカル: 例外
+ throw new IdentifiableError('ec3f65c0-a9d1-47d9-8791-b2e7b9dcdced', 'already following');
+ }
}
const followeeProfile = await this.userProfilesRepository.findOneByOrFail({ userId: followee.id });
@@ -144,7 +176,7 @@ export class UserFollowingService implements OnModuleInit {
let autoAccept = false;
// 鍵アカウントであっても、既にフォローされていた場合はスルー
- const isFollowing = await this.followingsRepository.exist({
+ const isFollowing = await this.followingsRepository.exists({
where: {
followerId: follower.id,
followeeId: followee.id,
@@ -156,7 +188,7 @@ export class UserFollowingService implements OnModuleInit {
// フォローしているユーザーは自動承認オプション
if (!autoAccept && (this.userEntityService.isLocalUser(followee) && followeeProfile.autoAcceptFollowed)) {
- const isFollowed = await this.followingsRepository.exist({
+ const isFollowed = await this.followingsRepository.exists({
where: {
followerId: followee.id,
followeeId: follower.id,
@@ -170,7 +202,7 @@ export class UserFollowingService implements OnModuleInit {
if (followee.isLocked && !autoAccept) {
autoAccept = !!(await this.accountMoveService.validateAlsoKnownAs(
follower,
- (oldSrc, newSrc) => this.followingsRepository.exist({
+ (oldSrc, newSrc) => this.followingsRepository.exists({
where: {
followeeId: followee.id,
followerId: newSrc.id,
@@ -189,8 +221,7 @@ export class UserFollowingService implements OnModuleInit {
await this.insertFollowingDoc(followee, follower, silent, withReplies);
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
- const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee, requestId), followee));
- this.queueService.deliver(followee, content, follower.inbox, false);
+ this.deliverAccept(follower, followee, requestId);
}
}
@@ -233,7 +264,7 @@ export class UserFollowingService implements OnModuleInit {
this.cacheService.userFollowingsCache.refresh(follower.id);
- const requestExist = await this.followRequestsRepository.exist({
+ const requestExist = await this.followRequestsRepository.exists({
where: {
followeeId: followee.id,
followerId: follower.id,
@@ -293,9 +324,9 @@ export class UserFollowingService implements OnModuleInit {
if (this.userEntityService.isLocalUser(follower) && !silent) {
// Publish follow event
this.userEntityService.pack(followee.id, follower, {
- detail: true,
+ schema: 'UserDetailedNotMe',
}).then(async packed => {
- this.globalEventService.publishMainStream(follower.id, 'follow', packed as Packed<'UserDetailedNotMe'>);
+ this.globalEventService.publishMainStream(follower.id, 'follow', packed);
const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('follow'));
for (const webhook of webhooks) {
@@ -304,8 +335,6 @@ export class UserFollowingService implements OnModuleInit {
});
}
});
-
- this.funoutTimelineService.purge(`homeTimeline:${follower.id}`);
}
// Publish followed event
@@ -362,7 +391,7 @@ export class UserFollowingService implements OnModuleInit {
if (!silent && this.userEntityService.isLocalUser(follower)) {
// Publish unfollow event
this.userEntityService.pack(followee.id, follower, {
- detail: true,
+ schema: 'UserDetailedNotMe',
}).then(async packed => {
this.globalEventService.publishMainStream(follower.id, 'unfollow', packed);
@@ -373,8 +402,6 @@ export class UserFollowingService implements OnModuleInit {
});
}
});
-
- this.funoutTimelineService.purge(`homeTimeline:${follower.id}`);
}
if (this.userEntityService.isLocalUser(follower) && this.userEntityService.isRemoteUser(followee)) {
@@ -483,6 +510,12 @@ export class UserFollowingService implements OnModuleInit {
if (blocking) throw new Error('blocking');
if (blocked) throw new Error('blocked');
+ // Remove old follow requests before creating a new one.
+ await this.followRequestsRepository.delete({
+ followeeId: followee.id,
+ followerId: follower.id,
+ });
+
const followRequest = await this.followRequestsRepository.insert({
id: this.idService.gen(),
followerId: follower.id,
@@ -504,7 +537,7 @@ export class UserFollowingService implements OnModuleInit {
this.userEntityService.pack(follower.id, followee).then(packed => this.globalEventService.publishMainStream(followee.id, 'receiveFollowRequest', packed));
this.userEntityService.pack(followee.id, followee, {
- detail: true,
+ schema: 'MeDetailed',
}).then(packed => this.globalEventService.publishMainStream(followee.id, 'meUpdated', packed));
// 通知を作成
@@ -535,7 +568,7 @@ export class UserFollowingService implements OnModuleInit {
}
}
- const requestExist = await this.followRequestsRepository.exist({
+ const requestExist = await this.followRequestsRepository.exists({
where: {
followeeId: followee.id,
followerId: follower.id,
@@ -543,7 +576,7 @@ export class UserFollowingService implements OnModuleInit {
});
if (!requestExist) {
- throw new IdentifiableError('17447091-ce07-46dd-b331-c1fd4f15b1e7', 'request not found');
+ throw new IdentifiableError('17447091-ce07-46dd-b331-c1fd4f15b1e7', 'No such follow request.');
}
await this.followRequestsRepository.delete({
@@ -552,7 +585,7 @@ export class UserFollowingService implements OnModuleInit {
});
this.userEntityService.pack(followee.id, followee, {
- detail: true,
+ schema: 'MeDetailed',
}).then(packed => this.globalEventService.publishMainStream(followee.id, 'meUpdated', packed));
}
@@ -569,18 +602,17 @@ export class UserFollowingService implements OnModuleInit {
});
if (request == null) {
- throw new IdentifiableError('8884c2dd-5795-4ac9-b27e-6a01d38190f9', 'No follow request.');
+ throw new IdentifiableError('8884c2dd-5795-4ac9-b27e-6a01d38190f9', 'No such follow request.');
}
await this.insertFollowingDoc(followee, follower, false, request.withReplies);
if (this.userEntityService.isRemoteUser(follower) && this.userEntityService.isLocalUser(followee)) {
- const content = this.apRendererService.addContext(this.apRendererService.renderAccept(this.apRendererService.renderFollow(follower, followee as MiPartialLocalUser, request.requestId!), followee));
- this.queueService.deliver(followee, content, follower.inbox, false);
+ this.deliverAccept(follower, followee as MiPartialLocalUser, request.requestId ?? undefined);
}
this.userEntityService.pack(followee.id, followee, {
- detail: true,
+ schema: 'MeDetailed',
}).then(packed => this.globalEventService.publishMainStream(followee.id, 'meUpdated', packed));
}
@@ -700,7 +732,7 @@ export class UserFollowingService implements OnModuleInit {
@bindThis
private async publishUnfollow(followee: Both, follower: Local): Promise {
const packedFollowee = await this.userEntityService.pack(followee.id, follower, {
- detail: true,
+ schema: 'UserDetailedNotMe',
});
this.globalEventService.publishMainStream(follower.id, 'unfollow', packedFollowee);
diff --git a/packages/backend/src/core/UserKeypairService.ts b/packages/backend/src/core/UserKeypairService.ts
index 425a97f3f..51ac99179 100644
--- a/packages/backend/src/core/UserKeypairService.ts
+++ b/packages/backend/src/core/UserKeypairService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/UserListService.ts b/packages/backend/src/core/UserListService.ts
index 702c731fc..c16af88ce 100644
--- a/packages/backend/src/core/UserListService.ts
+++ b/packages/backend/src/core/UserListService.ts
@@ -1,32 +1,36 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common';
+import { Inject, Injectable, OnApplicationShutdown, OnModuleInit } from '@nestjs/common';
import * as Redis from 'ioredis';
+import { ModuleRef } from '@nestjs/core';
import type { UserListMembershipsRepository } from '@/models/_.js';
import type { MiUser } from '@/models/User.js';
import type { MiUserList } from '@/models/UserList.js';
import type { MiUserListMembership } from '@/models/UserListMembership.js';
import { IdService } from '@/core/IdService.js';
+import type { GlobalEvents } from '@/core/GlobalEventService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { ProxyAccountService } from '@/core/ProxyAccountService.js';
import { bindThis } from '@/decorators.js';
-import { RoleService } from '@/core/RoleService.js';
import { QueueService } from '@/core/QueueService.js';
import { RedisKVCache } from '@/misc/cache.js';
-import type { GlobalEvents } from '@/core/GlobalEventService.js';
+import { RoleService } from '@/core/RoleService.js';
@Injectable()
-export class UserListService implements OnApplicationShutdown {
+export class UserListService implements OnApplicationShutdown, OnModuleInit {
public static TooManyUsersError = class extends Error {};
public membersCache: RedisKVCache>;
+ private roleService: RoleService;
constructor(
+ private moduleRef: ModuleRef,
+
@Inject(DI.redis)
private redisClient: Redis.Redis,
@@ -38,7 +42,6 @@ export class UserListService implements OnApplicationShutdown {
private userEntityService: UserEntityService,
private idService: IdService,
- private roleService: RoleService,
private globalEventService: GlobalEventService,
private proxyAccountService: ProxyAccountService,
private queueService: QueueService,
@@ -54,6 +57,10 @@ export class UserListService implements OnApplicationShutdown {
this.redisForSub.on('message', this.onMessage);
}
+ async onModuleInit() {
+ this.roleService = this.moduleRef.get(RoleService.name);
+ }
+
@bindThis
private async onMessage(_: string, data: string): Promise {
const obj = JSON.parse(data);
@@ -99,8 +106,7 @@ export class UserListService implements OnApplicationShutdown {
userListUserId: list.userId,
} as MiUserListMembership);
- this.globalEventService.publishInternalEvent('userListMemberAdded', { userListId: list.id, memberId: target.id });
- this.globalEventService.publishUserListStream(list.id, 'userAdded', await this.userEntityService.pack(target));
+ this.globalEventService.publishUserListStream(list.id, 'userAdded', await this.userEntityService.pack(target, me));
// このインスタンス内にこのリモートユーザーをフォローしているユーザーがいなくても投稿を受け取るためにダミーのユーザーがフォローしたということにする
if (this.userEntityService.isRemoteUser(target)) {
@@ -119,7 +125,7 @@ export class UserListService implements OnApplicationShutdown {
});
this.globalEventService.publishInternalEvent('userListMemberRemoved', { userListId: list.id, memberId: target.id });
- this.globalEventService.publishUserListStream(list.id, 'userRemoved', await this.userEntityService.pack(target));
+ this.globalEventService.publishUserListStream(list.id, 'userRemoved', await this.userEntityService.pack(target, null));
}
@bindThis
diff --git a/packages/backend/src/core/UserMutingService.ts b/packages/backend/src/core/UserMutingService.ts
index 397e6bdd5..06643be5f 100644
--- a/packages/backend/src/core/UserMutingService.ts
+++ b/packages/backend/src/core/UserMutingService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/UserService.ts b/packages/backend/src/core/UserService.ts
index d16e1be61..72fa4d928 100644
--- a/packages/backend/src/core/UserService.ts
+++ b/packages/backend/src/core/UserService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/UserSuspendService.ts b/packages/backend/src/core/UserSuspendService.ts
index 8940a142d..d594a223f 100644
--- a/packages/backend/src/core/UserSuspendService.ts
+++ b/packages/backend/src/core/UserSuspendService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/UtilityService.ts b/packages/backend/src/core/UtilityService.ts
index b95e41167..3f6d63609 100644
--- a/packages/backend/src/core/UtilityService.ts
+++ b/packages/backend/src/core/UtilityService.ts
@@ -1,11 +1,12 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { URL } from 'node:url';
import { toASCII } from 'punycode';
import { Inject, Injectable } from '@nestjs/common';
+import RE2 from 're2';
import { DI } from '@/di-symbols.js';
import type { Config } from '@/config.js';
import { bindThis } from '@/decorators.js';
@@ -41,6 +42,51 @@ export class UtilityService {
return silencedHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`));
}
+ @bindThis
+ public isSensitiveMediaHost(sensitiveMediaHosts: string[] | undefined, host: string | null): boolean {
+ if (!sensitiveMediaHosts || host == null) return false;
+ return sensitiveMediaHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`));
+ }
+
+ @bindThis
+ public concatNoteContentsForKeyWordCheck(content: {
+ cw?: string | null;
+ text?: string | null;
+ pollChoices?: string[] | null;
+ others?: string[] | null;
+ }): string {
+ /**
+ * ノートの内容を結合してキーワードチェック用の文字列を生成する
+ * cwとtextは内容が繋がっているかもしれないので間に何も入れずにチェックする
+ */
+ return `${content.cw ?? ''}${content.text ?? ''}\n${(content.pollChoices ?? []).join('\n')}\n${(content.others ?? []).join('\n')}`;
+ }
+
+ private static readonly isFilterRegExpPattern = /^\/(.+)\/(.*)$/;
+
+ @bindThis
+ public isKeyWordIncluded(text: string, keyWords: string[]): boolean {
+ if (keyWords.length === 0) return false;
+ if (text === '') return false;
+
+ return keyWords.some(filter => {
+ const regexp = UtilityService.isFilterRegExpPattern.exec(filter);
+
+ if (!regexp) {
+ const words = filter.split(' ');
+ return words.every(keyword => text.includes(keyword));
+ }
+
+ try {
+ // TODO: RE2インスタンスをキャッシュ
+ return new RE2(regexp[1], regexp[2]).test(text);
+ } catch (err) {
+ // This should never happen due to input sanitization.
+ return false;
+ }
+ });
+ }
+
@bindThis
public extractDbHost(uri: string): string {
const url = new URL(uri);
diff --git a/packages/backend/src/core/VideoProcessingService.ts b/packages/backend/src/core/VideoProcessingService.ts
index ffb757335..747fe4fc7 100644
--- a/packages/backend/src/core/VideoProcessingService.ts
+++ b/packages/backend/src/core/VideoProcessingService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/WebAuthnService.ts b/packages/backend/src/core/WebAuthnService.ts
index 5945dc291..06ff5f416 100644
--- a/packages/backend/src/core/WebAuthnService.ts
+++ b/packages/backend/src/core/WebAuthnService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -7,15 +7,18 @@ import { Inject, Injectable } from '@nestjs/common';
import * as Redis from 'ioredis';
import {
generateAuthenticationOptions,
- generateRegistrationOptions, verifyAuthenticationResponse,
+ generateRegistrationOptions,
+ verifyAuthenticationResponse,
verifyRegistrationResponse,
} from '@simplewebauthn/server';
import { AttestationFormat, isoCBOR } from '@simplewebauthn/server/helpers';
import { DI } from '@/di-symbols.js';
import type { UserSecurityKeysRepository } from '@/models/_.js';
import type { Config } from '@/config.js';
+import type Logger from '@/logger.js';
import { bindThis } from '@/decorators.js';
import { MetaService } from '@/core/MetaService.js';
+import { LoggerService } from '@/core/LoggerService.js';
import { MiUser } from '@/models/_.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';
import type {
@@ -26,10 +29,12 @@ import type {
PublicKeyCredentialDescriptorFuture,
PublicKeyCredentialRequestOptionsJSON,
RegistrationResponseJSON,
-} from '@simplewebauthn/typescript-types';
+} from '@simplewebauthn/types';
@Injectable()
export class WebAuthnService {
+ private logger: Logger;
+
constructor(
@Inject(DI.redis)
private redisClient: Redis.Redis,
@@ -41,7 +46,9 @@ export class WebAuthnService {
private userSecurityKeysRepository: UserSecurityKeysRepository,
private metaService: MetaService,
+ private loggerService: LoggerService,
) {
+ this.logger = this.loggerService.getLogger('webauthn');
}
@bindThis
@@ -100,7 +107,7 @@ export class WebAuthnService {
const challenge = await this.redisClient.get(`webauthn:challenge:${userId}`);
if (!challenge) {
- throw new IdentifiableError('7dbfb66c-9216-4e2b-9c27-cef2ac8efb84', 'challenge not found');
+ throw new IdentifiableError('7dbfb66c-9216-4e2b-9c27-cef2ac8efb84', 'Unable to find registration challenge. Please try again.');
}
await this.redisClient.del(`webauthn:challenge:${userId}`);
@@ -117,14 +124,14 @@ export class WebAuthnService {
requireUserVerification: true,
});
} catch (error) {
- console.error(error);
- throw new IdentifiableError('5c1446f8-8ca7-4d31-9f39-656afe9c5d87', 'verification failed');
+ this.logger.error('Failed to verify registration response', { error });
+ throw new IdentifiableError('5c1446f8-8ca7-4d31-9f39-656afe9c5d87', 'Unable to verify registration response. Please try again.');
}
const { verified } = verification;
if (!verified || !verification.registrationInfo) {
- throw new IdentifiableError('bb333667-3832-4a80-8bb5-c505be7d710d', 'verification failed');
+ throw new IdentifiableError('bb333667-3832-4a80-8bb5-c505be7d710d', 'Unable to verify registration response. Please try again.');
}
const { registrationInfo } = verification;
@@ -149,7 +156,7 @@ export class WebAuthnService {
});
if (keys.length === 0) {
- throw new IdentifiableError('f27fd449-9af4-4841-9249-1f989b9fa4a4', 'no keys found');
+ throw new IdentifiableError('f27fd449-9af4-4841-9249-1f989b9fa4a4', 'You have no registered security keys or passkeys yet.');
}
const authenticationOptions = await generateAuthenticationOptions({
@@ -171,7 +178,7 @@ export class WebAuthnService {
const challenge = await this.redisClient.get(`webauthn:challenge:${userId}`);
if (!challenge) {
- throw new IdentifiableError('2d16e51c-007b-4edd-afd2-f7dd02c947f6', 'challenge not found');
+ throw new IdentifiableError('2d16e51c-007b-4edd-afd2-f7dd02c947f6', 'Unable to find authentication challenge. Please try again.');
}
await this.redisClient.del(`webauthn:challenge:${userId}`);
@@ -182,7 +189,7 @@ export class WebAuthnService {
});
if (!key) {
- throw new IdentifiableError('36b96a7d-b547-412d-aeed-2d611cdc8cdc', 'unknown key');
+ throw new IdentifiableError('36b96a7d-b547-412d-aeed-2d611cdc8cdc', 'Unable to identify your security key. Please try with another key.');
}
// マイグレーション
@@ -191,7 +198,7 @@ export class WebAuthnService {
if (cert[0] === 0x04) { // 前の実装ではいつも 0x04 で始まっていた
const halfLength = (cert.length - 1) / 2;
- const cborMap = new Map();
+ const cborMap = new Map();
cborMap.set(1, 2); // kty, EC2
cborMap.set(3, -7); // alg, ES256
cborMap.set(-1, 1); // crv, P256
@@ -227,8 +234,8 @@ export class WebAuthnService {
requireUserVerification: true,
});
} catch (error) {
- console.error(error);
- throw new IdentifiableError('b18c89a7-5b5e-4cec-bb5b-0419f332d430', 'verification failed');
+ this.logger.error('Failed to verify authentication response', { error });
+ throw new IdentifiableError('b18c89a7-5b5e-4cec-bb5b-0419f332d430', 'Unable to verify authentication response. Please try again.');
}
const { verified, authenticationInfo } = verification;
diff --git a/packages/backend/src/core/WebfingerService.ts b/packages/backend/src/core/WebfingerService.ts
index 3d5747aeb..374536a74 100644
--- a/packages/backend/src/core/WebfingerService.ts
+++ b/packages/backend/src/core/WebfingerService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/WebhookService.ts b/packages/backend/src/core/WebhookService.ts
index 930e6ef64..8cafb6ad2 100644
--- a/packages/backend/src/core/WebhookService.ts
+++ b/packages/backend/src/core/WebhookService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -49,9 +49,11 @@ export class WebhookService implements OnApplicationShutdown {
switch (type) {
case 'webhookCreated':
if (body.active) {
- this.webhooks.push({
+ this.webhooks.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい
...body,
+ createdAt: new Date(body.createdAt),
latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null,
+ user: null, // joinなカラムは通常取ってこないので
});
}
break;
@@ -59,14 +61,18 @@ export class WebhookService implements OnApplicationShutdown {
if (body.active) {
const i = this.webhooks.findIndex(a => a.id === body.id);
if (i > -1) {
- this.webhooks[i] = {
+ this.webhooks[i] = { // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい
...body,
+ createdAt: new Date(body.createdAt),
latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null,
+ user: null, // joinなカラムは通常取ってこないので
};
} else {
- this.webhooks.push({
+ this.webhooks.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい
...body,
+ createdAt: new Date(body.createdAt),
latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null,
+ user: null, // joinなカラムは通常取ってこないので
});
}
} else {
diff --git a/packages/backend/src/core/activitypub/ApAudienceService.ts b/packages/backend/src/core/activitypub/ApAudienceService.ts
index 440852bdf..0fccc7b95 100644
--- a/packages/backend/src/core/activitypub/ApAudienceService.ts
+++ b/packages/backend/src/core/activitypub/ApAudienceService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -8,6 +8,7 @@ import promiseLimit from 'promise-limit';
import type { MiRemoteUser, MiUser } from '@/models/User.js';
import { concat, unique } from '@/misc/prelude/array.js';
import { bindThis } from '@/decorators.js';
+import { isNotNull } from '@/misc/is-not-null.js';
import { getApIds } from './type.js';
import { ApPersonService } from './models/ApPersonService.js';
import type { ApObject } from './type.js';
@@ -40,7 +41,7 @@ export class ApAudienceService {
const limit = promiseLimit(2);
const mentionedUsers = (await Promise.all(
others.map(id => limit(() => this.apPersonService.resolvePerson(id, resolver).catch(() => null))),
- )).filter((x): x is MiUser => x != null);
+ )).filter(isNotNull);
if (toGroups.public.length > 0) {
return {
@@ -58,7 +59,7 @@ export class ApAudienceService {
};
}
- if (toGroups.followers.length > 0) {
+ if (toGroups.followers.length > 0 || ccGroups.followers.length > 0) {
return {
visibility: 'followers',
mentionedUsers,
diff --git a/packages/backend/src/core/activitypub/ApDbResolverService.ts b/packages/backend/src/core/activitypub/ApDbResolverService.ts
index 995c5dcd5..f6b70ead4 100644
--- a/packages/backend/src/core/activitypub/ApDbResolverService.ts
+++ b/packages/backend/src/core/activitypub/ApDbResolverService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -106,12 +106,12 @@ export class ApDbResolverService implements OnApplicationShutdown {
return await this.cacheService.userByIdCache.fetchMaybe(
parsed.id,
- () => this.usersRepository.findOneBy({ id: parsed.id }).then(x => x ?? undefined),
+ () => this.usersRepository.findOneBy({ id: parsed.id, isDeleted: false }).then(x => x ?? undefined),
) as MiLocalUser | undefined ?? null;
} else {
return await this.cacheService.uriPersonCache.fetch(
parsed.uri,
- () => this.usersRepository.findOneBy({ uri: parsed.uri }),
+ () => this.usersRepository.findOneBy({ uri: parsed.uri, isDeleted: false }),
) as MiRemoteUser | null;
}
}
@@ -136,8 +136,12 @@ export class ApDbResolverService implements OnApplicationShutdown {
if (key == null) return null;
+ const user = await this.cacheService.findUserById(key.userId).catch(() => null) as MiRemoteUser | null;
+ if (user == null) return null;
+ if (user.isDeleted) return null;
+
return {
- user: await this.cacheService.findUserById(key.userId) as MiRemoteUser,
+ user,
key,
};
}
@@ -151,6 +155,7 @@ export class ApDbResolverService implements OnApplicationShutdown {
key: MiUserPublickey | null;
} | null> {
const user = await this.apPersonService.resolvePerson(uri) as MiRemoteUser;
+ if (user.isDeleted) return null;
const key = await this.publicKeyByUserIdCache.fetch(
user.id,
diff --git a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts
index 81003bcf1..5d07cd8e8 100644
--- a/packages/backend/src/core/activitypub/ApDeliverManagerService.ts
+++ b/packages/backend/src/core/activitypub/ApDeliverManagerService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -144,7 +144,7 @@ class DeliverManager {
}
// deliver
- this.queueService.deliverMany(this.actor, this.activity, inboxes);
+ await this.queueService.deliverMany(this.actor, this.activity, inboxes);
}
}
diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts
index 7aba14068..fd9c7c2ba 100644
--- a/packages/backend/src/core/activitypub/ApInboxService.ts
+++ b/packages/backend/src/core/activitypub/ApInboxService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -26,7 +26,9 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { QueueService } from '@/core/QueueService.js';
import type { UsersRepository, NotesRepository, FollowingsRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/_.js';
import { bindThis } from '@/decorators.js';
-import type { MiRemoteUser } from '@/models/User.js';
+import type { MiLocalUser, MiRemoteUser } from '@/models/User.js';
+import { isNotNull } from '@/misc/is-not-null.js';
+import { GlobalEventService } from '@/core/GlobalEventService.js';
import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js';
import { ApNoteService } from './models/ApNoteService.js';
import { ApLoggerService } from './ApLoggerService.js';
@@ -82,26 +84,29 @@ export class ApInboxService {
private apPersonService: ApPersonService,
private apQuestionService: ApQuestionService,
private queueService: QueueService,
+ private globalEventService: GlobalEventService,
) {
this.logger = this.apLoggerService.logger;
}
@bindThis
- public async performActivity(actor: MiRemoteUser, activity: IObject): Promise {
+ public async performActivity(actor: MiRemoteUser, activity: IObject, additionalCc?: MiLocalUser['id']): Promise {
if (isCollectionOrOrderedCollection(activity)) {
const resolver = this.apResolverService.createResolver();
for (const item of toArray(isCollection(activity) ? activity.items : activity.orderedItems)) {
const act = await resolver.resolve(item);
try {
- await this.performOneActivity(actor, act);
+ await this.performOneActivity(actor, act, additionalCc);
} catch (err) {
if (err instanceof Error || typeof err === 'string') {
this.logger.error(err);
+ } else {
+ throw err;
}
}
}
} else {
- await this.performOneActivity(actor, activity);
+ await this.performOneActivity(actor, activity, additionalCc);
}
// ついでにリモートユーザーの情報が古かったら更新しておく
@@ -115,15 +120,15 @@ export class ApInboxService {
}
@bindThis
- public async performOneActivity(actor: MiRemoteUser, activity: IObject): Promise {
+ public async performOneActivity(actor: MiRemoteUser, activity: IObject, additionalCc?: MiLocalUser['id']): Promise {
if (actor.isSuspended) return;
if (isCreate(activity)) {
- await this.create(actor, activity);
+ await this.create(actor, activity, additionalCc);
} else if (isDelete(activity)) {
await this.delete(actor, activity);
} else if (isUpdate(activity)) {
- await this.update(actor, activity);
+ await this.update(actor, activity, additionalCc);
} else if (isFollow(activity)) {
await this.follow(actor, activity);
} else if (isAccept(activity)) {
@@ -195,7 +200,7 @@ export class ApInboxService {
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(err => {
- this.logger.error(`Resolution failed: ${err}`);
+ this.logger.error(`Resolution failed: ${err}`, { error: err });
throw err;
});
@@ -256,7 +261,7 @@ export class ApInboxService {
const targetUri = getApId(activity.object);
- this.announceNote(actor, activity, targetUri);
+ await this.announceNote(actor, activity, targetUri);
}
@bindThis
@@ -288,7 +293,7 @@ export class ApInboxService {
} catch (err) {
// 対象が4xxならスキップ
if (err instanceof StatusError) {
- if (err.isClientError) {
+ if (!err.isRetryable) {
this.logger.warn(`Ignored announce target ${targetUri} - ${err.statusCode}`);
return;
}
@@ -306,9 +311,15 @@ export class ApInboxService {
this.logger.info(`Creating the (Re)Note: ${uri}`);
const activityAudience = await this.apAudienceService.parseAudience(actor, activity.to, activity.cc);
+ const createdAt = activity.published ? new Date(activity.published) : null;
+
+ if (createdAt && createdAt < this.idService.parse(renote.id).date) {
+ this.logger.warn('skip: malformed createdAt');
+ return;
+ }
await this.noteCreateService.create(actor, {
- createdAt: activity.published ? new Date(activity.published) : null,
+ createdAt,
renote,
visibility: activityAudience.visibility,
visibleUsers: activityAudience.visibleUsers,
@@ -338,7 +349,7 @@ export class ApInboxService {
}
@bindThis
- private async create(actor: MiRemoteUser, activity: ICreate): Promise {
+ private async create(actor: MiRemoteUser, activity: ICreate, additionalCc?: MiLocalUser['id']): Promise {
const uri = getApId(activity);
this.logger.info(`Create: ${uri}`);
@@ -362,19 +373,19 @@ export class ApInboxService {
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(e => {
- this.logger.error(`Resolution failed: ${e}`);
+ this.logger.error(`Resolution failed: ${e}`, { error: e });
throw e;
});
if (isPost(object)) {
- this.createNote(resolver, actor, object, false, activity);
+ await this.createNote(resolver, actor, object, false, activity, additionalCc);
} else {
this.logger.warn(`Unknown type: ${getApType(object)}`);
}
}
@bindThis
- private async createNote(resolver: Resolver, actor: MiRemoteUser, note: IObject, silent = false, activity?: ICreate): Promise {
+ private async createNote(resolver: Resolver, actor: MiRemoteUser, note: IObject, silent = false, activity?: ICreate, additionalCc?: MiLocalUser['id']): Promise {
const uri = getApId(note);
if (typeof note === 'object') {
@@ -393,12 +404,23 @@ export class ApInboxService {
try {
const exist = await this.apNoteService.fetchNote(note);
- if (exist) return 'skip: note exists';
+ if (exist) {
+ if (additionalCc && !await this.noteEntityService.isVisibleForMe(exist, additionalCc)) {
+ await this.noteCreateService.appendNoteVisibleUser(actor, exist, additionalCc);
+ return 'ok: note visible user appended';
+ }
+ return 'skip: note exists';
+ }
+
+ const createdNote = await this.apNoteService.createNote(note, resolver, silent);
+ if (createdNote && additionalCc && !await this.noteEntityService.isVisibleForMe(createdNote, additionalCc)) {
+ await this.noteCreateService.appendNoteVisibleUser(actor, createdNote, additionalCc);
+ return 'ok: note visible user appended';
+ }
- await this.apNoteService.createNote(note, resolver, silent);
return 'ok';
} catch (err) {
- if (err instanceof StatusError && err.isClientError) {
+ if (err instanceof StatusError && !err.isRetryable) {
return `skip ${err.statusCode}`;
} else {
throw err;
@@ -465,12 +487,15 @@ export class ApInboxService {
return 'skip: already deleted';
}
- const job = await this.queueService.createDeleteAccountJob(actor);
+ // リモートから消されたということなので、物理削除する
+ const job = await this.queueService.createDeleteAccountJob(actor, { force: true, soft: false });
await this.usersRepository.update(actor.id, {
isDeleted: true,
});
+ this.globalEventService.publishInternalEvent('remoteUserUpdated', { id: actor.id });
+
return `ok: queued ${job.name} ${job.id}`;
}
@@ -507,20 +532,22 @@ export class ApInboxService {
const userIds = uris
.filter(uri => uri.startsWith(this.config.url + '/users/'))
.map(uri => uri.split('/').at(-1))
- .filter((userId): userId is string => userId !== undefined);
+ .filter(isNotNull);
const users = await this.usersRepository.findBy({
id: In(userIds),
});
if (users.length < 1) return 'skip';
- await this.abuseUserReportsRepository.insert({
+ const report = await this.abuseUserReportsRepository.insert({
id: this.idService.gen(),
targetUserId: users[0].id,
targetUserHost: users[0].host,
reporterId: actor.id,
reporterHost: actor.host,
comment: `${activity.content}\n${JSON.stringify(uris, null, 2)}`,
- });
+ }).then(x => this.abuseUserReportsRepository.findOneByOrFail(x.identifiers[0]));
+
+ this.queueService.createReportAbuseJob(report);
return 'ok';
}
@@ -534,7 +561,7 @@ export class ApInboxService {
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(e => {
- this.logger.error(`Resolution failed: ${e}`);
+ this.logger.error(`Resolution failed: ${e}`, { error: e });
throw e;
});
@@ -600,7 +627,7 @@ export class ApInboxService {
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(e => {
- this.logger.error(`Resolution failed: ${e}`);
+ this.logger.error(`Resolution failed: ${e}`, { error: e });
throw e;
});
@@ -621,7 +648,7 @@ export class ApInboxService {
return 'skip: follower not found';
}
- const isFollowing = await this.followingsRepository.exist({
+ const isFollowing = await this.followingsRepository.exists({
where: {
followerId: follower.id,
followeeId: actor.id,
@@ -678,14 +705,14 @@ export class ApInboxService {
return 'skip: フォロー解除しようとしているユーザーはローカルユーザーではありません';
}
- const requestExist = await this.followRequestsRepository.exist({
+ const requestExist = await this.followRequestsRepository.exists({
where: {
followerId: actor.id,
followeeId: followee.id,
},
});
- const isFollowing = await this.followingsRepository.exist({
+ const isFollowing = await this.followingsRepository.exists({
where: {
followerId: actor.id,
followeeId: followee.id,
@@ -721,7 +748,7 @@ export class ApInboxService {
}
@bindThis
- private async update(actor: MiRemoteUser, activity: IUpdate): Promise {
+ private async update(actor: MiRemoteUser, activity: IUpdate, additionalCc?: MiLocalUser['id']): Promise {
if (actor.uri !== activity.actor) {
return 'skip: invalid actor';
}
@@ -731,7 +758,7 @@ export class ApInboxService {
const resolver = this.apResolverService.createResolver();
const object = await resolver.resolve(activity.object).catch(e => {
- this.logger.error(`Resolution failed: ${e}`);
+ this.logger.error(`Resolution failed: ${e}`, { error: e });
throw e;
});
@@ -739,8 +766,29 @@ export class ApInboxService {
await this.apPersonService.updatePerson(actor.uri, resolver, object);
return 'ok: Person updated';
} else if (getApType(object) === 'Question') {
- await this.apQuestionService.updateQuestion(object, resolver).catch(err => console.error(err));
+ await this.apQuestionService.updateQuestion(object, resolver).catch(err => this.logger.error(`err: failed to update question: ${err}`, { error: err }));
return 'ok: Question updated';
+ } else if (additionalCc && isPost(object)) {
+ const uri = getApId(object);
+ const unlock = await this.appLockService.getApLock(uri);
+
+ try {
+ const exist = await this.apNoteService.fetchNote(object);
+ if (exist && !await this.noteEntityService.isVisibleForMe(exist, additionalCc)) {
+ await this.noteCreateService.appendNoteVisibleUser(actor, exist, additionalCc);
+ return 'ok: note visible user appended';
+ } else {
+ return 'skip: nothing to do';
+ }
+ } catch (err) {
+ if (err instanceof StatusError && !err.isRetryable) {
+ return `skip ${err.statusCode}`;
+ } else {
+ throw err;
+ }
+ } finally {
+ unlock();
+ }
} else {
return `skip: Unknown type: ${getApType(object)}`;
}
diff --git a/packages/backend/src/core/activitypub/ApLoggerService.ts b/packages/backend/src/core/activitypub/ApLoggerService.ts
index cd9597e42..428d8061c 100644
--- a/packages/backend/src/core/activitypub/ApLoggerService.ts
+++ b/packages/backend/src/core/activitypub/ApLoggerService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/activitypub/ApMfmService.ts b/packages/backend/src/core/activitypub/ApMfmService.ts
index 60868627a..e2ec36913 100644
--- a/packages/backend/src/core/activitypub/ApMfmService.ts
+++ b/packages/backend/src/core/activitypub/ApMfmService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -25,8 +25,21 @@ export class ApMfmService {
}
@bindThis
- public getNoteHtml(note: MiNote): string | null {
- if (!note.text) return '';
- return this.mfmService.toHtml(mfm.parse(note.text), JSON.parse(note.mentionedRemoteUsers));
+ public getNoteHtml(note: MiNote, apAppend?: string) {
+ let noMisskeyContent = false;
+ const srcMfm = (note.text ?? '') + (apAppend ?? '');
+
+ const parsed = mfm.parse(srcMfm);
+
+ if (!apAppend && parsed.every(n => ['text', 'unicodeEmoji', 'emojiCode', 'mention', 'hashtag', 'url'].includes(n.type))) {
+ noMisskeyContent = true;
+ }
+
+ const content = this.mfmService.toHtml(parsed, JSON.parse(note.mentionedRemoteUsers));
+
+ return {
+ content,
+ noMisskeyContent,
+ };
}
}
diff --git a/packages/backend/src/core/activitypub/ApRendererService.ts b/packages/backend/src/core/activitypub/ApRendererService.ts
index 1891c341e..3a0367ba6 100644
--- a/packages/backend/src/core/activitypub/ApRendererService.ts
+++ b/packages/backend/src/core/activitypub/ApRendererService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -315,7 +315,7 @@ export class ApRendererService {
const getPromisedFiles = async (ids: string[]): Promise => {
if (ids.length === 0) return [];
const items = await this.driveFilesRepository.findBy({ id: In(ids) });
- return ids.map(id => items.find(item => item.id === id)).filter((item): item is MiDriveFile => item != null);
+ return ids.map(id => items.find(item => item.id === id)).filter(isNotNull);
};
let inReplyTo;
@@ -325,7 +325,7 @@ export class ApRendererService {
inReplyToNote = await this.notesRepository.findOneBy({ id: note.replyId });
if (inReplyToNote != null) {
- const inReplyToUserExist = await this.usersRepository.exist({ where: { id: inReplyToNote.userId } });
+ const inReplyToUserExist = await this.usersRepository.exists({ where: { id: inReplyToNote.userId } });
if (inReplyToUserExist) {
if (inReplyToNote.uri) {
@@ -389,17 +389,15 @@ export class ApRendererService {
poll = await this.pollsRepository.findOneBy({ noteId: note.id });
}
- let apText = text;
+ let apAppend = '';
if (quote) {
- apText += `\n\nRE: ${quote}`;
+ apAppend += `\n\nRE: ${quote}`;
}
const summary = note.cw === '' ? String.fromCharCode(0x200B) : note.cw;
- const content = this.apMfmService.getNoteHtml(Object.assign({}, note, {
- text: apText,
- }));
+ const { content, noMisskeyContent } = this.apMfmService.getNoteHtml(note, apAppend);
const emojis = await this.getEmojis(note.emojis);
const apemojis = emojis.filter(emoji => !emoji.localOnly).map(emoji => this.renderEmoji(emoji));
@@ -412,9 +410,6 @@ export class ApRendererService {
const asPoll = poll ? {
type: 'Question',
- content: this.apMfmService.getNoteHtml(Object.assign({}, note, {
- text: text,
- })),
[poll.expiresAt && poll.expiresAt < new Date() ? 'closed' : 'endTime']: poll.expiresAt,
[poll.multiple ? 'anyOf' : 'oneOf']: poll.choices.map((text, i) => ({
type: 'Note',
@@ -432,11 +427,13 @@ export class ApRendererService {
attributedTo,
summary: summary ?? undefined,
content: content ?? undefined,
- _misskey_content: text,
- source: {
- content: text,
- mediaType: 'text/x.misskeymarkdown',
- },
+ ...(noMisskeyContent ? {} : {
+ _misskey_content: text,
+ source: {
+ content: text,
+ mediaType: 'text/x.misskeymarkdown',
+ },
+ }),
_misskey_quote: quote,
quoteUrl: quote,
published: this.idService.parse(note.id).date.toISOString(),
@@ -572,7 +569,7 @@ export class ApRendererService {
@bindThis
public renderUndo(object: string | IObject, user: { id: MiUser['id'] }): IUndo {
- const id = typeof object !== 'string' && typeof object.id === 'string' && object.id.startsWith(this.config.url) ? `${object.id}/undo` : undefined;
+ const id = typeof object !== 'string' && typeof object.id === 'string' && new URL(object.id).origin === this.config.url ? `${object.id}/undo` : undefined;
return {
type: 'Undo',
@@ -625,6 +622,7 @@ export class ApRendererService {
'https://www.w3.org/ns/activitystreams',
'https://w3id.org/security/v1',
{
+ Key: 'sec:Key',
// as non-standards
manuallyApprovesFollowers: 'as:manuallyApprovesFollowers',
sensitive: 'as:sensitive',
diff --git a/packages/backend/src/core/activitypub/ApRequestService.ts b/packages/backend/src/core/activitypub/ApRequestService.ts
index b59ce5241..93ac8ce9a 100644
--- a/packages/backend/src/core/activitypub/ApRequestService.ts
+++ b/packages/backend/src/core/activitypub/ApRequestService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -14,6 +14,7 @@ import { HttpRequestService } from '@/core/HttpRequestService.js';
import { LoggerService } from '@/core/LoggerService.js';
import { bindThis } from '@/decorators.js';
import type Logger from '@/logger.js';
+import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/validator.js';
type Request = {
url: string;
@@ -34,9 +35,9 @@ type PrivateKey = {
};
export class ApRequestCreator {
- static createSignedPost(args: { key: PrivateKey, url: string, body: string, additionalHeaders: Record }): Signed {
+ static createSignedPost(args: { key: PrivateKey, url: string, body: string, digest?: string, additionalHeaders: Record }): Signed {
const u = new URL(args.url);
- const digestHeader = `SHA-256=${crypto.createHash('sha256').update(args.body).digest('base64')}`;
+ const digestHeader = args.digest ?? this.createDigest(args.body);
const request: Request = {
url: u.href,
@@ -59,6 +60,10 @@ export class ApRequestCreator {
};
}
+ static createDigest(body: string) {
+ return `SHA-256=${crypto.createHash('sha256').update(body).digest('base64')}`;
+ }
+
static createSignedGet(args: { key: PrivateKey, url: string, additionalHeaders: Record }): Signed {
const u = new URL(args.url);
@@ -66,7 +71,7 @@ export class ApRequestCreator {
url: u.href,
method: 'GET',
headers: this.#objectAssignWithLcKey({
- 'Accept': 'application/activity+json, application/ld+json',
+ 'Accept': 'application/activity+json, application/ld+json; profile="https://www.w3.org/ns/activitystreams"',
'Date': new Date().toUTCString(),
'Host': new URL(args.url).host,
}, args.additionalHeaders),
@@ -145,8 +150,8 @@ export class ApRequestService {
}
@bindThis
- public async signedPost(user: { id: MiUser['id'] }, url: string, object: unknown): Promise {
- const body = JSON.stringify(object);
+ public async signedPost(user: { id: MiUser['id'] }, url: string, object: unknown, digest?: string): Promise {
+ const body = typeof object === 'string' ? object : JSON.stringify(object);
const keypair = await this.userKeypairService.getUserKeypair(user.id);
@@ -157,6 +162,7 @@ export class ApRequestService {
},
url,
body,
+ digest,
additionalHeaders: {
},
});
@@ -190,6 +196,9 @@ export class ApRequestService {
const res = await this.httpRequestService.send(url, {
method: req.request.method,
headers: req.request.headers,
+ }, {
+ throwErrorWhenResponseNotOk: true,
+ validators: [validateContentTypeSetAsActivityPub],
});
return await res.json();
diff --git a/packages/backend/src/core/activitypub/ApResolverService.ts b/packages/backend/src/core/activitypub/ApResolverService.ts
index 9ca63c9ec..bb3c40f09 100644
--- a/packages/backend/src/core/activitypub/ApResolverService.ts
+++ b/packages/backend/src/core/activitypub/ApResolverService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -105,7 +105,7 @@ export class Resolver {
const object = (this.user
? await this.apRequestService.signedGet(value, this.user) as IObject
- : await this.httpRequestService.getJson(value, 'application/activity+json, application/ld+json')) as IObject;
+ : await this.httpRequestService.getActivityJson(value)) as IObject;
if (
Array.isArray(object['@context']) ?
diff --git a/packages/backend/src/core/activitypub/LdSignatureService.ts b/packages/backend/src/core/activitypub/LdSignatureService.ts
index 39b5ff8ab..9de184336 100644
--- a/packages/backend/src/core/activitypub/LdSignatureService.ts
+++ b/packages/backend/src/core/activitypub/LdSignatureService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -8,6 +8,7 @@ import { Injectable } from '@nestjs/common';
import { HttpRequestService } from '@/core/HttpRequestService.js';
import { bindThis } from '@/decorators.js';
import { CONTEXTS } from './misc/contexts.js';
+import { validateContentTypeSetAsJsonLD } from './misc/validator.js';
import type { JsonLdDocument } from 'jsonld';
import type { JsonLd, RemoteDocument } from 'jsonld/jsonld-spec.js';
@@ -133,7 +134,10 @@ class LdSignature {
},
timeout: this.loderTimeout,
},
- { throwErrorWhenResponseNotOk: false },
+ {
+ throwErrorWhenResponseNotOk: false,
+ validators: [validateContentTypeSetAsJsonLD],
+ },
).then(res => {
if (!res.ok) {
throw new Error(`${res.status} ${res.statusText}`);
diff --git a/packages/backend/src/core/activitypub/misc/contexts.ts b/packages/backend/src/core/activitypub/misc/contexts.ts
index 71c440e5c..88afdefcd 100644
--- a/packages/backend/src/core/activitypub/misc/contexts.ts
+++ b/packages/backend/src/core/activitypub/misc/contexts.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/activitypub/misc/validator.ts b/packages/backend/src/core/activitypub/misc/validator.ts
new file mode 100644
index 000000000..690beeffe
--- /dev/null
+++ b/packages/backend/src/core/activitypub/misc/validator.ts
@@ -0,0 +1,39 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import type { Response } from 'node-fetch';
+
+export function validateContentTypeSetAsActivityPub(response: Response): void {
+ const contentType = (response.headers.get('content-type') ?? '').toLowerCase();
+
+ if (contentType === '') {
+ throw new Error('Validate content type of AP response: No content-type header');
+ }
+ if (
+ contentType.startsWith('application/activity+json') ||
+ (contentType.startsWith('application/ld+json;') && contentType.includes('https://www.w3.org/ns/activitystreams'))
+ ) {
+ return;
+ }
+ throw new Error('Validate content type of AP response: Content type is not application/activity+json or application/ld+json');
+}
+
+const plusJsonSuffixRegex = /^\s*(application|text)\/[a-zA-Z0-9\.\-\+]+\+json\s*(;|$)/;
+
+export function validateContentTypeSetAsJsonLD(response: Response): void {
+ const contentType = (response.headers.get('content-type') ?? '').toLowerCase();
+
+ if (contentType === '') {
+ throw new Error('Validate content type of JSON LD: No content-type header');
+ }
+ if (
+ contentType.startsWith('application/ld+json') ||
+ contentType.startsWith('application/json') ||
+ plusJsonSuffixRegex.test(contentType)
+ ) {
+ return;
+ }
+ throw new Error('Validate content type of JSON LD: Content type is not application/ld+json or application/json');
+}
diff --git a/packages/backend/src/core/activitypub/models/ApImageService.ts b/packages/backend/src/core/activitypub/models/ApImageService.ts
index 7c76ff699..9a6db1db8 100644
--- a/packages/backend/src/core/activitypub/models/ApImageService.ts
+++ b/packages/backend/src/core/activitypub/models/ApImageService.ts
@@ -1,13 +1,13 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
import { DI } from '@/di-symbols.js';
import type { DriveFilesRepository } from '@/models/_.js';
-import type { MiDriveFile } from '@/models/DriveFile.js';
import type { MiRemoteUser } from '@/models/User.js';
+import type { MiDriveFile } from '@/models/DriveFile.js';
import { truncate } from '@/misc/truncate.js';
import { DB_MAX_IMAGE_COMMENT_LENGTH } from '@/const.js';
import { DriveService } from '@/core/DriveService.js';
diff --git a/packages/backend/src/core/activitypub/models/ApMentionService.ts b/packages/backend/src/core/activitypub/models/ApMentionService.ts
index 9aa8ba5ed..0ced7e88a 100644
--- a/packages/backend/src/core/activitypub/models/ApMentionService.ts
+++ b/packages/backend/src/core/activitypub/models/ApMentionService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -8,6 +8,7 @@ import promiseLimit from 'promise-limit';
import type { MiUser } from '@/models/_.js';
import { toArray, unique } from '@/misc/prelude/array.js';
import { bindThis } from '@/decorators.js';
+import { isNotNull } from '@/misc/is-not-null.js';
import { isMention } from '../type.js';
import { Resolver } from '../ApResolverService.js';
import { ApPersonService } from './ApPersonService.js';
@@ -27,7 +28,7 @@ export class ApMentionService {
const limit = promiseLimit(2);
const mentionedUsers = (await Promise.all(
hrefs.map(x => limit(() => this.apPersonService.resolvePerson(x, resolver).catch(() => null))),
- )).filter((x): x is MiUser => x != null);
+ )).filter(isNotNull);
return mentionedUsers;
}
diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts
index 1979cdda9..4da85be74 100644
--- a/packages/backend/src/core/activitypub/models/ApNoteService.ts
+++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -7,7 +7,7 @@ import { forwardRef, Inject, Injectable } from '@nestjs/common';
import promiseLimit from 'promise-limit';
import { In } from 'typeorm';
import { DI } from '@/di-symbols.js';
-import type { PollsRepository, EmojisRepository } from '@/models/_.js';
+import type { UsersRepository, PollsRepository, EmojisRepository } from '@/models/_.js';
import type { Config } from '@/config.js';
import type { MiRemoteUser } from '@/models/User.js';
import type { MiNote } from '@/models/Note.js';
@@ -24,6 +24,8 @@ import { StatusError } from '@/misc/status-error.js';
import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js';
import { checkHttps } from '@/misc/check-https.js';
+import { IdentifiableError } from '@/misc/identifiable-error.js';
+import { isNotNull } from '@/misc/is-not-null.js';
import { getOneApId, getApId, getOneApHrefNullable, validPost, isEmoji, getApType } from '../type.js';
import { ApLoggerService } from '../ApLoggerService.js';
import { ApMfmService } from '../ApMfmService.js';
@@ -46,6 +48,9 @@ export class ApNoteService {
@Inject(DI.config)
private config: Config,
+ @Inject(DI.usersRepository)
+ private usersRepository: UsersRepository,
+
@Inject(DI.pollsRepository)
private pollsRepository: PollsRepository,
@@ -92,6 +97,10 @@ export class ApNoteService {
return new Error(`invalid Note: attributedTo has different host. expected: ${expectHost}, actual: ${actualHost}`);
}
+ if (object.published && !this.idService.isSafeT(new Date(object.published).valueOf())) {
+ return new Error('invalid Note: published timestamp is malformed');
+ }
+
return null;
}
@@ -113,6 +122,8 @@ export class ApNoteService {
// eslint-disable-next-line no-param-reassign
if (resolver == null) resolver = this.apResolverService.createResolver();
+ const meta = await this.metaService.fetch();
+
const object = await resolver.resolve(value);
const entryUri = getApId(value);
@@ -122,8 +133,9 @@ export class ApNoteService {
resolver: { history: resolver.getHistory() },
value,
object,
+ error: err
});
- throw new Error('invalid note');
+ throw err;
}
const note = object as IPost;
@@ -147,11 +159,47 @@ export class ApNoteService {
throw new Error('invalid note.attributedTo: ' + note.attributedTo);
}
- const actor = await this.apPersonService.resolvePerson(getOneApId(note.attributedTo), resolver) as MiRemoteUser;
+ const uri = getOneApId(note.attributedTo);
- // 投稿者が凍結されていたらスキップ
+ // ローカルで投稿者を検索し、もし凍結されていたらスキップ
+ const cachedActor = await this.apPersonService.fetchPerson(uri) as MiRemoteUser;
+ if (cachedActor && cachedActor.isSuspended) {
+ throw new IdentifiableError('85ab9bd7-3a41-4530-959d-f07073900109', `User ${cachedActor.id} has been suspended.`);
+ }
+
+ const apMentions = await this.apMentionService.extractApMentions(note.tag, resolver);
+ const apHashtags = extractApHashtags(note.tag);
+
+ const cw = note.summary === '' ? null : note.summary;
+
+ // テキストのパース
+ let text: string | null = null;
+ if (note.source?.mediaType === 'text/x.misskeymarkdown' && typeof note.source.content === 'string') {
+ text = note.source.content;
+ } else if (typeof note._misskey_content !== 'undefined') {
+ text = note._misskey_content;
+ } else if (typeof note.content === 'string') {
+ text = this.apMfmService.htmlToMfm(note.content, note.tag);
+ }
+
+ const poll = await this.apQuestionService.extractPollFromQuestion(note, resolver).catch(() => undefined);
+
+ //#region Contents Check
+ // 添付ファイルとユーザーをこのサーバーで登録する前に内容をチェックする
+ /**
+ * 禁止ワードチェック
+ */
+ const hasProhibitedWords = await this.noteCreateService.checkProhibitedWordsContain(meta.prohibitedWords, { cw, text, pollChoices: poll?.choices });
+ if (hasProhibitedWords) {
+ throw new IdentifiableError('689ee33f-f97c-479a-ac49-1b9f8140af99', 'Notes including prohibited words are not allowed.');
+ }
+ //#endregion
+
+ const actor = cachedActor ?? await this.apPersonService.resolvePerson(uri, resolver) as MiRemoteUser;
+
+ // 解決した投稿者が凍結されていたらスキップ
if (actor.isSuspended) {
- throw new Error('actor has been suspended');
+ throw new IdentifiableError('85ab9bd7-3a41-4530-959d-f07073900109', `User ${actor.id} has been suspended.`);
}
const noteAudience = await this.apAudienceService.parseAudience(actor, note.to, note.cc, resolver);
@@ -166,8 +214,7 @@ export class ApNoteService {
}
}
- const apMentions = await this.apMentionService.extractApMentions(note.tag, resolver);
- const apHashtags = extractApHashtags(note.tag);
+ const isSensitiveMediaHost = this.utilityService.isSensitiveMediaHost(meta.sensitiveMediaHosts, this.utilityService.extractDbHost(note.id ?? entryUri));
// 添付ファイル
// TODO: attachmentは必ずしもImageではない
@@ -176,7 +223,7 @@ export class ApNoteService {
const files = (await Promise.all(toArray(note.attachment).map(attach => (
limit(() => this.apImageService.resolveImage(actor, {
...attach,
- sensitive: note.sensitive, // Noteがsensitiveなら添付もsensitiveにする
+ sensitive: isSensitiveMediaHost || note.sensitive, // Noteがsensitiveなら添付もsensitiveにする
}))
))));
@@ -212,12 +259,12 @@ export class ApNoteService {
return { status: 'ok', res };
} catch (e) {
return {
- status: (e instanceof StatusError && e.isClientError) ? 'permerror' : 'temperror',
+ status: (e instanceof StatusError && !e.isRetryable) ? 'permerror' : 'temperror',
};
}
};
- const uris = unique([note._misskey_quote, note.quoteUrl].filter((x): x is string => typeof x === 'string'));
+ const uris = unique([note._misskey_quote, note.quoteUrl].filter(isNotNull));
const results = await Promise.all(uris.map(tryResolveNote));
quote = results.filter((x): x is { status: 'ok', res: MiNote } => x.status === 'ok').map(x => x.res).at(0);
@@ -228,18 +275,6 @@ export class ApNoteService {
}
}
- const cw = note.summary === '' ? null : note.summary;
-
- // テキストのパース
- let text: string | null = null;
- if (note.source?.mediaType === 'text/x.misskeymarkdown' && typeof note.source.content === 'string') {
- text = note.source.content;
- } else if (typeof note._misskey_content !== 'undefined') {
- text = note._misskey_content;
- } else if (typeof note.content === 'string') {
- text = this.apMfmService.htmlToMfm(note.content, note.tag);
- }
-
// vote
if (reply && reply.hasPoll) {
const poll = await this.pollsRepository.findOneByOrFail({ noteId: reply.id });
@@ -269,8 +304,6 @@ export class ApNoteService {
const apEmojis = emojis.map(emoji => emoji.name);
- const poll = await this.apQuestionService.extractPollFromQuestion(note, resolver).catch(() => undefined);
-
try {
return await this.noteCreateService.create(actor, {
createdAt: note.published ? new Date(note.published) : null,
@@ -327,7 +360,7 @@ export class ApNoteService {
if (exist) return exist;
//#endregion
- if (uri.startsWith(this.config.url)) {
+ if (new URL(uri).origin === this.config.url) {
throw new StatusError('cannot resolve local note', 400, 'cannot resolve local note');
}
diff --git a/packages/backend/src/core/activitypub/models/ApPersonService.ts b/packages/backend/src/core/activitypub/models/ApPersonService.ts
index bf38d5fd6..56e4e521e 100644
--- a/packages/backend/src/core/activitypub/models/ApPersonService.ts
+++ b/packages/backend/src/core/activitypub/models/ApPersonService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -20,6 +20,7 @@ import type Logger from '@/logger.js';
import type { MiNote } from '@/models/Note.js';
import type { IdService } from '@/core/IdService.js';
import type { MfmService } from '@/core/MfmService.js';
+import type { RoleService } from '@/core/RoleService.js';
import { toArray } from '@/misc/prelude/array.js';
import type { GlobalEventService } from '@/core/GlobalEventService.js';
import type { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
@@ -38,6 +39,7 @@ import { MetaService } from '@/core/MetaService.js';
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
import type { AccountMoveService } from '@/core/AccountMoveService.js';
import { checkHttps } from '@/misc/check-https.js';
+import { isNotNull } from '@/misc/is-not-null.js';
import { getApId, getApType, getOneApHrefNullable, isActor, isCollection, isCollectionOrOrderedCollection, isPropertyValue } from '../type.js';
import { extractApHashtags } from './tag.js';
import type { OnModuleInit } from '@nestjs/common';
@@ -75,6 +77,7 @@ export class ApPersonService implements OnModuleInit {
private instanceChart: InstanceChart;
private apLoggerService: ApLoggerService;
private accountMoveService: AccountMoveService;
+ private roleService: RoleService;
private logger: Logger;
constructor(
@@ -123,6 +126,7 @@ export class ApPersonService implements OnModuleInit {
this.instanceChart = this.moduleRef.get('InstanceChart');
this.apLoggerService = this.moduleRef.get('ApLoggerService');
this.accountMoveService = this.moduleRef.get('AccountMoveService');
+ this.roleService = this.moduleRef.get('RoleService');
this.logger = this.apLoggerService.logger;
}
@@ -153,6 +157,21 @@ export class ApPersonService implements OnModuleInit {
throw new Error('invalid Actor: wrong inbox');
}
+ try {
+ new URL(x.inbox);
+ } catch {
+ throw new Error('invalid Actor: wrong inbox');
+ }
+
+ const sharedInbox = x.sharedInbox ?? x.endpoints?.sharedInbox;
+ if (typeof sharedInbox === 'string') {
+ try {
+ new URL(sharedInbox);
+ } catch {
+ throw new Error('invalid Actor: wrong sharedInbox');
+ }
+ }
+
if (!(typeof x.preferredUsername === 'string' && x.preferredUsername.length > 0 && x.preferredUsername.length <= 128 && /^\w([\w-.]*\w)?$/.test(x.preferredUsername))) {
throw new Error('invalid Actor: wrong username');
}
@@ -206,7 +225,7 @@ export class ApPersonService implements OnModuleInit {
if (cached) return cached;
// URIがこのサーバーを指しているならデータベースからフェッチ
- if (uri.startsWith(`${this.config.url}/`)) {
+ if (new URL(uri).origin === this.config.url) {
const id = uri.split('/').pop();
const u = await this.usersRepository.findOneBy({ id }) as MiLocalUser | null;
if (u) this.cacheService.uriPersonCache.set(uri, u);
@@ -225,20 +244,37 @@ export class ApPersonService implements OnModuleInit {
return null;
}
- private async resolveAvatarAndBanner(user: MiRemoteUser, icon: any, image: any): Promise> {
+ private async resolveAvatarAndBanner(user: MiRemoteUser, icon: any, image: any): Promise>> {
+ if (user == null) throw new Error('failed to create user: user is null');
+
const [avatar, banner] = await Promise.all([icon, image].map(img => {
- if (img == null) return null;
- if (user == null) throw new Error('failed to create user: user is null');
+ // if we have an explicitly missing image, return an
+ // explicitly-null set of values
+ if ((img == null) || (typeof img === 'object' && img.url == null)) {
+ return { id: null, url: null, blurhash: null };
+ }
+
return this.apImageService.resolveImage(user, img).catch(() => null);
}));
+ /*
+ we don't want to return nulls on errors! if the database fields
+ are already null, nothing changes; if the database has old
+ values, we should keep those. The exception is if the remote has
+ actually removed the images: in that case, the block above
+ returns the special {id:null}&c value, and we return those
+ */
return {
- avatarId: avatar?.id ?? null,
- bannerId: banner?.id ?? null,
- avatarUrl: avatar ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar') : null,
- bannerUrl: banner ? this.driveFileEntityService.getPublicUrl(banner) : null,
- avatarBlurhash: avatar?.blurhash ?? null,
- bannerBlurhash: banner?.blurhash ?? null,
+ ...( avatar ? {
+ avatarId: avatar.id,
+ avatarUrl: avatar.url ? this.driveFileEntityService.getPublicUrl(avatar, 'avatar') : null,
+ avatarBlurhash: avatar.blurhash,
+ } : {}),
+ ...( banner ? {
+ bannerId: banner.id,
+ bannerUrl: banner.url ? this.driveFileEntityService.getPublicUrl(banner) : null,
+ bannerBlurhash: banner.blurhash,
+ } : {}),
};
}
@@ -249,7 +285,7 @@ export class ApPersonService implements OnModuleInit {
public async createPerson(uri: string, resolver?: Resolver): Promise {
if (typeof uri !== 'string') throw new Error('uri is not string');
- if (uri.startsWith(this.config.url)) {
+ if (new URL(uri).origin === this.config.url) {
throw new StatusError('cannot resolve local user', 400, 'cannot resolve local user');
}
@@ -286,7 +322,7 @@ export class ApPersonService implements OnModuleInit {
const emojis = await this.apNoteService.extractEmojis(person.tag ?? [], host)
.then(_emojis => _emojis.map(emoji => emoji.name))
.catch(err => {
- this.logger.error('error occurred while fetching user emojis', { stack: err });
+ this.logger.error('error occurred while fetching user emojis', { error: err });
return [];
});
//#endregion
@@ -354,7 +390,7 @@ export class ApPersonService implements OnModuleInit {
user = u as MiRemoteUser;
} else {
- this.logger.error(e instanceof Error ? e : new Error(e as string));
+ this.logger.error('error occurred while creating user', { error: e });
throw e;
}
}
@@ -387,7 +423,7 @@ export class ApPersonService implements OnModuleInit {
// Register to the cache
this.cacheService.uriPersonCache.set(user.uri, user);
} catch (err) {
- this.logger.error('error occurred while fetching user avatar/banner', { stack: err });
+ this.logger.error('error occurred while fetching user avatar/banner', { error: err });
}
//#endregion
@@ -411,7 +447,7 @@ export class ApPersonService implements OnModuleInit {
if (typeof uri !== 'string') throw new Error('uri is not string');
// URIがこのサーバーを指しているならスキップ
- if (uri.startsWith(`${this.config.url}/`)) return;
+ if (new URL(uri).origin === this.config.url) return;
//#region このサーバーに既に登録されているか
const exist = await this.fetchPerson(uri) as MiRemoteUser | null;
@@ -447,6 +483,8 @@ export class ApPersonService implements OnModuleInit {
throw new Error('unexpected schema of person url: ' + url);
}
+ const policy = await this.roleService.getUserPolicies(exist.id);
+
const updates = {
lastFetchedAt: new Date(),
inbox: person.inbox,
@@ -462,7 +500,7 @@ export class ApPersonService implements OnModuleInit {
movedToUri: person.movedTo ?? null,
alsoKnownAs: person.alsoKnownAs ?? null,
isExplorable: person.discoverable,
- ...(await this.resolveAvatarAndBanner(exist, person.icon, person.image).catch(() => ({}))),
+ ...((policy.canUpdateAvatar || policy.canUpdateBanner) ? await this.resolveAvatarAndBanner(exist, policy.canUpdateAvatar ? person.icon : exist.avatarUrl, policy.canUpdateBanner ? person.image : exist.bannerUrl).catch(() => ({})) : {}),
} as Partial & Pick;
const moving = ((): boolean => {
@@ -619,7 +657,7 @@ export class ApPersonService implements OnModuleInit {
// とりあえずidを別の時間で生成して順番を維持
let td = 0;
- for (const note of featuredNotes.filter((note): note is MiNote => note != null)) {
+ for (const note of featuredNotes.filter(isNotNull)) {
td -= 1000;
transactionalEntityManager.insert(MiUserNotePining, {
id: this.idService.gen(Date.now() + td),
@@ -654,7 +692,7 @@ export class ApPersonService implements OnModuleInit {
await this.updatePerson(src.movedToUri, undefined, undefined, [...movePreventUris, src.uri]);
dst = await this.fetchPerson(src.movedToUri) ?? dst;
} else {
- if (src.movedToUri.startsWith(`${this.config.url}/`)) {
+ if (new URL(src.movedToUri).origin === this.config.url) {
// ローカルユーザーっぽいのにfetchPersonで見つからないということはmovedToUriが間違っている
return 'failed: movedTo is local but not found';
}
diff --git a/packages/backend/src/core/activitypub/models/ApQuestionService.ts b/packages/backend/src/core/activitypub/models/ApQuestionService.ts
index 27bd62268..4e3df00e0 100644
--- a/packages/backend/src/core/activitypub/models/ApQuestionService.ts
+++ b/packages/backend/src/core/activitypub/models/ApQuestionService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -10,6 +10,7 @@ import type { Config } from '@/config.js';
import type { IPoll } from '@/models/Poll.js';
import type Logger from '@/logger.js';
import { bindThis } from '@/decorators.js';
+import { isNotNull } from '@/misc/is-not-null.js';
import { isQuestion } from '../type.js';
import { ApLoggerService } from '../ApLoggerService.js';
import { ApResolverService } from '../ApResolverService.js';
@@ -51,7 +52,7 @@ export class ApQuestionService {
const choices = question[multiple ? 'anyOf' : 'oneOf']
?.map((x) => x.name)
- .filter((x): x is string => typeof x === 'string')
+ .filter(isNotNull)
?? [];
const votes = question[multiple ? 'anyOf' : 'oneOf']?.map((x) => x.replies?.totalItems ?? x._misskey_votes ?? 0);
@@ -70,7 +71,7 @@ export class ApQuestionService {
if (uri == null) throw new Error('uri is null');
// URIがこのサーバーを指しているならスキップ
- if (uri.startsWith(this.config.url + '/')) throw new Error('uri points local');
+ if (new URL(uri).origin === this.config.url) throw new Error('uri points local');
//#region このサーバーに既に登録されているか
const note = await this.notesRepository.findOneBy({ uri });
diff --git a/packages/backend/src/core/activitypub/models/icon.ts b/packages/backend/src/core/activitypub/models/icon.ts
index 9fed78020..5722507a3 100644
--- a/packages/backend/src/core/activitypub/models/icon.ts
+++ b/packages/backend/src/core/activitypub/models/icon.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/activitypub/models/identifier.ts b/packages/backend/src/core/activitypub/models/identifier.ts
index 22a7b0a76..dce4f410b 100644
--- a/packages/backend/src/core/activitypub/models/identifier.ts
+++ b/packages/backend/src/core/activitypub/models/identifier.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/activitypub/models/tag.ts b/packages/backend/src/core/activitypub/models/tag.ts
index 772ea1186..e7ceec326 100644
--- a/packages/backend/src/core/activitypub/models/tag.ts
+++ b/packages/backend/src/core/activitypub/models/tag.ts
@@ -1,9 +1,10 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { toArray } from '@/misc/prelude/array.js';
+import { isNotNull } from '@/misc/is-not-null.js';
import { isHashtag } from '../type.js';
import type { IObject, IApHashtag } from '../type.js';
@@ -15,7 +16,7 @@ export function extractApHashtags(tags: IObject | IObject[] | null | undefined):
return hashtags.map(tag => {
const m = tag.name.match(/^#(.+)/);
return m ? m[1] : null;
- }).filter((x): x is string => x != null);
+ }).filter(isNotNull);
}
export function extractApHashtagObjects(tags: IObject | IObject[] | null | undefined): IApHashtag[] {
diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts
index d9fcc9906..b43dddad6 100644
--- a/packages/backend/src/core/activitypub/type.ts
+++ b/packages/backend/src/core/activitypub/type.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/ChartLoggerService.ts b/packages/backend/src/core/chart/ChartLoggerService.ts
index bd90efec6..afc728d56 100644
--- a/packages/backend/src/core/chart/ChartLoggerService.ts
+++ b/packages/backend/src/core/chart/ChartLoggerService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/ChartManagementService.ts b/packages/backend/src/core/chart/ChartManagementService.ts
index f751a68cb..79681370a 100644
--- a/packages/backend/src/core/chart/ChartManagementService.ts
+++ b/packages/backend/src/core/chart/ChartManagementService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/active-users.ts b/packages/backend/src/core/chart/charts/active-users.ts
index f0918e059..05905f378 100644
--- a/packages/backend/src/core/chart/charts/active-users.ts
+++ b/packages/backend/src/core/chart/charts/active-users.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/ap-request.ts b/packages/backend/src/core/chart/charts/ap-request.ts
index 03c9b42be..04e771a95 100644
--- a/packages/backend/src/core/chart/charts/ap-request.ts
+++ b/packages/backend/src/core/chart/charts/ap-request.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/drive.ts b/packages/backend/src/core/chart/charts/drive.ts
index bbcbf1a95..613e074a9 100644
--- a/packages/backend/src/core/chart/charts/drive.ts
+++ b/packages/backend/src/core/chart/charts/drive.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/active-users.ts b/packages/backend/src/core/chart/charts/entities/active-users.ts
index e68022ef2..fc2b88a2b 100644
--- a/packages/backend/src/core/chart/charts/entities/active-users.ts
+++ b/packages/backend/src/core/chart/charts/entities/active-users.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/ap-request.ts b/packages/backend/src/core/chart/charts/entities/ap-request.ts
index a82451525..93e47e081 100644
--- a/packages/backend/src/core/chart/charts/entities/ap-request.ts
+++ b/packages/backend/src/core/chart/charts/entities/ap-request.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/drive.ts b/packages/backend/src/core/chart/charts/entities/drive.ts
index 4a56bd45c..4ea16da38 100644
--- a/packages/backend/src/core/chart/charts/entities/drive.ts
+++ b/packages/backend/src/core/chart/charts/entities/drive.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/federation.ts b/packages/backend/src/core/chart/charts/entities/federation.ts
index e067c71a7..5ed780434 100644
--- a/packages/backend/src/core/chart/charts/entities/federation.ts
+++ b/packages/backend/src/core/chart/charts/entities/federation.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/instance.ts b/packages/backend/src/core/chart/charts/entities/instance.ts
index 4ea10d56d..d0cac3e73 100644
--- a/packages/backend/src/core/chart/charts/entities/instance.ts
+++ b/packages/backend/src/core/chart/charts/entities/instance.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/notes.ts b/packages/backend/src/core/chart/charts/entities/notes.ts
index 26e2529b1..325236ab3 100644
--- a/packages/backend/src/core/chart/charts/entities/notes.ts
+++ b/packages/backend/src/core/chart/charts/entities/notes.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/per-user-drive.ts b/packages/backend/src/core/chart/charts/entities/per-user-drive.ts
index aec3dd514..25d4619dd 100644
--- a/packages/backend/src/core/chart/charts/entities/per-user-drive.ts
+++ b/packages/backend/src/core/chart/charts/entities/per-user-drive.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/per-user-following.ts b/packages/backend/src/core/chart/charts/entities/per-user-following.ts
index afb581305..1618bd22f 100644
--- a/packages/backend/src/core/chart/charts/entities/per-user-following.ts
+++ b/packages/backend/src/core/chart/charts/entities/per-user-following.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/per-user-notes.ts b/packages/backend/src/core/chart/charts/entities/per-user-notes.ts
index 60a0b01c8..30404b2e4 100644
--- a/packages/backend/src/core/chart/charts/entities/per-user-notes.ts
+++ b/packages/backend/src/core/chart/charts/entities/per-user-notes.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/per-user-pv.ts b/packages/backend/src/core/chart/charts/entities/per-user-pv.ts
index 78d4464d7..7a903afad 100644
--- a/packages/backend/src/core/chart/charts/entities/per-user-pv.ts
+++ b/packages/backend/src/core/chart/charts/entities/per-user-pv.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/per-user-reactions.ts b/packages/backend/src/core/chart/charts/entities/per-user-reactions.ts
index 761101d47..bb62bb238 100644
--- a/packages/backend/src/core/chart/charts/entities/per-user-reactions.ts
+++ b/packages/backend/src/core/chart/charts/entities/per-user-reactions.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/test-grouped.ts b/packages/backend/src/core/chart/charts/entities/test-grouped.ts
index 15eb1fd1f..599c1dc13 100644
--- a/packages/backend/src/core/chart/charts/entities/test-grouped.ts
+++ b/packages/backend/src/core/chart/charts/entities/test-grouped.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/test-intersection.ts b/packages/backend/src/core/chart/charts/entities/test-intersection.ts
index 2ef63977a..d29b39716 100644
--- a/packages/backend/src/core/chart/charts/entities/test-intersection.ts
+++ b/packages/backend/src/core/chart/charts/entities/test-intersection.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/test-unique.ts b/packages/backend/src/core/chart/charts/entities/test-unique.ts
index 56233585d..bdaa1716e 100644
--- a/packages/backend/src/core/chart/charts/entities/test-unique.ts
+++ b/packages/backend/src/core/chart/charts/entities/test-unique.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/test.ts b/packages/backend/src/core/chart/charts/entities/test.ts
index 163db4e79..c80ff55c9 100644
--- a/packages/backend/src/core/chart/charts/entities/test.ts
+++ b/packages/backend/src/core/chart/charts/entities/test.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/entities/users.ts b/packages/backend/src/core/chart/charts/entities/users.ts
index c7bffd3fd..f94a5029d 100644
--- a/packages/backend/src/core/chart/charts/entities/users.ts
+++ b/packages/backend/src/core/chart/charts/entities/users.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/federation.ts b/packages/backend/src/core/chart/charts/federation.ts
index fc474b002..5e4555ee9 100644
--- a/packages/backend/src/core/chart/charts/federation.ts
+++ b/packages/backend/src/core/chart/charts/federation.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/instance.ts b/packages/backend/src/core/chart/charts/instance.ts
index 9df0afb02..97f3bc6f2 100644
--- a/packages/backend/src/core/chart/charts/instance.ts
+++ b/packages/backend/src/core/chart/charts/instance.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/notes.ts b/packages/backend/src/core/chart/charts/notes.ts
index df3295dba..f763b5fff 100644
--- a/packages/backend/src/core/chart/charts/notes.ts
+++ b/packages/backend/src/core/chart/charts/notes.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/per-user-drive.ts b/packages/backend/src/core/chart/charts/per-user-drive.ts
index 18354359c..404964d8b 100644
--- a/packages/backend/src/core/chart/charts/per-user-drive.ts
+++ b/packages/backend/src/core/chart/charts/per-user-drive.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/per-user-following.ts b/packages/backend/src/core/chart/charts/per-user-following.ts
index 79bff2cb6..588ac638d 100644
--- a/packages/backend/src/core/chart/charts/per-user-following.ts
+++ b/packages/backend/src/core/chart/charts/per-user-following.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/per-user-notes.ts b/packages/backend/src/core/chart/charts/per-user-notes.ts
index 0db0e6f07..e4900772b 100644
--- a/packages/backend/src/core/chart/charts/per-user-notes.ts
+++ b/packages/backend/src/core/chart/charts/per-user-notes.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/per-user-pv.ts b/packages/backend/src/core/chart/charts/per-user-pv.ts
index cf1b4c71f..31708fefa 100644
--- a/packages/backend/src/core/chart/charts/per-user-pv.ts
+++ b/packages/backend/src/core/chart/charts/per-user-pv.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/per-user-reactions.ts b/packages/backend/src/core/chart/charts/per-user-reactions.ts
index 9f4f6e965..c29c4d287 100644
--- a/packages/backend/src/core/chart/charts/per-user-reactions.ts
+++ b/packages/backend/src/core/chart/charts/per-user-reactions.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/test-grouped.ts b/packages/backend/src/core/chart/charts/test-grouped.ts
index 00fb87223..7a2844f4e 100644
--- a/packages/backend/src/core/chart/charts/test-grouped.ts
+++ b/packages/backend/src/core/chart/charts/test-grouped.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/test-intersection.ts b/packages/backend/src/core/chart/charts/test-intersection.ts
index 45a7e805c..b8d0556c9 100644
--- a/packages/backend/src/core/chart/charts/test-intersection.ts
+++ b/packages/backend/src/core/chart/charts/test-intersection.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/test-unique.ts b/packages/backend/src/core/chart/charts/test-unique.ts
index e9d38eaf1..f94e00805 100644
--- a/packages/backend/src/core/chart/charts/test-unique.ts
+++ b/packages/backend/src/core/chart/charts/test-unique.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/test.ts b/packages/backend/src/core/chart/charts/test.ts
index 4dd6063b5..a90dc8f99 100644
--- a/packages/backend/src/core/chart/charts/test.ts
+++ b/packages/backend/src/core/chart/charts/test.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/charts/users.ts b/packages/backend/src/core/chart/charts/users.ts
index c2026c2ae..d148fc629 100644
--- a/packages/backend/src/core/chart/charts/users.ts
+++ b/packages/backend/src/core/chart/charts/users.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/chart/core.ts b/packages/backend/src/core/chart/core.ts
index 8d0a89f2d..a35d30b1b 100644
--- a/packages/backend/src/core/chart/core.ts
+++ b/packages/backend/src/core/chart/core.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -94,6 +94,29 @@ type ToJsonSchema = {
};
export function getJsonSchema(schema: S): ToJsonSchema>> {
+ const unflatten = (str: string, parent: Record) => {
+ const keys = str.split('.');
+ const key = keys.shift();
+ const nextKey = keys[0];
+
+ if (key == null) return;
+
+ if (parent.properties[key] == null) {
+ parent.properties[key] = nextKey ? {
+ type: 'object',
+ properties: {},
+ required: [],
+ } : {
+ type: 'array',
+ items: {
+ type: 'number',
+ },
+ };
+ }
+
+ if (nextKey) unflatten(keys.join('.'), parent.properties[key] as Record);
+ };
+
const jsonSchema = {
type: 'object',
properties: {} as Record,
@@ -101,10 +124,7 @@ export function getJsonSchema(schema: S): ToJsonSchema>>;
@@ -439,13 +459,15 @@ export default abstract class Chart {
}
}
- // bake unique count
+ // bake cardinality
for (const [k, v] of Object.entries(finalDiffs)) {
if (this.schema[k].uniqueIncrement) {
const name = COLUMN_PREFIX + k.replaceAll('.', COLUMN_DELIMITER) as keyof Columns;
const tempColumnName = UNIQUE_TEMP_COLUMN_PREFIX + k.replaceAll('.', COLUMN_DELIMITER) as keyof TempColumnsForUnique;
- queryForHour[name] = new Set([...(v as string[]), ...(logHour[tempColumnName] as unknown as string[])]).size;
- queryForDay[name] = new Set([...(v as string[]), ...(logDay[tempColumnName] as unknown as string[])]).size;
+ const cardinalityOfHour = new Set([...(v as string[]), ...(logHour[tempColumnName] as unknown as string[])]).size;
+ const cardinalityOfDay = new Set([...(v as string[]), ...(logDay[tempColumnName] as unknown as string[])]).size;
+ queryForHour[name] = cardinalityOfHour;
+ queryForDay[name] = cardinalityOfDay;
}
}
@@ -617,7 +639,7 @@ export default abstract class Chart {
// 要求された範囲にログがひとつもなかったら
if (logs.length === 0) {
// もっとも新しいログを持ってくる
- // (すくなくともひとつログが無いと隙間埋めできないため)
+ // (すくなくともひとつログが無いと補間できないため)
const recentLog = await repository.findOne({
where: group ? {
group: group,
@@ -632,9 +654,9 @@ export default abstract class Chart {
}
// 要求された範囲の最も古い箇所に位置するログが存在しなかったら
- } else if (!isTimeSame(new Date(logs.at(-1)!.date * 1000), gt)) {
+ } else if (!isTimeSame(new Date(logs[logs.length - 1].date * 1000), gt)) {
// 要求された範囲の最も古い箇所時点での最も新しいログを持ってきて末尾に追加する
- // (隙間埋めできないため)
+ // (補間できないため)
const outdatedLog = await repository.findOne({
where: {
date: LessThan(Chart.dateToTimestamp(gt)),
@@ -663,7 +685,7 @@ export default abstract class Chart {
if (log) {
chart.unshift(this.convertRawRecord(log));
} else {
- // 隙間埋め
+ // 補間
const latest = logs.find(l => isTimeBefore(new Date(l.date * 1000), current));
const data = latest ? this.convertRawRecord(latest) : null;
chart.unshift(this.getNewLog(data));
diff --git a/packages/backend/src/core/chart/entities.ts b/packages/backend/src/core/chart/entities.ts
index b6a1299a2..e424f2c8c 100644
--- a/packages/backend/src/core/chart/entities.ts
+++ b/packages/backend/src/core/chart/entities.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/entities/AbuseUserReportEntityService.ts b/packages/backend/src/core/entities/AbuseUserReportEntityService.ts
index 97de891ec..af44304e7 100644
--- a/packages/backend/src/core/entities/AbuseUserReportEntityService.ts
+++ b/packages/backend/src/core/entities/AbuseUserReportEntityService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -9,6 +9,8 @@ import type { AbuseUserReportsRepository } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js';
import { bindThis } from '@/decorators.js';
+import { Packed } from '@/misc/json-schema.js';
+import type { MiUser } from '@/models/User.js';
import { IdService } from '@/core/IdService.js';
import { UserEntityService } from './UserEntityService.js';
@@ -26,7 +28,8 @@ export class AbuseUserReportEntityService {
@bindThis
public async pack(
src: MiAbuseUserReport['id'] | MiAbuseUserReport,
- ) {
+ me: { id: MiUser['id'] } | null | undefined,
+ ) : Promise> {
const report = typeof src === 'object' ? src : await this.abuseUserReportsRepository.findOneByOrFail({ id: src });
return await awaitAll({
@@ -37,23 +40,27 @@ export class AbuseUserReportEntityService {
reporterId: report.reporterId,
targetUserId: report.targetUserId,
assigneeId: report.assigneeId,
- reporter: this.userEntityService.pack(report.reporter ?? report.reporterId, null, {
- detail: true,
+ reporter: this.userEntityService.pack(report.reporter ?? report.reporterId, me, {
+ schema: 'UserDetailed',
}),
- targetUser: this.userEntityService.pack(report.targetUser ?? report.targetUserId, null, {
- detail: true,
+ targetUser: this.userEntityService.pack(report.targetUser ?? report.targetUserId, me, {
+ schema: 'UserDetailed',
}),
- assignee: report.assigneeId ? this.userEntityService.pack(report.assignee ?? report.assigneeId, null, {
- detail: true,
+ assignee: report.assigneeId ? this.userEntityService.pack(report.assignee ?? report.assigneeId, me, {
+ schema: 'UserDetailed',
}) : null,
forwarded: report.forwarded,
+ category: report.category,
});
}
@bindThis
- public packMany(
- reports: any[],
- ) {
- return Promise.all(reports.map(x => this.pack(x)));
+ public async packMany(
+ reports: (MiAbuseUserReport['id'] | MiAbuseUserReport)[],
+ me: { id: MiUser['id'] } | null | undefined,
+ ) : Promise[]> {
+ return (await Promise.allSettled(reports.map(x => this.pack(x, me))))
+ .filter(result => result.status === 'fulfilled')
+ .map(result => (result as PromiseFulfilledResult>).value);
}
}
diff --git a/packages/backend/src/core/entities/AnnouncementEntityService.ts b/packages/backend/src/core/entities/AnnouncementEntityService.ts
new file mode 100644
index 000000000..b4a67460d
--- /dev/null
+++ b/packages/backend/src/core/entities/AnnouncementEntityService.ts
@@ -0,0 +1,73 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import { DI } from '@/di-symbols.js';
+import type { AnnouncementsRepository, AnnouncementReadsRepository, MiAnnouncement, MiUser } from '@/models/_.js';
+import type { Packed } from '@/misc/json-schema.js';
+import { bindThis } from '@/decorators.js';
+import { IdService } from '@/core/IdService.js';
+
+@Injectable()
+export class AnnouncementEntityService {
+ constructor(
+ @Inject(DI.announcementsRepository)
+ private announcementsRepository: AnnouncementsRepository,
+
+ @Inject(DI.announcementReadsRepository)
+ private announcementReadsRepository: AnnouncementReadsRepository,
+
+ private idService: IdService,
+ ) {
+ }
+
+ @bindThis
+ public async pack(
+ src: MiAnnouncement['id'] | MiAnnouncement & { isRead?: boolean | null },
+ me: { id: MiUser['id'] } | null | undefined,
+ ): Promise> {
+ const announcement = typeof src === 'object'
+ ? src
+ : await this.announcementsRepository.findOneByOrFail({
+ id: src,
+ }) as MiAnnouncement & { isRead?: boolean | null };
+
+ if (me && announcement.isRead === undefined) {
+ announcement.isRead = await this.announcementReadsRepository
+ .countBy({
+ announcementId: announcement.id,
+ userId: me.id,
+ })
+ .then((count: number) => count > 0);
+ }
+
+ return {
+ id: announcement.id,
+ createdAt: this.idService.parse(announcement.id).date.toISOString(),
+ updatedAt: announcement.updatedAt?.toISOString() ?? null,
+ title: announcement.title,
+ text: announcement.text,
+ imageUrl: announcement.imageUrl,
+ icon: announcement.icon,
+ display: announcement.display,
+ forYou: announcement.userId === me?.id,
+ needConfirmationToRead: announcement.needConfirmationToRead,
+ closeDuration: announcement.closeDuration,
+ displayOrder: announcement.displayOrder,
+ silence: announcement.silence,
+ isRead: announcement.isRead !== null ? announcement.isRead : undefined,
+ };
+ }
+
+ @bindThis
+ public async packMany(
+ announcements: (MiAnnouncement['id'] | MiAnnouncement & { isRead?: boolean | null } | MiAnnouncement)[],
+ me: { id: MiUser['id'] } | null | undefined,
+ ) : Promise[]> {
+ return (await Promise.allSettled(announcements.map(x => this.pack(x, me))))
+ .filter(result => result.status === 'fulfilled')
+ .map(result => (result as PromiseFulfilledResult>).value);
+ }
+}
diff --git a/packages/backend/src/core/entities/AntennaEntityService.ts b/packages/backend/src/core/entities/AntennaEntityService.ts
index 265a61e8a..64d6a3c97 100644
--- a/packages/backend/src/core/entities/AntennaEntityService.ts
+++ b/packages/backend/src/core/entities/AntennaEntityService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
diff --git a/packages/backend/src/core/entities/AppEntityService.ts b/packages/backend/src/core/entities/AppEntityService.ts
index 14a93cda5..a43711864 100644
--- a/packages/backend/src/core/entities/AppEntityService.ts
+++ b/packages/backend/src/core/entities/AppEntityService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -25,18 +25,18 @@ export class AppEntityService {
@bindThis
public async pack(
src: MiApp['id'] | MiApp,
- me?: { id: MiUser['id'] } | null | undefined,
+ me: { id: MiUser['id'] } | null | undefined,
options?: {
detail?: boolean,
includeSecret?: boolean,
includeProfileImageIds?: boolean
},
): Promise> {
- const opts = Object.assign({
+ const opts = {
detail: false,
includeSecret: false,
- includeProfileImageIds: false,
- }, options);
+ includeProfileImageIds: false, ...options
+ };
const app = typeof src === 'object' ? src : await this.appsRepository.findOneByOrFail({ id: src });
diff --git a/packages/backend/src/core/entities/AuthSessionEntityService.ts b/packages/backend/src/core/entities/AuthSessionEntityService.ts
index fd356cc89..0bc80386c 100644
--- a/packages/backend/src/core/entities/AuthSessionEntityService.ts
+++ b/packages/backend/src/core/entities/AuthSessionEntityService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -25,7 +25,7 @@ export class AuthSessionEntityService {
@bindThis
public async pack(
src: MiAuthSession['id'] | MiAuthSession,
- me?: { id: MiUser['id'] } | null | undefined,
+ me: { id: MiUser['id'] } | null | undefined,
) {
const session = typeof src === 'object' ? src : await this.authSessionsRepository.findOneByOrFail({ id: src });
diff --git a/packages/backend/src/core/entities/BlockingEntityService.ts b/packages/backend/src/core/entities/BlockingEntityService.ts
index b4760346b..8ebe91984 100644
--- a/packages/backend/src/core/entities/BlockingEntityService.ts
+++ b/packages/backend/src/core/entities/BlockingEntityService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -28,7 +28,7 @@ export class BlockingEntityService {
@bindThis
public async pack(
src: MiBlocking['id'] | MiBlocking,
- me?: { id: MiUser['id'] } | null | undefined,
+ me: { id: MiUser['id'] } | null | undefined,
): Promise> {
const blocking = typeof src === 'object' ? src : await this.blockingsRepository.findOneByOrFail({ id: src });
@@ -37,16 +37,18 @@ export class BlockingEntityService {
createdAt: this.idService.parse(blocking.id).date.toISOString(),
blockeeId: blocking.blockeeId,
blockee: this.userEntityService.pack(blocking.blockeeId, me, {
- detail: true,
+ schema: 'UserDetailedNotMe',
}),
});
}
@bindThis
- public packMany(
- blockings: any[],
- me: { id: MiUser['id'] },
- ) {
- return Promise.all(blockings.map(x => this.pack(x, me)));
+ public async packMany(
+ blockings: (MiBlocking['id'] | MiBlocking)[],
+ me: { id: MiUser['id'] } | null | undefined,
+ ) : Promise[]> {
+ return (await Promise.allSettled(blockings.map(x => this.pack(x, me))))
+ .filter(result => result.status === 'fulfilled')
+ .map(result => (result as PromiseFulfilledResult>).value);
}
}
diff --git a/packages/backend/src/core/entities/ChannelEntityService.ts b/packages/backend/src/core/entities/ChannelEntityService.ts
index 305946b8a..e6f519d61 100644
--- a/packages/backend/src/core/entities/ChannelEntityService.ts
+++ b/packages/backend/src/core/entities/ChannelEntityService.ts
@@ -1,20 +1,19 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { Inject, Injectable } from '@nestjs/common';
+import { In } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { ChannelFavoritesRepository, ChannelFollowingsRepository, ChannelsRepository, DriveFilesRepository, NotesRepository } from '@/models/_.js';
import type { Packed } from '@/misc/json-schema.js';
-import type { } from '@/models/Blocking.js';
import type { MiUser } from '@/models/User.js';
import type { MiChannel } from '@/models/Channel.js';
import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js';
import { DriveFileEntityService } from './DriveFileEntityService.js';
import { NoteEntityService } from './NoteEntityService.js';
-import { In } from 'typeorm';
@Injectable()
export class ChannelEntityService {
@@ -43,7 +42,7 @@ export class ChannelEntityService {
@bindThis
public async pack(
src: MiChannel['id'] | MiChannel,
- me?: { id: MiUser['id'] } | null | undefined,
+ me: { id: MiUser['id'] } | null | undefined,
detailed?: boolean,
): Promise> {
const channel = typeof src === 'object' ? src : await this.channelsRepository.findOneByOrFail({ id: src });
@@ -51,14 +50,14 @@ export class ChannelEntityService {
const banner = channel.bannerId ? await this.driveFilesRepository.findOneBy({ id: channel.bannerId }) : null;
- const isFollowing = meId ? await this.channelFollowingsRepository.exist({
+ const isFollowing = meId ? await this.channelFollowingsRepository.exists({
where: {
followerId: meId,
followeeId: channel.id,
},
}) : false;
- const isFavorited = meId ? await this.channelFavoritesRepository.exist({
+ const isFavorited = meId ? await this.channelFavoritesRepository.exists({
where: {
userId: meId,
channelId: channel.id,
@@ -98,5 +97,14 @@ export class ChannelEntityService {
} : {}),
};
}
-}
+ public async packMany(
+ channels: (MiChannel['id'] | MiChannel)[],
+ me: { id: MiUser['id'] } | null | undefined,
+ detailed?: boolean,
+ ): Promise[]> {
+ return (await Promise.allSettled(channels.map(x => this.pack(x, me, detailed))))
+ .filter(result => result.status === 'fulfilled')
+ .map(result => (result as PromiseFulfilledResult>).value);
+ }
+}
diff --git a/packages/backend/src/core/entities/ClipEntityService.ts b/packages/backend/src/core/entities/ClipEntityService.ts
index 96422894f..b0c2b07a2 100644
--- a/packages/backend/src/core/entities/ClipEntityService.ts
+++ b/packages/backend/src/core/entities/ClipEntityService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -8,7 +8,6 @@ import { DI } from '@/di-symbols.js';
import type { ClipFavoritesRepository, ClipsRepository, MiUser } from '@/models/_.js';
import { awaitAll } from '@/misc/prelude/await-all.js';
import type { Packed } from '@/misc/json-schema.js';
-import type { } from '@/models/Blocking.js';
import type { MiClip } from '@/models/Clip.js';
import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js';
@@ -31,7 +30,7 @@ export class ClipEntityService {
@bindThis
public async pack(
src: MiClip['id'] | MiClip,
- me?: { id: MiUser['id'] } | null | undefined,
+ me: { id: MiUser['id'] } | null | undefined,
): Promise> {
const meId = me ? me.id : null;
const clip = typeof src === 'object' ? src : await this.clipsRepository.findOneByOrFail({ id: src });
@@ -41,21 +40,23 @@ export class ClipEntityService {
createdAt: this.idService.parse(clip.id).date.toISOString(),
lastClippedAt: clip.lastClippedAt ? clip.lastClippedAt.toISOString() : null,
userId: clip.userId,
- user: this.userEntityService.pack(clip.user ?? clip.userId),
+ user: this.userEntityService.pack(clip.user ?? clip.userId, me),
name: clip.name,
description: clip.description,
isPublic: clip.isPublic,
favoritedCount: await this.clipFavoritesRepository.countBy({ clipId: clip.id }),
- isFavorited: meId ? await this.clipFavoritesRepository.exist({ where: { clipId: clip.id, userId: meId } }) : undefined,
+ isFavorited: meId ? await this.clipFavoritesRepository.exists({ where: { clipId: clip.id, userId: meId } }) : undefined,
});
}
@bindThis
- public packMany(
- clips: MiClip[],
- me?: { id: MiUser['id'] } | null | undefined,
- ) {
- return Promise.all(clips.map(x => this.pack(x, me)));
+ public async packMany(
+ clips: (MiClip['id'] | MiClip)[],
+ me: { id: MiUser['id'] } | null | undefined,
+ ) : Promise[]> {
+ return (await Promise.allSettled(clips.map(x => this.pack(x, me))))
+ .filter(result => result.status === 'fulfilled')
+ .map(result => (result as PromiseFulfilledResult>).value);
}
}
diff --git a/packages/backend/src/core/entities/DriveFileEntityService.ts b/packages/backend/src/core/entities/DriveFileEntityService.ts
index 14be00036..6f8f5797a 100644
--- a/packages/backend/src/core/entities/DriveFileEntityService.ts
+++ b/packages/backend/src/core/entities/DriveFileEntityService.ts
@@ -1,5 +1,5 @@
/*
- * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
@@ -187,6 +187,7 @@ export class DriveFileEntityService {
@bindThis
public async pack(
src: MiDriveFile['id'] | MiDriveFile,
+ me: { id: MiUser['id'] } | null | undefined,
options?: PackOptions,
): Promise> {
const opts = Object.assign({
@@ -214,13 +215,14 @@ export class DriveFileEntityService {
detail: true,
}) : null,
userId: opts.withUser ? file.userId : null,
- user: (opts.withUser && file.userId) ? this.userEntityService.pack(file.userId) : null,
+ user: (opts.withUser && file.userId) ? this.userEntityService.pack(file.userId, me) : null,
});
}
@bindThis
public async packNullable(
src: MiDriveFile['id'] | MiDriveFile,
+ me: { id: MiUser['id'] } | null | undefined,
options?: PackOptions,
): Promise | null> {
const opts = Object.assign({
@@ -248,28 +250,31 @@ export class DriveFileEntityService {
folder: opts.detail && file.folderId ? this.driveFolderEntityService.pack(file.folderId, {
detail: true,
}) : null,
- userId: opts.withUser ? file.userId : null,
- user: (opts.withUser && file.userId) ? this.userEntityService.pack(file.userId) : null,
+ userId: file.userId,
+ user: (opts.withUser && file.userId) ? this.userEntityService.pack(file.userId, me) : null,
});
}
@bindThis
public async packMany(
files: MiDriveFile[],
+ me: { id: MiUser['id'] } | null | undefined,
options?: PackOptions,
): Promise[]> {
- const items = await Promise.all(files.map(f => this.packNullable(f, options)));
- return items.filter((x): x is Packed<'DriveFile'> => x != null);
+ return (await Promise.allSettled(files.map(f => this.packNullable(f, me, options))))
+ .filter(result => result.status === 'fulfilled' && result.value != null)
+ .map(result => (result as PromiseFulfilledResult>).value);
}
@bindThis
public async packManyByIdsMap(
fileIds: MiDriveFile['id'][],
+ me: { id: MiUser['id'] } | null | undefined,
options?: PackOptions,
): Promise