mirror of
				https://github.com/yude-jp/yude.jp
				synced 2025-10-30 19:48:35 +09:00 
			
		
		
		
	Compare commits
	
		
			73 Commits
		
	
	
		
			aaa92c3a73
			...
			master
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 79246ee600 | |||
| 98ad910a9b | |||
| fc90f87285 | |||
| b07d6412ff | |||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 6d6365c240 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 1dd86ac2c8 | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 496fe5ee4b | ||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | cdcce3a39b | ||
| 7f3a8f8230 | |||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | fae52872f1 | ||
| 1c8bf364dd | |||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | ef653ed749 | ||
| 8deac1fede | |||
| 3fb52ddcfa | |||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | a36785dded | ||
| c60270c1c6 | |||
| 1b7319617b | |||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | aa6f4417e7 | ||
| ae6c8aa9c9 | |||
| 9389cc55f7 | |||
| ba0e41579a | |||
| b35caef45c | |||
| 7ac1c7199f | |||
| f697eb9b85 | |||
| 16bb6398e4 | |||
| 02b1adcf55 | |||
| 34e335037c | |||
| 0cb27e3cda | |||
| 92459e594f | |||
| c30312a46a | |||
| 5531b3a3bf | |||
| f0cf3729a0 | |||
| ec530601b4 | |||
| 30547e3b81 | |||
| 2529afa286 | |||
| b62f95d483 | |||
| 2bd3b69da1 | |||
| 5a0e87d7d4 | |||
| b6f427d605 | |||
| 92bb8b995c | |||
| 52c8cd8d1c | |||
| 22385a42c8 | |||
| 99f776b861 | |||
| 24327251ee | |||
| 1f7456db3c | |||
| a8321b6c60 | |||
| ff98956a10 | |||
| db6855fbc6 | |||
| b446a2ebae | |||
| 86844984d2 | |||
| a72a778a03 | |||
| d9559dd072 | |||
| c856a34867 | |||
| d3283b12b2 | |||
| 8513ee795f | |||
| 49bd87b276 | |||
| a095e20b6b | |||
| 33dbec3339 | |||
| 6eb140fc0a | |||
| ![dependabot[bot]](/assets/img/avatar_default.png)  | 08d054f8f6 | ||
| bed955aa95 | |||
| 37adbffcef | |||
| b1a778b5d0 | |||
| e32dde3363 | |||
| 429407820f | |||
| 4e8f0435f2 | |||
| d764ae8f32 | |||
| db8a0af6ca | |||
| 9e2f51eb5f | |||
| 979bbe2a7f | |||
| de69c49d46 | |||
| 1411e37d8f | |||
| a08bd36c3e | 
| @@ -1,5 +0,0 @@ | ||||
| SPOTIFY_CLIENT_ID= | ||||
| SPOTIFY_CLIENT_SECRET= | ||||
| SPOTIFY_REFRESH_TOKEN= | ||||
|  | ||||
| MICROCMS_API_KEY= | ||||
| @@ -1,3 +1,8 @@ | ||||
| { | ||||
|   "extends": "next/core-web-vitals" | ||||
|   "extends": "next/core-web-vitals", | ||||
|   "rules": { | ||||
|     "@next/next/no-document-import-in-page": "off", | ||||
|     "@next/next/no-img-element": "off", | ||||
|     "react-hooks/exhaustive-deps": "off" | ||||
|   } | ||||
| } | ||||
|   | ||||
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -11,5 +11,6 @@ yarn-error.log | ||||
| .vimrc~ | ||||
| ..vimrc.un~ | ||||
| .env.local | ||||
|  | ||||
| out | ||||
| .vercel | ||||
| .DS_Store | ||||
|   | ||||
| @@ -3,14 +3,11 @@ | ||||
| <img alt="Next JS" src="https://img.shields.io/badge/nextjs-%23000000.svg?style=for-the-badge&logo=next.js&logoColor=white"/> | ||||
| <img alt="TailwindCSS" src="https://img.shields.io/badge/tailwindcss-%2338B2AC.svg?style=for-the-badge&logo=tailwind-css&logoColor=white"/>\ | ||||
| Source code of [yude.jp](https://yude.jp).\ | ||||
| Built with [Next.js](https://nextjs.org/) and [Tailwind CSS](https://tailwindcss.com/) and deployed on [Vercel](https://vercel.com). | ||||
| Built with [Next.js](https://nextjs.org/) and [Tailwind CSS](https://tailwindcss.com/) and deployed to [Cloudflare Pages](https://pages.cloudflare.com/). | ||||
|  | ||||
| ## Development | ||||
| ### Setup | ||||
| 1. Run `yarn`. | ||||
| 1. Rename `.env.local.sample` as `.env.local` and set value.  | ||||
| ### Preview | ||||
| * Run `yarn dev`. | ||||
| 1. Run `yarn` to install dependencies. | ||||
| 2. Run `yarn dev` to serve. | ||||
|  | ||||
| ## License | ||||
| This repository is provided under the MIT License. | ||||
|   | ||||
| @@ -4,7 +4,7 @@ The following applies in addition to [yude.jp Terms of Service](https://yude.jp/ | ||||
| * Don't troll. | ||||
| * Don't cheat. | ||||
|  | ||||
| # List of available commands | ||||
| # Part of the list of available commands () | ||||
| * `/ll`: Switch the visibility of spawn checker. | ||||
| * `/mvspawn`: Teleport to spawn point of the world you're in. | ||||
|  | ||||
| @@ -17,6 +17,12 @@ You can also create a shared block by writing the player ID across multiple line | ||||
|  | ||||
| ## Skills | ||||
| You can use skills powered by mcMMO. | ||||
| ## Warp | ||||
| You can warp to registered points. | ||||
| To show registered points, run `/warps`. To warp, run `/warp <name>`. | ||||
|  | ||||
| # Game specifications | ||||
| * `keepInventory` is `true`, which means you won't drop inventory on death. | ||||
|  | ||||
| # Facility introduction | ||||
| ## Shrine (by shirachan_1204) | ||||
|   | ||||
| @@ -3,7 +3,7 @@ | ||||
| * ワールドのどこであっても自由に建築することができます。 | ||||
| * トロール (荒らし) を行わないでください。 | ||||
| * チートを行わないでください。 | ||||
| # 使用可能なコマンドの一覧 | ||||
| # 主な使用可能なコマンドの一覧 | ||||
| * `/ll`: スポーンチェッカーの表示を切り替えます。 | ||||
| * `/mvspawn`: ワールドのスポーン地点へ転移します。 | ||||
|  | ||||
| @@ -16,6 +16,12 @@ | ||||
|  | ||||
| ## スキル | ||||
| mcMMO を導入しているので、プラグインによるスキルを利用できます。   | ||||
| ## ワープ | ||||
| 登録されている地点へワープできます。 | ||||
| `/warps` で登録地点の一覧を表示し、`/warp (登録名)` でワープします。 | ||||
|  | ||||
| # ゲームの仕様 | ||||
| * `keepInventory` は `true` になっています。したがって、死亡によるインベントリーのドロップはありません。 | ||||
|  | ||||
| # 施設紹介 | ||||
| ## 神社 (by shirachan_1204) | ||||
|   | ||||
							
								
								
									
										23
									
								
								docs/services/en.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								docs/services/en.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| # Available services on yude.jp | ||||
|  | ||||
| ## Softwares | ||||
| * [AutoMuteUs](https://github.com/denverquane/automuteus)\ | ||||
| Among Us helper; API: [`galactus.yude.jp`](https://galactus.yude.jp) | ||||
| * [Nextcloud](https://nc.yude.jp) | ||||
| * [Mastodon](https://mstdn.yude.jp) | ||||
| * [Misskey](https://misskey.yude.jp) | ||||
| * [Pleroma](https//pleroma.yude.jp) | ||||
| * TeamSpeak 3: `yude.jp` | ||||
| * [Gitea](https://git.yude.jp) | ||||
| * [h5ai](https://files.yude.jp) | ||||
| * [JMusicBot (forked)](https://discord.com/oauth2/authorize?client_id=429638220456656896&scope=bot&permissions=338963472) | ||||
| * [Owncast](https://live.yude.jp) | ||||
| * [Minecraft Server](https://yude.jp/minecraft) | ||||
|  | ||||
| ## Anonymous communication | ||||
| ### Tor | ||||
| * Relay: [yudejp](https://metrics.torproject.org/rs.html#details/CF762EF3C86B104C301511894547C72371F952A4) | ||||
| * Hidden Service: [yude3mzscyufx5u3zup72ium7tgecy3bd67p7t6vqhaywvr7e2gqpcqd.onion](http://yude3mzscyufx5u3zup72ium7tgecy3bd67p7t6vqhaywvr7e2gqpcqd.onion) | ||||
|  | ||||
| ### I2P | ||||
| * Hidden Service: [yudejp.i2p/?i2paddresshelper=55ivoba6mo3mqlwvw5lqz7lchxqew2kh77kwkn5shefrj2dp3coq.b32.i2p](http://yudejp.i2p/?i2paddresshelper=55ivoba6mo3mqlwvw5lqz7lchxqew2kh77kwkn5shefrj2dp3coq.b32.i2p) | ||||
							
								
								
									
										23
									
								
								docs/services/ja.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								docs/services/ja.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| # yude.jp で運用中のサービス | ||||
|  | ||||
| ## ソフトウェア | ||||
| * [AutoMuteUs](https://github.com/denverquane/automuteus)\ | ||||
| Among Us の自動ミュートボット; API: [`galactus.yude.jp`](https://galactus.yude.jp) | ||||
| * [Nextcloud](https://nc.yude.jp) | ||||
| * [Mastodon](https://mstdn.yude.jp) | ||||
| * [Misskey](https://misskey.yude.jp) | ||||
| * [Pleroma](https//pleroma.yude.jp) | ||||
| * TeamSpeak 3: `yude.jp` | ||||
| * [Gitea](https://git.yude.jp) | ||||
| * [h5ai](https://files.yude.jp) | ||||
| * [JMusicBot (フォーク)](https://discord.com/oauth2/authorize?client_id=429638220456656896&scope=bot&permissions=338963472) | ||||
| * [Owncast](https://live.yude.jp) | ||||
| * [Minecraft サーバー](https://yude.jp/minecraft) | ||||
|  | ||||
| ## 秘匿化ネットワーク | ||||
| ### Tor | ||||
| * リレー: [yudejp](https://metrics.torproject.org/rs.html#details/CF762EF3C86B104C301511894547C72371F952A4) | ||||
| * Hidden Service: [yude3mzscyufx5u3zup72ium7tgecy3bd67p7t6vqhaywvr7e2gqpcqd.onion](http://yude3mzscyufx5u3zup72ium7tgecy3bd67p7t6vqhaywvr7e2gqpcqd.onion) | ||||
|  | ||||
| ### I2P | ||||
| * Hidden Service: [yudejp.i2p/?i2paddresshelper=55ivoba6mo3mqlwvw5lqz7lchxqew2kh77kwkn5shefrj2dp3coq.b32.i2p](http://yudejp.i2p/?i2paddresshelper=55ivoba6mo3mqlwvw5lqz7lchxqew2kh77kwkn5shefrj2dp3coq.b32.i2p) | ||||
							
								
								
									
										15
									
								
								i18n.json
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								i18n.json
									
									
									
									
									
								
							| @@ -1,15 +0,0 @@ | ||||
| { | ||||
|     "locales": ["en", "ja"], | ||||
|     "defaultLocale": "ja", | ||||
|     "pages": { | ||||
|       "*": ["common"], | ||||
|       "/": ["index", "minecraft", "common"], | ||||
|       "/profile": ["profile", "common"], | ||||
|       "/server": ["server", "common"], | ||||
|       "/house": ["house", "common"], | ||||
|       "/tos": ["tos", "common"], | ||||
|       "/hcunews": ["hcunews", "common"], | ||||
|       "/minecraft": ["minecraft", "common"], | ||||
|       "/404": ["404", "common"] | ||||
|     } | ||||
|   } | ||||
							
								
								
									
										12
									
								
								i18n/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								i18n/index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| var ja = require('./translations.ja.json'); | ||||
| var en = require('./translations.en.json') | ||||
|  | ||||
| const i18n = { | ||||
| 	translations: { | ||||
| 		ja: ja, | ||||
| 		en: en, | ||||
| 	}, | ||||
| 	defaultLang: 'ja' | ||||
| } | ||||
|  | ||||
| module.exports = i18n; | ||||
							
								
								
									
										67
									
								
								i18n/translations.en.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								i18n/translations.en.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| { | ||||
|     "caption": "The requested page does not exist on this website.", | ||||
|     "return": "Return to top", | ||||
|     "footer": "This page is provided under the MIT License.", | ||||
|     "source": "Source code", | ||||
|     "tos": "yude.jp Terms of Service", | ||||
|     "yes_playing": "Playing {{playing}}", | ||||
|     "listening": "Listening to {{listening}}", | ||||
|     "close": "Close", | ||||
|     "mutual": "Mutual links", | ||||
|     "status": "Service Status", | ||||
|     "icon_1": "Icon: ", | ||||
|     "icon_2": " ", | ||||
|     "post_list": "Posts listing", | ||||
|     "hcunews": "About @hcunews", | ||||
|     "house": "yude's house", | ||||
|     "home": "Home", | ||||
|     "profile": "yude's profile", | ||||
|     "blog": "yude's blog", | ||||
|     "status": "yude.jp Server Status", | ||||
|     "house": "yude's house", | ||||
|     "discord": "yude.jp Discord Server", | ||||
|     "mastodon": "Mastodon instance", | ||||
|     "title": "Minecraft Multiplayer", | ||||
|     "playing": "{{count}} player(s) online.", | ||||
|     "no_one": "No one is playing.", | ||||
|     "offline": "Server is down.", | ||||
|     "address": "Server address", | ||||
|     "fail": "Failed to retrieve server status.", | ||||
|     "loading": "Retrieving server status...", | ||||
|     "version": "Version", | ||||
|     "about": "About yude", | ||||
|     "desc": "Description", | ||||
|     "school": "Faculty of Information Science, Hiroshima City University.", | ||||
|     "hiroshima": "Hiroshima, Japan", | ||||
|     "location": "Location", | ||||
|     "link": "Links", | ||||
|     "link_all": "To see all of yude's account, please visit ", | ||||
|     "link_all_late": ".", | ||||
|     "here": "here", | ||||
|     "mail": "E-mail", | ||||
|     "birth": "Birthday", | ||||
|     "date": "November the 19th, 2001", | ||||
|     "contact": "Accounts", | ||||
|     "belongs": "Organization", | ||||
|     "grade": "B2", | ||||
|     "keys": "Public keys", | ||||
|     "download": "Download", | ||||
|     "fingerprint": "Digital fingerprint", | ||||
|     "view": "View", | ||||
|     "device": "Devices", | ||||
|     "account": "Accounts", | ||||
|     "wishlist": "Amazon Wishlist", | ||||
|     "status": "Server Status", | ||||
|     "location": "Location", | ||||
|     "tottori": "Tottori, Japan", | ||||
|     "hiroshima": "Hiroshima, Japan", | ||||
|     "model": "Model", | ||||
|     "region": "Region", | ||||
|     "service": "Service", | ||||
|     "shape": "Shape", | ||||
|     "tos": "yude.jp Terms of Service", | ||||
|     "input": "en", | ||||
|     "services": "Services", | ||||
|     "contents": "Contents", | ||||
|     "Blog": "Weblog" | ||||
| } | ||||
							
								
								
									
										67
									
								
								i18n/translations.ja.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								i18n/translations.ja.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| { | ||||
|     "caption": "要求されたページはこのウェブサイト上に存在しません。", | ||||
|     "return": "トップページへ戻る", | ||||
|     "footer": "このページは MIT License のもと提供されています。", | ||||
|     "source": "ソースコード", | ||||
|     "tos": "yude.jp サービス利用規約", | ||||
|     "yes_playing": "{{playing}} をプレイ中", | ||||
|     "listening": "{{listening}} を再生中", | ||||
|     "close": "閉じる", | ||||
|     "mutual": "相互リンク", | ||||
|     "status": "サービスの状態", | ||||
|     "icon_1": "アイコン: ", | ||||
|     "icon_2": "さん", | ||||
|     "post_list": "記事一覧", | ||||
|     "hcunews": "@hcunews について", | ||||
|     "house": "ゆでハウス", | ||||
|     "home": "ホーム", | ||||
|     "profile": "yude のプロフィール", | ||||
|     "blog": "yude のブログ", | ||||
|     "status": "yude.jp サーバー情報", | ||||
|     "house": "ゆでハウス", | ||||
|     "discord": "yude.jp Discord サーバー", | ||||
|     "mastodon": "Mastodon インスタンス", | ||||
|     "title": "Minecraft マルチプレイ", | ||||
|     "playing": "{{count}} 人がプレイしています。", | ||||
|     "no_one": "現在、誰もログインしていません。", | ||||
|     "offline": "サーバーがオフラインのようです。", | ||||
|     "address": "サーバー アドレス", | ||||
|     "fail": "サーバーの状態を取得できませんでした。", | ||||
|     "loading": "サーバーの状態を取得しています...", | ||||
|     "version": "バージョン", | ||||
|     "about": "yude について", | ||||
|     "desc": "概要", | ||||
|     "school": "広島市立大学 情報科学部", | ||||
|     "hiroshima": "日本, 広島県", | ||||
|     "location": "所在地", | ||||
|     "link": "リンク", | ||||
|     "link_all": "yude が所持しているすべてのアカウントの一覧は、", | ||||
|     "link_all_late": "にあります。", | ||||
|     "here": "こちら", | ||||
|     "mail": "メール", | ||||
|     "birth": "生年月日", | ||||
|     "date": "2001年11月19日", | ||||
|     "contact": "アカウント", | ||||
|     "belongs": "所属", | ||||
|     "grade": "2年", | ||||
|     "keys": "公開鍵", | ||||
|     "download": "ダウンロード", | ||||
|     "fingerprint": "電子指紋", | ||||
|     "view": "閲覧", | ||||
|     "device": "デバイス", | ||||
|     "account": "アカウント", | ||||
|     "wishlist": "Amazon ほしいものリスト", | ||||
|     "status": "サーバー情報", | ||||
|     "location": "場所", | ||||
|     "tottori": "日本, 鳥取県", | ||||
|     "hiroshima": "日本, 広島県", | ||||
|     "model": "モデル", | ||||
|     "region": "リージョン", | ||||
|     "service": "サービス", | ||||
|     "shape": "シェイプ", | ||||
|     "tos": "yude.jp サービス利用規約", | ||||
|     "input": "ja", | ||||
|     "services": "サービス", | ||||
|     "contents": "コンテンツ", | ||||
|     "blog": "ブログ" | ||||
| } | ||||
| @@ -1,6 +0,0 @@ | ||||
| import { createClient } from 'microcms-js-sdk'; | ||||
|  | ||||
| export const client = createClient({ | ||||
|   serviceDomain: 'yude', | ||||
|   apiKey: process.env.MICROCMS_API_KEY, | ||||
| }); | ||||
| @@ -1,4 +0,0 @@ | ||||
| { | ||||
|     "caption": "The requested page does not exist on this website.", | ||||
|     "return": "Return to top" | ||||
| } | ||||
| @@ -1,13 +0,0 @@ | ||||
| { | ||||
|     "footer": "This page is provided under the MIT License.", | ||||
|     "source": "Source code", | ||||
|     "tos": "yude.jp Terms of Service", | ||||
|     "yes_playing": "Playing {{playing}}", | ||||
|     "listening": "Listening to {{listening}}", | ||||
|     "close": "Close", | ||||
|     "mutual": "Mutual links", | ||||
|     "status": "Service Status", | ||||
|     "icon_1": "Icon: ", | ||||
|     "icon_2": "", | ||||
|     "post_list": "Posts listing" | ||||
| } | ||||
| @@ -1,3 +0,0 @@ | ||||
| { | ||||
|     "hcunews": "About @hcunews" | ||||
| } | ||||
| @@ -1,3 +0,0 @@ | ||||
| { | ||||
|     "house": "yude's house" | ||||
| } | ||||
| @@ -1,9 +0,0 @@ | ||||
| { | ||||
|     "home": "Home", | ||||
|     "profile": "yude's profile", | ||||
|     "blog": "yude's blog", | ||||
|     "status": "yude.jp Server Status", | ||||
|     "house": "yude's house", | ||||
|     "discord": "yude.jp Discord Server", | ||||
|     "mastodon": "Mastodon instance" | ||||
| } | ||||
| @@ -1,10 +0,0 @@ | ||||
| { | ||||
|     "title": "Minecraft Multiplayer", | ||||
|     "playing": "{{count}} player(s) online.", | ||||
|     "no_one": "No one is playing.", | ||||
|     "offline": "Server is down.", | ||||
|     "address": "Server address", | ||||
|     "fail": "Failed to retrieve server status.", | ||||
|     "loading": "Retrieving server status...", | ||||
|     "version": "Version" | ||||
| } | ||||
| @@ -1,24 +0,0 @@ | ||||
| { | ||||
|     "about": "About yude", | ||||
|     "desc": "Description", | ||||
|     "school": "Faculty of Information Science, Hiroshima City University.", | ||||
|     "hiroshima": "Hiroshima, Japan", | ||||
|     "location": "Location", | ||||
|     "link": "Links", | ||||
|     "link_all": "To see all of yude's account, please visit ", | ||||
|     "link_all_late": ".", | ||||
|     "here": "here", | ||||
|     "mail": "E-mail", | ||||
|     "birth": "Birthday", | ||||
|     "date": "November the 19th, 2001", | ||||
|     "contact": "Get in touch", | ||||
|     "belongs": "Organization", | ||||
|     "grade": "B2", | ||||
|     "keys": "Public keys", | ||||
|     "download": "Download", | ||||
|     "fingerprint": "Digital fingerprint", | ||||
|     "view": "View", | ||||
|     "device": "Devices", | ||||
|     "account": "Accounts", | ||||
|     "wishlist": "Amazon Wishlist" | ||||
| } | ||||
| @@ -1,10 +0,0 @@ | ||||
| { | ||||
|     "status": "Server Status", | ||||
|     "location": "Location", | ||||
|     "tottori": "Tottori, Japan", | ||||
|     "hiroshima": "Hiroshima, Japan", | ||||
|     "model": "Model", | ||||
|     "region": "Region", | ||||
|     "service": "Service", | ||||
|     "shape": "Shape" | ||||
| } | ||||
| @@ -1,4 +0,0 @@ | ||||
| { | ||||
|     "tos": "yude.jp Terms of Service", | ||||
|     "input": "en" | ||||
| } | ||||
| @@ -1,4 +0,0 @@ | ||||
| { | ||||
|     "caption": "要求されたページはこのウェブサイト上に存在しません。", | ||||
|     "return": "トップページへ戻る" | ||||
| } | ||||
| @@ -1,13 +0,0 @@ | ||||
| { | ||||
|     "footer": "このページは MIT License のもと提供されています。", | ||||
|     "source": "ソースコード", | ||||
|     "tos": "yude.jp サービス利用規約", | ||||
|     "yes_playing": "{{playing}} をプレイ中", | ||||
|     "listening": "{{listening}} を再生中", | ||||
|     "close": "閉じる", | ||||
|     "mutual": "相互リンク", | ||||
|     "status": "サービスの状態", | ||||
|     "icon_1": "アイコン: ", | ||||
|     "icon_2": "さん", | ||||
|     "post_list": "記事一覧" | ||||
| } | ||||
| @@ -1,3 +0,0 @@ | ||||
| { | ||||
|     "hcunews": "@hcunews について" | ||||
| } | ||||
| @@ -1,3 +0,0 @@ | ||||
| { | ||||
|     "house": "ゆでハウス" | ||||
| } | ||||
| @@ -1,9 +0,0 @@ | ||||
| { | ||||
|     "home": "ホーム", | ||||
|     "profile": "yude のプロフィール", | ||||
|     "blog": "yude のブログ", | ||||
|     "status": "yude.jp サーバー情報", | ||||
|     "house": "ゆでハウス", | ||||
|     "discord": "yude.jp Discord サーバー", | ||||
|     "mastodon": "Mastodon インスタンス" | ||||
| } | ||||
| @@ -1,10 +0,0 @@ | ||||
| { | ||||
|     "title": "Minecraft マルチプレイ", | ||||
|     "playing": "{{count}} 人がプレイしています。", | ||||
|     "no_one": "現在、誰もログインしていません。", | ||||
|     "offline": "サーバーがオフラインのようです。", | ||||
|     "address": "サーバー アドレス", | ||||
|     "fail": "サーバーの状態を取得できませんでした。", | ||||
|     "loading": "サーバーの状態を取得しています...", | ||||
|     "version": "バージョン" | ||||
| } | ||||
| @@ -1,24 +0,0 @@ | ||||
| { | ||||
|     "about": "yude について", | ||||
|     "desc": "概要", | ||||
|     "school": "広島市立大学 情報科学部", | ||||
|     "hiroshima": "日本, 広島県", | ||||
|     "location": "所在地", | ||||
|     "link": "リンク", | ||||
|     "link_all": "yude が所持しているすべてのアカウントの一覧は、", | ||||
|     "link_all_late": "にあります。", | ||||
|     "here": "こちら", | ||||
|     "mail": "メール", | ||||
|     "birth": "生年月日", | ||||
|     "date": "2001年11月19日", | ||||
|     "contact": "連絡先 / SNS", | ||||
|     "belongs": "所属", | ||||
|     "grade": "2年", | ||||
|     "keys": "公開鍵", | ||||
|     "download": "ダウンロード", | ||||
|     "fingerprint": "電子指紋", | ||||
|     "view": "閲覧", | ||||
|     "device": "デバイス", | ||||
|     "account": "アカウント", | ||||
|     "wishlist": "Amazon ほしいものリスト" | ||||
| } | ||||
| @@ -1,10 +0,0 @@ | ||||
| { | ||||
|     "status": "サーバー情報", | ||||
|     "location": "場所", | ||||
|     "tottori": "日本, 鳥取県", | ||||
|     "hiroshima": "日本, 広島県", | ||||
|     "model": "モデル", | ||||
|     "region": "リージョン", | ||||
|     "service": "サービス", | ||||
|     "shape": "シェイプ" | ||||
| } | ||||
| @@ -1,4 +0,0 @@ | ||||
| { | ||||
|     "tos": "yude.jp サービス利用規約", | ||||
|     "input": "ja" | ||||
| } | ||||
| @@ -1,5 +1,3 @@ | ||||
| const nextTranslate = require('next-translate') | ||||
|  | ||||
| const rewrites = async () => { | ||||
|   return [ | ||||
|     { | ||||
| @@ -7,17 +5,13 @@ const rewrites = async () => { | ||||
|       destination: '/minecraft/players/:uuid' | ||||
|     }, | ||||
|     { | ||||
|       source: '/minecraft/players/:uuid', | ||||
|       destination: '/404' | ||||
|       source: '/minecraft/players/:ign', | ||||
|       destination: '/minecraft/lookup/:ign' | ||||
|     } | ||||
|   ] | ||||
| } | ||||
|  | ||||
| module.exports = nextTranslate({ | ||||
|     i18n: { | ||||
|       locales: ['ja', 'en'], | ||||
|       defaultLocale: 'ja', | ||||
|     }, | ||||
| module.exports = { | ||||
|     images: { | ||||
|       domains: ['mackerel.io', 'mc-heads.net', 'crafatar.com'], | ||||
|     }, | ||||
| @@ -43,4 +37,4 @@ module.exports = nextTranslate({ | ||||
|       ] | ||||
|     }, | ||||
|     rewrites, | ||||
|   }) | ||||
|   } | ||||
| @@ -30,12 +30,13 @@ | ||||
|     "@tailwindcss/typography": "^0.4.0", | ||||
|     "autoprefixer": "^10.3.4", | ||||
|     "axios": "^0.21.4", | ||||
|     "microcms-js-sdk": "^1.2.0", | ||||
|     "moment": "^2.29.1", | ||||
|     "next": "^11.1.2", | ||||
|     "date-fns": "^2.24.0", | ||||
|     "moment": "^2.29.4", | ||||
|     "next": "^12.1.0", | ||||
|     "next-export-i18n": "^1.2.1", | ||||
|     "next-seo": "^4.28.1", | ||||
|     "next-themes": "^0.0.15", | ||||
|     "next-translate": "^1.1.0", | ||||
|     "next-translate": "^1.2.0", | ||||
|     "popper.js": "^1.16.1", | ||||
|     "postcss": "^8.3.6", | ||||
|     "prop-types": "^15.7.2", | ||||
|   | ||||
							
								
								
									
										29
									
								
								pages/404.js
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								pages/404.js
									
									
									
									
									
								
							| @@ -1,29 +0,0 @@ | ||||
| // Base layout | ||||
| import Layout from "./components/Layout" | ||||
|  | ||||
| // React Router | ||||
| import { useRouter } from 'next/router' | ||||
|  | ||||
| // Next.js | ||||
| import Link from 'next/link' | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
|  | ||||
| export default function Custom404(props) { | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|   const { t, lang } = useTranslation("404") | ||||
|  | ||||
|   return ( | ||||
|     <Layout title="404"> | ||||
|       <div className="text-center mb-10 mt-10"> | ||||
|       <p className="text-3xl">404</p> | ||||
|       <p className="text-xl">{t('caption')}</p> | ||||
|       <Link href="/"> | ||||
|         <a> | ||||
|             <p className="mt-5">{t('return')}</p> | ||||
|         </a> | ||||
|       </Link> | ||||
|       </div> | ||||
|     </Layout> | ||||
|   ) | ||||
| } | ||||
| @@ -1,23 +0,0 @@ | ||||
| // React | ||||
| import React, { useState, useEffect } from 'react'; | ||||
| import axios from 'axios'; | ||||
|  | ||||
| export const getName = async (props) => { | ||||
|   const uuid = props; | ||||
|   return fetch('https://api.ashcon.app/mojang/v2/user/' + uuid); | ||||
| }; | ||||
|  | ||||
| const RawPlayerName = async (req, res) => { | ||||
|     const { uuid } = req.query | ||||
|     const response = await getName(uuid); | ||||
|     const data = await response.json(); | ||||
|     if (response.status === 204 || response.status > 400) { | ||||
|       return res.status(200).send("404"); | ||||
|     } | ||||
|     const username = data.username; | ||||
|     return res.status(200).json({ | ||||
|       username, | ||||
|     }); | ||||
| }; | ||||
|  | ||||
| export default RawPlayerName | ||||
| @@ -1,60 +0,0 @@ | ||||
| import querystring from 'querystring'; | ||||
|  | ||||
| const { | ||||
|   SPOTIFY_CLIENT_ID: client_id, | ||||
|   SPOTIFY_CLIENT_SECRET: client_secret, | ||||
|   SPOTIFY_REFRESH_TOKEN: refresh_token, | ||||
| } = process.env; | ||||
|  | ||||
| const basic = Buffer.from(`${client_id}:${client_secret}`).toString('base64'); | ||||
| const NOW_PLAYING_ENDPOINT = `https://api.spotify.com/v1/me/player/currently-playing`; | ||||
| const TOKEN_ENDPOINT = `https://accounts.spotify.com/api/token`; | ||||
|  | ||||
| const getAccessToken = async () => { | ||||
|   const response = await fetch(TOKEN_ENDPOINT, { | ||||
|     method: 'POST', | ||||
|     headers: { | ||||
|       Authorization: `Basic ${basic}`, | ||||
|       'Content-Type': 'application/x-www-form-urlencoded', | ||||
|     }, | ||||
|     body: querystring.stringify({ | ||||
|       grant_type: 'refresh_token', | ||||
|       refresh_token, | ||||
|     }), | ||||
|   }); | ||||
|  | ||||
|   return response.json(); | ||||
| }; | ||||
|  | ||||
| export const getNowPlaying = async () => { | ||||
|   const { access_token } = await getAccessToken(); | ||||
|  | ||||
|   return fetch(NOW_PLAYING_ENDPOINT, { | ||||
|     headers: { | ||||
|       Authorization: `Bearer ${access_token}`, | ||||
|     }, | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| const Spotify = async (_, res) => { | ||||
|   const response = await getNowPlaying(); | ||||
|  | ||||
|   if (response.status === 204 || response.status > 400) { | ||||
|     return res.status(200).json({ isPlaying: false }); | ||||
|   } | ||||
|  | ||||
|   const song = await response.json(); | ||||
|   const isPlaying = song.is_playing; | ||||
|   const title = song.item.name; | ||||
|   const artist = song.item.artists.map((_artist) => _artist.name).join(', '); | ||||
|   const album = song.item.album.name; | ||||
|  | ||||
|   return res.status(200).json({ | ||||
|     album, | ||||
|     artist, | ||||
|     isPlaying, | ||||
|     title, | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| export default Spotify | ||||
| @@ -1,44 +1,38 @@ | ||||
| // React | ||||
| import React, { useState, useEffect } from 'react'; | ||||
| import axios from 'axios'; | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
| import { useRouter } from 'next/router' | ||||
|  | ||||
| function App (){ | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|   const { t, lang } = useTranslation("common") | ||||
|   const [data, setData] = useState({ hits: [] }); | ||||
|   useEffect(() => { | ||||
|     const fetchData = async () => { | ||||
|       const result = await axios( | ||||
|         'https://discord.com/api/guilds/723409709306216498/widget.json', | ||||
|       ); | ||||
|       setData(result.data); | ||||
|     };   | ||||
|     fetchData(); | ||||
|   }, []); | ||||
|   if (data === undefined){ | ||||
|     console.log("[Discord API] データの取得に失敗しました。 / Failed to retrieve data.") | ||||
|     return <p></p> | ||||
|   }else{ | ||||
|   const str = JSON.stringify(data) | ||||
| // Data fetching | ||||
| import useSwr from 'swr' | ||||
| const fetcher = (url) => fetch(url).then((res) => res.json()) | ||||
|  | ||||
| // i18n | ||||
| import { useTranslation, useLanguageQuery } from 'next-export-i18n'; | ||||
|  | ||||
| export default function DiscordPlaying() { | ||||
|   const { t } = useTranslation(); | ||||
|   const [query] = useLanguageQuery(); | ||||
|    | ||||
|   if (str.indexOf("game") !== -1){ | ||||
|   const yes_playing = t('yes_playing', {playing: data.members[0].game.name}) | ||||
|   return <p>{yes_playing}</p> | ||||
|   }else{ | ||||
|   return <></> | ||||
|   } | ||||
|   const { data, error } = useSwr( | ||||
|     `https://discord.com/api/guilds/723409709306216498/widget.json`, | ||||
|      fetcher | ||||
|    ) | ||||
|   if (error){ | ||||
|     console.log("[Discord API] データの取得に失敗しました。 / Failed to retrieve data.") | ||||
|     return <></> | ||||
|   } else { | ||||
|     if (!data) { | ||||
|       return <p>Loading...</p> | ||||
|     } else { | ||||
|       if (data.members) { | ||||
|         if (data.members[0].game) { | ||||
|           const yes_playing = t('yes_playing', {playing: data.members[0].game.name}) | ||||
|           return <p>{yes_playing}</p> | ||||
|         } else { | ||||
|           return <></> | ||||
|         } | ||||
|       } else { | ||||
|         return <></>  | ||||
|       } | ||||
|     } | ||||
| } | ||||
| }; | ||||
|  | ||||
| export async function getServerSideProps() { | ||||
|   // Fetch data from external API | ||||
|   const res = await fetch(url) | ||||
|   const data = await res.json() | ||||
|  | ||||
|   // Pass data to the page via props | ||||
|   return { props: { data } } | ||||
| } | ||||
|  | ||||
| export default App; | ||||
| @@ -1,4 +1,7 @@ | ||||
| // React | ||||
| import React, { useState, useEffect } from 'react'; | ||||
|  | ||||
| // Data fetching | ||||
| import axios from 'axios'; | ||||
|  | ||||
| const App = () => { | ||||
|   | ||||
| @@ -1,20 +0,0 @@ | ||||
| // Next.js | ||||
| import Link from 'next/link' | ||||
| import Image from 'next/image' | ||||
|  | ||||
| const happybusy = (props) => { | ||||
|   return ( | ||||
|     <Link href="https://www.eff.org/pages/blue-ribbon-campaign"> | ||||
|       <a> | ||||
|         <Image | ||||
|           src="/images/brstrip.gif" | ||||
|           width={150} | ||||
|           height={41} | ||||
|           alt="EFF Blue Ribbon Campaign" | ||||
|         /> | ||||
|       </a> | ||||
|     </Link> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| export default happybusy | ||||
| @@ -1,13 +1,15 @@ | ||||
| // Tailwind CSS | ||||
| import "tailwindcss/tailwind.css"; | ||||
| import Link from 'next/link'; | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
| import { useRouter } from 'next/router' | ||||
| export default function Footer(props) { | ||||
|      | ||||
|     const router = useRouter() | ||||
|     const { locale, locales, defaultLocale, pathname } = router | ||||
|     const { t, lang } = useTranslation("common") | ||||
|  | ||||
| // Next.js | ||||
| import Link from 'next/link'; | ||||
|  | ||||
| // i18n | ||||
| import { useTranslation, useLanguageQuery } from 'next-export-i18n'; | ||||
|  | ||||
| export default function Footer(props) { | ||||
|   const { t } = useTranslation(); | ||||
|   const [query] = useLanguageQuery(); | ||||
|     return ( | ||||
|       <> | ||||
|         <div className="container mx-auto px-6"> | ||||
|   | ||||
| @@ -1,16 +1,16 @@ | ||||
| // Next.js | ||||
| import Link from 'next/link' | ||||
| import Image from 'next/image' | ||||
|  | ||||
| const HappyBusy = (props) => { | ||||
|   return ( | ||||
|     <Link href="https://sites.google.com/site/happybusy/"> | ||||
|         <a> | ||||
|           <Image | ||||
|           <img | ||||
|             src="/images/busy_banner.png" | ||||
|             width={200} | ||||
|             height={42} | ||||
|             alt="時間のないサイト運営者リング" | ||||
|             className="mx-auto" | ||||
|           /> | ||||
|         </a> | ||||
|     </Link> | ||||
|   | ||||
| @@ -1,14 +1,14 @@ | ||||
| import React from "react"; | ||||
| import Popper from "popper.js"; | ||||
| import { useRouter } from 'next/router' | ||||
| import Link from 'next/link'; | ||||
| import { faLanguage } from '@fortawesome/free-solid-svg-icons' | ||||
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||||
|  | ||||
| const Dropdown = ({ color }) => { | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
| // i18n | ||||
| import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||
|  | ||||
|  | ||||
| const Dropdown = ({ color }) => { | ||||
|   // dropdown props | ||||
|   const [dropdownPopoverShow, setDropdownPopoverShow] = React.useState(false); | ||||
|   const btnDropdownRef = React.createRef(); | ||||
| @@ -31,7 +31,7 @@ const Dropdown = ({ color }) => { | ||||
|     <> | ||||
|  | ||||
| <div className="text-left mr-2 ml-2 my-3 float-right"> | ||||
|     <button type="button" className="inline-flex justify-center w-full rounded-md border border-gray-300 dark:border-gray-800 shadow-sm px-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 dark:bg-gray-700 dark:text-white focus:outline-none" id="options-menu" aria-haspopup="true" aria-expanded="true" | ||||
|     <button type="button" className="inline-flex justify-center rounded-md border border-gray-300 dark:border-gray-800 shadow-sm px-2 bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 dark:bg-gray-700 dark:text-white focus:outline-none h-10" id="options-menu" aria-haspopup="true" aria-expanded="true" | ||||
|     style={{ transition: "all .15s ease" }} | ||||
|     ref={btnDropdownRef} | ||||
|     onClick={() => { | ||||
| @@ -40,20 +40,20 @@ const Dropdown = ({ color }) => { | ||||
|         : openDropdownPopover(); | ||||
|     }} | ||||
|     > | ||||
|       <FontAwesomeIcon icon={faLanguage} className="w-12 h-9" /> | ||||
|       <FontAwesomeIcon icon={faLanguage} size="3x" /> | ||||
|       <svg className="-mr-1 ml-2 h-9 w-3" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true"> | ||||
|         <path fillRule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clipRule="evenodd" /> | ||||
|       </svg> | ||||
|     </button>   | ||||
|   <div ref={popoverDropdownRef} className={ | ||||
|               (dropdownPopoverShow ? "block " : "hidden ") + "z-10 origin-top-right absolute right-0 mt-2 w-40 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 dark:bg-gray-700"}> | ||||
|               (dropdownPopoverShow ? "block " : "hidden ") + "z-10 origin-top-right absolute right-0 mt-2 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 dark:bg-gray-700"}> | ||||
|     <div className="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu"> | ||||
|     <Link href="#" locale="ja"> | ||||
|       <a href="#" className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-700 dark:text-white dark:hover:bg-gray-800" role="menuitem">日本語</a> | ||||
|     </Link> | ||||
|     <Link href="#" locale="en"> | ||||
|       <a href="#" className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-700 dark:text-white dark:hover:bg-gray-800" role="menuitem">English</a> | ||||
|     </Link> | ||||
|     <LanguageSwitcher lang="ja"> | ||||
|       <a href="#" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 hover:text-gray-700 dark:text-white dark:hover:bg-gray-800" role="menuitem">日本語</a> | ||||
|     </LanguageSwitcher> | ||||
|     <LanguageSwitcher lang="en"> | ||||
|       <a href="#" className="block px-4 py-2 text-gray-700 hover:bg-gray-100 hover:text-gray-700 dark:text-white dark:hover:bg-gray-800" role="menuitem">English</a> | ||||
|     </LanguageSwitcher> | ||||
|     </div> | ||||
|   </div> | ||||
| </div> | ||||
|   | ||||
| @@ -1,21 +1,19 @@ | ||||
| // Next.js | ||||
| import Head from "next/head" | ||||
|  | ||||
| // Tailwind CSS | ||||
| import "tailwindcss/tailwind.css"; | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
| import { useRouter } from 'next/router' | ||||
|  | ||||
| // React | ||||
| import React, { useEffect, useState } from 'react' | ||||
|  | ||||
| // Components | ||||
| import Footer from "./Footer/Footer" | ||||
| import Navbar from "./Navbar" | ||||
|  | ||||
| const Layout = (props) => { | ||||
|   const { title, children } = props | ||||
|   const siteTitle = "yude.jp" | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|  | ||||
|   const { t, lang } = useTranslation("common") | ||||
|   const footer = t('footer') | ||||
|   const source = t('source') | ||||
|   const tos = t('tos') | ||||
|   return ( | ||||
|     <div className="page"> | ||||
|       <Head> | ||||
|   | ||||
| @@ -5,13 +5,13 @@ import Link from 'next/link' | ||||
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | ||||
|  | ||||
| const FontAwesomeMenu = (props) => { | ||||
|   const { icon, dest } = props | ||||
|   const { icon, dest, query } = props | ||||
|  | ||||
|   return ( | ||||
|     <div> | ||||
|         <Link href={`${dest}`}> | ||||
|         <Link href={{ pathname: dest, query: query }}> | ||||
|             <a> | ||||
|                 <FontAwesomeIcon icon={icon} className="w-10 h-10 fill-current inline transition duration-200 ease-in-out transform hover:-translate-y-1 hover:scale-110" /> | ||||
|                 <FontAwesomeIcon icon={icon} size="5x" className="w-9 h-9 fill-current inline transition duration-200 ease-in-out transform hover:-translate-y-1 hover:scale-110" /> | ||||
|             </a> | ||||
|         </Link> | ||||
|     </div> | ||||
|   | ||||
| @@ -1,10 +1,15 @@ | ||||
| // Next.js | ||||
| import Link from 'next/link' | ||||
|  | ||||
| const MinecraftMenu = () => { | ||||
| const MinecraftMenu = (props) => { | ||||
|   const { query } = props | ||||
|    | ||||
|   if (!query) { | ||||
|     return <p>Loading...</p> | ||||
|   } else { | ||||
|   return ( | ||||
|     <div> | ||||
|         <Link href="/minecraft"> | ||||
|         <Link href={{ pathname: "/minecraft", query: query }}> | ||||
|             <a> | ||||
|                 <svg className="fill-current text-black dark:text-white w-10 h-10 inline transition duration-200 ease-in-out transform hover:-translate-y-1 hover:scale-110" version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 304.8 304.8"> | ||||
|                     <path d="M 39.10262 126.138 L 39.16748 12.39574 L 152.7982 12.33506 L 266.4289 12.27438 L 266.4289 126.0773 L 266.4289 239.8803 L 152.7333 239.8803 L 39.03775 239.8803 L 39.10262 126.138 Z M 260.4857 126.0776 L 260.4857 18.55703 L 152.8628 18.55703 L 45.23985 18.55703 L 45.23985 126.0776 L 45.23985 233.5982 L 152.8628 233.5982 L 260.4857 233.5982 L 260.4857 126.0776 Z M 103.8963 162.9245 L 103.8963 126.0776 L 116.1702 126.0776 L 128.4441 126.0776 L 128.4441 113.8758 L 128.4441 101.674 L 152.8628 101.674 L 177.2814 101.674 L 177.2814 113.8758 L 177.2814 126.0776 L 189.3835 126.0776 L 201.4856 126.0776 L 201.6573 150.5415 C 201.7517 163.9967 201.829 180.5779 201.8291 187.3885 L 201.8293 199.7715 L 189.6869 199.7715 L 177.5446 199.7715 L 177.4776 187.5093 L 177.4106 175.2471 L 152.7982 175.1855 L 128.1857 175.1239 L 128.1857 187.4477 L 128.1857 199.7715 L 116.041 199.7715 L 103.8963 199.7715 L 103.8963 162.9245 Z M 79.34843 77.02888 L 79.34843 52.62534 L 103.7671 52.62534 L 128.1857 52.62534 L 128.1857 77.02888 L 128.1857 101.4324 L 103.7671 101.4324 L 79.34843 101.4324 L 79.34843 77.02888 Z M 177.5398 77.02888 L 177.5398 52.62534 L 201.9585 52.62534 L 226.3771 52.62534 L 226.3771 77.02888 L 226.3771 101.4324 L 201.9585 101.4324 L 177.5398 101.4324 L 177.5398 77.02888 Z"/> | ||||
| @@ -14,5 +19,6 @@ const MinecraftMenu = () => { | ||||
|     </div> | ||||
|   ) | ||||
| } | ||||
| } | ||||
|  | ||||
| export default MinecraftMenu | ||||
| @@ -1,15 +1,14 @@ | ||||
| // React | ||||
| import React, { useState, useEffect } from 'react'; | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
| import { useRouter } from 'next/router' | ||||
|  | ||||
| // i18n | ||||
| import { useTranslation, useLanguageQuery } from 'next-export-i18n'; | ||||
|  | ||||
| import axios from 'axios'; | ||||
| import Image from 'next/image' | ||||
| import { list } from 'postcss'; | ||||
|  | ||||
| export default function Minecraft(props) { | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|   const { t, lang } = useTranslation("minecraft") | ||||
|  | ||||
|   const { t } = useTranslation(); | ||||
|   const [query] = useLanguageQuery(); | ||||
|   const [data, setData] = useState({ hits: [] }); | ||||
|  | ||||
|   useEffect(() => { | ||||
| @@ -25,7 +24,7 @@ export default function Minecraft(props) { | ||||
|     if (data === undefined){ | ||||
|         console.log("[Minecraft Query] データの取得に失敗しました。 / Failed to retrieve data.") | ||||
|         return ( | ||||
|         <p>{t('minecraft:fail')}</p> | ||||
|         <p>{t('fail')}</p> | ||||
|         ) | ||||
|       }else{ | ||||
|         const status = data.online | ||||
| @@ -36,13 +35,13 @@ export default function Minecraft(props) { | ||||
|             {(() => { | ||||
|             if (status == true) { | ||||
|             if (player == undefined || player == 0) { | ||||
|               return <span>{t('minecraft:no_one')}</span> | ||||
|               return <span>{t('no_one')}</span> | ||||
|             } else { | ||||
|               return <span>{t('minecraft:playing', {count: player})}</span> | ||||
|               return <span>{t('playing', {count: player})}</span> | ||||
|             }}else if (status == false) { | ||||
|               return <span>{t('minecraft:offline')}</span> | ||||
|               return <span>{t('offline')}</span> | ||||
|             }else { | ||||
|               return <span>{t('minecraft:loading')}</span> | ||||
|               return <span>{t('loading')}</span> | ||||
|             } | ||||
|           })()} | ||||
|  | ||||
| @@ -54,7 +53,7 @@ export default function Minecraft(props) { | ||||
|                 url.push('https://mc-heads.net/avatar/' + data.players.list[i]) | ||||
|               } | ||||
|               for (var i in url){ | ||||
|                 list.push(<Image src={url[i]} key={i} className="inline" height="50" width="50" alt={i}/>) | ||||
|                 list.push(<img src={url[i]} key={i} className="inline" height="50" width="50" alt={i}/>) | ||||
|               } | ||||
|               return <div>{list}</div> | ||||
|             } | ||||
|   | ||||
| @@ -1,11 +1,10 @@ | ||||
| import React, { useState, useEffect } from 'react'; | ||||
| import Image from 'next/image' | ||||
|  | ||||
| function App (props) { | ||||
|   const uuid = props; | ||||
|  | ||||
|   return ( | ||||
|     <Image | ||||
|     <img | ||||
|         src={"https://crafatar.com/renders/body/" + uuid.uuid} | ||||
|         width={110} | ||||
|         height={250} | ||||
|   | ||||
| @@ -1,14 +1,19 @@ | ||||
| // React | ||||
| import React, { useState, useEffect } from 'react'; | ||||
|  | ||||
| // Data fetching | ||||
| import axios from 'axios'; | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
| import { useRouter } from 'next/router' | ||||
|  | ||||
| // i18n | ||||
| import { useTranslation, useLanguageQuery } from 'next-export-i18n'; | ||||
|  | ||||
| // Components | ||||
| import LastPlayed from './LastPlayed' | ||||
|  | ||||
| function App (props) { | ||||
|   const { t } = useTranslation(); | ||||
|   const [query] = useLanguageQuery(); | ||||
|   const uuid = props; | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|   const { t, lang } = useTranslation("common")   | ||||
|   const [data, setData] = useState({ hits: [] }); | ||||
|  | ||||
|   useEffect(() => { | ||||
|   | ||||
| @@ -1,4 +1,7 @@ | ||||
| // React | ||||
| import React, { useState, useEffect } from 'react'; | ||||
|  | ||||
| // Data fetching | ||||
| import axios from 'axios'; | ||||
|  | ||||
| function App (props) { | ||||
|   | ||||
| @@ -9,7 +9,7 @@ const fetcher = (url) => fetch(url).then((res) => res.json()) | ||||
| function App (props) { | ||||
|   const uuid = props; | ||||
|   const { data, error } = useSwr( | ||||
|     uuid.uuid ? `/api/PlayerName/${uuid.uuid}` : null, | ||||
|     uuid.uuid ? `https://api.ashcon.app/mojang/v2/user/${uuid.uuid}` : null, | ||||
|     fetcher | ||||
|   ) | ||||
|    | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| function App (props) { | ||||
|     return ( | ||||
|         <div className="text-center"> | ||||
|             <h2>入力された UUID に該当するプレイヤーが見つかりませんでした。</h2> | ||||
|             <h2>入力された UUID またはプレイヤー名に該当するプレイヤーが見つかりませんでした。</h2> | ||||
|         </div> | ||||
|     ) | ||||
|   } | ||||
|   | ||||
| @@ -1,13 +1,24 @@ | ||||
| // Tailwind CSS | ||||
| import "tailwindcss/tailwind.css"; | ||||
|  | ||||
| // Next.js | ||||
| import Link from 'next/link'; | ||||
|  | ||||
| // Components | ||||
| import LangSelector from "./LangSelector" | ||||
| import ThemeSelector from "./ThemeSelector" | ||||
|  | ||||
| // i18n | ||||
| import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||
|  | ||||
| const Navbar = () => { | ||||
|   const { t } = useTranslation(); | ||||
|   const [query] = useLanguageQuery(); | ||||
|    | ||||
|     return ( | ||||
|       <> | ||||
|         <nav className='flex items-center flex-wrap p-3'> | ||||
|         <Link href='/'> | ||||
|         <Link href={{ pathname: '/', query: query }}> | ||||
|           <a className='inline-flex items-center p-2'> | ||||
|             <span className='text-xl text-black font-bold tracking-wide dark:text-white font-mono animate-heartbeat'> | ||||
|               yude.jp | ||||
|   | ||||
| @@ -7,10 +7,10 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | ||||
| const Button = (props) => { | ||||
|     const { icon, dest, caption } = props | ||||
|     return ( | ||||
|         <Link href={`${dest}`}> | ||||
|         <Link href={{ pathname: dest }}> | ||||
|             <a> | ||||
|                 <button | ||||
|                 className="bg-pink-600 text-white active:bg-pink-600 mt-3 font-bold text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1       ease-linear transition-all duration-150" | ||||
|                 className="bg-pink-600 text-white active:bg-pink-600 mt-3 font-bold text-sm px-6 py-3 rounded shadow hover:shadow-lg outline-none focus:outline-none mr-1 mb-1 ease-linear transition-all duration-150" | ||||
|                 type="button" | ||||
|                 > | ||||
|                 <FontAwesomeIcon icon={icon} className="w-5 h-5 inline"/> {caption} | ||||
|   | ||||
| @@ -8,9 +8,9 @@ const Contact = (props) => { | ||||
|     const { icon, dest, caption } = props | ||||
|     return ( | ||||
|         <div className="hover:underline"> | ||||
|             <Link href={`${dest}`}> | ||||
|             <Link href={{ pathname: dest }}> | ||||
|                 <a> | ||||
|                     <FontAwesomeIcon icon={icon} className="w-7 h-7 inline lg:w-10 lg:h-10 md:w-7 md:h-7"/> | ||||
|                     <FontAwesomeIcon icon={icon} size="5x" className="w-9 h-9 fill-current inline transition duration-200 ease-in-out transform hover:-translate-y-1 hover:scale-110" /> | ||||
|                     <p className="font-mono text-xl">{caption}</p> | ||||
|                 </a> | ||||
|             </Link> | ||||
|   | ||||
| @@ -1,20 +1,20 @@ | ||||
| // React | ||||
| import React, { useState, useEffect } from 'react'; | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
|  | ||||
| // i18n | ||||
| import { useTranslation, useLanguageQuery } from 'next-export-i18n'; | ||||
|  | ||||
| // Font Awesome | ||||
| import { faKey, faEye, faDownload } from '@fortawesome/free-solid-svg-icons' | ||||
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||||
| import { useRouter } from 'next/router' | ||||
|  | ||||
| // Next.js | ||||
| import Link from 'next/link' | ||||
|  | ||||
| export default function Modal() { | ||||
|   const [showModal, setShowModal] = React.useState(false); | ||||
|   const router = useRouter() | ||||
|   const { t, lang } = useTranslation("common") | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|   const close = t('common:close') | ||||
|   const keys = t('profile:keys') | ||||
|   const view = t('profile:view') | ||||
|   const fingerprint = t('profile:fingerprint') | ||||
|   const download = t('profile:download') | ||||
|   const { t } = useTranslation(); | ||||
|   const [query] = useLanguageQuery(); | ||||
|  | ||||
|   return ( | ||||
|     <> | ||||
| @@ -23,7 +23,7 @@ export default function Modal() { | ||||
|         type="button" | ||||
|         onClick={() => setShowModal(true)} | ||||
|       > | ||||
|         <FontAwesomeIcon icon={faKey} className="w-5 h-5 inline"/> {keys} | ||||
|         <FontAwesomeIcon icon={faKey} className="w-5 h-5 inline"/> {t('keys')} | ||||
|       </button> | ||||
|       {showModal ? ( | ||||
|         <> | ||||
| @@ -36,17 +36,17 @@ export default function Modal() { | ||||
|                 {/* Modal body */} | ||||
|                 <div className="relative p-2 flex-auto text-black text-left"> | ||||
|                  | ||||
|                 <p className="text-2xl"><FontAwesomeIcon icon={faKey} className="w-5 h-5 inline"/> {keys}</p> | ||||
|                 <p className="text-2xl"><FontAwesomeIcon icon={faKey} className="w-5 h-5 inline"/> {t('keys')}</p> | ||||
|           <ul className="list-disc my-2"> | ||||
|           <li> | ||||
|             <span className="font-bold">PGP </span> | ||||
|             <Link href="/yudejp.gpg"> | ||||
|               <a className="hover:underline"> | ||||
|                 <FontAwesomeIcon icon={faDownload} className="w-5 h-5 inline"/>  | ||||
|                 {download} | ||||
|                 {t('download')} | ||||
|               </a> | ||||
|             </Link> | ||||
|             <p>{fingerprint}:</p> | ||||
|             <p>{t('fingerprint')}:</p> | ||||
|             <div className="overflow-x-auto"> | ||||
|               <div className="whitespace-nowrap"> | ||||
|                 <code>3745 F270 DB4E 8975 6B07  62BE EB0F E5D9 25C4 A968</code> | ||||
| @@ -58,10 +58,10 @@ export default function Modal() { | ||||
|             <Link href="https://github.com/yude.keys"> | ||||
|               <a className="hover:underline"> | ||||
|                 <FontAwesomeIcon icon={faEye} className="w-5 h-5 inline"/>  | ||||
|                 {view} | ||||
|                 {t('view')} | ||||
|               </a> | ||||
|             </Link> | ||||
|             <p>{fingerprint}:</p> | ||||
|             <p>{t('fingerprint')}:</p> | ||||
|             <div className="overflow-x-auto"> | ||||
|               <div className="whitespace-nowrap"> | ||||
|               <code>2048 SHA256:xwSL4DORWmroWdC6P0GU1m1yZl/cXqjo9rCCWqqO+Dc</code> | ||||
| @@ -78,7 +78,7 @@ export default function Modal() { | ||||
|                     type="button" | ||||
|                     onClick={() => setShowModal(false)} | ||||
|                   > | ||||
|                     {close} | ||||
|                     {t('close')} | ||||
|                   </button> | ||||
|                 </div> | ||||
|               </div> | ||||
|   | ||||
| @@ -1,17 +1,21 @@ | ||||
| // React | ||||
| import React, { useState, useEffect } from 'react'; | ||||
|  | ||||
| // Data fetching | ||||
| import axios from 'axios'; | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
| import { useRouter } from 'next/router' | ||||
|  | ||||
| // i18n | ||||
| import { useTranslation, useLanguageQuery } from 'next-export-i18n'; | ||||
|  | ||||
| function App () { | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|   const { t, lang } = useTranslation("common")   | ||||
|   const { t } = useTranslation(); | ||||
|   const [query] = useLanguageQuery(); | ||||
|    | ||||
|   const [data, setData] = useState({ hits: [] }); | ||||
|   useEffect(() => { | ||||
|     const fetchData = async () => { | ||||
|       const result = await axios( | ||||
|         '/api/Spotify', | ||||
|         'https://vercel-spotify-api.vercel.app/api/Spotify', | ||||
|       ); | ||||
|       setData(result.data); | ||||
|     };   | ||||
|   | ||||
| @@ -1,15 +1,17 @@ | ||||
| import React, { useState, useEffect } from 'react'; | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
| // React | ||||
| import React from 'react'; | ||||
|  | ||||
| // Font Awesome | ||||
| import { faUserClock } from '@fortawesome/free-solid-svg-icons' | ||||
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||||
| import { useRouter } from 'next/router' | ||||
|  | ||||
| // i18n | ||||
| import { useTranslation } from 'next-export-i18n'; | ||||
|  | ||||
| export default function Modal() { | ||||
|   const [showModal, setShowModal] = React.useState(false); | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|   const { t, lang } = useTranslation("common") | ||||
|   const close = t('common:close') | ||||
|   const { t } = useTranslation(); | ||||
|    | ||||
|   return ( | ||||
|     <> | ||||
|       <button | ||||
| @@ -38,7 +40,7 @@ export default function Modal() { | ||||
|                     type="button" | ||||
|                     onClick={() => setShowModal(false)} | ||||
|                   > | ||||
|                     {close} | ||||
|                     {t('close')} | ||||
|                   </button> | ||||
|                 </div> | ||||
|               </div> | ||||
|   | ||||
| @@ -7,9 +7,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||||
|  | ||||
| const ThemeSelector = (props) => { | ||||
|   const { title, children } = props | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|    | ||||
|   const [isMounted, setIsMounted] = useState(false); | ||||
|   const { theme, setTheme, getTheme } = useTheme(); | ||||
|   useEffect(() => { | ||||
|   | ||||
| @@ -1,8 +1,10 @@ | ||||
| // Base layout | ||||
| import Layout from "./components/Layout" | ||||
|  | ||||
| // React, i18n | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
| // i18n | ||||
| import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||
|  | ||||
| // React | ||||
| import React from "react" | ||||
| import ReactMarkdown from "react-markdown" | ||||
|  | ||||
| @@ -12,22 +14,27 @@ import ja from '../docs/hcunews/ja.md' | ||||
| import en from '../docs/hcunews/en.md' | ||||
|  | ||||
| export default function HcuNews() { | ||||
|     const { t, lang } = useTranslation("hcunews") | ||||
|     const { t } = useTranslation(); | ||||
|     const [query] = useLanguageQuery(); | ||||
|  | ||||
|     return( | ||||
|         <Layout title={t('hcunews')}> | ||||
|         <div> | ||||
|             <h1>{t('hcunews')}</h1> | ||||
|             {lang === 'ja' ? ( | ||||
|                 <ReactMarkdown plugins={[gfm]}> | ||||
|                     {ja} | ||||
|                 </ReactMarkdown> | ||||
|             ) : ( | ||||
|                 <ReactMarkdown plugins={[gfm]}> | ||||
|                     {en} | ||||
|                 </ReactMarkdown> | ||||
|             )} | ||||
|         </div> | ||||
|         </Layout> | ||||
|     ) | ||||
|     } | ||||
|     if (!query) { | ||||
|         return <p>Loading...</p> | ||||
|     } else { | ||||
|         return ( | ||||
|             <Layout title={t('hcunews')}> | ||||
|             <div> | ||||
|                 <h1>{t('hcunews')}</h1> | ||||
|                 {query["lang"] === 'ja' ? ( | ||||
|                     <ReactMarkdown plugins={[gfm]}> | ||||
|                         {ja} | ||||
|                     </ReactMarkdown> | ||||
|                 ) : ( | ||||
|                     <ReactMarkdown plugins={[gfm]}> | ||||
|                         {en} | ||||
|                     </ReactMarkdown> | ||||
|                 )} | ||||
|             </div> | ||||
|             </Layout> | ||||
|         ) | ||||
|     } | ||||
| } | ||||
| @@ -1,12 +1,16 @@ | ||||
| // Base layout | ||||
| import Layout from "./components/Layout" | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
|  | ||||
| // i18n | ||||
| import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||
|  | ||||
| // Next.js router | ||||
| import { useRouter } from 'next/router' | ||||
|  | ||||
| export default function About(props) { | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|   const { t, lang } = useTranslation("house") | ||||
|  | ||||
|   const { t } = useTranslation(); | ||||
|   const [query] = useLanguageQuery(); | ||||
|    | ||||
|   return ( | ||||
|     <Layout title={t('house')}> | ||||
|       <div> | ||||
|   | ||||
| @@ -5,66 +5,64 @@ import Layout from "./components/Layout" | ||||
| import FAMenu from "./components/Menu/FontAwesomeMenu" | ||||
|  | ||||
| // Banner | ||||
| import BlueRibbon from "./components/Footer/BlueRibbon" | ||||
| import HappyBusy from "./components/Footer/HappyBusy" | ||||
|  | ||||
| // Next.js | ||||
| import Image from 'next/image' | ||||
| import Link from 'next/link' | ||||
|  | ||||
| // i18n | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
| import { useTranslation, useLanguageQuery } from 'next-export-i18n'; | ||||
|  | ||||
| // React Router | ||||
| import { useRouter } from 'next/router' | ||||
| import MinecraftMenu from "./components/Menu/MinecraftMenu" | ||||
|  | ||||
| // Font Awesome | ||||
| import { faDiscord, faGit, faMastodon, faGithub } from '@fortawesome/free-brands-svg-icons' | ||||
| import { faBook, faUser, faServer, faHouseUser, faHeart } from '@fortawesome/free-solid-svg-icons' | ||||
| import { faDiscord, faGit, faGithub } from '@fortawesome/free-brands-svg-icons' | ||||
| import { faBook, faUser, faServer, faScrewdriver, faHeart } from '@fortawesome/free-solid-svg-icons' | ||||
|  | ||||
| export default function Index(props) { | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|   const { t, lang } = useTranslation("index") | ||||
|  | ||||
|   const { t } = useTranslation(); | ||||
|   const [query] = useLanguageQuery(); | ||||
|    | ||||
|   if (!query) { | ||||
|      return <p>Loading...</p> | ||||
|   } else { | ||||
|   return ( | ||||
|     <> | ||||
|       <Layout title={t('home')}> | ||||
|         <div className="my-9 text-center"> | ||||
|           <div className="m-10"> | ||||
|           <Image | ||||
|           <img | ||||
|               className   = "mx-auto" | ||||
|               src         = "/images/avatar_riru.png" | ||||
|               alt         = "yude's avatar" | ||||
|               width       = {200} | ||||
|               height      = {200} | ||||
|               unoptimized = {true} | ||||
|           /> | ||||
|           </div> | ||||
|            | ||||
|           {/* Index menu */} | ||||
|           <div className="grid grid-cols-3 gap-10"> | ||||
|             <FAMenu dest="/profile" icon={faUser} /> | ||||
|             <FAMenu dest="/server" icon={faServer} /> | ||||
|             <FAMenu dest="/house" icon={faHouseUser} /> | ||||
|             <FAMenu dest="https://scrapbox.io/yude" icon={faBook} /> | ||||
|             <FAMenu dest="/profile" query={query} icon={faUser} /> | ||||
|             <FAMenu dest="/server" query={query} icon={faServer} /> | ||||
|             <FAMenu dest="/services" query={query} icon={faScrewdriver} /> | ||||
|             <FAMenu dest="https://discord.gg/X6srY7X" icon={faDiscord} />           | ||||
|             <FAMenu dest="https://github.com/yudejp" icon={faGithub} /> | ||||
|             <FAMenu dest="https://git.yude.jp" icon={faGit} /> | ||||
|             <MinecraftMenu /> | ||||
|             <FAMenu dest="/mutual" icon={faHeart} /> | ||||
|             <MinecraftMenu query={query} /> | ||||
|             <FAMenu dest="/mutual" icon={faHeart} query={query} /> | ||||
|           </div> | ||||
|            | ||||
|           {/* Banner */} | ||||
|           <div className="mx-auto mt-10"> | ||||
|             <BlueRibbon /> | ||||
|             <HappyBusy /> | ||||
|           </div> | ||||
|            | ||||
|           {/* Avatar by */} | ||||
|           <p className="mt-3 text-sm font-bold text-gray-900 dark:text-gray-400">{t('common:icon_1')}<Link href="https://twitter.com/R_I_R_U_"><a className="hover:underline">梨留りる {t('common:icon_2')}</a></Link></p> | ||||
|           <p className="mt-3 text-sm font-bold text-gray-900 dark:text-gray-400">{t('icon_1')}<Link href="https://twitter.com/R_I_R_U_"><a className="hover:underline">梨留りる {t('icon_2')}</a></Link></p> | ||||
|         </div> | ||||
|       </Layout> | ||||
|     </> | ||||
|   ) | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -6,10 +6,9 @@ import React, { useState, useEffect } from 'react'; | ||||
| import { useRouter } from 'next/router' | ||||
|  | ||||
| // i18n | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
| import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||
|  | ||||
| // Next.js | ||||
| import Image from 'next/image' | ||||
| import Link from 'next/link' | ||||
|  | ||||
| // Custom pages | ||||
| @@ -29,17 +28,17 @@ import en from '../docs/minecraft/en.md' | ||||
| import { NextSeo } from 'next-seo'; | ||||
|  | ||||
| export default function About(props) { | ||||
|     const router = useRouter() | ||||
|      | ||||
|     // i18n | ||||
|     const { locale, locales, defaultLocale, pathname } = router | ||||
|     const { t, lang } = useTranslation("minecraft") | ||||
|      | ||||
|     const { t } = useTranslation(); | ||||
|     const [query] = useLanguageQuery(); | ||||
|    | ||||
|     // Copy server address to clipboard | ||||
|     const copyText = () => { | ||||
|       navigator.clipboard.writeText("yude.jp"); | ||||
|     }; | ||||
|  | ||||
|     if (!query) { | ||||
|       return <p>Loading...</p> | ||||
|     } else { | ||||
|     return ( | ||||
|           <> | ||||
|             <NextSeo | ||||
| @@ -51,7 +50,7 @@ export default function About(props) { | ||||
|             <div> | ||||
|                 <p className="my-2 text-3xl text-center">{t('title')}</p> | ||||
|                 <div className="w-full"> | ||||
|                 <Image | ||||
|                 <img | ||||
|                     src         = "/images/dynmap.png" | ||||
|                     alt         = "Minecraft brief world map generated by Dynmap" | ||||
|                     width       = {1354} | ||||
| @@ -72,7 +71,7 @@ export default function About(props) { | ||||
|                   </button> | ||||
|                 </p> | ||||
|                  | ||||
|                 <p>{t('version')}: 1.17</p> | ||||
|                 <p>{t('version')}: 1.18.1</p> | ||||
|                  | ||||
|                 <Link href="https://bluemap.yude.jp"> | ||||
|                   <a> | ||||
| @@ -86,7 +85,7 @@ export default function About(props) { | ||||
|               </div> | ||||
|                | ||||
|               {/* Load markdown contents */} | ||||
|                 {lang === 'ja' ? ( | ||||
|                 {query["lang"] === 'ja' ? ( | ||||
|                   <ReactMarkdown plugins={[gfm]}> | ||||
|                       {ja} | ||||
|                   </ReactMarkdown> | ||||
| @@ -99,4 +98,5 @@ export default function About(props) { | ||||
|             </Layout> | ||||
|           </> | ||||
|         ) | ||||
|       } | ||||
| } | ||||
							
								
								
									
										56
									
								
								pages/minecraft/lookup/[ign].js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								pages/minecraft/lookup/[ign].js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
|  // Base layout | ||||
|  import Layout from "../../components/Layout" | ||||
|  | ||||
|  // React | ||||
|  import { useRouter } from 'next/router' | ||||
|   | ||||
|  // Data fetching | ||||
|  import useSwr from 'swr' | ||||
|  const fetcher = (url) => fetch(url).then((res) => res.json()) | ||||
|   | ||||
|  // Components | ||||
|  import WrongUUID from '../../components/Minecraft/WrongUUID' | ||||
|   | ||||
|  export default function UUID() { | ||||
|    const router = useRouter() | ||||
|    const { ign } = router.query | ||||
|    const { data, error } = useSwr( | ||||
|     ign ? `https://api.ashcon.app/mojang/v2/user/${ign}` : null, | ||||
|      fetcher | ||||
|    ) | ||||
|    if (error) { | ||||
|      return ( | ||||
|        <> | ||||
|          <Layout title="エラー - プレイヤー情報"> | ||||
|          <p className="text-2xl">エラーが発生しました。</p> | ||||
|          </Layout> | ||||
|        </> | ||||
|      ) | ||||
|    } else { | ||||
|      if (!data) { | ||||
|        return ( | ||||
|          <> | ||||
|            <Layout title="読み込み中... - プレイヤー情報"> | ||||
|             <p className="text-2xl">読み込み中</p> | ||||
|            </Layout> | ||||
|          </> | ||||
|        ) | ||||
|      } else { | ||||
|        if (data.code) { | ||||
|          return ( | ||||
|            <> | ||||
|              <Layout title="404 - プレイヤー情報"> | ||||
|                <WrongUUID /> | ||||
|              </Layout> | ||||
|            </> | ||||
|          ) | ||||
|        } else { | ||||
|          router.push('/minecraft/players/' + data.uuid) | ||||
|          return ( | ||||
|           <p>リダイレクトしています...</p> | ||||
|          ) | ||||
|        } | ||||
|      } | ||||
|    } | ||||
|  } | ||||
|   | ||||
| @@ -16,7 +16,7 @@ export default function UUID() { | ||||
|   const router = useRouter() | ||||
|   const { uuid } = router.query | ||||
|   const { data, error } = useSwr( | ||||
|     uuid ? `/api/PlayerName/${uuid}` : null, | ||||
|     uuid ? `https://api.ashcon.app/mojang/v2/user/${uuid}` : null, | ||||
|     fetcher | ||||
|   ) | ||||
|   if (error) { | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| import Layout from "./components/Layout" | ||||
|  | ||||
| // i18n | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
| import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||
|  | ||||
| // React Router etc. | ||||
| import { useRouter } from 'next/router' | ||||
| @@ -18,18 +18,21 @@ import en from '../docs/mutual/en.md' | ||||
| import { NextSeo } from 'next-seo'; | ||||
|  | ||||
| export default function Tos(props) { | ||||
|     const router = useRouter() | ||||
|     const { locale, locales, defaultLocale, pathname } = router | ||||
|     const { t, lang } = useTranslation("common") | ||||
|     const { t } = useTranslation(); | ||||
|     const [query] = useLanguageQuery(); | ||||
|      | ||||
|     if (!query) { | ||||
|       return <p>Loading...</p> | ||||
|     } else { | ||||
|     return( | ||||
|           <> | ||||
|             <NextSeo | ||||
|               title="相互リンク" | ||||
|               description="yude.jp と相互にリンクを貼っている Web サイトの一覧" | ||||
|             /> | ||||
|             <Layout title={t('common:mutual')}> | ||||
|             <Layout title={t('mutual')}> | ||||
|               <div> | ||||
|                 {lang === 'ja' ? ( | ||||
|                 {query["lang"] === 'ja' ? ( | ||||
|                   <ReactMarkdown plugins={[gfm]}> | ||||
|                       {ja} | ||||
|                   </ReactMarkdown> | ||||
| @@ -42,4 +45,5 @@ export default function Tos(props) { | ||||
|             </Layout> | ||||
|           </> | ||||
|         ) | ||||
|       } | ||||
|     } | ||||
| @@ -1,54 +0,0 @@ | ||||
| // Base layout | ||||
| import Layout from "./components/Layout" | ||||
|  | ||||
| // Next.js | ||||
| import Link from "next/link"; | ||||
|  | ||||
| // i18n | ||||
| import { useRouter } from 'next/router' | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
|  | ||||
| // microCMS library | ||||
| import { client } from "../libs/client"; | ||||
|  | ||||
| // next-seo | ||||
| import { NextSeo } from 'next-seo'; | ||||
|  | ||||
| export default function Home({ blog }) { | ||||
|     const router = useRouter() | ||||
|     const { locale, locales, defaultLocale, pathname } = router | ||||
|     const { t, lang } = useTranslation("common") | ||||
|     return ( | ||||
|           <> | ||||
|           <NextSeo | ||||
|             title="記事一覧" | ||||
|             description="yude のブログの記事一覧 / yude's blog posts listing" | ||||
|           /> | ||||
|           <Layout title={t('common:post_list')}> | ||||
|               <div> | ||||
|               <h1 className="text-center">{t('common:post_list')}</h1> | ||||
|                 <ul> | ||||
|                   {blog.map((blog) => ( | ||||
|                     <li key={blog.id}> | ||||
|                       <Link href={`/posts/${blog.id}`}> | ||||
|                         <a>{blog.title}</a> | ||||
|                       </Link> | ||||
|                     </li> | ||||
|                   ))} | ||||
|                 </ul> | ||||
|               </div> | ||||
|           </Layout> | ||||
|           </> | ||||
|     ); | ||||
| } | ||||
|  | ||||
| // Passing data to template | ||||
| export const getStaticProps = async () => { | ||||
|   const data = await client.get({ endpoint: "blog" }); | ||||
|  | ||||
|   return { | ||||
|     props: { | ||||
|       blog: data.contents, | ||||
|     }, | ||||
|   }; | ||||
| }; | ||||
| @@ -1,58 +0,0 @@ | ||||
| // Base layout | ||||
| import Layout from "../components/Layout" | ||||
|  | ||||
| // microCMS library | ||||
| import { client } from "../../libs/client"; | ||||
|  | ||||
| // next-seo | ||||
| import { NextSeo } from 'next-seo'; | ||||
|  | ||||
| // React | ||||
| import * as React from "react"; | ||||
|  | ||||
| // React Moment | ||||
| import Moment from 'react-moment'; | ||||
|  | ||||
| export default function BlogId({ blog }) { | ||||
|   return ( | ||||
|     <> | ||||
|     <Layout title={blog.title + " - yude.jp"}> | ||||
|     <NextSeo | ||||
|       title={blog.title + " - yude.jp"} | ||||
|       description={blog.publishedAt + "に更新された「" + blog.title + "」というタイトルの記事です。"} | ||||
|     /> | ||||
|         <h1>{blog.title}</h1> | ||||
|         <p> | ||||
|           <Moment format="YYYY/MM/DD HH:mm"> | ||||
|           {blog.updated} | ||||
|           </Moment> | ||||
|         </p> | ||||
|         <div | ||||
|           dangerouslySetInnerHTML={{ | ||||
|             __html: `${blog.content}`, | ||||
|           }} | ||||
|         /> | ||||
|     </Layout> | ||||
|     </> | ||||
|   ); | ||||
| } | ||||
|  | ||||
| // Specify path for static generator | ||||
| export const getStaticPaths = async () => { | ||||
|   const data = await client.get({ endpoint: "blog" }); | ||||
|  | ||||
|   const paths = data.contents.map((content) => `/posts/${content.id}`); | ||||
|   return { paths, fallback: false }; | ||||
| }; | ||||
|  | ||||
| // Passing data to template | ||||
| export const getStaticProps = async (context) => { | ||||
|   const id = context.params.id; | ||||
|   const data = await client.get({ endpoint: "blog", contentId: id }); | ||||
|  | ||||
|   return { | ||||
|     props: { | ||||
|       blog: data, | ||||
|     }, | ||||
|   }; | ||||
| }; | ||||
| @@ -2,17 +2,15 @@ | ||||
| import Layout from "./components/Layout" | ||||
|  | ||||
| // i18n | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
| import { useTranslation, useLanguageQuery } from 'next-export-i18n'; | ||||
|  | ||||
| // Font Awesome | ||||
| import { faDiscord, faTwitter, faGithub, faKeybase, faInstagram, faMastodon, faSteam, faAmazon } from '@fortawesome/free-brands-svg-icons' | ||||
| import { faEnvelope, faBirthdayCake, faMapPin, faSchool, faPhone, faInfo, faLink, faMobile } from '@fortawesome/free-solid-svg-icons' | ||||
| import { faEnvelope, faBirthdayCake, faMapPin, faSchool, faPhone, faBlog, faBookDead, faInfo, faBookmark, faLink, faMobile } from '@fortawesome/free-solid-svg-icons' | ||||
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||||
|  | ||||
| // Next.js, React | ||||
| import Link from 'next/link' | ||||
| import Image from 'next/image' | ||||
| import { useRouter } from 'next/router' | ||||
|  | ||||
| // Discord | ||||
| import DiscordStatus from './components/Discord/DiscordStatus' | ||||
| @@ -30,9 +28,8 @@ import NintendoSW from "./components/Profile/NintendoSW" | ||||
| import { NextSeo } from 'next-seo'; | ||||
|  | ||||
| export default function Profile(props) { | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|   const { t, lang } = useTranslation("profile") | ||||
|   const { t } = useTranslation(); | ||||
|   const [query] = useLanguageQuery(); | ||||
|  | ||||
|   return ( | ||||
|     <> | ||||
| @@ -47,7 +44,7 @@ export default function Profile(props) { | ||||
|           } | ||||
|           <div> | ||||
|             <div className="flex mb-10 justify-center"> | ||||
|             <Image | ||||
|             <img | ||||
|               className   = "rounded-full hover:animate-rumble z-0 p-15" | ||||
|               src         = "/images/avatar_mel.png" | ||||
|               alt         = "yude's avatar" | ||||
| @@ -89,6 +86,19 @@ export default function Profile(props) { | ||||
|               <p className="ml-9">{t('hiroshima')}</p> | ||||
|             </div> | ||||
|           </div> | ||||
|            | ||||
|           { | ||||
|            // Contents | ||||
|           } | ||||
|           <div> | ||||
|             <div className="text-left"> | ||||
|                 <p className="text-2xl"><FontAwesomeIcon icon={faBookDead} className="w-5 h-5 inline"/> {t('contents')}</p> | ||||
|             </div> | ||||
|             <div className="my-2 grid grid-cols-2 lg:grid-cols-5 md:grid-cols-3 sm:grid-cols-2justify-items-center gap-y-6"> | ||||
|               <Contact dest="https://blog.yude.jp" icon={faBlog} caption={t('blog')} /> | ||||
|               <Contact dest="https://scrapbox.io/yude" icon={faBookmark} caption="Scrapbox" /> | ||||
|             </div> | ||||
|           </div> | ||||
|    | ||||
|           { | ||||
|            // Contact  | ||||
| @@ -120,7 +130,7 @@ export default function Profile(props) { | ||||
|           </div> | ||||
|            | ||||
|         </div> | ||||
|           <p className="mt-3 text-sm font-bold text-gray-900 dark:text-gray-400">{t('common:icon_1')}<Link href="https://twitter.com/xmnts"><a className="hover:underline">Minkasy {t('common:icon_2')}</a></Link></p> | ||||
|           <p className="mt-3 text-sm font-bold text-gray-900 dark:text-gray-400">{t('icon_1')}<Link href="https://twitter.com/xmnts"><a className="hover:underline">Minkasy {t('icon_2')}</a></Link></p> | ||||
|         </div> | ||||
|          | ||||
|       </Layout> | ||||
|   | ||||
| @@ -2,18 +2,14 @@ | ||||
| import Layout from "./components/Layout" | ||||
|  | ||||
| // i18n | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
|  | ||||
| // React Router | ||||
| import { useRouter } from 'next/router' | ||||
| import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||
|  | ||||
| // next-seo | ||||
| import { NextSeo } from 'next-seo'; | ||||
|  | ||||
| export default function Server(props) { | ||||
|   const router = useRouter() | ||||
|   const { locale, locales, defaultLocale, pathname } = router | ||||
|   const { t, lang } = useTranslation("server") | ||||
|   const { t } = useTranslation(); | ||||
|   const [query] = useLanguageQuery(); | ||||
|  | ||||
|   return ( | ||||
|     <> | ||||
| @@ -32,45 +28,22 @@ export default function Server(props) { | ||||
|           </div> | ||||
|            | ||||
|           { | ||||
|               // yui | ||||
|               // sandy | ||||
|           } | ||||
|           <h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">yui</h2> | ||||
|           <h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">sandy</h2> | ||||
|           <div className="flex xl:w-2/3 text-center"> | ||||
|           <div className="flex-1"><p className="font-bold">CPU </p>i7-2600</div> | ||||
|           <div className="flex-1"><p className="font-bold">RAM </p>DDR3 24GB</div> | ||||
|           <div className="flex-1"><p className="font-bold">OS </p>Arch Linux</div> | ||||
|           <div className="flex-1"><p className="font-bold">{t('location')} </p>{t('hiroshima')}</div> | ||||
|           </div> | ||||
|           <iframe className="w-full h-96" src="https://mackerel.io/embed/public/embed/heHnGhDanoIDlf7jjxUe9yPVrsG3deeH5ptD8suErrq5w46crWEIYdLfzLoukzfF?period=24h" height="400" frameBorder="0" scrolling="no"></iframe> | ||||
|           <a href="https://mackerel.io/orgs/yude/hosts/4dkbQuMQjvo/-/graphs/loadavg#period=10m"><img src="https://mackerel.io/embed/public/embed/heHnGhDanoIDlf7jjxUe9yPVrsG3deeH5ptD8suErrq5w46crWEIYdLfzLoukzfF.png?period=10m" className="w-full" /></a> | ||||
|            | ||||
|            | ||||
|           { | ||||
|               // saika | ||||
|               // oracle1 | ||||
|           } | ||||
|           <h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">saika</h2> | ||||
|           <div className="flex xl:w-2/3 text-center"> | ||||
|           <div className="flex-1"><p className="font-bold">CPU </p>i5-6500</div> | ||||
|           <div className="flex-1"><p className="font-bold">RAM </p>DDR4 8GB</div> | ||||
|           <div className="flex-1"><p className="font-bold">OS </p>Ubuntu Server 20.04.3 LTS</div> | ||||
|           <div className="flex-1"><p className="font-bold">{t('location')} </p>{t('hiroshima')}</div> | ||||
|           </div> | ||||
|           <iframe className="w-full h-96" src="https://mackerel.io/embed/public/embed/QCRK3wZxG7ufgunJ5iuIs9cIEJ490swAmlYMF50nNLmJw6gASXyVlzhrybiE2A1G?period=24h" height="400" frameBorder="0" scrolling="no"></iframe> | ||||
|            | ||||
|           { | ||||
|               // yukino | ||||
|           } | ||||
|           <h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">yukino</h2> | ||||
|           <div className="flex xl:w-2/3 text-center"> | ||||
|           <div className="flex-1"><p className="font-bold">{t('model')} </p>Raspberry Pi 4 Model B Rev 1.2</div> | ||||
|           <div className="flex-1"><p className="font-bold">RAM </p>4GB</div> | ||||
|           <div className="flex-1"><p className="font-bold">OS </p>Raspbian GNU/Linux 10 (buster)</div> | ||||
|           <div className="flex-1"><p className="font-bold">{t('location')} </p>{t('tottori')}</div> | ||||
|           </div> | ||||
|           <iframe className="w-full h-96" src="https://mackerel.io/embed/public/embed/5HVbQiwuxrMithyrGjmmQCCOVgJ6Ptf94SDA2qWSTsh2rtz7pjePihYzaW5QEml4?period=24h" height="400" frameBorder="0" scrolling="no"></iframe> | ||||
|            | ||||
|           { | ||||
|               // iroha | ||||
|           } | ||||
|           <h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">iroha</h2> | ||||
|           <h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">oracle1</h2> | ||||
|           <div className="flex xl:w-2/3 text-center"> | ||||
|           <div className="flex-1"><p className="font-bold">{t('service')} </p>Oracle Cloud</div> | ||||
|           <div className="flex-1"><p className="font-bold">{t('shape')} </p>VM.Standard.E2.1.Micro</div> | ||||
| @@ -78,13 +51,12 @@ export default function Server(props) { | ||||
|           <div className="flex-1"><p className="font-bold">OS </p>Ubuntu 20.04 LTS</div> | ||||
|           <div className="flex-1"><p className="font-bold">{t('region')} </p>Japan Central (Osaka)</div> | ||||
|           </div> | ||||
|           <iframe className="w-full h-96" src="https://mackerel.io/embed/public/embed/wgmTz7aTgvwfyU6qVHrJJmQlpOHCUJK6qw0W9sJTX68WOI8TFtc27YvJ7dwkQEGv?period=24h" height="400" frameBorder="0" scrolling="no"></iframe> | ||||
|            | ||||
|           <a href="https://mackerel.io/orgs/yude/hosts/4ftHfeojMCU/-/graphs/loadavg#period=10m"><img src="https://mackerel.io/embed/public/embed/vcn6LE4P2hh6GzvtMbIAWxsXpDh6eSoNyAXdhfYaj9yDN6FJwOHIiz9ktqToj1HG.png?period=10m" className="w-full" /></a> | ||||
|            | ||||
|           { | ||||
|               // komachi | ||||
|               // oracle2 | ||||
|           } | ||||
|           <h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">komachi</h2> | ||||
|           <h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">oracle2</h2> | ||||
|           <div className="flex xl:w-2/3 text-center"> | ||||
|           <div className="flex-1"><p className="font-bold">{t('service')} </p>Oracle Cloud</div> | ||||
|           <div className="flex-1"><p className="font-bold">{t('shape')} </p>VM.Standard.E2.1.Micro</div> | ||||
| @@ -92,8 +64,21 @@ export default function Server(props) { | ||||
|           <div className="flex-1"><p className="font-bold">OS </p>Ubuntu 20.04 LTS</div> | ||||
|           <div className="flex-1"><p className="font-bold">{t('region')} </p>Japan Central (Osaka)</div> | ||||
|           </div> | ||||
|           <iframe className="w-full h-96" src="https://mackerel.io/embed/public/embed/vcn6LE4P2hh6GzvtMbIAWxsXpDh6eSoNyAXdhfYaj9yDN6FJwOHIiz9ktqToj1HG?period=24h" height="400" frameBorder="0" scrolling="no"></iframe> | ||||
|    | ||||
|           <a href="https://mackerel.io/orgs/yude/hosts/4frgQ1QuivJ/-/graphs/loadavg#period=10m"><img src="https://mackerel.io/embed/public/embed/wgmTz7aTgvwfyU6qVHrJJmQlpOHCUJK6qw0W9sJTX68WOI8TFtc27YvJ7dwkQEGv.png?period=10m" className="w-full" /></a> | ||||
|            | ||||
|           { | ||||
|               // oracle-a1-1 | ||||
|           } | ||||
|           <h2 className="text-2xl text-left font-bold leading-7 sm:text-3xl sm:truncate">oracle-a1-1</h2> | ||||
|           <div className="flex xl:w-2/3 text-center"> | ||||
|           <div className="flex-1"><p className="font-bold">{t('service')} </p>Oracle Cloud</div> | ||||
|           <div className="flex-1"><p className="font-bold">{t('shape')} </p>VM.Standard.A1.Flex</div> | ||||
|           <div className="flex-1"><p className="font-bold">RAM </p>6GB</div> | ||||
|           <div className="flex-1"><p className="font-bold">OS </p>Ubuntu 20.04.3 LTS</div> | ||||
|           <div className="flex-1"><p className="font-bold">{t('region')} </p>Japan Central (Osaka)</div> | ||||
|           </div> | ||||
|           <a href="https://mackerel.io/orgs/yude/hosts/4qzeqT6kToQ/-/graphs/loadavg#period=10m"><img src="https://mackerel.io/embed/public/embed/2C7NdtqLgGFGPiO2IctDGuaMdjBwhXyp0i8imkaJT2GFI55syPaxxACEYIRWDHnS.png?period=10m" className="w-full" /></a> | ||||
|            | ||||
|         </div> | ||||
|       </Layout> | ||||
|     </> | ||||
|   | ||||
							
								
								
									
										49
									
								
								pages/services.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								pages/services.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,49 @@ | ||||
| // Base layout | ||||
| import Layout from "./components/Layout" | ||||
|  | ||||
| // i18n | ||||
| import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||
|  | ||||
| // React Router etc. | ||||
| import { useRouter } from 'next/router' | ||||
| import React from "react" | ||||
|  | ||||
| // React Markdown | ||||
| import ReactMarkdown from "react-markdown" | ||||
| import gfm from 'remark-gfm'; | ||||
| import ja from '../docs/services/ja.md' | ||||
| import en from '../docs/services/en.md' | ||||
|  | ||||
| // next-seo | ||||
| import { NextSeo } from 'next-seo'; | ||||
|  | ||||
| export default function Tos(props) { | ||||
|     const { t } = useTranslation(); | ||||
|     const [query] = useLanguageQuery(); | ||||
|      | ||||
|     if (!query) { | ||||
|       return <p>Loading...</p> | ||||
|     } else { | ||||
|     return( | ||||
|           <> | ||||
|             <NextSeo | ||||
|               title="サービス" | ||||
|               description="yude.jp で運用中のサービス" | ||||
|             /> | ||||
|             <Layout title={t('services')}> | ||||
|               <div> | ||||
|                 {query["lang"] === 'ja' ? ( | ||||
|                   <ReactMarkdown plugins={[gfm]}> | ||||
|                       {ja} | ||||
|                   </ReactMarkdown> | ||||
|                 ) : ( | ||||
|                   <ReactMarkdown plugins={[gfm]}> | ||||
|                       {en} | ||||
|                   </ReactMarkdown> | ||||
|                 )} | ||||
|               </div> | ||||
|             </Layout> | ||||
|           </> | ||||
|         ) | ||||
|       } | ||||
|     } | ||||
							
								
								
									
										51
									
								
								pages/tos.js
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								pages/tos.js
									
									
									
									
									
								
							| @@ -1,29 +1,40 @@ | ||||
| // Base layout | ||||
| import Layout from "./components/Layout" | ||||
| import useTranslation from 'next-translate/useTranslation' | ||||
|  | ||||
| // i18n | ||||
| import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||
|  | ||||
| // Next.js, React | ||||
| import { useRouter } from 'next/router' | ||||
| import React from "react" | ||||
|  | ||||
| // React Markdown | ||||
| import ReactMarkdown from "react-markdown" | ||||
| import gfm from 'remark-gfm'; | ||||
| import ja from '../docs/tos/ja.md' | ||||
| import en from '../docs/tos/en.md' | ||||
|  | ||||
| export default function Tos(props) { | ||||
|     const router = useRouter() | ||||
|     const { locale, locales, defaultLocale, pathname } = router | ||||
|     const { t, lang } = useTranslation("tos") | ||||
|     return( | ||||
|         <Layout title={t('tos')}> | ||||
|         <div> | ||||
|           {lang === 'ja' ? ( | ||||
|             <ReactMarkdown plugins={[gfm]}> | ||||
|                 {ja} | ||||
|             </ReactMarkdown> | ||||
|           ) : ( | ||||
|             <ReactMarkdown plugins={[gfm]}> | ||||
|                 {en} | ||||
|             </ReactMarkdown> | ||||
|           )} | ||||
|         </div> | ||||
|         </Layout> | ||||
|         ) | ||||
|     } | ||||
|     const { t } = useTranslation(); | ||||
|     const [query] = useLanguageQuery(); | ||||
|      | ||||
|     if (!query) { | ||||
|       return <p>Loading...</p> | ||||
|     } else { | ||||
|       return ( | ||||
|           <Layout title={t('tos')}> | ||||
|           <div> | ||||
|             {query["lang"] === 'ja' ? ( | ||||
|               <ReactMarkdown plugins={[gfm]}> | ||||
|                   {ja} | ||||
|               </ReactMarkdown> | ||||
|             ) : ( | ||||
|               <ReactMarkdown plugins={[gfm]}> | ||||
|                   {en} | ||||
|               </ReactMarkdown> | ||||
|             )} | ||||
|           </div> | ||||
|           </Layout> | ||||
|           ) | ||||
|     } | ||||
|   } | ||||
		Reference in New Issue
	
	Block a user