i18n Support and Task improvements (#80)

* fix: release workflow

* feat: move mostly to internal tasks system

* feat: migrate object clean to new task system

* fix: release not  getting good base version

* chore: set version v0.3.0

* chore: style

* feat: basic task concurrency

* feat: temp pages to fill in page links

* feat: inital i18n support

* feat: localize store page

* chore: style

* fix: weblate doesn't like multifile thing

* fix: update nuxt

* feat: improved error logging

* fix: using old task api

* feat: basic translation docs

* feat: add i18n eslint plugin

* feat: translate store and auth pages

* feat: more translation progress

* feat: admin dash i18n progress

* feat: enable update check by default in prod

* fix: using wrong i18n keys

* fix: crash in library sources page

* feat: finish i18n work

* fix: missing i18n translations

* feat: use twemoji for emojis

* feat: sanatize object ids

* fix: EmojiText's alt text

* fix: UserWidget not using links

* feat: cache and auth for emoji api

* fix: add more missing translations
This commit is contained in:
Husky
2025-06-04 19:53:30 -04:00
committed by GitHub
parent c7fab132ab
commit 681efe95af
86 changed files with 5175 additions and 2816 deletions

View File

@ -4,12 +4,12 @@
<h2
class="mt-2 text-xl font-semibold tracking-tight text-zinc-100 sm:text-3xl"
>
Devices
{{ $t("account.devices.title") }}
</h2>
<p
class="mt-2 text-pretty text-sm font-medium text-zinc-400 sm:text-md/8"
>
Manage the devices authorized to access your Drop account.
{{ $t("account.devices.subheader") }}
</p>
</div>
@ -24,28 +24,28 @@
scope="col"
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-zinc-100 sm:pl-6"
>
Name
{{ $t("name") }}
</th>
<th
scope="col"
class="px-3 py-3.5 text-left text-sm font-semibold text-zinc-100"
>
Platform
{{ $t("account.devices.platform") }}
</th>
<th
scope="col"
class="px-3 py-3.5 text-left text-sm font-semibold text-zinc-100"
>
Capabilities
{{ $t("account.devices.capabilities") }}
</th>
<th
scope="col"
class="px-3 py-3.5 text-left text-sm font-semibold text-zinc-100"
>
Last Connected
{{ $t("account.devices.lastConnected") }}
</th>
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6">
<span class="sr-only">Actions</span>
<span class="sr-only">{{ $t("actions") }}</span>
</th>
</tr>
</thead>
@ -80,7 +80,7 @@
</div>
</td>
<td class="whitespace-nowrap px-3 py-4 text-sm text-zinc-400">
{{ DateTime.fromISO(client.lastConnected).toRelative() }}
<RelativeTime :date="client.lastConnected" />
</td>
<td
class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6"
@ -89,13 +89,16 @@
class="inline-flex items-center rounded-md bg-red-400/10 px-2 py-1 text-xs font-medium text-red-400 ring-1 ring-inset ring-red-400/20 transition-all duration-200 hover:bg-red-400/20 hover:scale-105 active:scale-95"
@click="() => revokeClientWrapper(client.id)"
>
Revoke<span class="sr-only">, {{ client.name }}</span>
{{ $t("account.devices.revoke") }}
<span class="sr-only">
{{ $t("chars.srComma", [client.name]) }}
</span>
</button>
</td>
</tr>
<tr v-if="clients.length === 0">
<td colspan="5" class="py-8 text-center text-sm text-zinc-400">
No devices connected to your account.
{{ $t("account.devices.noDevices") }}
</td>
</tr>
</tbody>
@ -107,16 +110,25 @@
<script setup lang="ts">
import { CheckIcon } from "@heroicons/vue/24/outline";
import { DateTime } from "luxon";
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore pending https://github.com/nitrojs/nitro/issues/2758
const clients = ref(await $dropFetch("/api/v1/user/client"));
const { t } = useI18n();
async function revokeClient(id: string) {
await $dropFetch(`/api/v1/user/client/${id}`, { method: "DELETE" });
}
// clients.value.push({
// id: "example-client",
// userId: "example-user",
// name: "Example Client",
// platform: "Windows",
// capabilities: ["TrackPlaytime"],
// lastConnected: new Date().toISOString(),
// });
function revokeClientWrapper(id: string) {
revokeClient(id)
.then(() => {
@ -127,8 +139,8 @@ function revokeClientWrapper(id: string) {
createModal(
ModalType.Notification,
{
title: "Failed to revoke client",
description: `Failed to revoke client: ${e}`,
title: t("errors.revokeClient"),
description: t("errors.revokeClientFull", String(e)),
},
(_, c) => c(),
);

View File

@ -5,7 +5,7 @@
<h2
class="text-xl font-semibold tracking-tight text-zinc-100 sm:text-3xl"
>
Notifications
{{ $t("account.notifications.notifications") }}
</h2>
<button
:disabled="notifications.length === 0"
@ -13,13 +13,13 @@
@click="markAllAsRead"
>
<CheckIcon class="size-4" />
Mark all as read
{{ $t("account.notifications.markAllAsRead") }}
</button>
</div>
<p
class="mt-2 text-pretty text-sm font-medium text-zinc-400 sm:text-md/8"
>
View and manage your notifications.
{{ $t("account.notifications.desc") }}
</p>
</div>
@ -52,7 +52,7 @@
</div>
<div class="ml-4 flex flex-shrink-0 items-center gap-x-2">
<span class="text-xs text-zinc-500">
{{ DateTime.fromISO(notification.created).toRelative() }}
<RelativeTime :date="notification.created" />
</span>
<button
v-if="!notification.read"
@ -61,7 +61,7 @@
@click="markAsRead(notification.id)"
>
<CheckIcon class="size-3" />
Mark as read
{{ $t("account.notifications.markAsRead") }}
</button>
<button
type="button"
@ -69,7 +69,7 @@
@click="deleteNotification(notification.id)"
>
<TrashIcon class="size-3" />
Delete
{{ $t("delete") }}
</button>
</div>
</div>
@ -80,7 +80,9 @@
v-if="notifications.length === 0"
class="rounded-xl border border-zinc-800 bg-zinc-900 p-8 text-center"
>
<p class="text-sm text-zinc-400">No notifications</p>
<p class="text-sm text-zinc-400">
{{ $t("account.notifications.none") }}
</p>
</div>
</div>
</div>
@ -88,7 +90,6 @@
<script setup lang="ts">
import { CheckIcon, TrashIcon } from "@heroicons/vue/24/outline";
import { DateTime } from "luxon";
import type { Notification } from "~/prisma/client";
import type { SerializeObject } from "nitropack";
@ -96,8 +97,10 @@ definePageMeta({
layout: "default",
});
const { t } = useI18n();
useHead({
title: "Notifications",
title: t("account.notifications.title"),
});
// Fetch notifications