Merge remote-tracking branch 'upstream/master' into devel

This commit is contained in:
gutfuckllc 2018-08-05 16:54:54 -04:00
commit 752186066b
20 changed files with 381 additions and 219 deletions

View File

@ -88,7 +88,7 @@ common:
i-like-sushi: "Je préfère les sushis (au pudding)" i-like-sushi: "Je préfère les sushis (au pudding)"
show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi" show-reversi-board-labels: "Afficher les étiquettes des lignes et colonnes dans Reversi"
verified-user: "Utilisateur·trice vérifié·e" verified-user: "Utilisateur·trice vérifié·e"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "Désactiver les textes animés dans les publications"
reversi: reversi:
drawn: "Partie nulle" drawn: "Partie nulle"
my-turn: "Cest votre tour" my-turn: "Cest votre tour"
@ -99,7 +99,7 @@ common:
black: "Noirs" black: "Noirs"
white: "Blancs" white: "Blancs"
total: "Total" total: "Total"
this-turn: "Tour de {}" this-turn: "Tour {}"
widgets: widgets:
analog-clock: "Horloge analogique" analog-clock: "Horloge analogique"
profile: "Profil" profile: "Profil"
@ -117,7 +117,7 @@ common:
notifications: "Notifications" notifications: "Notifications"
users: "Utilisateurs" users: "Utilisateurs"
polls: "Sondages" polls: "Sondages"
post-form: "投稿フォーム" post-form: "Formulaire de publication"
messaging: "Messagerie" messaging: "Messagerie"
server: "Info sur le serveur" server: "Info sur le serveur"
donation: "Dons" donation: "Dons"
@ -170,8 +170,8 @@ common/views/components/games/reversi/reversi.vue:
waiting-for: "En attente de {}" waiting-for: "En attente de {}"
cancel: "Annuler" cancel: "Annuler"
common/views/components/games/reversi/reversi.game.vue: common/views/components/games/reversi/reversi.game.vue:
surrender: "投了" surrender: "Se rendre"
surrendered: "投了により" surrendered: "Par abandon"
common/views/components/games/reversi/reversi.index.vue: common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi" title: "Misskey Reversi"
sub-title: "Jouer à Reversi avec vos amis·es !" sub-title: "Jouer à Reversi avec vos amis·es !"
@ -201,10 +201,10 @@ common/views/components/games/reversi/reversi.room.vue:
this-game-is-started-soon: "La partie commencera dans quelques instants" this-game-is-started-soon: "La partie commencera dans quelques instants"
waiting-for-other: "En attente que l'adversaire soit prêt" waiting-for-other: "En attente que l'adversaire soit prêt"
waiting-for-me: "En attente que vous soyez prêt" waiting-for-me: "En attente que vous soyez prêt"
waiting-for-both: "準備中" waiting-for-both: "En attente que vous soyez prêt"
cancel: "Annuler" cancel: "Annuler"
ready: "Prêt" ready: "Prêt"
cancel-ready: "準備続行" cancel-ready: "Annuler \"Je suis prêt\""
common/views/components/connect-failed.vue: common/views/components/connect-failed.vue:
title: "Impossible de se connecter au server." title: "Impossible de se connecter au server."
description: "Il y a soit un problème avec votre connexion internet, soit le serveur est hors-ligne ou en maintenance. Veuillez {ressayer} plus tard." description: "Il y a soit un problème avec votre connexion internet, soit le serveur est hors-ligne ou en maintenance. Veuillez {ressayer} plus tard."
@ -721,7 +721,7 @@ desktop/views/components/timeline.vue:
global: "Global" global: "Global"
list: "Listes" list: "Listes"
desktop/views/components/ui.header.vue: desktop/views/components/ui.header.vue:
welcome-back: "Vous êtes de retour !" welcome-back: "Content de vous revoir !"
desktop/views/components/ui.header.account.vue: desktop/views/components/ui.header.account.vue:
profile: "Votre profil" profile: "Votre profil"
drive: "Drive" drive: "Drive"
@ -990,7 +990,7 @@ mobile/views/pages/drive.vue:
drive: "Drive" drive: "Drive"
more: "Afficher plus ..." more: "Afficher plus ..."
mobile/views/pages/signup.vue: mobile/views/pages/signup.vue:
lets-start: "📦 始めましょう" lets-start: "Commençons ! 📦"
mobile/views/pages/followers.vue: mobile/views/pages/followers.vue:
followers-of: "Abonné·e·s de {}" followers-of: "Abonné·e·s de {}"
mobile/views/pages/following.vue: mobile/views/pages/following.vue:
@ -1059,9 +1059,9 @@ mobile/views/pages/settings.vue:
i-am-under-limited-internet: "J'ai un accès Internet limité" i-am-under-limited-internet: "J'ai un accès Internet limité"
circle-icons: "Utiliser des icônes circulaires" circle-icons: "Utiliser des icônes circulaires"
timeline: "Fil d'actualité" timeline: "Fil d'actualité"
show-reply-target: "リプライ先を表示する" show-reply-target: "Afficher les réponses"
show-my-renotes: "Afficher mes republications" show-my-renotes: "Afficher mes republications"
show-renoted-my-notes: "Renoteされた自分の投稿を表示する" show-renoted-my-notes: "Afficher les notes que j'ai repartagé"
post-style: "Style de la publication" post-style: "Style de la publication"
post-style-standard: "Standard" post-style-standard: "Standard"
post-style-smart: "Intelligent" post-style-smart: "Intelligent"

View File

