refactor: 🌐 Internationalize every string

This commit is contained in:
Jesse Wierzbinski 2024-12-07 22:17:22 +01:00
parent 8c3ddc2a28
commit 2ceee4827f
No known key found for this signature in database
41 changed files with 932 additions and 428 deletions

View file

@ -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>

View file

@ -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>

View file

@ -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>

View file

@ -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 || "";

View file

@ -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,

View file

@ -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";

View file

@ -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;

View file

@ -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>

View file

@ -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 "";
}

View file

@ -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">

View file

@ -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>

View file

@ -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">

View file

@ -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: [
{

View file

@ -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";