diff --git a/CHANGELOG.md b/CHANGELOG.md
index 993899ca2ff7..716937d628ec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -58,6 +58,9 @@
- Fix: ipv4とipv6の両方が利用可能な環境でallowedPrivateNetworksが設定されていた場合プライベートipの検証ができていなかった問題を修正
- Fix: properly handle cc followers
+### Service Worker
+- Enhance: オフライン表示のデザインを改善・多言語対応
+
## 2023.12.2
### General
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 6e763cda101d..910b1edad8b5 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -9554,6 +9554,16 @@ export interface Locale extends ILocale {
*/
"lookingForPlayer": string;
};
+ "_offlineScreen": {
+ /**
+ * オフライン - サーバーに接続できません
+ */
+ "title": string;
+ /**
+ * サーバーに接続できません
+ */
+ "header": string;
+ };
}
declare const locales: {
[lang: string]: Locale;
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index fd1c891ee750..6460397db791 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -2544,3 +2544,7 @@ _reversi:
timeLimitForEachTurn: "1ターンの時間制限"
freeMatch: "フリーマッチ"
lookingForPlayer: "対戦相手を探しています"
+
+_offlineScreen:
+ title: "オフライン - サーバーに接続できません"
+ header: "サーバーに接続できません"
diff --git a/packages/sw/src/sw.ts b/packages/sw/src/sw.ts
index b79fd8ce7a14..f423eaca20fc 100644
--- a/packages/sw/src/sw.ts
+++ b/packages/sw/src/sw.ts
@@ -6,6 +6,7 @@
import { get } from 'idb-keyval';
import * as Misskey from 'misskey-js';
import type { PushNotificationDataMap } from '@/types.js';
+import type { I18n, Locale } from '@/scripts/i18n.js';
import { createEmptyNotification, createNotification } from '@/scripts/create-notification.js';
import { swLang } from '@/scripts/lang.js';
import * as swos from '@/scripts/operations.js';
@@ -26,8 +27,15 @@ globalThis.addEventListener('activate', ev => {
);
});
-function offlineContentHTML(): string {
- return `Offline. Service Worker @${_VERSION_} `;
+async function offlineContentHTML() {
+ const i18n = await (swLang.i18n ?? swLang.fetchLocale()) as Partial>;
+ const messages = {
+ title: i18n.ts?._offlineScreen?.title ?? 'Offline - Could not connect to server',
+ header: i18n.ts?._offlineScreen?.header ?? 'Could not connect to server',
+ reload: i18n.ts?.reload ?? 'Reload',
+ };
+
+ return `${messages.title}${messages.header}
v${_VERSION_}
`;
}
globalThis.addEventListener('fetch', ev => {
@@ -43,8 +51,9 @@ globalThis.addEventListener('fetch', ev => {
if (!isHTMLRequest) return;
ev.respondWith(
fetch(ev.request)
- .catch(() => {
- return new Response(offlineContentHTML(), {
+ .catch(async () => {
+ const html = await offlineContentHTML();
+ return new Response(html, {
status: 200,
headers: {
'content-type': 'text/html',