@ -5,125 +5,125 @@ meta:
common: common:
misskey: "A ⭐ of fediverse" misskey: "A ⭐ of fediverse"
about-title: "A ⭐ of fediverse." about-title: "A ⭐ of fediverse."
about: "Misskeyを見つけていただき、ありがとうございます。Misskeyは、地球で生まれた<b>分散マイクロブログSNS</b>です。Fediverse(様々なSNSで構成される宇宙)の中に存在するため、他のSNSと相互に繋がっています。暫し都会の喧騒から離れて、新しいインターネットにダイブしてみませんか。" about: "Misskey를 찾아 주셔서 감사합니다. Misskey은 지구에서 태어난 <b>분산 마이크로 블로그 SNS </b> 입니다. Fediverse (다양한 SNS로 구성되는 우주)에 존재하는 다른 SNS와 상호 연결되어 있습니다. 잠시 도시의 번잡함에서 벗어나 새로운 인터넷에 다이브 해 보지 않겠습니까."
adblock: adblock:
detected: "広告ブロッカーを無効にしてください" detected: "광고 차단기를 해제하십시오"
warning: "<strong>Misskeyは広告を掲載していません</strong>が、広告をブロックする機能が有効だと一部の機能が利用できなかったり、不具合が発生する場合があります。" warning: "<strong>Misskey는 광고를 게재하지 않습니다</strong> 그러나 광고를 차단하는 기능 기능을 사용할 경우 일부 기능을 사용할 수 없게 될 가능성이나 결함이 발생하는 경우가 있습니다."
application-authorization: "アプリの連携" application-authorization: "앱의 연계"
close: "閉じる" close: "닫기"
customization-tips: customization-tips:
title: "カスタマイズのヒント" title: "사용자 정의 팁"
paragraph1: "ホームのカスタマイズでは、ウィジェットを追加/削除したり、ドラッグ&ドロップして並べ替えたりすることができます。" paragraph1: "홈 정의는 위젯을 추가 / 삭제하거나 드래그 앤 드롭하여 정렬 할 수 있습니다."
paragraph2: "一部のウィジェットは、<strong><strong>右</strong>クリック</strong>することで表示を変更することができます。" paragraph2: "일부 위젯은 <strong>오른쪽 클릭</strong> 하여 모양을 변경할 수 있습니다."
paragraph3: "ウィジェットを削除するには、ヘッダーの<strong>「ゴミ箱」</strong>と書かれたエリアにウィジェットをドラッグ&ドロップします。" paragraph3: "위젯을 삭제하려면 헤더 <strong>\"휴지통\"</strong> 라고 쓰여진 영역으로 끌어다 놓습니다."
paragraph4: "カスタマイズを終了するには、右上の「完了」をクリックします。" paragraph4: "사용자 정의를 종료하려면 오른쪽 상단의 '완료' 를 클릭합니다."
gotit: "Got it!" gotit: "Got it!"
notification: notification:
file-uploaded: "ファイルがアップロードされました" file-uploaded: "파일이 업로드되었습니다"
message-from: "{}さんからメッセージ:" message-from: "{}씨로부터 메시지:"
reversi-invited: "対局への招待があります" reversi-invited: "대결에 초대되어 있습니다"
reversi-invited-by: "{}さんから" reversi-invited-by: "{}"
notified-by: "{}さんから" notified-by: "{}"
reply-from: "{}さんから返信:" reply-from: "{}님으로부터 답글:"
quoted-by: "{}さんが引用:" quoted-by: "{}씨가 인용:"
name: "Misskey" name: "Misskey"
time: time:
unknown: "なぞのじかん" unknown: "수수께끼의 시간"
future: "未来" future: "미래"
just_now: "たった今" just_now: "방금"
seconds_ago: "{}秒前" seconds_ago: "{}초전"
minutes_ago: "{}分前" minutes_ago: "{}분전"
hours_ago: "{}時間前" hours_ago: "{}시간전"
days_ago: "{}日前" days_ago: "{}일전"
weeks_ago: "{}週間前" weeks_ago: "{}주전"
months_ago: "{}ヶ月前" months_ago: "{}개월전"
years_ago: "{}年前" years_ago: "{}년전"
trash: "ゴミ箱" trash: "휴지통"
date: date:
full-year: "" full-year: ""
month: "" month: ""
day: "" day: ""
hours: "" hours: ""
minutes: "" minutes: ""
weekday-short: weekday-short:
sunday: "" sunday: ""
monday: "" monday: ""
tuesday: "" tuesday: ""
wednesday: "" wednesday: ""
thursday: "" thursday: ""
friday: "" friday: ""
saturday: "" saturday: ""
weekday: weekday:
sunday: "日曜日" sunday: "일요일"
monday: "月曜日" monday: "월요일"
tuesday: "火曜日" tuesday: "화요일"
wednesday: "水曜日" wednesday: "수요일"
thursday: "木曜日" thursday: "목요일"
friday: "金曜日" friday: "금요일"
saturday: "土曜日" saturday: "토요일"
reactions: reactions:
like: "いいね" like: "좋네"
love: "しゅき" love: "좋아"
laugh: "" laugh: "크크"
hmm: "ふぅ~む" hmm: "음..."
surprise: "わお" surprise: "와우"
congrats: "おめでとう" congrats: "받으세요"
angry: "おこ" angry: "화냈어"
confused: "こまこまのこまり" confused: "곤란하고 있어"
pudding: "Pudding" pudding: "Pudding"
note-placeholders: note-placeholders:
a: "今どうしてる?" a: "지금 어떻게하고있어?"
b: "何かありましたか?" b: "뭔가 있었습니까?"
c: "何をお考えですか?" c: "무엇을 생각하십니까?"
d: "言いたいことは?" d: "말하고 싶은 것은?"
e: "ここに書いてください" e: "여기에 써주십시오"
f: "あなたが書くのを待っています..." f: "당신이 쓸 것을 당신 기다리고 있습니다..."
search: "検索" search: "검색"
delete: "削除" delete: "삭제"
loading: "読み込み中" loading: "로드 중"
ok: "わかった" ok: "확인"
update-available-title: "更新があります" update-available-title: "갱신이 있습니다"
update-available: "Misskeyの新しいバージョンがあります({newer}。現在{current}を利用中)。ページを再度読み込みすると更新が適用されます。" update-available: "Misskey의 새로운 버전이 있습니다 ({newer} 현재 {current}을 사용 중). 페이지를 다시로드하면 업데이트가 적용됩니다."
my-token-regenerated: "あなたのトークンが更新されたのでサインアウトします。" my-token-regenerated: "당신의 토큰이 업데이트되어 있기 때문에 로그 아웃합니다."
i-like-sushi: "私は(プリンよりむしろ)寿司が好き" i-like-sushi: "나는(푸딩보다 오히려)스시가 좋아"
show-reversi-board-labels: "リバーシのボードの行と列のラベルを表示" show-reversi-board-labels: "리버시 보드의 행과 열 레이블을 표시"
verified-user: "認証済みのユーザー" verified-user: "인증 된 사용자"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "게시물의 문자 애니메이션을 비활성화 할"
reversi: reversi:
drawn: "引き分け" drawn: "무승부"
my-turn: "あなたのターンです" my-turn: "당신의 차례입니다"
opponent-turn: "相手のターンです" opponent-turn: "상대의 차례입니다"
turn-of: "{}のターンです" turn-of: "{}의 차례입니다"
past-turn-of: "{}のターン" past-turn-of: "{}"
won: "{}の勝ち" won: "{} 승리"
black: "" black: "검정"
white: "" white: "흰색"
total: "合計" total: "합계"
this-turn: "{}ターン目" this-turn: "{}턴눈"
widgets: widgets:
analog-clock: "アナログ時計" analog-clock: "아날로그 시계"
profile: "プロフィール" profile: "프로필"
calendar: "カレンダー" calendar: "달력"
timemachine: "カレンダー(タイムマシン)" timemachine: "달력(타임머신)"
activity: "アクティビティ" activity: "활동"
rss: "RSSリーダー" rss: "RSS 리더"
memo: "付箋" memo: "끈끈이"
trends: "トレンド" trends: "트렌드"
photo-stream: "フォトストリーム" photo-stream: "포토 스트림"
posts-monitor: "投稿チャート" posts-monitor: "게시물 차트"
slideshow: "スライドショー" slideshow: "슬라이드 쇼"
version: "バージョン" version: "버전"
broadcast: "ブロードキャスト" broadcast: "브로드 캐스트"
notifications: "通知" notifications: "통지"
users: "おすすめユーザー" users: "추천 사용자"
polls: "アンケート" polls: "설문"
post-form: "投稿フォーム" post-form: "게시 양식"
messaging: "メッセージ" messaging: "메시지"
server: "サーバー情報" server: "서버 정보"
donation: "寄付のお願い" donation: "기부 요청"
nav: "ナビゲーション" nav: "네비게이션"
tips: "ヒント" tips: ""
hashtags: "ハッシュタグ" hashtags: "해시 태그"
deck: deck:
widgets: "ウィジェット" widgets: "ウィジェット"
home: "ホーム" home: "ホーム"

View File

@ -15,8 +15,8 @@ common:
title: "Wskazówki o dostosowywaniu" title: "Wskazówki o dostosowywaniu"
paragraph1: "Dostosowywanie strony głównej pozwala na dodawanie, usuwanie, przeciąganie i zmienianie kolejności widżetów." paragraph1: "Dostosowywanie strony głównej pozwala na dodawanie, usuwanie, przeciąganie i zmienianie kolejności widżetów."
paragraph2: "一部のウィジェットは、<strong><strong>右</strong>クリック</strong>することで表示を変更することができます。" paragraph2: "一部のウィジェットは、<strong><strong>右</strong>クリック</strong>することで表示を変更することができます。"
paragraph3: "ウィジェットを削除するには、ヘッダーの<strong>「ゴミ箱」</strong>と書かれたエリアにウィジェットをドラッグ&ドロップします。" paragraph3: "Aby usunąć widżet, <strong>przeciągnij i upuść widżet do części nazwanej „Kosz”</strong> w nagłówku."
paragraph4: "カスタマイズを終了するには、右上の「完了」をクリックします。" paragraph4: "Aby zakończyć dostosowywanie, naciśnij „Zakończ” w w prawym górnym rogu."
gotit: "Rozumiem!" gotit: "Rozumiem!"
notification: notification:
file-uploaded: "Wysłano plik!" file-uploaded: "Wysłano plik!"
@ -88,7 +88,7 @@ common:
i-like-sushi: "Wolę sushi od puddingu" i-like-sushi: "Wolę sushi od puddingu"
show-reversi-board-labels: "Pokazuj podpisy wierszy i kolumn w Reversi" show-reversi-board-labels: "Pokazuj podpisy wierszy i kolumn w Reversi"
verified-user: "Zweryfikowany użytkownik" verified-user: "Zweryfikowany użytkownik"
disable-animated-mfm: "投稿内の動きのあるテキストを無効にする" disable-animated-mfm: "Wyłącz animowany tekst we wpisach"
reversi: reversi:
drawn: "Remis" drawn: "Remis"
my-turn: "Twoja kolej" my-turn: "Twoja kolej"
@ -142,58 +142,58 @@ common:
stack-left: "Przypnij do lewej" stack-left: "Przypnij do lewej"
pop-right: "Odepnij w prawo" pop-right: "Odepnij w prawo"
auth/views/form.vue: auth/views/form.vue:
share-access: "<i>{{ app.name }}</i>があなたのアカウントにアクセスすることを<b>許可</b>しますか?" share-access: "Czy chcesz <b>zezwolić</b> <i>{{ app.name }}</i> na dostęp do Twojego konta?"
permission-ask: "このアプリは次の権限を要求しています:" permission-ask: "Ta aplikacja wymaga następujących uprawnień:"
account-read: "アカウントの情報を見る。" account-read: "Wyświetlanie informacji o koncie:"
account-write: "アカウントの情報を操作する。" account-write: "Modyfikowanie informacji o koncie:"
note-write: "投稿する。" note-write: "Publikacja."
like-write: "いいねしたりいいね解除する。" like-write: "Reagowanie na wpisy."
following-write: "フォローしたりフォロー解除する。" following-write: "Śledzenie i cofanie śledzenia."
drive-read: "ドライブを見る。" drive-read: "Odczytywanie Twojego dysku."
drive-write: "ドライブを操作する。" drive-write: "Wysyłanie i usuwanie plików na Twoim dysku."
notification-read: "通知を見る。" notification-read: "Odczytywanie Twoich powiadomień."
notification-write: "通知を操作する。" notification-write: "Zarządzanie Twoimi powiadomieniami."
cancel: "キャンセル" cancel: "Anuluj"
accept: "アクセスを許可" accept: "Przyznaj dostęp."
auth/views/index.vue: auth/views/index.vue:
loading: "読み込み中" loading: "Ładowanie"
denied: "アプリケーションの連携をキャンセルしました。" denied: "Odrzucono uwierzytelnianie aplikacji."
denied-paragraph: "このアプリがあなたのアカウントにアクセスすることはありません。" denied-paragraph: "Ta aplikacja nie uzyska dostępu do Twojego konta."
already-authorized: "このアプリは既に連携済みです" already-authorized: "Ta aplikacja została już uwierzytelniona."
allowed: "アプリケーションの連携を許可しました" allowed: "アプリケーションの連携を許可しました"
callback-url: "アプリケーションに戻っています" callback-url: "Powracam do aplikacji."
please-go-back: "アプリケーションに戻って、やっていってください。" please-go-back: "Wróć do aplikacji."
error: "セッションが存在しません。" error: "Sesja nie istnieje."
sign-in: "サインインしてください" sign-in: "Proszę zalogować się."
common/views/components/games/reversi/reversi.vue: common/views/components/games/reversi/reversi.vue:
matching: matching:
waiting-for: "{}を待っています" waiting-for: "Oczekiwanie na {}"
cancel: "キャンセル" cancel: "Anuluj"
common/views/components/games/reversi/reversi.game.vue: common/views/components/games/reversi/reversi.game.vue:
surrender: "投了" surrender: "投了"
surrendered: "投了により" surrendered: "投了により"
common/views/components/games/reversi/reversi.index.vue: common/views/components/games/reversi/reversi.index.vue:
title: "Misskey Reversi" title: "Misskey Reversi"
sub-title: "他のMisskeyユーザーとリバーシで対戦しよう" sub-title: "Zagraj w Reversi ze znajomymi!"
invite: "招待" invite: "Zaproś"
rule: "遊び方" rule: "Jak grać"
rule-desc: "リバーシは、相手と交互に石をボードに置いて、相手の石を挟んで自分の色に変えてゆき、最終的に残った石が多い方が勝ちというボードゲームです。" rule-desc: "リバーシは、相手と交互に石をボードに置いて、相手の石を挟んで自分の色に変えてゆき、最終的に残った石が多い方が勝ちというボードゲームです。"
mode-invite: "招待" mode-invite: "Zaproś"
mode-invite-desc: "指定したユーザーと対戦するモードです。" mode-invite-desc: "Zaproś użytkownika do gry."
invitations: "対局の招待があります!" invitations: "Otrzymałeś(-aś) zaproszenie!"
my-games: "自分の対局" my-games: "Moje gry"
all-games: "みんなの対局" all-games: "Wszystkie gry"
enter-username: "ユーザー名を入力してください" enter-username: "Wprowadź nazwę użytkownika"
game-state: game-state:
ended: "終了" ended: "Zakończono"
playing: "進行中" playing: "W trakcie"
common/views/components/games/reversi/reversi.room.vue: common/views/components/games/reversi/reversi.room.vue:
settings-of-the-game: "ゲームの設定" settings-of-the-game: "Ustawienia gry"
choose-map: "マップを選択" choose-map: "Wybierz mapę"
random: "ランダム" random: "Losowy"
black-or-white: "先手/後手" black-or-white: "Czarny/biały"
black-is: "{}が黒" black-is: "{}が黒"
rules: "ルール" rules: "Zasady"
is-llotheo: "石の少ない方が勝ち(ロセオ)" is-llotheo: "石の少ない方が勝ち(ロセオ)"
looped-map: "ループマップ" looped-map: "ループマップ"
can-put-everywhere: "どこでも置けるモード" can-put-everywhere: "どこでも置けるモード"
@ -366,23 +366,23 @@ common/views/widgets/slideshow.vue:
folder: "Naciśnij i wybierz folder" folder: "Naciśnij i wybierz folder"
no-image: "Brak obrazu w tym folderze" no-image: "Brak obrazu w tym folderze"
common/views/widgets/tips.vue: common/views/widgets/tips.vue:
tips-line1: "<kbd>t</kbd>でタイムラインにフォーカスできます" tips-line1: "Możesz przejść do osi czasu używając <kbd>t</kbd>."
tips-line2: "<kbd>p</kbd>または<kbd>n</kbd>で投稿フォームを開きます" tips-line2: "Otwórz formularz nowego wpisu używając <kbd>p</kbd> lub <kbd>n</kbd>."
tips-line3: "投稿フォームにはファイルをドラッグ&ドロップできます" tips-line3: "Możesz przeciągnąć i upuścić pliki w formularzu wpisu."
tips-line4: "投稿フォームにクリップボードにある画像データをペーストできます" tips-line4: "投稿フォームにクリップボードにある画像データをペーストできます"
tips-line5: "ドライブにファイルをドラッグ&ドロップしてアップロードできます" tips-line5: "Możesz wysłać pliki przeciągając i upuszczając je w Dysku."
tips-line6: "ドライブでファイルをドラッグしてフォルダ移動できます" tips-line6: "Możesz przenieść katalog przeciągając go w Dysku."
tips-line7: "ドライブでフォルダをドラッグしてフォルダ移動できます" tips-line7: "ドライブでフォルダをドラッグしてフォルダ移動できます"
tips-line8: "Strona główna może zostać dostosowana w ustawieniach." tips-line8: "Strona główna może zostać dostosowana w ustawieniach."
tips-line9: "Misskey jest dostępny na licencji AGPLv3." tips-line9: "Misskey jest dostępny na licencji AGPLv3."
tips-line10: "タイムマシンウィジェットを利用すると、簡単に過去のタイムラインに遡れます" tips-line10: "タイムマシンウィジェットを利用すると、簡単に過去のタイムラインに遡れます"
tips-line11: "投稿の ... をクリックして、投稿をユーザーページにピン留めできます" tips-line11: "Możesz przypiąć wpis na stronie użytkownika klikając na „…”"
tips-line13: "投稿に添付したファイルは全てドライブに保存されます" tips-line13: "投稿に添付したファイルは全てドライブに保存されます"
tips-line14: "ホームのカスタマイズ中、ウィジェットを右クリックしてデザインを変更できます" tips-line14: "ホームのカスタマイズ中、ウィジェットを右クリックしてデザインを変更できます"
tips-line17: "「**」でテキストを囲むと**強調表示**されます" tips-line17: "Oznaczenie tekstu **w ten sposób** wyróżni go."
tips-line19: "いくつかのウィンドウはブラウザの外に切り離すことができます" tips-line19: "Część okien może zostać odłączona z przeglądarki."
tips-line20: "カレンダーウィジェットのパーセンテージは、経過の割合を示しています" tips-line20: "カレンダーウィジェットのパーセンテージは、経過の割合を示しています"
tips-line21: "APIを利用してbotの開発なども行えます" tips-line21: "Możesz też używać API, aby tworzyć boty."
tips-line23: "まゆかわいいよまゆ" tips-line23: "まゆかわいいよまゆ"
tips-line24: "Misskey zaczął działać w 2014." tips-line24: "Misskey zaczął działać w 2014."
tips-line25: "Możesz otrzymywać powiadomienia nawet jeżeli Misskey nie jest otwarty w obsługiwanej przeglądarce." tips-line25: "Możesz otrzymywać powiadomienia nawet jeżeli Misskey nie jest otwarty w obsługiwanej przeglądarce."

