mirror of
https://github.com/versia-pub/frontend.git
synced 2026-03-14 03:59:15 +01:00
refactor: 🌐 Internationalize every string
This commit is contained in:
parent
8c3ddc2a28
commit
2ceee4827f
41 changed files with 932 additions and 428 deletions
|
|
@ -23,7 +23,7 @@
|
|||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Mention someone</p>
|
||||
<p>{{ m.game_tough_seal_adore() }}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
|
|
@ -34,7 +34,7 @@
|
|||
</Toggle>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Enable Markdown</p>
|
||||
<p>{{ m.plane_born_koala_hope() }}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Select v-model:model-value="state.visibility">
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Insert emoji</p>
|
||||
<p>{{ m.blue_ornate_coyote_tickle() }}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Attach a file</p>
|
||||
<p>{{ m.top_patchy_earthworm_vent() }}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Tooltip>
|
||||
|
|
@ -82,12 +82,12 @@
|
|||
</Toggle>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<p>Mark as sensitive</p>
|
||||
<p>{{ m.frail_broad_mallard_dart() }}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<Button type="submit" size="lg" class="ml-auto" :disabled="sending" @click="submit">
|
||||
<Loader v-if="sending" class="!size-5 animate-spin" />
|
||||
{{ relation?.type === "edit" ? "Save" : "Send" }}
|
||||
{{ relation?.type === "edit" ? m.gaudy_strong_puma_slide() : m.free_teal_bulldog_learn() }}
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</template>
|
||||
|
|
@ -110,6 +110,7 @@ import { SelectTrigger } from "radix-vue";
|
|||
import { toast } from "vue-sonner";
|
||||
import Note from "~/components/notes/note.vue";
|
||||
import { Select, SelectContent, SelectItem } from "~/components/ui/select";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import { SettingIds } from "~/settings";
|
||||
import { Button } from "../ui/button";
|
||||
import { Input } from "../ui/input";
|
||||
|
|
@ -145,11 +146,11 @@ const getMentions = () => {
|
|||
const peopleToMention = relation.note.mentions
|
||||
.concat(relation.note.account)
|
||||
// Deduplicate mentions
|
||||
.filter((m, i, a) => a.indexOf(m) === i)
|
||||
.filter((men, i, a) => a.indexOf(men) === i)
|
||||
// Remove self
|
||||
.filter((m) => m.id !== identity.value?.account.id);
|
||||
.filter((men) => men.id !== identity.value?.account.id);
|
||||
|
||||
const mentions = peopleToMention.map((m) => `@${m.acct}`).join(" ");
|
||||
const mentions = peopleToMention.map((me) => `@${me.acct}`).join(" ");
|
||||
|
||||
return `${mentions} `;
|
||||
};
|
||||
|
|
@ -165,10 +166,10 @@ const state = reactive({
|
|||
? relation.note.visibility
|
||||
: "public") as Status["visibility"],
|
||||
files: (relation?.type === "edit"
|
||||
? relation.note.media_attachments.map((m) => ({
|
||||
apiId: m.id,
|
||||
file: new File([], m.url),
|
||||
alt: m.description,
|
||||
? relation.note.media_attachments.map((a) => ({
|
||||
apiId: a.id,
|
||||
file: new File([], a.url),
|
||||
alt: a.description,
|
||||
uploading: false,
|
||||
updating: false,
|
||||
}))
|
||||
|
|
@ -276,23 +277,23 @@ const uploadFiles = (files: File[]) => {
|
|||
const visibilities = {
|
||||
public: {
|
||||
icon: Globe,
|
||||
name: "Public",
|
||||
text: "Can be seen by anyone.",
|
||||
name: m.lost_trick_dog_grace(),
|
||||
text: m.last_mean_peacock_zip(),
|
||||
},
|
||||
unlisted: {
|
||||
icon: LockOpen,
|
||||
name: "Unlisted",
|
||||
text: "Can be seen by anyone with the link.",
|
||||
name: m.funny_slow_jannes_walk(),
|
||||
text: m.grand_strong_gibbon_race(),
|
||||
},
|
||||
private: {
|
||||
icon: Lock,
|
||||
name: "Private",
|
||||
text: "Can only be seen by your followers.",
|
||||
name: m.grassy_empty_raven_startle(),
|
||||
text: m.white_teal_ostrich_yell(),
|
||||
},
|
||||
direct: {
|
||||
icon: AtSign,
|
||||
name: "Direct",
|
||||
text: "Can only be seen by mentioned users.",
|
||||
name: m.pretty_bold_baboon_wave(),
|
||||
text: m.lucky_mean_robin_link(),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -2,6 +2,7 @@
|
|||
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||||
import type { Status, StatusSource } from "@versia/client/types";
|
||||
import { toast } from "vue-sonner";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import Composer from "./composer.vue";
|
||||
|
||||
useListen("composer:open", () => {
|
||||
|
|
@ -11,7 +12,7 @@ useListen("composer:open", () => {
|
|||
});
|
||||
|
||||
useListen("composer:edit", async (note) => {
|
||||
const id = toast.loading("Loading note data...", {
|
||||
const id = toast.loading(m.wise_late_fireant_walk(), {
|
||||
duration: 0,
|
||||
});
|
||||
const { data: source } = await client.value.getStatusSource(note.id);
|
||||
|
|
@ -56,13 +57,16 @@ const relation = ref(
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<Dialog v-model:open="open" @update:open="o => {if (!o) { relation = null}}">
|
||||
<DialogContent :hide-close="true" class="sm:max-w-xl max-w-full w-full grid-rows-[minmax(0,1fr)_auto] max-h-[90dvh] p-5 pt-6 top-0 sm:top-1/2 translate-y-0 sm:-translate-y-1/2">
|
||||
<Dialog v-model:open="open" @update:open="o => { if (!o) { relation = null } }">
|
||||
<DialogContent :hide-close="true"
|
||||
class="sm:max-w-xl max-w-full w-full grid-rows-[minmax(0,1fr)_auto] max-h-[90dvh] p-5 pt-6 top-0 sm:top-1/2 translate-y-0 sm:-translate-y-1/2">
|
||||
<DialogTitle class="sr-only">
|
||||
{{ relation?.type === "reply" ? "Reply" : relation?.type === "quote" ? "Quote" : "Compose" }}
|
||||
{{ relation?.type === "reply" ? m.loved_busy_mantis_slide() : relation?.type === "quote" ? "Quote" :
|
||||
m.chunky_dull_marlin_trip() }}
|
||||
</DialogTitle>
|
||||
<DialogDescription class="sr-only">
|
||||
{{ relation?.type === "reply" ? "Reply to this status" : relation?.type === "quote" ? "Quote this status" : "Compose a new status" }}
|
||||
{{ relation?.type === "reply" ? m.tired_grassy_vulture_forgive() : relation?.type === "quote" ?
|
||||
m.livid_livid_nils_snip() : m.brief_cool_capybara_fear() }}
|
||||
</DialogDescription>
|
||||
<Composer :relation="relation ?? undefined" />
|
||||
</DialogContent>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
import { Input } from "@/components/ui/input";
|
||||
import { Label } from "@/components/ui/label";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import type { ConfirmModalOptions, ConfirmModalResult } from "./composable.ts";
|
||||
|
||||
defineProps<{
|
||||
|
|
@ -41,14 +42,14 @@ const inputValue = ref<string>("");
|
|||
|
||||
<div v-if="modalOptions.inputType === 'text'" class="grid gap-4 py-4">
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label for="confirmInput" class="text-right">Value</Label>
|
||||
<Label for="confirmInput" class="text-right">{{ m.mean_mean_badger_inspire() }}</Label>
|
||||
<Input id="confirmInput" v-model="inputValue" class="col-span-3" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-else-if="modalOptions.inputType === 'textarea'" class="grid gap-4 py-4">
|
||||
<div class="grid grid-cols-4 items-center gap-4">
|
||||
<Label for="confirmTextarea" class="text-right">Value</Label>
|
||||
<Label for="confirmTextarea" class="text-right">{{ m.mean_mean_badger_inspire() }}</Label>
|
||||
<Textarea id="confirmTextarea" v-model="inputValue" class="col-span-3" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import {
|
||||
type ConfirmModalOptions,
|
||||
type ConfirmModalResult,
|
||||
|
|
@ -20,11 +21,11 @@ import {
|
|||
|
||||
const isOpen = ref(false);
|
||||
const modalOptions = ref<ConfirmModalOptions>({
|
||||
title: "Confirm",
|
||||
title: m.antsy_whole_alligator_blink(),
|
||||
message: "",
|
||||
inputType: "none",
|
||||
confirmText: "Confirm",
|
||||
cancelText: "Cancel",
|
||||
confirmText: m.antsy_whole_alligator_blink(),
|
||||
cancelText: m.soft_bold_ant_attend(),
|
||||
});
|
||||
const inputValue = ref("");
|
||||
const resolvePromise = ref<((result: ConfirmModalResult) => void) | null>(null);
|
||||
|
|
@ -32,11 +33,11 @@ const resolvePromise = ref<((result: ConfirmModalResult) => void) | null>(null);
|
|||
function open(options: ConfirmModalOptions): Promise<ConfirmModalResult> {
|
||||
isOpen.value = true;
|
||||
modalOptions.value = {
|
||||
title: options.title || "Confirm",
|
||||
title: options.title || m.antsy_whole_alligator_blink(),
|
||||
message: options.message,
|
||||
inputType: options.inputType || "none",
|
||||
confirmText: options.confirmText || "Confirm",
|
||||
cancelText: options.cancelText || "Cancel",
|
||||
confirmText: options.confirmText || m.antsy_whole_alligator_blink(),
|
||||
cancelText: options.cancelText || m.soft_bold_ant_attend(),
|
||||
};
|
||||
inputValue.value = options.defaultValue || "";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,22 +1,22 @@
|
|||
<template>
|
||||
<div class="flex flex-row w-full items-stretch justify-around text-sm *:max-w-28 *:w-full *:text-muted-foreground">
|
||||
<Button variant="ghost" @click="emit('reply')" title="Reply" :disabled="!identity">
|
||||
<Button variant="ghost" @click="emit('reply')" :title="m.drab_tense_turtle_comfort()" :disabled="!identity">
|
||||
<Reply class="size-5 text-primary" />
|
||||
{{ numberFormat(replyCount) }}
|
||||
</Button>
|
||||
<Button variant="ghost" @click="liked ? unlike() : like()" :title="liked ? 'Unlike' : 'Like'" :disabled="!identity">
|
||||
<Button variant="ghost" @click="liked ? unlike() : like()" :title="liked ? m.vexed_fluffy_clownfish_dance() : m.royal_close_samuel_scold()" :disabled="!identity">
|
||||
<Heart class="size-5 text-primary" />
|
||||
{{ numberFormat(likeCount) }}
|
||||
</Button>
|
||||
<Button variant="ghost" @click="reblogged ? unreblog() : reblog()" :title="reblogged ? 'Unreblog' : 'Reblog'" :disabled="!identity">
|
||||
<Button variant="ghost" @click="reblogged ? unreblog() : reblog()" :title="reblogged ? m.lime_neat_ox_stab() : m.aware_helpful_marlin_drop()" :disabled="!identity">
|
||||
<Repeat class="size-5 text-primary" />
|
||||
{{ numberFormat(reblogCount) }}
|
||||
</Button>
|
||||
<Button variant="ghost" @click="emit('quote')" title="Quote" :disabled="!identity">
|
||||
<Button variant="ghost" @click="emit('quote')" :title="m.true_shy_jackal_drip()" :disabled="!identity">
|
||||
<Quote class="size-5 text-primary" />
|
||||
</Button>
|
||||
<Menu :api-note-string="apiNoteString" :url="url" :remote-url="remoteUrl" :is-remote="isRemote" :author-id="authorId" @edit="emit('edit')" :note-id="noteId" @delete="emit('delete')">
|
||||
<Button variant="ghost" title="Actions">
|
||||
<Button variant="ghost" :title="m.busy_merry_cowfish_absorb()">
|
||||
<Ellipsis class="size-5 text-primary" />
|
||||
</Button>
|
||||
</Menu>
|
||||
|
|
@ -27,6 +27,8 @@
|
|||
import { Ellipsis, Heart, Quote, Repeat, Reply } from "lucide-vue-next";
|
||||
import { toast } from "vue-sonner";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import { languageTag } from "~/paraglide/runtime";
|
||||
import { SettingIds } from "~/settings";
|
||||
import { confirmModalService } from "../modals/composable";
|
||||
import Menu from "./menu.vue";
|
||||
|
|
@ -58,9 +60,9 @@ const confirmReblogs = useSetting(SettingIds.ConfirmReblog);
|
|||
const like = async () => {
|
||||
if (confirmLikes.value.value) {
|
||||
const confirmation = await confirmModalService.confirm({
|
||||
title: "Like status",
|
||||
message: "Are you sure you want to like this status?",
|
||||
confirmText: "Like",
|
||||
title: m.slimy_least_ray_aid(),
|
||||
message: m.stale_new_ray_jolt(),
|
||||
confirmText: m.royal_close_samuel_scold(),
|
||||
inputType: "none",
|
||||
});
|
||||
|
||||
|
|
@ -69,19 +71,19 @@ const like = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
const id = toast.loading("Liking status...");
|
||||
const id = toast.loading(m.slimy_candid_tiger_read());
|
||||
const { data } = await client.value.favouriteStatus(noteId);
|
||||
toast.dismiss(id);
|
||||
toast.success("Status liked");
|
||||
toast.success(m.mealy_slow_buzzard_commend());
|
||||
useEvent("note:edit", data);
|
||||
};
|
||||
|
||||
const unlike = async () => {
|
||||
if (confirmLikes.value.value) {
|
||||
const confirmation = await confirmModalService.confirm({
|
||||
title: "Unlike status",
|
||||
message: "Are you sure you want to unlike this status?",
|
||||
confirmText: "Unlike",
|
||||
title: m.odd_strong_halibut_prosper(),
|
||||
message: m.slow_blue_parrot_savor(),
|
||||
confirmText: m.vexed_fluffy_clownfish_dance(),
|
||||
inputType: "none",
|
||||
});
|
||||
|
||||
|
|
@ -90,19 +92,19 @@ const unlike = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
const id = toast.loading("Unliking status...");
|
||||
const id = toast.loading(m.busy_active_leopard_strive());
|
||||
const { data } = await client.value.unfavouriteStatus(noteId);
|
||||
toast.dismiss(id);
|
||||
toast.success("Status unliked");
|
||||
toast.success(m.fresh_direct_bear_affirm());
|
||||
useEvent("note:edit", data);
|
||||
};
|
||||
|
||||
const reblog = async () => {
|
||||
if (confirmReblogs.value.value) {
|
||||
const confirmation = await confirmModalService.confirm({
|
||||
title: "Reblog status",
|
||||
message: "Are you sure you want to reblog this status?",
|
||||
confirmText: "Reblog",
|
||||
title: m.best_mellow_llama_surge(),
|
||||
message: m.salty_plain_mallard_gaze(),
|
||||
confirmText: m.aware_helpful_marlin_drop(),
|
||||
inputType: "none",
|
||||
});
|
||||
|
||||
|
|
@ -111,19 +113,19 @@ const reblog = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
const id = toast.loading("Reblogging status...");
|
||||
const id = toast.loading(m.late_sunny_cobra_scold());
|
||||
const { data } = await client.value.reblogStatus(noteId);
|
||||
toast.dismiss(id);
|
||||
toast.success("Status reblogged");
|
||||
toast.success(m.weird_moving_hawk_lift());
|
||||
useEvent("note:edit", data.reblog || data);
|
||||
};
|
||||
|
||||
const unreblog = async () => {
|
||||
if (confirmReblogs.value.value) {
|
||||
const confirmation = await confirmModalService.confirm({
|
||||
title: "Unreblog status",
|
||||
message: "Are you sure you want to unreblog this status?",
|
||||
confirmText: "Unreblog",
|
||||
title: m.main_fancy_octopus_loop(),
|
||||
message: m.odd_alive_swan_express(),
|
||||
confirmText: m.lime_neat_ox_stab(),
|
||||
inputType: "none",
|
||||
});
|
||||
|
||||
|
|
@ -132,16 +134,16 @@ const unreblog = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
const id = toast.loading("Unreblogging status...");
|
||||
const id = toast.loading(m.white_sharp_gorilla_embrace());
|
||||
const { data } = await client.value.unreblogStatus(noteId);
|
||||
toast.dismiss(id);
|
||||
toast.success("Status unreblogged");
|
||||
toast.success(m.royal_polite_moose_catch());
|
||||
useEvent("note:edit", data);
|
||||
};
|
||||
|
||||
const numberFormat = (number = 0) =>
|
||||
number !== 0
|
||||
? new Intl.NumberFormat(undefined, {
|
||||
? new Intl.NumberFormat(languageTag(), {
|
||||
notation: "compact",
|
||||
compactDisplay: "short",
|
||||
maximumFractionDigits: 1,
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
<template>
|
||||
<Alert variant="warning" v-if="(sensitive || contentWarning) && showCw.value"
|
||||
class="mb-4 py-2 px-4 grid grid-cols-[auto,1fr,auto] gap-2 items-center [&>svg~*]:pl-0 [&>svg+div]:translate-y-0 [&>svg]:static">
|
||||
<AlertTitle class="sr-only">Sensitive content</AlertTitle>
|
||||
<AlertTitle class="sr-only">{{ m.livid_tangy_lionfish_clasp() }}</AlertTitle>
|
||||
<div>
|
||||
<TriangleAlert class="size-4" />
|
||||
</div>
|
||||
<AlertDescription>
|
||||
{{ contentWarning || "This content is sensitive" }}
|
||||
{{ contentWarning || m.sour_seemly_bird_hike() }}
|
||||
</AlertDescription>
|
||||
<Button @click="blurred = !blurred" variant="outline" size="sm">{{ blurred ? "Show" : "Hide" }}</Button>
|
||||
<Button @click="blurred = !blurred" variant="outline" size="sm">{{ blurred ? m.bald_direct_turtle_win() : m.known_flaky_cockroach_dash() }}</Button>
|
||||
</Alert>
|
||||
|
||||
<div ref="container" :class="cn('overflow-y-hidden relative duration-200', (blurred && showCw.value) && 'blur-md')" :style="{
|
||||
|
|
@ -23,9 +23,10 @@
|
|||
<Button v-if="isOverflowing" @click="collapsed = !collapsed"
|
||||
class="absolute bottom-2 right-1/2 translate-x-1/2">{{
|
||||
collapsed
|
||||
? `Show more${plainContent ? ` • ${formattedCharacterCount} characters` : ""
|
||||
}`
|
||||
: "Show less"
|
||||
? `${m.lazy_honest_mammoth_bump()}${plainContent ? ` • ${m.dark_spare_goldfish_charm({
|
||||
count: formattedCharacterCount ?? '0',
|
||||
})}` : "" }`
|
||||
: m.that_misty_mule_arrive()
|
||||
}}</Button>
|
||||
</div>
|
||||
|
||||
|
|
@ -41,6 +42,7 @@ import { cn } from "@/lib/utils";
|
|||
import type { Attachment, Emoji, Status } from "@versia/client/types";
|
||||
import { TriangleAlert } from "lucide-vue-next";
|
||||
import { Button } from "~/components/ui/button";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import { languageTag } from "~/paraglide/runtime";
|
||||
import { type BooleanSetting, SettingIds } from "~/settings";
|
||||
import { Alert, AlertDescription, AlertTitle } from "../ui/alert";
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
<span @click="copyText"
|
||||
class="select-none cursor-pointer space-x-1">
|
||||
<Clipboard class="size-4 -translate-y-0.5 inline" />
|
||||
Click to copy
|
||||
{{ m.clean_yummy_owl_reside() }}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
|
|
@ -18,6 +18,7 @@ import { cn } from "@/lib/utils";
|
|||
import { Check, Clipboard } from "lucide-vue-next";
|
||||
import type { HTMLAttributes } from "vue";
|
||||
import { toast } from "vue-sonner";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
|
||||
const { text } = defineProps<{
|
||||
text: string;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import {
|
|||
} from "lucide-vue-next";
|
||||
import { toast } from "vue-sonner";
|
||||
import { confirmModalService } from "~/components/modals/composable.ts";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import { SettingIds } from "~/settings";
|
||||
|
||||
const { authorId, noteId } = defineProps<{
|
||||
|
|
@ -45,23 +46,23 @@ const confirmDeletes = useSetting(SettingIds.ConfirmDelete);
|
|||
|
||||
const copyText = (text: string) => {
|
||||
copy(text);
|
||||
toast.success("Copied to clipboard");
|
||||
toast.success(m.flat_nice_worm_dream());
|
||||
};
|
||||
|
||||
const blockUser = async (userId: string) => {
|
||||
const id = toast.loading("Blocking user...");
|
||||
const id = toast.loading(m.top_cute_bison_nudge());
|
||||
await client.value.blockAccount(userId);
|
||||
toast.dismiss(id);
|
||||
|
||||
toast.success("User blocked");
|
||||
toast.success(m.main_weary_racoon_peek());
|
||||
};
|
||||
|
||||
const _delete = async () => {
|
||||
if (confirmDeletes.value.value) {
|
||||
const confirmation = await confirmModalService.confirm({
|
||||
title: "Delete status",
|
||||
message: "Are you sure you want to delete this status?",
|
||||
confirmText: "Delete",
|
||||
title: m.calm_icy_weasel_twirl(),
|
||||
message: m.gray_fun_toucan_slide(),
|
||||
confirmText: m.royal_best_tern_transform(),
|
||||
inputType: "none",
|
||||
});
|
||||
|
||||
|
|
@ -70,11 +71,11 @@ const _delete = async () => {
|
|||
}
|
||||
}
|
||||
|
||||
const id = toast.loading("Deleting status...");
|
||||
const id = toast.loading(m.new_funny_fox_boil());
|
||||
await client.value.deleteStatus(noteId);
|
||||
toast.dismiss(id);
|
||||
|
||||
toast.success("Status deleted");
|
||||
toast.success(m.green_tasty_bumblebee_beam());
|
||||
emit("delete");
|
||||
};
|
||||
</script>
|
||||
|
|
@ -85,57 +86,57 @@ const _delete = async () => {
|
|||
<slot />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent class="min-w-56">
|
||||
<DropdownMenuLabel>Note Actions</DropdownMenuLabel>
|
||||
<DropdownMenuLabel>{{ m.many_misty_parakeet_fall() }}</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem v-if="authorIsMe" as="button" @click="emit('edit')">
|
||||
<Pencil class="mr-2 size-4" />
|
||||
<span>Edit</span>
|
||||
{{ m.front_lime_grizzly_persist() }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem as="button" @click="copyText(apiNoteString)">
|
||||
<Code class="mr-2 size-4" />
|
||||
<span>Copy API data</span>
|
||||
{{ m.yummy_moving_scallop_sail() }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem as="button" @click="copyText(noteId)">
|
||||
<Hash class="mr-2 size-4" />
|
||||
<span>Copy ID</span>
|
||||
{{ m.sunny_zany_jellyfish_pop() }}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem as="button" @click="copyText(url)">
|
||||
<Link class="mr-2 size-4" />
|
||||
<span>Copy link</span>
|
||||
{{ m.ago_new_pelican_drip() }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem as="button" v-if="isRemote" @click="copyText(remoteUrl)">
|
||||
<Link class="mr-2 size-4" />
|
||||
<span>Copy link (origin)</span>
|
||||
{{ m.solid_witty_zebra_walk() }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem as="a" v-if="isRemote" target="_blank" rel="noopener noreferrer" :href="remoteUrl">
|
||||
<ExternalLink class="mr-2 size-4" />
|
||||
<span>Open on remote</span>
|
||||
{{ m.active_trite_lark_inspire() }}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator v-if="authorIsMe" />
|
||||
<DropdownMenuGroup v-if="authorIsMe">
|
||||
<DropdownMenuItem as="button" :disabled="true">
|
||||
<Delete class="mr-2 size-4" />
|
||||
<span>Delete and redraft</span>
|
||||
{{ m.real_green_clownfish_pet() }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem as="button" @click="_delete">
|
||||
<Trash class="mr-2 size-4" />
|
||||
<span>Delete</span>
|
||||
{{ m.tense_quick_cod_favor() }}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator v-if="loggedIn && !authorIsMe" />
|
||||
<DropdownMenuGroup v-if="loggedIn && !authorIsMe">
|
||||
<DropdownMenuItem as="button" :disabled="true">
|
||||
<Flag class="mr-2 size-4" />
|
||||
<span>Report</span>
|
||||
{{ m.great_few_jaguar_rise() }}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem as="button" @click="blockUser(authorId)">
|
||||
<Ban class="mr-2 size-4" />
|
||||
<span>Block user</span>
|
||||
{{ m.misty_soft_sparrow_vent() }}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
</DropdownMenuContent>
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ import {
|
|||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "~/components/ui/tooltip";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import Note from "../notes/note.vue";
|
||||
import Avatar from "../profiles/avatar.vue";
|
||||
import FollowRequest from "./follow-request.vue";
|
||||
|
|
@ -85,17 +86,17 @@ const icon = computed(() => {
|
|||
const text = computed(() => {
|
||||
switch (notification.type) {
|
||||
case "mention":
|
||||
return "Mentioned you";
|
||||
return m.fuzzy_orange_tuna_succeed();
|
||||
case "reblog":
|
||||
return "Reblogged your note";
|
||||
return m.grand_proof_quail_read();
|
||||
case "follow":
|
||||
return "Followed you";
|
||||
return m.top_steep_scallop_care();
|
||||
case "favourite":
|
||||
return "Liked your note";
|
||||
return m.swift_just_beetle_devour();
|
||||
case "follow_request":
|
||||
return "Requested to follow you";
|
||||
return m.seemly_short_thrush_bloom();
|
||||
case "follow_accept":
|
||||
return "Accepted your follow request";
|
||||
return m.weird_seemly_termite_scold();
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
{{ emoji.shortcode }}
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
{{ emoji.global ? m.lime_day_squid_pout() : m.witty_heroic_trout_cry() }}
|
||||
{{ emoji.global ? m.real_tame_moose_greet() : m.witty_heroic_trout_cry() }}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardFooter class="p-0" v-if="canEdit">
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
<Card class="grid grid-cols-[1fr,auto] items-center p-6 gap-2">
|
||||
<CardHeader class="space-y-0.5 p-0">
|
||||
<CardTitle class="text-base">
|
||||
{{ setting.title }}
|
||||
{{ setting.title() }}
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
{{ setting.description }}
|
||||
{{ setting.description() }}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardFooter class="p-0">
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem v-for="option of setting.options" :value="option.value">
|
||||
{{ option.label }}
|
||||
{{ option.label() }}
|
||||
</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
|
|
|
|||
|
|
@ -2,10 +2,10 @@
|
|||
<Card class="grid grid-cols-[1fr,auto] items-center p-6 gap-2">
|
||||
<CardHeader class="space-y-0.5 p-0">
|
||||
<CardTitle class="text-base">
|
||||
{{ setting.title }}
|
||||
{{ setting.title() }}
|
||||
</CardTitle>
|
||||
<CardDescription>
|
||||
{{ setting.description }}
|
||||
{{ setting.description() }}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardFooter class="p-0">
|
||||
|
|
|
|||
|
|
@ -120,7 +120,6 @@ import {
|
|||
SidebarRail,
|
||||
} from "~/components/ui/sidebar";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import { setLanguageTag } from "~/paraglide/runtime";
|
||||
import { type EnumSetting, SettingIds } from "~/settings";
|
||||
import Avatar from "../profiles/avatar.vue";
|
||||
import { Button } from "../ui/button";
|
||||
|
|
@ -128,8 +127,6 @@ import AccountSwitcher from "./account-switcher.vue";
|
|||
|
||||
const sidebarStyle = useSetting(SettingIds.SidebarStyle) as Ref<EnumSetting>;
|
||||
|
||||
setLanguageTag("fr");
|
||||
|
||||
const data = {
|
||||
navMain: [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -18,9 +18,9 @@
|
|||
<!-- If there are some posts, but the user scrolled to the end -->
|
||||
<Card v-if="hasReachedEnd && items.length > 0" class="shadow-none bg-transparent border-none p-4">
|
||||
<CardHeader class="text-center gap-y-4">
|
||||
<CardTitle class="text-">No more data.</CardTitle>
|
||||
<CardTitle>{{ m.steep_suave_fish_snap() }}</CardTitle>
|
||||
<CardDescription>
|
||||
You've scrolled so far, there's nothing left to show.
|
||||
{{ m.muddy_bland_shark_accept() }}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
|
|
@ -28,16 +28,16 @@
|
|||
<!-- If there are no posts at all -->
|
||||
<Card v-else-if="hasReachedEnd && items.length === 0" class="shadow-none bg-transparent border-none p-4">
|
||||
<CardHeader class="text-center gap-y-4">
|
||||
<CardTitle class="text-">There's nothing to show here.</CardTitle>
|
||||
<CardTitle>{{ m.fine_arable_lemming_fold() }}</CardTitle>
|
||||
<CardDescription>
|
||||
Either you're all caught up or there's nothing to show.
|
||||
{{ m.petty_honest_fish_stir() }}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
|
||||
<div v-else-if="!infiniteScroll.value" class="py-10 px-4">
|
||||
<Button variant="secondary" @click="loadNext" :disabled="isLoading" class="w-full">
|
||||
Load More
|
||||
{{ m.gaudy_bland_gorilla_talk() }}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
|
@ -55,6 +55,7 @@ import {
|
|||
CardHeader,
|
||||
CardTitle,
|
||||
} from "~/components/ui/card";
|
||||
import * as m from "~/paraglide/messages.js";
|
||||
import { SettingIds } from "~/settings";
|
||||
import { Button } from "../ui/button";
|
||||
import TimelineItem from "./timeline-item.vue";
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue