diff --git a/app/sign-in/page.tsx b/app/sign-in/page.tsx
index 13ecc9d3..023c9274 100644
--- a/app/sign-in/page.tsx
+++ b/app/sign-in/page.tsx
@@ -5,6 +5,7 @@ import { clsx } from 'clsx/lite';
import { redirect } from 'next/navigation';
import LinkWithStatus from '@/components/LinkWithStatus';
import { IoArrowBack } from 'react-icons/io5';
+import { APP_TEXT } from '@/app/config';
export default async function SignInPage() {
const session = await auth();
@@ -27,7 +28,7 @@ export default async function SignInPage() {
)}
>
- Home
+ {APP_TEXT.nav.home}
);
diff --git a/src/admin/SignInOrUploadClient.tsx b/src/admin/SignInOrUploadClient.tsx
index d6a04e31..16bc16c2 100644
--- a/src/admin/SignInOrUploadClient.tsx
+++ b/src/admin/SignInOrUploadClient.tsx
@@ -4,6 +4,7 @@ import { useAppState } from '@/state/AppState';
import SignInForm from '@/auth/SignInForm';
import clsx from 'clsx/lite';
import PhotoUploadWithStatus from '@/photo/PhotoUploadWithStatus';
+import { APP_TEXT } from '@/app/config';
export default function SignInOrUploadClient({
shouldResize,
@@ -21,10 +22,10 @@ export default function SignInOrUploadClient({
)}>
{isCheckingAuth
- ? 'Loading ...'
+ ? APP_TEXT.misc.loading
: isUserSignedIn
- ? 'Add your first photo'
- : 'Sign in to upload photos'}
+ ? APP_TEXT.onboarding.setupFirstPhoto
+ : APP_TEXT.onboarding.setupSignIn}
{!isCheckingAuth && isUserSignedIn === false &&
diff --git a/src/camera/CameraOGTile.tsx b/src/camera/CameraOGTile.tsx
index 5e74795f..1c67e989 100644
--- a/src/camera/CameraOGTile.tsx
+++ b/src/camera/CameraOGTile.tsx
@@ -1,11 +1,9 @@
import { Photo, PhotoDateRange } from '@/photo';
import { absolutePathForCameraImage, pathForCamera } from '@/app/paths';
-import OGTile from '@/components/OGTile';
+import OGTile, { OGLoadingState } from '@/components/OGTile';
import { Camera } from '.';
import { descriptionForCameraPhotos, titleForCamera } from './meta';
-export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed';
-
export default function CameraOGTile({
camera,
photos,
diff --git a/src/camera/meta.ts b/src/camera/meta.ts
index 7d8bcaa9..9d7b3ce8 100644
--- a/src/camera/meta.ts
+++ b/src/camera/meta.ts
@@ -20,7 +20,7 @@ export const titleForCamera = (
photos: Photo[],
explicitCount?: number,
) => [
- APP_TEXT.category.cameraShare(
+ APP_TEXT.category.cameraTitle(
formatCameraText(cameraFromPhoto(photos[0], camera)),
),
photoQuantityText(explicitCount ?? photos.length),
diff --git a/src/components/useNavigateOrRunActionWithToast.tsx b/src/components/useNavigateOrRunActionWithToast.tsx
index 9a727630..260e71a2 100644
--- a/src/components/useNavigateOrRunActionWithToast.tsx
+++ b/src/components/useNavigateOrRunActionWithToast.tsx
@@ -1,3 +1,4 @@
+import { APP_TEXT } from '@/app/config';
import { toastWaiting } from '@/toast';
import { useRouter } from 'next/navigation';
import { useCallback, useEffect, useRef, useTransition } from 'react';
@@ -6,7 +7,7 @@ import { toast } from 'sonner';
export default function useNavigateOrRunActionWithToast({
pathOrAction,
- toastMessage = 'Loading...',
+ toastMessage = APP_TEXT.misc.loading,
dismissDelay = 1500,
}: {
pathOrAction?: string | (() => Promise
| undefined)
diff --git a/src/film/FilmOGTile.tsx b/src/film/FilmOGTile.tsx
index 399f7d08..b0db04b8 100644
--- a/src/film/FilmOGTile.tsx
+++ b/src/film/FilmOGTile.tsx
@@ -3,11 +3,9 @@ import {
absolutePathForFilmImage,
pathForFilm,
} from '@/app/paths';
-import OGTile from '@/components/OGTile';
+import OGTile, { OGLoadingState } from '@/components/OGTile';
import { descriptionForFilmPhotos, titleForFilm } from '.';
-export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed';
-
export default function FilmOGTile({
film,
photos,
diff --git a/src/focal/FocalLengthOGTile.tsx b/src/focal/FocalLengthOGTile.tsx
index 6262bd31..c3ebd695 100644
--- a/src/focal/FocalLengthOGTile.tsx
+++ b/src/focal/FocalLengthOGTile.tsx
@@ -3,11 +3,9 @@ import {
absolutePathForFocalLengthImage,
pathForFocalLength,
} from '@/app/paths';
-import OGTile from '@/components/OGTile';
+import OGTile, { OGLoadingState } from '@/components/OGTile';
import { descriptionForFocalLengthPhotos, titleForFocalLength } from '.';
-export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed';
-
export default function FocalLengthOGTile({
focal,
photos,
diff --git a/src/i18n/locales/pt-br.ts b/src/i18n/locales/pt-br.ts
index 77772584..cc645f83 100644
--- a/src/i18n/locales/pt-br.ts
+++ b/src/i18n/locales/pt-br.ts
@@ -57,7 +57,7 @@ const TEXT: I18NDeepPartial = {
},
theme: {
theme: 'Tema',
- system: 'Usar Sistema',
+ system: 'Sistema',
light: 'Modo Claro',
dark: 'Modo Escuro',
},
@@ -93,7 +93,18 @@ const TEXT: I18NDeepPartial = {
deleteConfirm: (photoTitle: string) =>
`Tem certeza que deseja excluir "${photoTitle}"?`,
},
+ onboarding: {
+ setupComplete: 'Configuração Concluída!',
+ setupIncomplete: 'Finalizar Configuração',
+ setupSignIn: 'Entre para enviar fotos',
+ setupFirstPhoto: 'Adicione sua primeira foto',
+ // eslint-disable-next-line max-len
+ setupConfig: 'Altere o nome do site e outras configurações editando as variáveis de ambiente referenciadas em',
+ },
misc: {
+ loading: 'Carregando ...',
+ finishing: 'Finalizando ...',
+ uploading: 'Enviando',
repo: 'Feito com',
copyPhrase: (label: string) => `${label} copiado`,
},
diff --git a/src/i18n/locales/us-en.ts b/src/i18n/locales/us-en.ts
index 0182bfe5..7b57b67e 100644
--- a/src/i18n/locales/us-en.ts
+++ b/src/i18n/locales/us-en.ts
@@ -56,7 +56,7 @@ const TEXT = {
},
theme: {
theme: 'Theme',
- system: 'Use System',
+ system: 'System',
light: 'Light Mode',
dark: 'Dark Mode',
},
@@ -92,7 +92,18 @@ const TEXT = {
deleteConfirm: (photoTitle: string) =>
`Are you sure you want to delete "${photoTitle}?"`,
},
+ onboarding: {
+ setupComplete: 'Setup Complete!',
+ setupIncomplete: 'Finish Setup',
+ setupSignIn: 'Sign in to upload photos',
+ setupFirstPhoto: 'Add your first photo',
+ // eslint-disable-next-line max-len
+ setupConfig: 'Change the site name and other configuration by editing environment variables referenced in',
+ },
misc: {
+ loading: 'Loading ...',
+ finishing: 'Finishing ...',
+ uploading: 'Uploading',
repo: 'Made with',
copyPhrase: (label: string) => `${label} copied`,
},
diff --git a/src/lens/LensOGTile.tsx b/src/lens/LensOGTile.tsx
index cf6e7263..ba286f4a 100644
--- a/src/lens/LensOGTile.tsx
+++ b/src/lens/LensOGTile.tsx
@@ -1,11 +1,9 @@
import { Photo, PhotoDateRange } from '@/photo';
import { absolutePathForLensImage, pathForLens } from '@/app/paths';
-import OGTile from '@/components/OGTile';
+import OGTile, { OGLoadingState } from '@/components/OGTile';
import { Lens } from '.';
import { titleForLens, descriptionForLensPhotos } from './meta';
-export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed';
-
export default function LensOGTile({
lens,
photos,
diff --git a/src/photo/PhotoOGTile.tsx b/src/photo/PhotoOGTile.tsx
index aa4e2803..3bc60dfa 100644
--- a/src/photo/PhotoOGTile.tsx
+++ b/src/photo/PhotoOGTile.tsx
@@ -5,9 +5,7 @@ import {
} from '@/photo';
import { PhotoSetCategory } from '../category';
import { absolutePathForPhotoImage, pathForPhoto } from '@/app/paths';
-import OGTile from '@/components/OGTile';
-
-export type OGLoadingState = 'unloaded' | 'loading' | 'loaded' | 'failed';
+import OGTile, { OGLoadingState } from '@/components/OGTile';
export default function PhotoOGTile({
photo,
diff --git a/src/photo/PhotoUploadWithStatus.tsx b/src/photo/PhotoUploadWithStatus.tsx
index 9f6cdc69..405e116d 100644
--- a/src/photo/PhotoUploadWithStatus.tsx
+++ b/src/photo/PhotoUploadWithStatus.tsx
@@ -11,6 +11,7 @@ import { useRef } from 'react';
import { useEffect } from 'react';
import Spinner from '@/components/Spinner';
import ResponsiveText from '@/components/primitives/ResponsiveText';
+import { APP_TEXT } from '@/app/config';
export default function PhotoUploadWithStatus({
inputRef,
@@ -72,10 +73,11 @@ export default function PhotoUploadWithStatus({
}
};
}, [resetUploadState]);
+
const isFinishing = isPending && shouldResetUploadStateAfterPending.current;
const uploadStatusText = filesLength > 1
- ? `${fileUploadIndex + 1} of ${filesLength}`
+ ? APP_TEXT.utility.paginate(fileUploadIndex + 1, filesLength)
: undefined;
return (
@@ -158,19 +160,19 @@ export default function PhotoUploadWithStatus({
{isUploading
? isFinishing
? <>
- Finishing ...
+ {APP_TEXT.misc.finishing}
>
: <>
{!showButton && uploadStatusText
? <>
- Uploading {uploadStatusText}
+ {APP_TEXT.misc.uploading} {uploadStatusText}
{': '}
{fileUploadName}
>
:
- Uploading {fileUploadName}
+ {APP_TEXT.misc.uploading} {fileUploadName}
}
>
: !showButton && <>Initializing>}
diff --git a/src/photo/PhotosEmptyState.tsx b/src/photo/PhotosEmptyState.tsx
index 69a931df..3365b776 100644
--- a/src/photo/PhotosEmptyState.tsx
+++ b/src/photo/PhotosEmptyState.tsx
@@ -1,6 +1,10 @@
import Container from '@/components/Container';
import AppGrid from '@/components/AppGrid';
-import { IS_SITE_READY, PRESERVE_ORIGINAL_UPLOADS } from '@/app/config';
+import {
+ APP_TEXT,
+ IS_SITE_READY,
+ PRESERVE_ORIGINAL_UPLOADS,
+} from '@/app/config';
import AdminAppConfiguration from '@/admin/AdminAppConfiguration';
import { clsx } from 'clsx/lite';
import { HiOutlinePhotograph } from 'react-icons/hi';
@@ -29,7 +33,9 @@ export default function PhotosEmptyState() {
'font-bold text-2xl',
'text-gray-700 dark:text-gray-200',
)}>
- {!IS_SITE_READY ? 'Finish Setup' : 'Setup Complete!'}
+ {!IS_SITE_READY
+ ? APP_TEXT.onboarding.setupIncomplete
+ : APP_TEXT.onboarding.setupComplete}
{!IS_SITE_READY
?
@@ -43,8 +49,7 @@ export default function PhotosEmptyState() {
}}
/>
- Change this site's name and other configuration
- by editing environment variables referenced in
+ {APP_TEXT.onboarding.setupConfig}
{' '}