View File

@ -1,8 +1,8 @@
{ {
"name": "misskey", "name": "misskey",
"author": "syuilo <i@syuilo.com>", "author": "syuilo <i@syuilo.com>",
"version": "5.14.0", "version": "5.17.0",
"clientVersion": "1.0.7997", "clientVersion": "1.0.8026",
"codename": "nighthike", "codename": "nighthike",
"main": "./built/index.js", "main": "./built/index.js",
"private": true, "private": true,
@ -59,7 +59,7 @@
"@types/mocha": "5.2.3", "@types/mocha": "5.2.3",
"@types/mongodb": "3.1.3", "@types/mongodb": "3.1.3",
"@types/ms": "0.7.30", "@types/ms": "0.7.30",
"@types/node": "10.5.5", "@types/node": "10.5.6",
"@types/portscanner": "2.1.0", "@types/portscanner": "2.1.0",
"@types/pug": "2.0.4", "@types/pug": "2.0.4",
"@types/qrcode": "1.2.0", "@types/qrcode": "1.2.0",
@ -88,7 +88,7 @@
"bootstrap-vue": "2.0.0-rc.11", "bootstrap-vue": "2.0.0-rc.11",
"cafy": "11.3.0", "cafy": "11.3.0",
"chalk": "2.4.1", "chalk": "2.4.1",
"commander": "2.16.0", "commander": "2.17.0",
"crc-32": "1.2.0", "crc-32": "1.2.0",
"css-loader": "1.0.0", "css-loader": "1.0.0",
"dateformat": "3.0.3", "dateformat": "3.0.3",
@ -183,6 +183,7 @@
"showdown-highlightjs-extension": "0.1.2", "showdown-highlightjs-extension": "0.1.2",
"single-line-log": "1.1.2", "single-line-log": "1.1.2",
"speakeasy": "2.0.0", "speakeasy": "2.0.0",
"stringz": "1.0.0",
"style-loader": "0.21.0", "style-loader": "0.21.0",
"stylus": "0.54.5", "stylus": "0.54.5",
"stylus-loader": "3.0.2", "stylus-loader": "3.0.2",

View File

@ -1,8 +1,9 @@
<template> <template>
<div class="xqnhankfuuilcwvhgsopeqncafzsquya"> <div class="xqnhankfuuilcwvhgsopeqncafzsquya">
<button class="go-index" v-if="selfNav" @click="goIndex">%fa:arrow-left%</button>
<header><b><router-link :to="blackUser | userPage">{{ blackUser | userName }}</router-link></b>(%i18n:common.reversi.black%) vs <b><router-link :to="whiteUser | userPage">{{ whiteUser | userName }}</router-link></b>(%i18n:common.reversi.white%)</header> <header><b><router-link :to="blackUser | userPage">{{ blackUser | userName }}</router-link></b>(%i18n:common.reversi.black%) vs <b><router-link :to="whiteUser | userPage">{{ whiteUser | userName }}</router-link></b>(%i18n:common.reversi.white%)</header>
<div style="overflow: hidden"> <div style="overflow: hidden; line-height: 28px;">
<p class="turn" v-if="!iAmPlayer && !game.isEnded">{{ '%i18n:common.reversi.turn-of%'.replace('{}', $options.filters.userName(turnUser)) }}<mk-ellipsis/></p> <p class="turn" v-if="!iAmPlayer && !game.isEnded">{{ '%i18n:common.reversi.turn-of%'.replace('{}', $options.filters.userName(turnUser)) }}<mk-ellipsis/></p>
<p class="turn" v-if="logPos != logs.length">{{ '%i18n:common.reversi.past-turn-of%'.replace('{}', $options.filters.userName(turnUser)) }}</p> <p class="turn" v-if="logPos != logs.length">{{ '%i18n:common.reversi.past-turn-of%'.replace('{}', $options.filters.userName(turnUser)) }}</p>
<p class="turn1" v-if="iAmPlayer && !game.isEnded && !isMyTurn">%i18n:common.reversi.opponent-turn%<mk-ellipsis/></p> <p class="turn1" v-if="iAmPlayer && !game.isEnded && !isMyTurn">%i18n:common.reversi.opponent-turn%<mk-ellipsis/></p>
@ -69,7 +70,20 @@ import Reversi, { Color } from '../../../../../../../games/reversi/core';
import { url } from '../../../../../config'; import { url } from '../../../../../config';
export default Vue.extend({ export default Vue.extend({
props: ['initGame', 'connection'], props: {
initGame: {
type: Object,
require: true
},
connection: {
type: Object,
require: true
},
selfNav: {
type: Boolean,
require: true
}
},
data() { data() {
return { return {
@ -276,6 +290,10 @@ export default Vue.extend({
(this as any).api('games/reversi/games/surrender', { (this as any).api('games/reversi/games/surrender', {
gameId: this.game.id gameId: this.game.id
}); });
},
goIndex() {
this.$emit('go-index');
} }
} }
}); });
@ -287,6 +305,14 @@ export default Vue.extend({
root(isDark) root(isDark)
text-align center text-align center
> .go-index
position absolute
top 0
left 0
z-index 1
width 42px
height 42px
> header > header
padding 8px padding 8px
border-bottom dashed 1px isDark ? #4c5761 : #c4cdd4 border-bottom dashed 1px isDark ? #4c5761 : #c4cdd4

View File

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<x-room v-if="!g.isStarted" :game="g" :connection="connection"/> <x-room v-if="!g.isStarted" :game="g" :connection="connection"/>
<x-game v-else :init-game="g" :connection="connection"/> <x-game v-else :init-game="g" :connection="connection" :self-nav="selfNav" @go-index="goIndex"/>
</div> </div>
</template> </template>
@ -16,7 +16,16 @@ export default Vue.extend({
XGame, XGame,
XRoom XRoom
}, },
props: ['game'], props: {
game: {
type: Object,
required: true
},
selfNav: {
type: Boolean,
require: true
}
},
data() { data() {
return { return {
connection: null, connection: null,
@ -36,6 +45,9 @@ export default Vue.extend({
onStarted(game) { onStarted(game) {
Object.assign(this.g, game); Object.assign(this.g, game);
this.$forceUpdate(); this.$forceUpdate();
},
goIndex() {
this.$emit('go-index');
} }
} }
}); });

View File

@ -96,11 +96,7 @@ export default Vue.extend({
methods: { methods: {
go(game) { go(game) {
(this as any).api('games/reversi/games/show', {
gameId: game.id
}).then(game => {
this.$emit('go', game); this.$emit('go', game);
});
}, },
match() { match() {

View File

@ -1,7 +1,7 @@
<template> <template>
<div class="vchtoekanapleubgzioubdtmlkribzfd"> <div class="vchtoekanapleubgzioubdtmlkribzfd">
<div v-if="game"> <div v-if="game">
<x-gameroom :game="game"/> <x-gameroom :game="game" :self-nav="selfNav" @go-index="goIndex"/>
</div> </div>
<div class="matching" v-else-if="matching"> <div class="matching" v-else-if="matching">
<h1>{{ '%i18n:@matching.waiting-for%'.split('{}')[0] }}<b>{{ matching | userName }}</b>{{ '%i18n:@matching.waiting-for%'.split('{}')[1] }}<mk-ellipsis/></h1> <h1>{{ '%i18n:@matching.waiting-for%'.split('{}')[0] }}<b>{{ matching | userName }}</b>{{ '%i18n:@matching.waiting-for%'.split('{}')[1] }}<mk-ellipsis/></h1>
@ -34,6 +34,11 @@ export default Vue.extend({
gameId: { gameId: {
type: String, type: String,
required: false required: false
},
selfNav: {
type: Boolean,
require: false,
default: true
} }
}, },
@ -95,18 +100,24 @@ export default Vue.extend({
(this as any).api('games/reversi/games/show', { (this as any).api('games/reversi/games/show', {
gameId: this.gameId gameId: this.gameId
}).then(game => { }).then(game => {
this.nav(game, true); this.game = game;
Progress.done(); Progress.done();
}); });
} }
}, },
nav(game, silent) { async nav(game, actualNav = true) {
this.matching = null; if (this.selfNav) {
this.game = game; //
if (game != null && (game.settings == null || game.settings.map == null)) {
game = await (this as any).api('games/reversi/games/show', {
gameId: game.id
});
}
if (!silent) { this.game = game;
this.$emit('nav', this.game); } else {
this.$emit('nav', game, actualNav);
} }
}, },
@ -125,7 +136,8 @@ export default Vue.extend({
}).then(game => { }).then(game => {
if (game) { if (game) {
this.matching = null; this.matching = null;
this.game = game;
this.nav(game);
} }
}); });
}, },
@ -133,6 +145,11 @@ export default Vue.extend({
onMatched(game) { onMatched(game) {
this.matching = null; this.matching = null;
this.game = game; this.game = game;
this.nav(game, false);
},
goIndex() {
this.nav(null);
} }
} }
}); });

View File

@ -1,5 +1,6 @@
import Vue from 'vue'; import Vue from 'vue';
import * as emojilib from 'emojilib'; import * as emojilib from 'emojilib';
import { length } from 'stringz';
import parse from '../../../../../mfm/parse'; import parse from '../../../../../mfm/parse';
import getAcct from '../../../../../misc/acct/render'; import getAcct from '../../../../../misc/acct/render';
import { url } from '../../../config'; import { url } from '../../../config';
@ -40,10 +41,13 @@ export default Vue.component('misskey-flavored-markdown', {
ast = this.ast; ast = this.ast;
} }
let bigCount = 0;
let motionCount = 0;
// Parse ast to DOM // Parse ast to DOM
const els = flatten(ast.map(token => { const els = flatten(ast.map(token => {
switch (token.type) { switch (token.type) {
case 'text': case 'text': {
const text = token.content.replace(/(\r\n|\n|\r)/g, '\n'); const text = token.content.replace(/(\r\n|\n|\r)/g, '\n');
if (this.shouldBreak) { if (this.shouldBreak) {
@ -54,30 +58,52 @@ export default Vue.component('misskey-flavored-markdown', {
} else { } else {
return createElement('span', text.replace(/\n/g, ' ')); return createElement('span', text.replace(/\n/g, ' '));
} }
}
case 'bold': case 'bold': {
return createElement('b', token.bold); return createElement('b', token.bold);
}
case 'big': case 'big': {
bigCount++;
const isLong = length(token.big) > 10;
const isMany = bigCount > 3;
return (createElement as any)('strong', { return (createElement as any)('strong', {
attrs: { attrs: {
style: 'display: inline-block; font-size: 200%;' style: `display: inline-block; font-size: ${ isMany ? '100%' : '150%' };`
}, },
directives: [this.$store.state.settings.disableAnimatedMfm ? {} : { directives: [this.$store.state.settings.disableAnimatedMfm || isLong || isMany ? {} : {
name: 'animate-css', name: 'animate-css',
value: { classes: 'tada', iteration: 'infinite' } value: { classes: 'tada', iteration: 'infinite' }
}] }]
}, token.big); }, token.big);
}
case 'url': case 'motion': {
motionCount++;
const isLong = length(token.motion) > 10;
const isMany = motionCount > 3;
return (createElement as any)('span', {
attrs: {
style: 'display: inline-block;'
},
directives: [this.$store.state.settings.disableAnimatedMfm || isLong || isMany ? {} : {
name: 'animate-css',
value: { classes: 'rubberBand', iteration: 'infinite' }
}]
}, token.motion);
}
case 'url': {
return createElement(MkUrl, { return createElement(MkUrl, {
props: { props: {
url: token.content, url: token.content,
target: '_blank' target: '_blank'
} }
}); });
}
case 'link': case 'link': {
return createElement('a', { return createElement('a', {
attrs: { attrs: {
class: 'link', class: 'link',
@ -86,8 +112,9 @@ export default Vue.component('misskey-flavored-markdown', {
title: token.url title: token.url
} }
}, token.title); }, token.title);
}
case 'mention': case 'mention': {
return (createElement as any)('a', { return (createElement as any)('a', {
attrs: { attrs: {
href: `${url}/@${getAcct(token)}`, href: `${url}/@${getAcct(token)}`,
@ -99,16 +126,18 @@ export default Vue.component('misskey-flavored-markdown', {
value: token.content value: token.content
}] }]
}, token.content); }, token.content);
}
case 'hashtag': case 'hashtag': {
return createElement('a', { return createElement('a', {
attrs: { attrs: {
href: `${url}/tags/${encodeURIComponent(token.hashtag)}`, href: `${url}/tags/${encodeURIComponent(token.hashtag)}`,
target: '_blank' target: '_blank'
} }
}, token.content); }, token.content);
}
case 'code': case 'code': {
return createElement('pre', { return createElement('pre', {
class: 'code' class: 'code'
}, [ }, [
@ -118,15 +147,17 @@ export default Vue.component('misskey-flavored-markdown', {
} }
}) })
]); ]);
}
case 'inline-code': case 'inline-code': {
return createElement('code', { return createElement('code', {
domProps: { domProps: {
innerHTML: token.html innerHTML: token.html
} }
}); });
}
case 'quote': case 'quote': {
const text2 = token.quote.replace(/(\r\n|\n|\r)/g, '\n'); const text2 = token.quote.replace(/(\r\n|\n|\r)/g, '\n');
if (this.shouldBreak) { if (this.shouldBreak) {
@ -145,28 +176,33 @@ export default Vue.component('misskey-flavored-markdown', {
} }
}, text2.replace(/\n/g, ' ')); }, text2.replace(/\n/g, ' '));
} }
}
case 'title': case 'title': {
return createElement('div', { return createElement('div', {
attrs: { attrs: {
class: 'title' class: 'title'
} }
}, token.title); }, token.title);
}
case 'emoji': case 'emoji': {
const emoji = emojilib.lib[token.emoji]; const emoji = emojilib.lib[token.emoji];
return createElement('span', emoji ? emoji.char : token.content); return createElement('span', emoji ? emoji.char : token.content);
}
case 'search': case 'search': {
return createElement(MkGoogle, { return createElement(MkGoogle, {
props: { props: {
q: token.query q: token.query
} }
}); });
}
default: default: {
console.log('unknown ast type:', token.type); console.log('unknown ast type:', token.type);
} }
}
})); }));
const _els = []; const _els = [];

