diff --git a/.gitignore b/.gitignore
index d7b486b977..bdc14fea0a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -58,6 +58,7 @@ api-docs.json
ormconfig.json
temp
/packages/frontend/src/**/*.stories.ts
+tsdoc-metadata.json
# blender backups
*.blend1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9325615e46..c9df810efd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,5 @@
+
+
+
+
+
({{ i18n.ts._reversi.black }}) vs ({{ i18n.ts._reversi.white }})
+
+
+
+
+
+
+
+
+
+
{{ i18n.ts._reversi.opponentTurn }}
+
{{ i18n.ts._reversi.myTurn }}
+
+
+
+ ({{ i18n.ts._reversi.surrendered }})
+
+ {{ i18n.ts._reversi.drawn }}
+
+
+
+
+
+ {{ String.fromCharCode(64 + i) }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ String.fromCharCode(64 + i) }}
+
+
+
+
{{ i18n.tsx._reversi.turnCount({ count: logPos }) }} {{ i18n.ts._reversi.black }}:{{ engine.blackCount }} {{ i18n.ts._reversi.white }}:{{ engine.whiteCount }} {{ i18n.ts._reversi.total }}:{{ engine.blackCount + engine.whiteCount }}
+
+
+ {{ i18n.ts._reversi.surrender }}
+
+
+
+
{{ logPos }} / {{ game.logs.length }}
+
+
+
+
+
+
+
+
+
+
+
{{ i18n.ts._reversi.isLlotheo }}
+
{{ i18n.ts._reversi.loopedMap }}
+
{{ i18n.ts._reversi.canPutEverywhere }}
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/frontend/src/pages/reversi/game.setting.vue b/packages/frontend/src/pages/reversi/game.setting.vue
new file mode 100644
index 0000000000..301a177de1
--- /dev/null
+++ b/packages/frontend/src/pages/reversi/game.setting.vue
@@ -0,0 +1,236 @@
+
+
+
+
+
+ vs
+
+
+
{{ i18n.ts._reversi.gameSettings }}
+
+
+
+
{{ mapName }}
+
{{ i18n.ts._reversi.chooseBoard }}
+
+
+
+
+
+
+ {{ i18n.ts._reversi.blackOrWhite }}
+
+
+
+
+
+
+
+
+
+ {{ i18n.ts._reversi.rules }}
+
+
+ {{ i18n.ts._reversi.isLlotheo }}
+ {{ i18n.ts._reversi.loopedMap }}
+ {{ i18n.ts._reversi.canPutEverywhere }}
+
+
+
+
+
+
+
+
+ {{ i18n.ts._reversi.thisGameIsStartedSoon }}
+ {{ i18n.ts._reversi.waitingForOther }}
+ {{ i18n.ts._reversi.waitingForMe }}
+ {{ i18n.ts._reversi.waitingBoth }}
+
+
+ {{ i18n.ts.cancel }}
+ {{ i18n.ts._reversi.ready }}
+ {{ i18n.ts._reversi.cancelReady }}
+
+
+
+
+
+
+
+
+
+
diff --git a/packages/frontend/src/pages/reversi/game.vue b/packages/frontend/src/pages/reversi/game.vue
new file mode 100644
index 0000000000..dbbeb20f42
--- /dev/null
+++ b/packages/frontend/src/pages/reversi/game.vue
@@ -0,0 +1,68 @@
+
+
+
+
+
+
+
+
+
diff --git a/packages/frontend/src/pages/reversi/index.vue b/packages/frontend/src/pages/reversi/index.vue
new file mode 100644
index 0000000000..c483e36c24
--- /dev/null
+++ b/packages/frontend/src/pages/reversi/index.vue
@@ -0,0 +1,271 @@
+
+
+
+
+
+
+
+
+
+
+ {{ i18n.ts._reversi.freeMatch }}
+ {{ i18n.ts.invite }}
+
+
+
+ {{ i18n.ts.invitations }}
+
+
+
+
+
+
+ {{ i18n.ts._reversi.myGames }}
+
+
+
+
+
+ vs
+
+
+ {{ g.isEnded ? i18n.ts._reversi.ended : i18n.ts._reversi.playing }}
+
+
+
+
+
+
+
+
+
+ {{ i18n.ts._reversi.allGames }}
+
+
+
+
+
+ vs
+
+
+ {{ g.isEnded ? i18n.ts._reversi.ended : i18n.ts._reversi.playing }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ i18n.ts._reversi.lookingForPlayer }}
+
+
+ {{ i18n.ts.cancel }}
+
+
+
+
+
+
+
+
diff --git a/packages/frontend/src/pages/settings/2fa.vue b/packages/frontend/src/pages/settings/2fa.vue
index 35331738fd..dae1f03ccb 100644
--- a/packages/frontend/src/pages/settings/2fa.vue
+++ b/packages/frontend/src/pages/settings/2fa.vue
@@ -141,7 +141,7 @@ async function unregisterKey(key) {
const confirm = await os.confirm({
type: 'question',
title: i18n.ts._2fa.removeKey,
- text: i18n.t('_2fa.removeKeyConfirm', { name: key.name }),
+ text: i18n.tsx._2fa.removeKeyConfirm({ name: key.name }),
});
if (confirm.canceled) return;
diff --git a/packages/frontend/src/pages/settings/apps.vue b/packages/frontend/src/pages/settings/apps.vue
index 4a778d4b38..525b4e7519 100644
--- a/packages/frontend/src/pages/settings/apps.vue
+++ b/packages/frontend/src/pages/settings/apps.vue
@@ -30,7 +30,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.details }}
- - {{ i18n.t(`_permissions.${p}`) }}
+ - {{ i18n.ts._permissions[p] }}
diff --git a/packages/frontend/src/pages/settings/avatar-decoration.vue b/packages/frontend/src/pages/settings/avatar-decoration.vue
index df479cae51..39766978fc 100644
--- a/packages/frontend/src/pages/settings/avatar-decoration.vue
+++ b/packages/frontend/src/pages/settings/avatar-decoration.vue
@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ i18n.t('_profile.avatarDecorationMax', { max: $i.policies.avatarDecorationLimit }) }} ({{ i18n.t('remainingN', { n: $i.policies.avatarDecorationLimit - $i.avatarDecorations.length }) }})
+ {{ i18n.tsx._profile.avatarDecorationMax({ max: $i.policies.avatarDecorationLimit }) }} ({{ i18n.tsx.remainingN({ n: $i.policies.avatarDecorationLimit - $i.avatarDecorations.length }) }})
diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue
index 7df18e2dcb..aa9f842310 100644
--- a/packages/frontend/src/pages/settings/general.vue
+++ b/packages/frontend/src/pages/settings/general.vue
@@ -91,9 +91,9 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.mediaListWithOneImageAppearance }}
-
-
-
+
+
+
diff --git a/packages/frontend/src/pages/settings/migration.vue b/packages/frontend/src/pages/settings/migration.vue
index 2699f0ad63..6e5de0a333 100644
--- a/packages/frontend/src/pages/settings/migration.vue
+++ b/packages/frontend/src/pages/settings/migration.vue
@@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ i18n.t('_accountMigration.moveFromLabel', { n: i + 1 }) }}
+ {{ i18n.tsx._accountMigration.moveFromLabel({ n: i + 1 }) }}
@@ -97,7 +97,7 @@ async function move(): Promise {
const account = moveToAccount.value;
const confirm = await os.confirm({
type: 'warning',
- text: i18n.t('_accountMigration.migrationConfirm', { account }),
+ text: i18n.tsx._accountMigration.migrationConfirm({ account }),
});
if (confirm.canceled) return;
await os.apiWithDialog('i/move', {
diff --git a/packages/frontend/src/pages/settings/mute-block.word-mute.vue b/packages/frontend/src/pages/settings/mute-block.word-mute.vue
index 0e8bc702dd..3f98aade92 100644
--- a/packages/frontend/src/pages/settings/mute-block.word-mute.vue
+++ b/packages/frontend/src/pages/settings/mute-block.word-mute.vue
@@ -64,7 +64,7 @@ async function save() {
os.alert({
type: 'error',
title: i18n.ts.regexpError,
- text: i18n.t('regexpErrorDescription', { tab: 'word mute', line: i + 1 }) + '\n' + err.toString(),
+ text: i18n.tsx.regexpErrorDescription({ tab: 'word mute', line: i + 1 }) + '\n' + err.toString(),
});
// re-throw error so these invalid settings are not saved
throw err;
diff --git a/packages/frontend/src/pages/settings/notifications.vue b/packages/frontend/src/pages/settings/notifications.vue
index 8709821595..bf76c083df 100644
--- a/packages/frontend/src/pages/settings/notifications.vue
+++ b/packages/frontend/src/pages/settings/notifications.vue
@@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.notificationRecieveConfig }}
- {{ i18n.t('_notification._types.' + type) }}
+ {{ i18n.ts._notification._types[type] }}
{{
$i.notificationRecieveConfig[type]?.type === 'never' ? i18n.ts.none :
diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue
index 08bdf71d01..cf9063c8bb 100644
--- a/packages/frontend/src/pages/settings/profile.vue
+++ b/packages/frontend/src/pages/settings/profile.vue
@@ -212,7 +212,7 @@ function changeAvatar(ev) {
const { canceled } = await os.confirm({
type: 'question',
- text: i18n.t('cropImageAsk'),
+ text: i18n.ts.cropImageAsk,
okText: i18n.ts.cropYes,
cancelText: i18n.ts.cropNo,
});
@@ -238,7 +238,7 @@ function changeBanner(ev) {
const { canceled } = await os.confirm({
type: 'question',
- text: i18n.t('cropImageAsk'),
+ text: i18n.ts.cropImageAsk,
okText: i18n.ts.cropYes,
cancelText: i18n.ts.cropNo,
});
diff --git a/packages/frontend/src/pages/settings/sounds.vue b/packages/frontend/src/pages/settings/sounds.vue
index 9fbcce2286..a116a0407f 100644
--- a/packages/frontend/src/pages/settings/sounds.vue
+++ b/packages/frontend/src/pages/settings/sounds.vue
@@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.sounds }}
- {{ i18n.t('_sfx.' + type) }}
+ {{ i18n.ts._sfx[type] }}
{{ getSoundTypeName(sounds[type].type) }}
updated(type, res)"/>
@@ -33,9 +33,9 @@ SPDX-License-Identifier: AGPL-3.0-only