chore(i18n): update language files with new "load more" translations

This commit is contained in:
Fatih Kadir Akın
2025-12-18 13:23:02 +03:00
parent 9e6e138685
commit 88780b37c7
15 changed files with 35 additions and 8 deletions
+2 -1
View File
@@ -119,7 +119,8 @@
"privatePrompts": "الأوامر الخاصة",
"noPrompts": "لم يتم العثور على أوامر",
"noPromptsDescription": "حاول تعديل معايير البحث أو التصفية للعثور على ما تبحث عنه.",
"noMorePrompts": "وصلت إلى النهاية",
"noMorePrompts": "لقد وصلت إلى النهاية",
"loadMore": "تحميل المزيد",
"loading": "جاري التحميل...",
"promptTitle": "العنوان",
"promptContent": "المحتوى",
+1
View File
@@ -120,6 +120,7 @@
"noPrompts": "Keine Prompts gefunden",
"noPromptsDescription": "Versuchen Sie, Ihre Such- oder Filterkriterien anzupassen, um das Gesuchte zu finden.",
"noMorePrompts": "Sie haben das Ende erreicht",
"loadMore": "Mehr laden",
"loading": "Laden...",
"promptTitle": "Titel",
"promptContent": "Inhalt",
+1
View File
@@ -120,6 +120,7 @@
"noPrompts": "Δεν βρέθηκαν prompts",
"noPromptsDescription": "Δοκιμάστε να προσαρμόσετε την αναζήτηση ή τα φίλτρα σας.",
"noMorePrompts": "Φτάσατε στο τέλος",
"loadMore": "Φόρτωση περισσότερων",
"loading": "Φόρτωση...",
"promptTitle": "Τίτλος",
"promptContent": "Περιεχόμενο",
+1
View File
@@ -120,6 +120,7 @@
"noPrompts": "No prompts found",
"noPromptsDescription": "Try adjusting your search or filter criteria to find what you're looking for.",
"noMorePrompts": "You've reached the end",
"loadMore": "Load More",
"loading": "Loading...",
"promptTitle": "Title",
"promptContent": "Content",
+1
View File
@@ -151,6 +151,7 @@
"deletePromptDescription": "Esta acción no se puede deshacer. El prompt será eliminado permanentemente.",
"deleteError": "Error al eliminar el prompt",
"noMorePrompts": "Has llegado al final",
"loadMore": "Cargar más",
"loading": "Cargando...",
"types": {
"text": "Texto",
+1
View File
@@ -120,6 +120,7 @@
"noPrompts": "Aucun prompt trouvé",
"noPromptsDescription": "Essayez d'ajuster votre recherche ou vos critères de filtre pour trouver ce que vous cherchez.",
"noMorePrompts": "Vous avez atteint la fin",
"loadMore": "Charger plus",
"loading": "Chargement...",
"promptTitle": "Titre",
"promptContent": "Contenu",
+1
View File
@@ -120,6 +120,7 @@
"noPrompts": "לא נמצאו פרומפטים",
"noPromptsDescription": "נסה להתאים את החיפוש או הסינון שלך.",
"noMorePrompts": "הגעת לסוף",
"loadMore": "טען עוד",
"loading": "טוען...",
"promptTitle": "כותרת",
"promptContent": "תוכן",
+1
View File
@@ -120,6 +120,7 @@
"noPrompts": "Nessun prompt trovato",
"noPromptsDescription": "Prova a modificare i criteri di ricerca o filtro per trovare quello che cerchi.",
"noMorePrompts": "Hai raggiunto la fine",
"loadMore": "Carica altro",
"loading": "Caricamento...",
"promptTitle": "Titolo",
"promptContent": "Contenuto",
+2 -1
View File
@@ -150,7 +150,8 @@
"deletePromptTitle": "このプロンプトを削除しますか?",
"deletePromptDescription": "この操作は取り消せません。プロンプトは完全に削除されます。",
"deleteError": "プロンプトの削除に失敗しました",
"noMorePrompts": "最後まで表示しました",
"noMorePrompts": "すべて表示しました",
"loadMore": "もっと読み込む",
"loading": "読み込み中...",
"types": {
"text": "テキスト",
+2 -1
View File
@@ -119,7 +119,8 @@
"privatePrompts": "비공개 프롬프트",
"noPrompts": "프롬프트가 없습니다",
"noPromptsDescription": "원하는 것을 찾으려면 검색 또는 필터 조건을 조정해 보세요.",
"noMorePrompts": "마지막까지 확인했습니다",
"noMorePrompts": "끝에 도달했습니다",
"loadMore": "더 보기",
"loading": "로딩 중...",
"promptTitle": "제목",
"promptContent": "내용",
+1
View File
@@ -120,6 +120,7 @@
"noPrompts": "Nenhum prompt encontrado",
"noPromptsDescription": "Tente ajustar sua busca ou critérios de filtro para encontrar o que procura.",
"noMorePrompts": "Você chegou ao fim",
"loadMore": "Carregar mais",
"loading": "Carregando...",
"promptTitle": "Título",
"promptContent": "Conteúdo",
+1
View File
@@ -120,6 +120,7 @@
"noPrompts": "Промпты не найдены",
"noPromptsDescription": "Попробуйте изменить параметры поиска или фильтры.",
"noMorePrompts": "Вы достигли конца",
"loadMore": "Загрузить ещё",
"loading": "Загрузка...",
"promptTitle": "Заголовок",
"promptContent": "Содержимое",
+1
View File
@@ -120,6 +120,7 @@
"noPrompts": "Prompt bulunamadı",
"noPromptsDescription": "Aradığınızı bulmak için arama veya filtre kriterlerinizi değiştirmeyi deneyin.",
"noMorePrompts": "Sona ulaştınız",
"loadMore": "Daha Fazla Yükle",
"loading": "Yükleniyor...",
"promptTitle": "Başlık",
"promptContent": "İçerik",
+2 -1
View File
@@ -150,7 +150,8 @@
"deletePromptTitle": "删除此提示词?",
"deletePromptDescription": "此操作无法撤销。提示词将被永久删除。",
"deleteError": "删除提示词失败",
"noMorePrompts": "已到达末尾",
"noMorePrompts": "已经到底了",
"loadMore": "加载更多",
"loading": "加载中...",
"types": {
"text": "文本",
@@ -3,8 +3,9 @@
import { useEffect, useRef, useState, useCallback } from "react";
import { useSearchParams } from "next/navigation";
import { useTranslations } from "next-intl";
import { Loader2, SearchX } from "lucide-react";
import { Loader2, SearchX, RefreshCw } from "lucide-react";
import { Skeleton } from "@/components/ui/skeleton";
import { Button } from "@/components/ui/button";
import { useFilterContext } from "./filter-context";
import { PromptCard, type PromptCardProps } from "./prompt-card";
@@ -54,6 +55,7 @@ export function InfinitePromptList({
const [page, setPage] = useState(1);
const [isLoading, setIsLoading] = useState(false);
const [hasMore, setHasMore] = useState(initialPrompts.length < initialTotal);
const [hasError, setHasError] = useState(false);
const loaderRef = useRef<HTMLDivElement>(null);
const abortControllerRef = useRef<AbortController | null>(null);
@@ -67,6 +69,7 @@ export function InfinitePromptList({
setPrompts(initialPrompts);
setPage(1);
setHasMore(initialPrompts.length < initialTotal);
setHasError(false);
setFilterPending(false);
}, [initialPrompts, initialTotal, setFilterPending]);
@@ -82,6 +85,7 @@ export function InfinitePromptList({
abortControllerRef.current = controller;
setIsLoading(true);
setHasError(false);
try {
const nextPage = page + 1;
const params = new URLSearchParams();
@@ -115,6 +119,7 @@ export function InfinitePromptList({
return;
}
console.error("Failed to load more prompts:", error);
setHasError(true);
} finally {
// Only clear loading if this controller is still active
if (abortControllerRef.current === controller) {
@@ -123,8 +128,10 @@ export function InfinitePromptList({
}
}, [isLoading, hasMore, page, filters]);
// Intersection Observer for infinite scroll
// Intersection Observer for infinite scroll (disabled if there was an error)
useEffect(() => {
if (hasError) return;
const observer = new IntersectionObserver(
(entries) => {
if (entries[0].isIntersecting && hasMore && !isLoading) {
@@ -139,7 +146,7 @@ export function InfinitePromptList({
}
return () => observer.disconnect();
}, [loadMore, hasMore, isLoading]);
}, [loadMore, hasMore, isLoading, hasError]);
// Cleanup abort controller on unmount
useEffect(() => {
@@ -183,7 +190,7 @@ export function InfinitePromptList({
))}
</div>
{/* Loader / End indicator */}
{/* Loader / End indicator / Error state */}
<div ref={loaderRef} className="flex items-center justify-center py-4">
{isLoading && (
<div className="flex items-center gap-2 text-sm text-muted-foreground">
@@ -191,6 +198,12 @@ export function InfinitePromptList({
{t("loading")}
</div>
)}
{!isLoading && hasError && hasMore && (
<Button variant="outline" size="sm" onClick={loadMore}>
<RefreshCw className="h-4 w-4 mr-2" />
{t("loadMore")}
</Button>
)}
{!hasMore && prompts.length > 0 && (
<p className="text-xs text-muted-foreground">{t("noMorePrompts")}</p>
)}