View File

@ -45,6 +45,9 @@ root(isDark)
color isDark ? #fff : #606266 color isDark ? #fff : #606266
transition 0.1s transition 0.1s
*
pointer-events none
&:hover &:hover
&:focus &:focus
color $theme-color color $theme-color

View File

@ -1,6 +1,6 @@
<template> <template>
<component :is="ui ? 'mk-ui' : 'div'"> <component :is="ui ? 'mk-ui' : 'div'">
<mk-reversi :game-id="$route.params.game" @nav="nav"/> <mk-reversi :game-id="$route.params.game" @nav="nav" :self-nav="false"/>
</component> </component>
</template> </template>
@ -14,9 +14,14 @@ export default Vue.extend({
} }
}, },
methods: { methods: {
nav(game) { nav(game, actualNav) {
history.pushState(null, null, '/reversi/' + game.id); if (actualNav) {
}, this.$router.push('/reversi/' + game.id);
} else {
// TODO: https://github.com/vuejs/vue-router/issues/703
this.$router.push('/reversi/' + game.id);
}
}
} }
}); });
</script> </script>

View File

@ -1,7 +1,7 @@
<template> <template>
<mk-ui> <mk-ui>
<span slot="header">%fa:gamepad%%i18n:@reversi%</span> <span slot="header">%fa:gamepad%%i18n:@reversi%</span>
<mk-reversi :game-id="$route.params.game" @nav="nav"/> <mk-reversi :game-id="$route.params.game" @nav="nav" :self-nav="false"/>
</mk-ui> </mk-ui>
</template> </template>
@ -14,8 +14,13 @@ export default Vue.extend({
document.documentElement.style.background = '#fff'; document.documentElement.style.background = '#fff';
}, },
methods: { methods: {
nav(game) { nav(game, actualNav) {
history.pushState(null, null, '/reversi/' + game.id); if (actualNav) {
this.$router.push('/reversi/' + game.id);
} else {
// TODO: https://github.com/vuejs/vue-router/issues/703
this.$router.push('/reversi/' + game.id);
}
} }
} }
}); });

