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~ | ||||||
| ..vimrc.un~ | ..vimrc.un~ | ||||||
| .env.local | .env.local | ||||||
|  | out | ||||||
| .vercel | .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="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"/>\ | <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).\ | 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 | ## Development | ||||||
| ### Setup | 1. Run `yarn` to install dependencies. | ||||||
| 1. Run `yarn`. | 2. Run `yarn dev` to serve. | ||||||
| 1. Rename `.env.local.sample` as `.env.local` and set value.  |  | ||||||
| ### Preview |  | ||||||
| * Run `yarn dev`. |  | ||||||
|  |  | ||||||
| ## License | ## License | ||||||
| This repository is provided under the MIT 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 troll. | ||||||
| * Don't cheat. | * Don't cheat. | ||||||
|  |  | ||||||
| # List of available commands | # Part of the list of available commands () | ||||||
| * `/ll`: Switch the visibility of spawn checker. | * `/ll`: Switch the visibility of spawn checker. | ||||||
| * `/mvspawn`: Teleport to spawn point of the world you're in. | * `/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 | ## Skills | ||||||
| You can use skills powered by mcMMO. | 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 | # Facility introduction | ||||||
| ## Shrine (by shirachan_1204) | ## Shrine (by shirachan_1204) | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ | |||||||
| * ワールドのどこであっても自由に建築することができます。 | * ワールドのどこであっても自由に建築することができます。 | ||||||
| * トロール (荒らし) を行わないでください。 | * トロール (荒らし) を行わないでください。 | ||||||
| * チートを行わないでください。 | * チートを行わないでください。 | ||||||
| # 使用可能なコマンドの一覧 | # 主な使用可能なコマンドの一覧 | ||||||
| * `/ll`: スポーンチェッカーの表示を切り替えます。 | * `/ll`: スポーンチェッカーの表示を切り替えます。 | ||||||
| * `/mvspawn`: ワールドのスポーン地点へ転移します。 | * `/mvspawn`: ワールドのスポーン地点へ転移します。 | ||||||
|  |  | ||||||
| @@ -16,6 +16,12 @@ | |||||||
|  |  | ||||||
| ## スキル | ## スキル | ||||||
| mcMMO を導入しているので、プラグインによるスキルを利用できます。   | mcMMO を導入しているので、プラグインによるスキルを利用できます。   | ||||||
|  | ## ワープ | ||||||
|  | 登録されている地点へワープできます。 | ||||||
|  | `/warps` で登録地点の一覧を表示し、`/warp (登録名)` でワープします。 | ||||||
|  |  | ||||||
|  | # ゲームの仕様 | ||||||
|  | * `keepInventory` は `true` になっています。したがって、死亡によるインベントリーのドロップはありません。 | ||||||
|  |  | ||||||
| # 施設紹介 | # 施設紹介 | ||||||
| ## 神社 (by shirachan_1204) | ## 神社 (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 () => { | const rewrites = async () => { | ||||||
|   return [ |   return [ | ||||||
|     { |     { | ||||||
| @@ -7,17 +5,13 @@ const rewrites = async () => { | |||||||
|       destination: '/minecraft/players/:uuid' |       destination: '/minecraft/players/:uuid' | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|       source: '/minecraft/players/:uuid', |       source: '/minecraft/players/:ign', | ||||||
|       destination: '/404' |       destination: '/minecraft/lookup/:ign' | ||||||
|     } |     } | ||||||
|   ] |   ] | ||||||
| } | } | ||||||
|  |  | ||||||
| module.exports = nextTranslate({ | module.exports = { | ||||||
|     i18n: { |  | ||||||
|       locales: ['ja', 'en'], |  | ||||||
|       defaultLocale: 'ja', |  | ||||||
|     }, |  | ||||||
|     images: { |     images: { | ||||||
|       domains: ['mackerel.io', 'mc-heads.net', 'crafatar.com'], |       domains: ['mackerel.io', 'mc-heads.net', 'crafatar.com'], | ||||||
|     }, |     }, | ||||||
| @@ -43,4 +37,4 @@ module.exports = nextTranslate({ | |||||||
|       ] |       ] | ||||||
|     }, |     }, | ||||||
|     rewrites, |     rewrites, | ||||||
|   }) |   } | ||||||
| @@ -30,12 +30,13 @@ | |||||||
|     "@tailwindcss/typography": "^0.4.0", |     "@tailwindcss/typography": "^0.4.0", | ||||||
|     "autoprefixer": "^10.3.4", |     "autoprefixer": "^10.3.4", | ||||||
|     "axios": "^0.21.4", |     "axios": "^0.21.4", | ||||||
|     "microcms-js-sdk": "^1.2.0", |     "date-fns": "^2.24.0", | ||||||
|     "moment": "^2.29.1", |     "moment": "^2.29.4", | ||||||
|     "next": "^11.1.2", |     "next": "^12.1.0", | ||||||
|  |     "next-export-i18n": "^1.2.1", | ||||||
|     "next-seo": "^4.28.1", |     "next-seo": "^4.28.1", | ||||||
|     "next-themes": "^0.0.15", |     "next-themes": "^0.0.15", | ||||||
|     "next-translate": "^1.1.0", |     "next-translate": "^1.2.0", | ||||||
|     "popper.js": "^1.16.1", |     "popper.js": "^1.16.1", | ||||||
|     "postcss": "^8.3.6", |     "postcss": "^8.3.6", | ||||||
|     "prop-types": "^15.7.2", |     "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 React, { useState, useEffect } from 'react'; | ||||||
| import axios from 'axios'; |  | ||||||
| import useTranslation from 'next-translate/useTranslation' |  | ||||||
| import { useRouter } from 'next/router' |  | ||||||
|  |  | ||||||
| function App (){ | // Data fetching | ||||||
|   const router = useRouter() | import useSwr from 'swr' | ||||||
|   const { locale, locales, defaultLocale, pathname } = router | const fetcher = (url) => fetch(url).then((res) => res.json()) | ||||||
|   const { t, lang } = useTranslation("common") |  | ||||||
|   const [data, setData] = useState({ hits: [] }); | // i18n | ||||||
|   useEffect(() => { | import { useTranslation, useLanguageQuery } from 'next-export-i18n'; | ||||||
|     const fetchData = async () => { |  | ||||||
|       const result = await axios( | export default function DiscordPlaying() { | ||||||
|         'https://discord.com/api/guilds/723409709306216498/widget.json', |   const { t } = useTranslation(); | ||||||
|       ); |   const [query] = useLanguageQuery(); | ||||||
|       setData(result.data); |  | ||||||
|     };   |  | ||||||
|     fetchData(); |  | ||||||
|   }, []); |  | ||||||
|   if (data === undefined){ |  | ||||||
|     console.log("[Discord API] データの取得に失敗しました。 / Failed to retrieve data.") |  | ||||||
|     return <p></p> |  | ||||||
|   }else{ |  | ||||||
|   const str = JSON.stringify(data) |  | ||||||
|    |    | ||||||
|   if (str.indexOf("game") !== -1){ |   const { data, error } = useSwr( | ||||||
|   const yes_playing = t('yes_playing', {playing: data.members[0].game.name}) |     `https://discord.com/api/guilds/723409709306216498/widget.json`, | ||||||
|   return <p>{yes_playing}</p> |      fetcher | ||||||
|   }else{ |    ) | ||||||
|   return <></> |   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'; | import React, { useState, useEffect } from 'react'; | ||||||
|  |  | ||||||
|  | // Data fetching | ||||||
| import axios from 'axios'; | import axios from 'axios'; | ||||||
|  |  | ||||||
| const App = () => { | 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 "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 ( |     return ( | ||||||
|       <> |       <> | ||||||
|         <div className="container mx-auto px-6"> |         <div className="container mx-auto px-6"> | ||||||
|   | |||||||
| @@ -1,16 +1,16 @@ | |||||||
| // Next.js | // Next.js | ||||||
| import Link from 'next/link' | import Link from 'next/link' | ||||||
| import Image from 'next/image' |  | ||||||
|  |  | ||||||
| const HappyBusy = (props) => { | const HappyBusy = (props) => { | ||||||
|   return ( |   return ( | ||||||
|     <Link href="https://sites.google.com/site/happybusy/"> |     <Link href="https://sites.google.com/site/happybusy/"> | ||||||
|         <a> |         <a> | ||||||
|           <Image |           <img | ||||||
|             src="/images/busy_banner.png" |             src="/images/busy_banner.png" | ||||||
|             width={200} |             width={200} | ||||||
|             height={42} |             height={42} | ||||||
|             alt="時間のないサイト運営者リング" |             alt="時間のないサイト運営者リング" | ||||||
|  |             className="mx-auto" | ||||||
|           /> |           /> | ||||||
|         </a> |         </a> | ||||||
|     </Link> |     </Link> | ||||||
|   | |||||||
| @@ -1,14 +1,14 @@ | |||||||
| import React from "react"; | import React from "react"; | ||||||
| import Popper from "popper.js"; | import Popper from "popper.js"; | ||||||
| import { useRouter } from 'next/router' |  | ||||||
| import Link from 'next/link'; | import Link from 'next/link'; | ||||||
| import { faLanguage } from '@fortawesome/free-solid-svg-icons' | import { faLanguage } from '@fortawesome/free-solid-svg-icons' | ||||||
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||||||
|  |  | ||||||
| const Dropdown = ({ color }) => { | // i18n | ||||||
|   const router = useRouter() | import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||||
|   const { locale, locales, defaultLocale, pathname } = router |  | ||||||
|  |  | ||||||
|  |  | ||||||
|  | const Dropdown = ({ color }) => { | ||||||
|   // dropdown props |   // dropdown props | ||||||
|   const [dropdownPopoverShow, setDropdownPopoverShow] = React.useState(false); |   const [dropdownPopoverShow, setDropdownPopoverShow] = React.useState(false); | ||||||
|   const btnDropdownRef = React.createRef(); |   const btnDropdownRef = React.createRef(); | ||||||
| @@ -31,7 +31,7 @@ const Dropdown = ({ color }) => { | |||||||
|     <> |     <> | ||||||
|  |  | ||||||
| <div className="text-left mr-2 ml-2 my-3 float-right"> | <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" }} |     style={{ transition: "all .15s ease" }} | ||||||
|     ref={btnDropdownRef} |     ref={btnDropdownRef} | ||||||
|     onClick={() => { |     onClick={() => { | ||||||
| @@ -40,20 +40,20 @@ const Dropdown = ({ color }) => { | |||||||
|         : openDropdownPopover(); |         : 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"> |       <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" /> |         <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> |       </svg> | ||||||
|     </button>   |     </button>   | ||||||
|   <div ref={popoverDropdownRef} className={ |   <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"> |     <div className="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu"> | ||||||
|     <Link href="#" locale="ja"> |     <LanguageSwitcher lang="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> |       <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> | ||||||
|     </Link> |     </LanguageSwitcher> | ||||||
|     <Link href="#" locale="en"> |     <LanguageSwitcher lang="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> |       <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> | ||||||
|     </Link> |     </LanguageSwitcher> | ||||||
|     </div> |     </div> | ||||||
|   </div> |   </div> | ||||||
| </div> | </div> | ||||||
|   | |||||||
| @@ -1,21 +1,19 @@ | |||||||
|  | // Next.js | ||||||
| import Head from "next/head" | import Head from "next/head" | ||||||
|  |  | ||||||
|  | // Tailwind CSS | ||||||
| import "tailwindcss/tailwind.css"; | import "tailwindcss/tailwind.css"; | ||||||
| import useTranslation from 'next-translate/useTranslation' |  | ||||||
| import { useRouter } from 'next/router' | // React | ||||||
| import React, { useEffect, useState } from 'react' | import React, { useEffect, useState } from 'react' | ||||||
|  |  | ||||||
|  | // Components | ||||||
| import Footer from "./Footer/Footer" | import Footer from "./Footer/Footer" | ||||||
| import Navbar from "./Navbar" | import Navbar from "./Navbar" | ||||||
|  |  | ||||||
| const Layout = (props) => { | const Layout = (props) => { | ||||||
|   const { title, children } = props |   const { title, children } = props | ||||||
|   const siteTitle = "yude.jp" |   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 ( |   return ( | ||||||
|     <div className="page"> |     <div className="page"> | ||||||
|       <Head> |       <Head> | ||||||
|   | |||||||
| @@ -5,13 +5,13 @@ import Link from 'next/link' | |||||||
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | ||||||
|  |  | ||||||
| const FontAwesomeMenu = (props) => { | const FontAwesomeMenu = (props) => { | ||||||
|   const { icon, dest } = props |   const { icon, dest, query } = props | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <div> |     <div> | ||||||
|         <Link href={`${dest}`}> |         <Link href={{ pathname: dest, query: query }}> | ||||||
|             <a> |             <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> |             </a> | ||||||
|         </Link> |         </Link> | ||||||
|     </div> |     </div> | ||||||
|   | |||||||
| @@ -1,10 +1,15 @@ | |||||||
| // Next.js | // Next.js | ||||||
| import Link from 'next/link' | import Link from 'next/link' | ||||||
|  |  | ||||||
| const MinecraftMenu = () => { | const MinecraftMenu = (props) => { | ||||||
|  |   const { query } = props | ||||||
|  |    | ||||||
|  |   if (!query) { | ||||||
|  |     return <p>Loading...</p> | ||||||
|  |   } else { | ||||||
|   return ( |   return ( | ||||||
|     <div> |     <div> | ||||||
|         <Link href="/minecraft"> |         <Link href={{ pathname: "/minecraft", query: query }}> | ||||||
|             <a> |             <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"> |                 <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"/> |                     <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> |     </div> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  | } | ||||||
|  |  | ||||||
| export default MinecraftMenu | export default MinecraftMenu | ||||||
| @@ -1,15 +1,14 @@ | |||||||
|  | // React | ||||||
| import React, { useState, useEffect } from '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 axios from 'axios'; | ||||||
| import Image from 'next/image' |  | ||||||
| import { list } from 'postcss'; |  | ||||||
|  |  | ||||||
| export default function Minecraft(props) { | export default function Minecraft(props) { | ||||||
|   const router = useRouter() |   const { t } = useTranslation(); | ||||||
|   const { locale, locales, defaultLocale, pathname } = router |   const [query] = useLanguageQuery(); | ||||||
|   const { t, lang } = useTranslation("minecraft") |  | ||||||
|  |  | ||||||
|   const [data, setData] = useState({ hits: [] }); |   const [data, setData] = useState({ hits: [] }); | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
| @@ -25,7 +24,7 @@ export default function Minecraft(props) { | |||||||
|     if (data === undefined){ |     if (data === undefined){ | ||||||
|         console.log("[Minecraft Query] データの取得に失敗しました。 / Failed to retrieve data.") |         console.log("[Minecraft Query] データの取得に失敗しました。 / Failed to retrieve data.") | ||||||
|         return ( |         return ( | ||||||
|         <p>{t('minecraft:fail')}</p> |         <p>{t('fail')}</p> | ||||||
|         ) |         ) | ||||||
|       }else{ |       }else{ | ||||||
|         const status = data.online |         const status = data.online | ||||||
| @@ -36,13 +35,13 @@ export default function Minecraft(props) { | |||||||
|             {(() => { |             {(() => { | ||||||
|             if (status == true) { |             if (status == true) { | ||||||
|             if (player == undefined || player == 0) { |             if (player == undefined || player == 0) { | ||||||
|               return <span>{t('minecraft:no_one')}</span> |               return <span>{t('no_one')}</span> | ||||||
|             } else { |             } else { | ||||||
|               return <span>{t('minecraft:playing', {count: player})}</span> |               return <span>{t('playing', {count: player})}</span> | ||||||
|             }}else if (status == false) { |             }}else if (status == false) { | ||||||
|               return <span>{t('minecraft:offline')}</span> |               return <span>{t('offline')}</span> | ||||||
|             }else { |             }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]) |                 url.push('https://mc-heads.net/avatar/' + data.players.list[i]) | ||||||
|               } |               } | ||||||
|               for (var i in url){ |               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> |               return <div>{list}</div> | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -1,11 +1,10 @@ | |||||||
| import React, { useState, useEffect } from 'react'; | import React, { useState, useEffect } from 'react'; | ||||||
| import Image from 'next/image' |  | ||||||
|  |  | ||||||
| function App (props) { | function App (props) { | ||||||
|   const uuid = props; |   const uuid = props; | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <Image |     <img | ||||||
|         src={"https://crafatar.com/renders/body/" + uuid.uuid} |         src={"https://crafatar.com/renders/body/" + uuid.uuid} | ||||||
|         width={110} |         width={110} | ||||||
|         height={250} |         height={250} | ||||||
|   | |||||||
| @@ -1,14 +1,19 @@ | |||||||
|  | // React | ||||||
| import React, { useState, useEffect } from 'react'; | import React, { useState, useEffect } from 'react'; | ||||||
|  |  | ||||||
|  | // Data fetching | ||||||
| import axios from 'axios'; | 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' | import LastPlayed from './LastPlayed' | ||||||
|  |  | ||||||
| function App (props) { | function App (props) { | ||||||
|  |   const { t } = useTranslation(); | ||||||
|  |   const [query] = useLanguageQuery(); | ||||||
|   const uuid = props; |   const uuid = props; | ||||||
|   const router = useRouter() |  | ||||||
|   const { locale, locales, defaultLocale, pathname } = router |  | ||||||
|   const { t, lang } = useTranslation("common")   |  | ||||||
|   const [data, setData] = useState({ hits: [] }); |   const [data, setData] = useState({ hits: [] }); | ||||||
|  |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|   | |||||||
| @@ -1,4 +1,7 @@ | |||||||
|  | // React | ||||||
| import React, { useState, useEffect } from 'react'; | import React, { useState, useEffect } from 'react'; | ||||||
|  |  | ||||||
|  | // Data fetching | ||||||
| import axios from 'axios'; | import axios from 'axios'; | ||||||
|  |  | ||||||
| function App (props) { | function App (props) { | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ const fetcher = (url) => fetch(url).then((res) => res.json()) | |||||||
| function App (props) { | function App (props) { | ||||||
|   const uuid = props; |   const uuid = props; | ||||||
|   const { data, error } = useSwr( |   const { data, error } = useSwr( | ||||||
|     uuid.uuid ? `/api/PlayerName/${uuid.uuid}` : null, |     uuid.uuid ? `https://api.ashcon.app/mojang/v2/user/${uuid.uuid}` : null, | ||||||
|     fetcher |     fetcher | ||||||
|   ) |   ) | ||||||
|    |    | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| function App (props) { | function App (props) { | ||||||
|     return ( |     return ( | ||||||
|         <div className="text-center"> |         <div className="text-center"> | ||||||
|             <h2>入力された UUID に該当するプレイヤーが見つかりませんでした。</h2> |             <h2>入力された UUID またはプレイヤー名に該当するプレイヤーが見つかりませんでした。</h2> | ||||||
|         </div> |         </div> | ||||||
|     ) |     ) | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,13 +1,24 @@ | |||||||
|  | // Tailwind CSS | ||||||
| import "tailwindcss/tailwind.css"; | import "tailwindcss/tailwind.css"; | ||||||
|  |  | ||||||
|  | // Next.js | ||||||
| import Link from 'next/link'; | import Link from 'next/link'; | ||||||
|  |  | ||||||
|  | // Components | ||||||
| import LangSelector from "./LangSelector" | import LangSelector from "./LangSelector" | ||||||
| import ThemeSelector from "./ThemeSelector" | import ThemeSelector from "./ThemeSelector" | ||||||
|  |  | ||||||
|  | // i18n | ||||||
|  | import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||||
|  |  | ||||||
| const Navbar = () => { | const Navbar = () => { | ||||||
|  |   const { t } = useTranslation(); | ||||||
|  |   const [query] = useLanguageQuery(); | ||||||
|  |    | ||||||
|     return ( |     return ( | ||||||
|       <> |       <> | ||||||
|         <nav className='flex items-center flex-wrap p-3'> |         <nav className='flex items-center flex-wrap p-3'> | ||||||
|         <Link href='/'> |         <Link href={{ pathname: '/', query: query }}> | ||||||
|           <a className='inline-flex items-center p-2'> |           <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'> |             <span className='text-xl text-black font-bold tracking-wide dark:text-white font-mono animate-heartbeat'> | ||||||
|               yude.jp |               yude.jp | ||||||
|   | |||||||
| @@ -7,10 +7,10 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; | |||||||
| const Button = (props) => { | const Button = (props) => { | ||||||
|     const { icon, dest, caption } = props |     const { icon, dest, caption } = props | ||||||
|     return ( |     return ( | ||||||
|         <Link href={`${dest}`}> |         <Link href={{ pathname: dest }}> | ||||||
|             <a> |             <a> | ||||||
|                 <button |                 <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" |                 type="button" | ||||||
|                 > |                 > | ||||||
|                 <FontAwesomeIcon icon={icon} className="w-5 h-5 inline"/> {caption} |                 <FontAwesomeIcon icon={icon} className="w-5 h-5 inline"/> {caption} | ||||||
|   | |||||||
| @@ -8,9 +8,9 @@ const Contact = (props) => { | |||||||
|     const { icon, dest, caption } = props |     const { icon, dest, caption } = props | ||||||
|     return ( |     return ( | ||||||
|         <div className="hover:underline"> |         <div className="hover:underline"> | ||||||
|             <Link href={`${dest}`}> |             <Link href={{ pathname: dest }}> | ||||||
|                 <a> |                 <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> |                     <p className="font-mono text-xl">{caption}</p> | ||||||
|                 </a> |                 </a> | ||||||
|             </Link> |             </Link> | ||||||
|   | |||||||
| @@ -1,20 +1,20 @@ | |||||||
|  | // React | ||||||
| import React, { useState, useEffect } from '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 { faKey, faEye, faDownload } from '@fortawesome/free-solid-svg-icons' | ||||||
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||||||
| import { useRouter } from 'next/router' |  | ||||||
|  | // Next.js | ||||||
| import Link from 'next/link' | import Link from 'next/link' | ||||||
|  |  | ||||||
| export default function Modal() { | export default function Modal() { | ||||||
|   const [showModal, setShowModal] = React.useState(false); |   const [showModal, setShowModal] = React.useState(false); | ||||||
|   const router = useRouter() |   const { t } = useTranslation(); | ||||||
|   const { t, lang } = useTranslation("common") |   const [query] = useLanguageQuery(); | ||||||
|   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') |  | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
| @@ -23,7 +23,7 @@ export default function Modal() { | |||||||
|         type="button" |         type="button" | ||||||
|         onClick={() => setShowModal(true)} |         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> |       </button> | ||||||
|       {showModal ? ( |       {showModal ? ( | ||||||
|         <> |         <> | ||||||
| @@ -36,17 +36,17 @@ export default function Modal() { | |||||||
|                 {/* Modal body */} |                 {/* Modal body */} | ||||||
|                 <div className="relative p-2 flex-auto text-black text-left"> |                 <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"> |           <ul className="list-disc my-2"> | ||||||
|           <li> |           <li> | ||||||
|             <span className="font-bold">PGP </span> |             <span className="font-bold">PGP </span> | ||||||
|             <Link href="/yudejp.gpg"> |             <Link href="/yudejp.gpg"> | ||||||
|               <a className="hover:underline"> |               <a className="hover:underline"> | ||||||
|                 <FontAwesomeIcon icon={faDownload} className="w-5 h-5 inline"/>  |                 <FontAwesomeIcon icon={faDownload} className="w-5 h-5 inline"/>  | ||||||
|                 {download} |                 {t('download')} | ||||||
|               </a> |               </a> | ||||||
|             </Link> |             </Link> | ||||||
|             <p>{fingerprint}:</p> |             <p>{t('fingerprint')}:</p> | ||||||
|             <div className="overflow-x-auto"> |             <div className="overflow-x-auto"> | ||||||
|               <div className="whitespace-nowrap"> |               <div className="whitespace-nowrap"> | ||||||
|                 <code>3745 F270 DB4E 8975 6B07  62BE EB0F E5D9 25C4 A968</code> |                 <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"> |             <Link href="https://github.com/yude.keys"> | ||||||
|               <a className="hover:underline"> |               <a className="hover:underline"> | ||||||
|                 <FontAwesomeIcon icon={faEye} className="w-5 h-5 inline"/>  |                 <FontAwesomeIcon icon={faEye} className="w-5 h-5 inline"/>  | ||||||
|                 {view} |                 {t('view')} | ||||||
|               </a> |               </a> | ||||||
|             </Link> |             </Link> | ||||||
|             <p>{fingerprint}:</p> |             <p>{t('fingerprint')}:</p> | ||||||
|             <div className="overflow-x-auto"> |             <div className="overflow-x-auto"> | ||||||
|               <div className="whitespace-nowrap"> |               <div className="whitespace-nowrap"> | ||||||
|               <code>2048 SHA256:xwSL4DORWmroWdC6P0GU1m1yZl/cXqjo9rCCWqqO+Dc</code> |               <code>2048 SHA256:xwSL4DORWmroWdC6P0GU1m1yZl/cXqjo9rCCWqqO+Dc</code> | ||||||
| @@ -78,7 +78,7 @@ export default function Modal() { | |||||||
|                     type="button" |                     type="button" | ||||||
|                     onClick={() => setShowModal(false)} |                     onClick={() => setShowModal(false)} | ||||||
|                   > |                   > | ||||||
|                     {close} |                     {t('close')} | ||||||
|                   </button> |                   </button> | ||||||
|                 </div> |                 </div> | ||||||
|               </div> |               </div> | ||||||
|   | |||||||
| @@ -1,17 +1,21 @@ | |||||||
|  | // React | ||||||
| import React, { useState, useEffect } from 'react'; | import React, { useState, useEffect } from 'react'; | ||||||
|  |  | ||||||
|  | // Data fetching | ||||||
| import axios from 'axios'; | 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 () { | function App () { | ||||||
|   const router = useRouter() |   const { t } = useTranslation(); | ||||||
|   const { locale, locales, defaultLocale, pathname } = router |   const [query] = useLanguageQuery(); | ||||||
|   const { t, lang } = useTranslation("common")   |    | ||||||
|   const [data, setData] = useState({ hits: [] }); |   const [data, setData] = useState({ hits: [] }); | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|     const fetchData = async () => { |     const fetchData = async () => { | ||||||
|       const result = await axios( |       const result = await axios( | ||||||
|         '/api/Spotify', |         'https://vercel-spotify-api.vercel.app/api/Spotify', | ||||||
|       ); |       ); | ||||||
|       setData(result.data); |       setData(result.data); | ||||||
|     };   |     };   | ||||||
|   | |||||||
| @@ -1,15 +1,17 @@ | |||||||
| import React, { useState, useEffect } from 'react'; | // React | ||||||
| import useTranslation from 'next-translate/useTranslation' | import React from 'react'; | ||||||
|  |  | ||||||
|  | // Font Awesome | ||||||
| import { faUserClock } from '@fortawesome/free-solid-svg-icons' | import { faUserClock } from '@fortawesome/free-solid-svg-icons' | ||||||
| import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||||||
| import { useRouter } from 'next/router' |  | ||||||
|  | // i18n | ||||||
|  | import { useTranslation } from 'next-export-i18n'; | ||||||
|  |  | ||||||
| export default function Modal() { | export default function Modal() { | ||||||
|   const [showModal, setShowModal] = React.useState(false); |   const [showModal, setShowModal] = React.useState(false); | ||||||
|   const router = useRouter() |   const { t } = useTranslation(); | ||||||
|   const { locale, locales, defaultLocale, pathname } = router |    | ||||||
|   const { t, lang } = useTranslation("common") |  | ||||||
|   const close = t('common:close') |  | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       <button |       <button | ||||||
| @@ -38,7 +40,7 @@ export default function Modal() { | |||||||
|                     type="button" |                     type="button" | ||||||
|                     onClick={() => setShowModal(false)} |                     onClick={() => setShowModal(false)} | ||||||
|                   > |                   > | ||||||
|                     {close} |                     {t('close')} | ||||||
|                   </button> |                   </button> | ||||||
|                 </div> |                 </div> | ||||||
|               </div> |               </div> | ||||||
|   | |||||||
| @@ -7,9 +7,6 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | |||||||
|  |  | ||||||
| const ThemeSelector = (props) => { | const ThemeSelector = (props) => { | ||||||
|   const { title, children } = props |   const { title, children } = props | ||||||
|   const router = useRouter() |  | ||||||
|   const { locale, locales, defaultLocale, pathname } = router |  | ||||||
|    |  | ||||||
|   const [isMounted, setIsMounted] = useState(false); |   const [isMounted, setIsMounted] = useState(false); | ||||||
|   const { theme, setTheme, getTheme } = useTheme(); |   const { theme, setTheme, getTheme } = useTheme(); | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|   | |||||||
| @@ -1,8 +1,10 @@ | |||||||
| // Base layout | // Base layout | ||||||
| import Layout from "./components/Layout" | import Layout from "./components/Layout" | ||||||
|  |  | ||||||
| // React, i18n | // i18n | ||||||
| import useTranslation from 'next-translate/useTranslation' | import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||||
|  |  | ||||||
|  | // React | ||||||
| import React from "react" | import React from "react" | ||||||
| import ReactMarkdown from "react-markdown" | import ReactMarkdown from "react-markdown" | ||||||
|  |  | ||||||
| @@ -12,22 +14,27 @@ import ja from '../docs/hcunews/ja.md' | |||||||
| import en from '../docs/hcunews/en.md' | import en from '../docs/hcunews/en.md' | ||||||
|  |  | ||||||
| export default function HcuNews() { | export default function HcuNews() { | ||||||
|     const { t, lang } = useTranslation("hcunews") |     const { t } = useTranslation(); | ||||||
|  |     const [query] = useLanguageQuery(); | ||||||
|  |  | ||||||
|     return( |     if (!query) { | ||||||
|         <Layout title={t('hcunews')}> |         return <p>Loading...</p> | ||||||
|         <div> |     } else { | ||||||
|             <h1>{t('hcunews')}</h1> |         return ( | ||||||
|             {lang === 'ja' ? ( |             <Layout title={t('hcunews')}> | ||||||
|                 <ReactMarkdown plugins={[gfm]}> |             <div> | ||||||
|                     {ja} |                 <h1>{t('hcunews')}</h1> | ||||||
|                 </ReactMarkdown> |                 {query["lang"] === 'ja' ? ( | ||||||
|             ) : ( |                     <ReactMarkdown plugins={[gfm]}> | ||||||
|                 <ReactMarkdown plugins={[gfm]}> |                         {ja} | ||||||
|                     {en} |                     </ReactMarkdown> | ||||||
|                 </ReactMarkdown> |                 ) : ( | ||||||
|             )} |                     <ReactMarkdown plugins={[gfm]}> | ||||||
|         </div> |                         {en} | ||||||
|         </Layout> |                     </ReactMarkdown> | ||||||
|     ) |                 )} | ||||||
|     } |             </div> | ||||||
|  |             </Layout> | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,12 +1,16 @@ | |||||||
|  | // Base layout | ||||||
| import Layout from "./components/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' | import { useRouter } from 'next/router' | ||||||
|  |  | ||||||
| export default function About(props) { | export default function About(props) { | ||||||
|   const router = useRouter() |   const { t } = useTranslation(); | ||||||
|   const { locale, locales, defaultLocale, pathname } = router |   const [query] = useLanguageQuery(); | ||||||
|   const { t, lang } = useTranslation("house") |    | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <Layout title={t('house')}> |     <Layout title={t('house')}> | ||||||
|       <div> |       <div> | ||||||
|   | |||||||
| @@ -5,66 +5,64 @@ import Layout from "./components/Layout" | |||||||
| import FAMenu from "./components/Menu/FontAwesomeMenu" | import FAMenu from "./components/Menu/FontAwesomeMenu" | ||||||
|  |  | ||||||
| // Banner | // Banner | ||||||
| import BlueRibbon from "./components/Footer/BlueRibbon" |  | ||||||
| import HappyBusy from "./components/Footer/HappyBusy" | import HappyBusy from "./components/Footer/HappyBusy" | ||||||
|  |  | ||||||
| // Next.js | // Next.js | ||||||
| import Image from 'next/image' |  | ||||||
| import Link from 'next/link' | import Link from 'next/link' | ||||||
|  |  | ||||||
| // i18n | // i18n | ||||||
| import useTranslation from 'next-translate/useTranslation' | import { useTranslation, useLanguageQuery } from 'next-export-i18n'; | ||||||
|  |  | ||||||
| // React Router | // React Router | ||||||
| import { useRouter } from 'next/router' |  | ||||||
| import MinecraftMenu from "./components/Menu/MinecraftMenu" | import MinecraftMenu from "./components/Menu/MinecraftMenu" | ||||||
|  |  | ||||||
| // Font Awesome | // Font Awesome | ||||||
| import { faDiscord, faGit, faMastodon, faGithub } from '@fortawesome/free-brands-svg-icons' | import { faDiscord, faGit, faGithub } from '@fortawesome/free-brands-svg-icons' | ||||||
| import { faBook, faUser, faServer, faHouseUser, faHeart } from '@fortawesome/free-solid-svg-icons' | import { faBook, faUser, faServer, faScrewdriver, faHeart } from '@fortawesome/free-solid-svg-icons' | ||||||
|  |  | ||||||
| export default function Index(props) { | export default function Index(props) { | ||||||
|   const router = useRouter() |   const { t } = useTranslation(); | ||||||
|   const { locale, locales, defaultLocale, pathname } = router |   const [query] = useLanguageQuery(); | ||||||
|   const { t, lang } = useTranslation("index") |    | ||||||
|  |   if (!query) { | ||||||
|  |      return <p>Loading...</p> | ||||||
|  |   } else { | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       <Layout title={t('home')}> |       <Layout title={t('home')}> | ||||||
|         <div className="my-9 text-center"> |         <div className="my-9 text-center"> | ||||||
|           <div className="m-10"> |           <div className="m-10"> | ||||||
|           <Image |           <img | ||||||
|  |               className   = "mx-auto" | ||||||
|               src         = "/images/avatar_riru.png" |               src         = "/images/avatar_riru.png" | ||||||
|               alt         = "yude's avatar" |               alt         = "yude's avatar" | ||||||
|               width       = {200} |               width       = {200} | ||||||
|               height      = {200} |               height      = {200} | ||||||
|               unoptimized = {true} |  | ||||||
|           /> |           /> | ||||||
|           </div> |           </div> | ||||||
|            |            | ||||||
|           {/* Index menu */} |           {/* Index menu */} | ||||||
|           <div className="grid grid-cols-3 gap-10"> |           <div className="grid grid-cols-3 gap-10"> | ||||||
|             <FAMenu dest="/profile" icon={faUser} /> |             <FAMenu dest="/profile" query={query} icon={faUser} /> | ||||||
|             <FAMenu dest="/server" icon={faServer} /> |             <FAMenu dest="/server" query={query} icon={faServer} /> | ||||||
|             <FAMenu dest="/house" icon={faHouseUser} /> |             <FAMenu dest="/services" query={query} icon={faScrewdriver} /> | ||||||
|             <FAMenu dest="https://scrapbox.io/yude" icon={faBook} /> |  | ||||||
|             <FAMenu dest="https://discord.gg/X6srY7X" icon={faDiscord} />           |             <FAMenu dest="https://discord.gg/X6srY7X" icon={faDiscord} />           | ||||||
|             <FAMenu dest="https://github.com/yudejp" icon={faGithub} /> |             <FAMenu dest="https://github.com/yudejp" icon={faGithub} /> | ||||||
|             <FAMenu dest="https://git.yude.jp" icon={faGit} /> |             <FAMenu dest="https://git.yude.jp" icon={faGit} /> | ||||||
|             <MinecraftMenu /> |             <MinecraftMenu query={query} /> | ||||||
|             <FAMenu dest="/mutual" icon={faHeart} /> |             <FAMenu dest="/mutual" icon={faHeart} query={query} /> | ||||||
|           </div> |           </div> | ||||||
|            |            | ||||||
|           {/* Banner */} |           {/* Banner */} | ||||||
|           <div className="mx-auto mt-10"> |           <div className="mx-auto mt-10"> | ||||||
|             <BlueRibbon /> |  | ||||||
|             <HappyBusy /> |             <HappyBusy /> | ||||||
|           </div> |           </div> | ||||||
|            |            | ||||||
|           {/* Avatar by */} |           {/* 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> |         </div> | ||||||
|       </Layout> |       </Layout> | ||||||
|     </> |     </> | ||||||
|   ) |   ) | ||||||
| } | } | ||||||
|  | } | ||||||
|   | |||||||
| @@ -6,10 +6,9 @@ import React, { useState, useEffect } from 'react'; | |||||||
| import { useRouter } from 'next/router' | import { useRouter } from 'next/router' | ||||||
|  |  | ||||||
| // i18n | // i18n | ||||||
| import useTranslation from 'next-translate/useTranslation' | import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||||
|  |  | ||||||
| // Next.js | // Next.js | ||||||
| import Image from 'next/image' |  | ||||||
| import Link from 'next/link' | import Link from 'next/link' | ||||||
|  |  | ||||||
| // Custom pages | // Custom pages | ||||||
| @@ -29,17 +28,17 @@ import en from '../docs/minecraft/en.md' | |||||||
| import { NextSeo } from 'next-seo'; | import { NextSeo } from 'next-seo'; | ||||||
|  |  | ||||||
| export default function About(props) { | export default function About(props) { | ||||||
|     const router = useRouter() |     const { t } = useTranslation(); | ||||||
|      |     const [query] = useLanguageQuery(); | ||||||
|     // i18n |    | ||||||
|     const { locale, locales, defaultLocale, pathname } = router |  | ||||||
|     const { t, lang } = useTranslation("minecraft") |  | ||||||
|      |  | ||||||
|     // Copy server address to clipboard |     // Copy server address to clipboard | ||||||
|     const copyText = () => { |     const copyText = () => { | ||||||
|       navigator.clipboard.writeText("yude.jp"); |       navigator.clipboard.writeText("yude.jp"); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|  |     if (!query) { | ||||||
|  |       return <p>Loading...</p> | ||||||
|  |     } else { | ||||||
|     return ( |     return ( | ||||||
|           <> |           <> | ||||||
|             <NextSeo |             <NextSeo | ||||||
| @@ -51,7 +50,7 @@ export default function About(props) { | |||||||
|             <div> |             <div> | ||||||
|                 <p className="my-2 text-3xl text-center">{t('title')}</p> |                 <p className="my-2 text-3xl text-center">{t('title')}</p> | ||||||
|                 <div className="w-full"> |                 <div className="w-full"> | ||||||
|                 <Image |                 <img | ||||||
|                     src         = "/images/dynmap.png" |                     src         = "/images/dynmap.png" | ||||||
|                     alt         = "Minecraft brief world map generated by Dynmap" |                     alt         = "Minecraft brief world map generated by Dynmap" | ||||||
|                     width       = {1354} |                     width       = {1354} | ||||||
| @@ -72,7 +71,7 @@ export default function About(props) { | |||||||
|                   </button> |                   </button> | ||||||
|                 </p> |                 </p> | ||||||
|                  |                  | ||||||
|                 <p>{t('version')}: 1.17</p> |                 <p>{t('version')}: 1.18.1</p> | ||||||
|                  |                  | ||||||
|                 <Link href="https://bluemap.yude.jp"> |                 <Link href="https://bluemap.yude.jp"> | ||||||
|                   <a> |                   <a> | ||||||
| @@ -86,7 +85,7 @@ export default function About(props) { | |||||||
|               </div> |               </div> | ||||||
|                |                | ||||||
|               {/* Load markdown contents */} |               {/* Load markdown contents */} | ||||||
|                 {lang === 'ja' ? ( |                 {query["lang"] === 'ja' ? ( | ||||||
|                   <ReactMarkdown plugins={[gfm]}> |                   <ReactMarkdown plugins={[gfm]}> | ||||||
|                       {ja} |                       {ja} | ||||||
|                   </ReactMarkdown> |                   </ReactMarkdown> | ||||||
| @@ -99,4 +98,5 @@ export default function About(props) { | |||||||
|             </Layout> |             </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 router = useRouter() | ||||||
|   const { uuid } = router.query |   const { uuid } = router.query | ||||||
|   const { data, error } = useSwr( |   const { data, error } = useSwr( | ||||||
|     uuid ? `/api/PlayerName/${uuid}` : null, |     uuid ? `https://api.ashcon.app/mojang/v2/user/${uuid}` : null, | ||||||
|     fetcher |     fetcher | ||||||
|   ) |   ) | ||||||
|   if (error) { |   if (error) { | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ | |||||||
| import Layout from "./components/Layout" | import Layout from "./components/Layout" | ||||||
|  |  | ||||||
| // i18n | // i18n | ||||||
| import useTranslation from 'next-translate/useTranslation' | import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||||
|  |  | ||||||
| // React Router etc. | // React Router etc. | ||||||
| import { useRouter } from 'next/router' | import { useRouter } from 'next/router' | ||||||
| @@ -18,18 +18,21 @@ import en from '../docs/mutual/en.md' | |||||||
| import { NextSeo } from 'next-seo'; | import { NextSeo } from 'next-seo'; | ||||||
|  |  | ||||||
| export default function Tos(props) { | export default function Tos(props) { | ||||||
|     const router = useRouter() |     const { t } = useTranslation(); | ||||||
|     const { locale, locales, defaultLocale, pathname } = router |     const [query] = useLanguageQuery(); | ||||||
|     const { t, lang } = useTranslation("common") |      | ||||||
|  |     if (!query) { | ||||||
|  |       return <p>Loading...</p> | ||||||
|  |     } else { | ||||||
|     return( |     return( | ||||||
|           <> |           <> | ||||||
|             <NextSeo |             <NextSeo | ||||||
|               title="相互リンク" |               title="相互リンク" | ||||||
|               description="yude.jp と相互にリンクを貼っている Web サイトの一覧" |               description="yude.jp と相互にリンクを貼っている Web サイトの一覧" | ||||||
|             /> |             /> | ||||||
|             <Layout title={t('common:mutual')}> |             <Layout title={t('mutual')}> | ||||||
|               <div> |               <div> | ||||||
|                 {lang === 'ja' ? ( |                 {query["lang"] === 'ja' ? ( | ||||||
|                   <ReactMarkdown plugins={[gfm]}> |                   <ReactMarkdown plugins={[gfm]}> | ||||||
|                       {ja} |                       {ja} | ||||||
|                   </ReactMarkdown> |                   </ReactMarkdown> | ||||||
| @@ -42,4 +45,5 @@ export default function Tos(props) { | |||||||
|             </Layout> |             </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" | import Layout from "./components/Layout" | ||||||
|  |  | ||||||
| // i18n | // i18n | ||||||
| import useTranslation from 'next-translate/useTranslation' | import { useTranslation, useLanguageQuery } from 'next-export-i18n'; | ||||||
|  |  | ||||||
| // Font Awesome | // Font Awesome | ||||||
| import { faDiscord, faTwitter, faGithub, faKeybase, faInstagram, faMastodon, faSteam, faAmazon } from '@fortawesome/free-brands-svg-icons' | 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' | import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' | ||||||
|  |  | ||||||
| // Next.js, React | // Next.js, React | ||||||
| import Link from 'next/link' | import Link from 'next/link' | ||||||
| import Image from 'next/image' |  | ||||||
| import { useRouter } from 'next/router' |  | ||||||
|  |  | ||||||
| // Discord | // Discord | ||||||
| import DiscordStatus from './components/Discord/DiscordStatus' | import DiscordStatus from './components/Discord/DiscordStatus' | ||||||
| @@ -30,9 +28,8 @@ import NintendoSW from "./components/Profile/NintendoSW" | |||||||
| import { NextSeo } from 'next-seo'; | import { NextSeo } from 'next-seo'; | ||||||
|  |  | ||||||
| export default function Profile(props) { | export default function Profile(props) { | ||||||
|   const router = useRouter() |   const { t } = useTranslation(); | ||||||
|   const { locale, locales, defaultLocale, pathname } = router |   const [query] = useLanguageQuery(); | ||||||
|   const { t, lang } = useTranslation("profile") |  | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
| @@ -47,7 +44,7 @@ export default function Profile(props) { | |||||||
|           } |           } | ||||||
|           <div> |           <div> | ||||||
|             <div className="flex mb-10 justify-center"> |             <div className="flex mb-10 justify-center"> | ||||||
|             <Image |             <img | ||||||
|               className   = "rounded-full hover:animate-rumble z-0 p-15" |               className   = "rounded-full hover:animate-rumble z-0 p-15" | ||||||
|               src         = "/images/avatar_mel.png" |               src         = "/images/avatar_mel.png" | ||||||
|               alt         = "yude's avatar" |               alt         = "yude's avatar" | ||||||
| @@ -89,6 +86,19 @@ export default function Profile(props) { | |||||||
|               <p className="ml-9">{t('hiroshima')}</p> |               <p className="ml-9">{t('hiroshima')}</p> | ||||||
|             </div> |             </div> | ||||||
|           </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  |            // Contact  | ||||||
| @@ -120,7 +130,7 @@ export default function Profile(props) { | |||||||
|           </div> |           </div> | ||||||
|            |            | ||||||
|         </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> |         </div> | ||||||
|          |          | ||||||
|       </Layout> |       </Layout> | ||||||
|   | |||||||
| @@ -2,18 +2,14 @@ | |||||||
| import Layout from "./components/Layout" | import Layout from "./components/Layout" | ||||||
|  |  | ||||||
| // i18n | // i18n | ||||||
| import useTranslation from 'next-translate/useTranslation' | import { useTranslation, useLanguageQuery, LanguageSwitcher } from 'next-export-i18n'; | ||||||
|  |  | ||||||
| // React Router |  | ||||||
| import { useRouter } from 'next/router' |  | ||||||
|  |  | ||||||
| // next-seo | // next-seo | ||||||
| import { NextSeo } from 'next-seo'; | import { NextSeo } from 'next-seo'; | ||||||
|  |  | ||||||
| export default function Server(props) { | export default function Server(props) { | ||||||
|   const router = useRouter() |   const { t } = useTranslation(); | ||||||
|   const { locale, locales, defaultLocale, pathname } = router |   const [query] = useLanguageQuery(); | ||||||
|   const { t, lang } = useTranslation("server") |  | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
| @@ -32,45 +28,22 @@ export default function Server(props) { | |||||||
|           </div> |           </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 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">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">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">OS </p>Arch Linux</div> | ||||||
|           <div className="flex-1"><p className="font-bold">{t('location')} </p>{t('hiroshima')}</div> |           <div className="flex-1"><p className="font-bold">{t('location')} </p>{t('hiroshima')}</div> | ||||||
|           </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> |           <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">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> |  | ||||||
|           <div className="flex xl:w-2/3 text-center"> |           <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('service')} </p>Oracle Cloud</div> | ||||||
|           <div className="flex-1"><p className="font-bold">{t('shape')} </p>VM.Standard.E2.1.Micro</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">OS </p>Ubuntu 20.04 LTS</div> | ||||||
|           <div className="flex-1"><p className="font-bold">{t('region')} </p>Japan Central (Osaka)</div> |           <div className="flex-1"><p className="font-bold">{t('region')} </p>Japan Central (Osaka)</div> | ||||||
|           </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 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('service')} </p>Oracle Cloud</div> | ||||||
|           <div className="flex-1"><p className="font-bold">{t('shape')} </p>VM.Standard.E2.1.Micro</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">OS </p>Ubuntu 20.04 LTS</div> | ||||||
|           <div className="flex-1"><p className="font-bold">{t('region')} </p>Japan Central (Osaka)</div> |           <div className="flex-1"><p className="font-bold">{t('region')} </p>Japan Central (Osaka)</div> | ||||||
|           </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> |         </div> | ||||||
|       </Layout> |       </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 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 { useRouter } from 'next/router' | ||||||
| import React from "react" | import React from "react" | ||||||
|  |  | ||||||
|  | // React Markdown | ||||||
| import ReactMarkdown from "react-markdown" | import ReactMarkdown from "react-markdown" | ||||||
| import gfm from 'remark-gfm'; | import gfm from 'remark-gfm'; | ||||||
| import ja from '../docs/tos/ja.md' | import ja from '../docs/tos/ja.md' | ||||||
| import en from '../docs/tos/en.md' | import en from '../docs/tos/en.md' | ||||||
|  |  | ||||||
| export default function Tos(props) { | export default function Tos(props) { | ||||||
|     const router = useRouter() |     const { t } = useTranslation(); | ||||||
|     const { locale, locales, defaultLocale, pathname } = router |     const [query] = useLanguageQuery(); | ||||||
|     const { t, lang } = useTranslation("tos") |      | ||||||
|     return( |     if (!query) { | ||||||
|         <Layout title={t('tos')}> |       return <p>Loading...</p> | ||||||
|         <div> |     } else { | ||||||
|           {lang === 'ja' ? ( |       return ( | ||||||
|             <ReactMarkdown plugins={[gfm]}> |           <Layout title={t('tos')}> | ||||||
|                 {ja} |           <div> | ||||||
|             </ReactMarkdown> |             {query["lang"] === 'ja' ? ( | ||||||
|           ) : ( |               <ReactMarkdown plugins={[gfm]}> | ||||||
|             <ReactMarkdown plugins={[gfm]}> |                   {ja} | ||||||
|                 {en} |               </ReactMarkdown> | ||||||
|             </ReactMarkdown> |             ) : ( | ||||||
|           )} |               <ReactMarkdown plugins={[gfm]}> | ||||||
|         </div> |                   {en} | ||||||
|         </Layout> |               </ReactMarkdown> | ||||||
|         ) |             )} | ||||||
|     } |           </div> | ||||||
|  |           </Layout> | ||||||
|  |           ) | ||||||
|  |     } | ||||||
|  |   } | ||||||
		Reference in New Issue
	
	Block a user