View File

@ -18,6 +18,12 @@ const handlers: { [key: string]: (window: any, token: any, mentionedRemoteUsers:
document.body.appendChild(b); document.body.appendChild(b);
}, },
motion({ document }, { big }) {
const b = document.createElement('strong');
b.textContent = big;
document.body.appendChild(b);
},
code({ document }, { code }) { code({ document }, { code }) {
const pre = document.createElement('pre'); const pre = document.createElement('pre');
const inner = document.createElement('code'); const inner = document.createElement('code');

View File

@ -1,5 +1,5 @@
/** /**
* Bold * Big
*/ */
export type TextElementBig = { export type TextElementBig = {

View File

@ -0,0 +1,20 @@
/**
* Motion
*/
export type TextElementMotion = {
type: 'motion'
content: string
motion: string
};
export default function(text: string) {
const match = text.match(/^\(\(\((.+?)\)\)\)/) || text.match(/^<motion>(.+?)<\/motion>/);
if (!match) return null;
const motion = match[0];
return {
type: 'motion',
content: motion,
motion: match[1]
} as TextElementMotion;
}

View File

@ -14,6 +14,7 @@ import { TextElementQuote } from './elements/quote';
import { TextElementSearch } from './elements/search'; import { TextElementSearch } from './elements/search';
import { TextElementTitle } from './elements/title'; import { TextElementTitle } from './elements/title';
import { TextElementUrl } from './elements/url'; import { TextElementUrl } from './elements/url';
import { TextElementMotion } from './elements/motion';
const elements = [ const elements = [
require('./elements/big'), require('./elements/big'),
@ -27,7 +28,8 @@ const elements = [
require('./elements/inline-code'), require('./elements/inline-code'),
require('./elements/quote'), require('./elements/quote'),
require('./elements/emoji'), require('./elements/emoji'),
require('./elements/search') require('./elements/search'),
require('./elements/motion')
].map(element => element.default as TextElementProcessor); ].map(element => element.default as TextElementProcessor);
export type TextElement = { type: 'text', content: string } export type TextElement = { type: 'text', content: string }
@ -42,7 +44,8 @@ export type TextElement = { type: 'text', content: string }
| TextElementQuote | TextElementQuote
| TextElementSearch | TextElementSearch
| TextElementTitle | TextElementTitle
| TextElementUrl; | TextElementUrl
| TextElementMotion;
export type TextElementProcessor = (text: string, i: number) => TextElement | TextElement[]; export type TextElementProcessor = (text: string, i: number) => TextElement | TextElement[];
export default (source: string): TextElement[] => { export default (source: string): TextElement[] => {

View File

@ -12,7 +12,7 @@ export const meta = {
requireCredential: true, requireCredential: true,
params: { params: {
gameId: $.type(ID).optional.note({ gameId: $.type(ID).note({
desc: { desc: {
ja: '投了したい対局' ja: '投了したい対局'
} }

View File

@ -11,7 +11,7 @@ const handler = new EventEmitter();
let bot: IUser; let bot: IUser;
const post = async (text: string) => { const post = async (text: string, home = true) => {
if (bot == null) { if (bot == null) {
const account = await User.findOne({ const account = await User.findOne({
usernameLower: config.github_bot.username.toLowerCase() usernameLower: config.github_bot.username.toLowerCase()
@ -25,7 +25,7 @@ const post = async (text: string) => {
} }
} }
createNote(bot, { text, visibility: 'home' }); createNote(bot, { text, visibility: home ? 'home' : 'public' });
}; };
// Init router // Init router
@ -130,7 +130,7 @@ handler.on('issue_comment', event => {
handler.on('watch', event => { handler.on('watch', event => {
const sender = event.sender; const sender = event.sender;
post(`⭐️ Starred by **${sender.login}** ⭐️`); post(`(((⭐️))) Starred by **${sender.login}** (((⭐️)))`, false);
}); });
handler.on('fork', event => { handler.on('fork', event => {

View File

@ -103,6 +103,24 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
data.visibleUsers = data.visibleUsers.filter(x => x != null); data.visibleUsers = data.visibleUsers.filter(x => x != null);
} }
if (data.reply && data.reply.deletedAt != null) {
return rej();
}
if (data.renote && data.renote.deletedAt != null) {
return rej();
}
// リプライ先が自分以外の非公開の投稿なら禁止
if (data.reply && data.reply.visibility == 'private' && !data.reply.userId.equals(user._id)) {
return rej();
}
// Renote先が自分以外の非公開の投稿なら禁止
if (data.renote && data.renote.visibility == 'private' && !data.renote.userId.equals(user._id)) {
return rej();
}
if (data.text) { if (data.text) {
data.text = data.text.trim(); data.text = data.text.trim();
} }

View File

@ -34,11 +34,25 @@ describe('Text', () => {
it('big', () => { it('big', () => {
const tokens = analyze('***Strawberry*** Pasta'); const tokens = analyze('***Strawberry*** Pasta');
assert.deepEqual([ assert.deepEqual([
{ type: 'big', content: '***Strawberry***', bold: 'Strawberry' }, { type: 'big', content: '***Strawberry***', big: 'Strawberry' },
{ type: 'text', content: ' Pasta' } { type: 'text', content: ' Pasta' }
], tokens); ], tokens);
}); });
it('motion', () => {
const tokens1 = analyze('(((Strawberry))) Pasta');
assert.deepEqual([
{ type: 'motion', content: '(((Strawberry)))', motion: 'Strawberry' },
{ type: 'text', content: ' Pasta' }
], tokens1);
const tokens2 = analyze('<motion>Strawberry</motion> Pasta');
assert.deepEqual([
{ type: 'motion', content: '<motion>Strawberry</motion>', motion: 'Strawberry' },
{ type: 'text', content: ' Pasta' }
], tokens2);
});
it('mention', () => { it('mention', () => {
const tokens = analyze('@himawari お腹ペコい'); const tokens = analyze('@himawari お腹ペコい');
assert.deepEqual([ assert.deepEqual([