mirror of
https://github.com/Sonny93/my-links.git
synced 2025-12-09 07:03:25 +00:00
feat: use existing translation on all pages
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
import { PREFER_DARK_THEME } from '#constants/session';
|
||||
import {
|
||||
DARK_THEME_DEFAULT_VALUE,
|
||||
PREFER_DARK_THEME,
|
||||
} from '#constants/session';
|
||||
import { defineConfig } from '@adonisjs/inertia';
|
||||
|
||||
export default defineConfig({
|
||||
@@ -12,7 +15,8 @@ export default defineConfig({
|
||||
*/
|
||||
sharedData: {
|
||||
errors: (ctx) => ctx.session?.flashMessages.get('errors'),
|
||||
preferDarkTheme: (ctx) => ctx.session?.get(PREFER_DARK_THEME, true),
|
||||
preferDarkTheme: (ctx) =>
|
||||
ctx.session?.get(PREFER_DARK_THEME, DARK_THEME_DEFAULT_VALUE),
|
||||
auth: async (ctx) => {
|
||||
await ctx.auth?.check();
|
||||
return {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import type Collection from '#models/collection';
|
||||
import { route } from '@izzyjs/route/client';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { BsThreeDotsVertical } from 'react-icons/bs';
|
||||
import { GoPencil } from 'react-icons/go';
|
||||
import { IoIosAddCircleOutline } from 'react-icons/io';
|
||||
@@ -8,30 +9,34 @@ import Dropdown from '~/components/common/dropdown/dropdown';
|
||||
import { DropdownItemLink } from '~/components/common/dropdown/dropdown_item';
|
||||
import { appendCollectionId } from '~/lib/navigation';
|
||||
|
||||
const CollectionControls = ({
|
||||
export default function CollectionControls({
|
||||
collectionId,
|
||||
}: {
|
||||
collectionId: Collection['id'];
|
||||
}) => (
|
||||
<Dropdown label={<BsThreeDotsVertical />} svgSize={18}>
|
||||
<DropdownItemLink href={route('link.create-form').url}>
|
||||
<IoIosAddCircleOutline /> Add
|
||||
</DropdownItemLink>
|
||||
<DropdownItemLink
|
||||
href={appendCollectionId(route('collection.edit-form').url, collectionId)}
|
||||
>
|
||||
<GoPencil /> Edit
|
||||
</DropdownItemLink>
|
||||
<DropdownItemLink
|
||||
href={appendCollectionId(
|
||||
route('collection.delete-form').url,
|
||||
collectionId
|
||||
)}
|
||||
danger
|
||||
>
|
||||
<IoTrashOutline /> Delete
|
||||
</DropdownItemLink>
|
||||
</Dropdown>
|
||||
);
|
||||
|
||||
export default CollectionControls;
|
||||
}) {
|
||||
const { t } = useTranslation('common');
|
||||
return (
|
||||
<Dropdown label={<BsThreeDotsVertical />} svgSize={18}>
|
||||
<DropdownItemLink href={route('link.create-form').url}>
|
||||
<IoIosAddCircleOutline /> {t('link.create')}
|
||||
</DropdownItemLink>
|
||||
<DropdownItemLink
|
||||
href={appendCollectionId(
|
||||
route('collection.edit-form').url,
|
||||
collectionId
|
||||
)}
|
||||
>
|
||||
<GoPencil /> {t('collection.edit')}
|
||||
</DropdownItemLink>
|
||||
<DropdownItemLink
|
||||
href={appendCollectionId(
|
||||
route('collection.delete-form').url,
|
||||
collectionId
|
||||
)}
|
||||
danger
|
||||
>
|
||||
<IoTrashOutline /> {t('collection.delete')}
|
||||
</DropdownItemLink>
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import CollectionItem from '~/components/dashboard/collection/list/collection_item';
|
||||
import CollectionListContainer from '~/components/dashboard/collection/list/collection_list_container';
|
||||
import useActiveCollection from '~/hooks/use_active_collection';
|
||||
@@ -17,7 +18,10 @@ const SideMenu = styled.nav(({ theme }) => ({
|
||||
|
||||
const CollectionLabel = styled.p(({ theme }) => ({
|
||||
color: theme.colors.grey,
|
||||
marginBlock: '0.35em',
|
||||
paddingInline: '15px',
|
||||
}));
|
||||
|
||||
const CollectionListStyle = styled.div({
|
||||
padding: '1px',
|
||||
paddingRight: '5px',
|
||||
@@ -29,6 +33,7 @@ const CollectionListStyle = styled.div({
|
||||
});
|
||||
|
||||
export default function CollectionList() {
|
||||
const { t } = useTranslation('common');
|
||||
const { collections } = useCollections();
|
||||
const { activeCollection, setActiveCollection } = useActiveCollection();
|
||||
|
||||
@@ -60,7 +65,10 @@ export default function CollectionList() {
|
||||
return (
|
||||
<SideMenu>
|
||||
<CollectionListContainer>
|
||||
<CollectionLabel>Collections • {collections.length}</CollectionLabel>
|
||||
<CollectionLabel>
|
||||
{t('collection.collections', { count: collections.length })} •{' '}
|
||||
{collections.length}
|
||||
</CollectionLabel>
|
||||
<CollectionListStyle>
|
||||
{collections.map((collection) => (
|
||||
<CollectionItem collection={collection} key={collection.id} />
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { route } from '@izzyjs/route/client';
|
||||
import { useCallback } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AiFillStar, AiOutlineStar } from 'react-icons/ai';
|
||||
import { BsThreeDotsVertical } from 'react-icons/bs';
|
||||
import { GoPencil } from 'react-icons/go';
|
||||
@@ -22,6 +23,7 @@ const StartItem = styled(DropdownItemButton)(({ theme }) => ({
|
||||
|
||||
export default function LinkControls({ link }: { link: Link }) {
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation('common');
|
||||
const { collections, setCollections } = useCollections();
|
||||
|
||||
const toggleFavorite = useCallback(
|
||||
@@ -74,11 +76,11 @@ export default function LinkControls({ link }: { link: Link }) {
|
||||
<StartItem onClick={onFavorite}>
|
||||
{!link.favorite ? (
|
||||
<>
|
||||
<AiFillStar /> Add to favorites
|
||||
<AiFillStar /> {t('add-favorite')}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<AiOutlineStar /> Remove from favorites
|
||||
<AiOutlineStar /> {t('remove-favorite')}
|
||||
</>
|
||||
)}
|
||||
</StartItem>
|
||||
@@ -88,7 +90,7 @@ export default function LinkControls({ link }: { link: Link }) {
|
||||
link.collectionId
|
||||
)}
|
||||
>
|
||||
<GoPencil /> Edit
|
||||
<GoPencil /> {t('link.edit')}
|
||||
</DropdownItemLink>
|
||||
<DropdownItemLink
|
||||
href={appendCollectionId(
|
||||
@@ -97,7 +99,7 @@ export default function LinkControls({ link }: { link: Link }) {
|
||||
)}
|
||||
danger
|
||||
>
|
||||
<IoTrashOutline /> Delete
|
||||
<IoTrashOutline /> {t('link.delete')}
|
||||
</DropdownItemLink>
|
||||
</Dropdown>
|
||||
);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import TextEllipsis from '~/components/common/text_ellipsis';
|
||||
import LinkFavicon from '~/components/dashboard/link/link_favicon';
|
||||
import FavoriteListContainer from '~/components/dashboard/side_nav/favorite/favorite_container';
|
||||
@@ -7,13 +8,18 @@ import useFavorites from '~/hooks/use_favorites';
|
||||
|
||||
const FavoriteLabel = styled.p(({ theme }) => ({
|
||||
color: theme.colors.grey,
|
||||
marginBlock: '0.35em',
|
||||
paddingInline: '15px',
|
||||
}));
|
||||
|
||||
const NoFavorite = () => (
|
||||
<FavoriteLabel css={{ textAlign: 'center' }}>
|
||||
Your favorites will appear here
|
||||
</FavoriteLabel>
|
||||
);
|
||||
const NoFavorite = () => {
|
||||
const { t } = useTranslation('common');
|
||||
return (
|
||||
<FavoriteLabel css={{ textAlign: 'center' }}>
|
||||
{t('favorites-appears-here')}
|
||||
</FavoriteLabel>
|
||||
);
|
||||
};
|
||||
|
||||
const FavoriteListStyle = styled.div({
|
||||
padding: '1px',
|
||||
@@ -26,6 +32,7 @@ const FavoriteListStyle = styled.div({
|
||||
});
|
||||
|
||||
export default function FavoriteList() {
|
||||
const { t } = useTranslation('common');
|
||||
const { favorites } = useFavorites();
|
||||
if (favorites.length === 0) {
|
||||
return <NoFavorite key="no-favorite" />;
|
||||
@@ -33,8 +40,8 @@ export default function FavoriteList() {
|
||||
|
||||
return (
|
||||
<FavoriteListContainer>
|
||||
<FavoriteLabel css={{ marginBlock: '0.35em', paddingInline: '15px' }}>
|
||||
Favorites • {favorites.length}
|
||||
<FavoriteLabel>
|
||||
{t('favorite')} • {favorites.length}
|
||||
</FavoriteLabel>
|
||||
<FavoriteListStyle>
|
||||
{favorites.map(({ id, name, url }) => (
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { route } from '@izzyjs/route/client';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AiOutlineFolderAdd } from 'react-icons/ai';
|
||||
import { IoAdd } from 'react-icons/io5';
|
||||
import { MdOutlineAdminPanelSettings } from 'react-icons/md';
|
||||
@@ -30,13 +31,14 @@ const AddButton = styled(ItemLink)(({ theme }) => ({
|
||||
}));
|
||||
|
||||
export default function SideNavigation() {
|
||||
const { t } = useTranslation('common');
|
||||
const { activeCollection } = useActiveCollection();
|
||||
return (
|
||||
<SideMenu>
|
||||
<div css={{ paddingInline: '10px' }}>
|
||||
<UserCard />
|
||||
<AdminButton>
|
||||
<MdOutlineAdminPanelSettings /> Administrator
|
||||
<MdOutlineAdminPanelSettings /> {t('admin')}
|
||||
</AdminButton>
|
||||
<ModalSettings openItem={SettingsButton} />
|
||||
<AddButton
|
||||
@@ -45,10 +47,10 @@ export default function SideNavigation() {
|
||||
activeCollection?.id
|
||||
)}
|
||||
>
|
||||
<IoAdd /> Create link
|
||||
<IoAdd /> {t('link.create')}
|
||||
</AddButton>
|
||||
<AddButton href={route('collection.create-form').url}>
|
||||
<AiOutlineFolderAdd /> Create collection
|
||||
<AiOutlineFolderAdd /> {t('collection.create')}
|
||||
</AddButton>
|
||||
</div>
|
||||
<FavoriteList />
|
||||
|
||||
@@ -4,6 +4,7 @@ import TextBox from '~/components/common/form/textbox';
|
||||
import BackToDashboard from '~/components/common/navigation/back_to_dashboard';
|
||||
import FormLayout from '~/components/layouts/form_layout';
|
||||
import { Visibility } from '../../../app/enums/visibility';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export type FormCollectionData = {
|
||||
name: string;
|
||||
@@ -30,6 +31,7 @@ export default function FormCollection({
|
||||
setData: (name: string, value: string) => void;
|
||||
handleSubmit: () => void;
|
||||
}) {
|
||||
const { t } = useTranslation('common');
|
||||
const handleOnCheck = ({ target }: ChangeEvent<HTMLInputElement>) =>
|
||||
setData(
|
||||
'visibility',
|
||||
@@ -50,8 +52,8 @@ export default function FormCollection({
|
||||
>
|
||||
<BackToDashboard>
|
||||
<TextBox
|
||||
label="Collection name"
|
||||
placeholder="Collection name"
|
||||
label={t('collection.name')}
|
||||
placeholder={t('collection.name')}
|
||||
name="name"
|
||||
onChange={setData}
|
||||
value={data.name}
|
||||
@@ -60,8 +62,8 @@ export default function FormCollection({
|
||||
autoFocus
|
||||
/>
|
||||
<TextBox
|
||||
label="Collection description"
|
||||
placeholder="Collection description"
|
||||
label={t('collection.name')}
|
||||
placeholder={t('collection.name')}
|
||||
name="description"
|
||||
onChange={setData}
|
||||
value={data.description ?? undefined}
|
||||
|
||||
28
inertia/components/lang_selector.tsx
Normal file
28
inertia/components/lang_selector.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { ChangeEvent } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { LS_LANG_KEY } from '~/constants';
|
||||
import { languages } from '~/i18n';
|
||||
|
||||
export default function LangSelector() {
|
||||
const { t, i18n } = useTranslation('common');
|
||||
|
||||
const onToggleLanguageClick = ({
|
||||
target,
|
||||
}: ChangeEvent<HTMLSelectElement>) => {
|
||||
i18n.changeLanguage(target.value);
|
||||
localStorage.setItem(LS_LANG_KEY, target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
<select
|
||||
onChange={onToggleLanguageClick}
|
||||
name="lang-selector"
|
||||
id="lang-selector"
|
||||
defaultValue={i18n.language}
|
||||
>
|
||||
{languages.map((lang) => (
|
||||
<option value={lang}>{t(`language.${lang}`)}</option>
|
||||
))}
|
||||
</select>
|
||||
);
|
||||
}
|
||||
@@ -1,13 +1,16 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { Link } from '@inertiajs/react';
|
||||
import { Head, Link } from '@inertiajs/react';
|
||||
import { route } from '@izzyjs/route/client';
|
||||
import { FormEvent, ReactNode } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import Button from '~/components/common/form/_button';
|
||||
import Form from '~/components/common/form/_form';
|
||||
import TransitionLayout from '~/components/layouts/_transition_layout';
|
||||
import i18n from '~/i18n';
|
||||
import { appendCollectionId } from '~/lib/navigation';
|
||||
import BaseLayout from './_base_layout';
|
||||
|
||||
const FormLayoutStyle = styled.div(({ theme }) => ({
|
||||
const FormLayoutStyle = styled(TransitionLayout)(({ theme }) => ({
|
||||
height: 'fit-content',
|
||||
width: theme.media.mobile,
|
||||
maxWidth: '100%',
|
||||
@@ -30,31 +33,33 @@ interface FormLayoutProps {
|
||||
collectionId?: string;
|
||||
}
|
||||
|
||||
const FormLayout = ({
|
||||
export default function FormLayout({
|
||||
title,
|
||||
children,
|
||||
canSubmit,
|
||||
handleSubmit,
|
||||
textSubmitButton = 'Confirm',
|
||||
textSubmitButton = i18n.t('common:confirm'),
|
||||
disableHomeLink = false,
|
||||
collectionId,
|
||||
}: FormLayoutProps) => (
|
||||
<BaseLayout>
|
||||
<FormLayoutStyle>
|
||||
<h2>{title}</h2>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
{children}
|
||||
<Button type="submit" disabled={!canSubmit}>
|
||||
{textSubmitButton}
|
||||
</Button>
|
||||
</Form>
|
||||
{!disableHomeLink && (
|
||||
<Link href={appendCollectionId(route('dashboard').url, collectionId)}>
|
||||
← Back to home
|
||||
</Link>
|
||||
)}
|
||||
</FormLayoutStyle>
|
||||
</BaseLayout>
|
||||
);
|
||||
|
||||
export default FormLayout;
|
||||
}: FormLayoutProps) {
|
||||
const { t } = useTranslation('common');
|
||||
return (
|
||||
<BaseLayout>
|
||||
<FormLayoutStyle>
|
||||
<Head title={title} />
|
||||
<h2>{title}</h2>
|
||||
<Form onSubmit={handleSubmit}>
|
||||
{children}
|
||||
<Button type="submit" disabled={!canSubmit}>
|
||||
{textSubmitButton}
|
||||
</Button>
|
||||
</Form>
|
||||
{!disableHomeLink && (
|
||||
<Link href={appendCollectionId(route('dashboard').url, collectionId)}>
|
||||
{t('back-home')}
|
||||
</Link>
|
||||
)}
|
||||
</FormLayoutStyle>
|
||||
</BaseLayout>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import styled from '@emotion/styled';
|
||||
import { Link } from '@inertiajs/react';
|
||||
import { route } from '@izzyjs/route/client';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { IoIosLogOut } from 'react-icons/io';
|
||||
import Dropdown from '~/components/common/dropdown/dropdown';
|
||||
import {
|
||||
@@ -49,7 +50,9 @@ const UserCard = styled.div({
|
||||
});
|
||||
|
||||
export default function Navbar() {
|
||||
const { t } = useTranslation('common');
|
||||
const { isAuthenticated, user } = useUser();
|
||||
|
||||
return (
|
||||
<Nav>
|
||||
<NavList>
|
||||
@@ -73,9 +76,14 @@ export default function Navbar() {
|
||||
</li>
|
||||
</>
|
||||
) : (
|
||||
<li>
|
||||
<Link href={route('auth.login').url}>Login</Link>
|
||||
</li>
|
||||
<>
|
||||
<li>
|
||||
<ModalSettings openItem={DropdownItemButton} />
|
||||
</li>
|
||||
<li>
|
||||
<Link href={route('auth.login').url}>{t('login')}</Link>
|
||||
</li>
|
||||
</>
|
||||
)}
|
||||
</NavList>
|
||||
</Nav>
|
||||
@@ -83,7 +91,9 @@ export default function Navbar() {
|
||||
}
|
||||
|
||||
function ProfileDropdown() {
|
||||
const { t } = useTranslation('common');
|
||||
const { user } = useUser();
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
label={
|
||||
@@ -99,7 +109,7 @@ function ProfileDropdown() {
|
||||
>
|
||||
<ModalSettings openItem={DropdownItemButton} />
|
||||
<DropdownItemLink href={route('auth.logout').url} danger>
|
||||
<IoIosLogOut /> Logout
|
||||
<IoIosLogOut /> {t('logout')}
|
||||
</DropdownItemLink>
|
||||
</Dropdown>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { BsGear } from 'react-icons/bs';
|
||||
import Modal from '~/components/common/modal/modal';
|
||||
import LangSelector from '~/components/lang_selector';
|
||||
import ThemeSwitcher from '~/components/theme_switcher';
|
||||
import useToggle from '~/hooks/use_modal';
|
||||
|
||||
@@ -9,19 +11,16 @@ export default function ModalSettings({
|
||||
// TODO: fix this :()
|
||||
openItem: any;
|
||||
}) {
|
||||
const { t } = useTranslation('common');
|
||||
const { isShowing, open, close } = useToggle();
|
||||
return (
|
||||
<>
|
||||
<OpenItem onClick={open}>
|
||||
<BsGear />
|
||||
Settings
|
||||
{t('settings')}
|
||||
</OpenItem>
|
||||
<Modal title="Settings" opened={isShowing} close={close}>
|
||||
Modal settings
|
||||
<hr />
|
||||
<select>
|
||||
<option>EN</option>
|
||||
</select>
|
||||
<Modal title={t('settings')} opened={isShowing} close={close}>
|
||||
<LangSelector />
|
||||
<hr />
|
||||
<ThemeSwitcher />
|
||||
</Modal>
|
||||
|
||||
1
inertia/constants/index.ts
Normal file
1
inertia/constants/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export const LS_LANG_KEY = 'language';
|
||||
@@ -12,6 +12,7 @@ import frResourceLogin from './locales/fr/login.json';
|
||||
import frResourcePrivacy from './locales/fr/privacy.json';
|
||||
import frResourceTerms from './locales/fr/terms.json';
|
||||
|
||||
import { LS_LANG_KEY } from '~/constants';
|
||||
import enResourceAbout from './locales/en/about.json';
|
||||
import enResourceAdmin from './locales/en/admin.json';
|
||||
import enResourceCommon from './locales/en/common.json';
|
||||
@@ -51,9 +52,16 @@ export const resources = {
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const languages = ['en', 'fr'] as const;
|
||||
|
||||
const lng =
|
||||
typeof window !== 'undefined'
|
||||
? localStorage.getItem(LS_LANG_KEY) || undefined
|
||||
: undefined;
|
||||
i18n.use(initReactI18next).init({
|
||||
returnNull: false,
|
||||
resources,
|
||||
lng,
|
||||
fallbackLng: 'en',
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"slogan": "Manage your links in the best possible way",
|
||||
"confirm": "Confirm",
|
||||
"cancel": "Cancel",
|
||||
"back-home": "← Back to home page",
|
||||
"back-home": "← Back to home",
|
||||
"logout": "Logout",
|
||||
"login": "Login",
|
||||
"link": {
|
||||
@@ -12,25 +12,29 @@
|
||||
"description": "Link description",
|
||||
"create": "Create a link",
|
||||
"edit": "Edit a link",
|
||||
"remove": "Delete a link",
|
||||
"remove-confirm": "Confirm deletion?"
|
||||
"delete": "Delete a link",
|
||||
"delete-confirm": "Confirm deletion?"
|
||||
},
|
||||
"collection": {
|
||||
"collections": "Collections",
|
||||
"collection": "Collection",
|
||||
"collections": "Collection",
|
||||
"collections_other": "Collections",
|
||||
"name": "Collection name",
|
||||
"description": "Collection description",
|
||||
"no-description": "No description",
|
||||
"visibility": "Public",
|
||||
"create": "Create a collection",
|
||||
"edit": "Edit a collection",
|
||||
"remove": "Delete a collection",
|
||||
"remove-confirm": "Confirm deletion?",
|
||||
"remove-description": "You must delete all links in this collection before you can delete this collection."
|
||||
"delete": "Delete a collection",
|
||||
"delete-confirm": "Confirm deletion?",
|
||||
"delete-description": "You must delete all links in this collection before you can delete this collection."
|
||||
},
|
||||
"favorite": "Favorite",
|
||||
"add-favorite": "Add to favorites",
|
||||
"remove-favorite": "Remove from favorites",
|
||||
"favorites-appears-here": "Your favorites will appear here",
|
||||
"no-item-found": "No item found",
|
||||
"search": "Search",
|
||||
"admin": "Administrator",
|
||||
"avatar": "{{name}}'s avatar",
|
||||
"generic-error": "Something went wrong",
|
||||
"generic-error-description": "An error has occurred, if this happens again please <a href=\"https://github.com/Sonny93/my-links\" target=\"_blank\">create an issue</a> with as much detail as possible.",
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
"description": "Description du lien",
|
||||
"create": "Créer un lien",
|
||||
"edit": "Modifier un lien",
|
||||
"remove": "Supprimer un lien",
|
||||
"remove-confirm": "Confirmer la suppression ?"
|
||||
"delete": "Supprimer un lien",
|
||||
"delete-confirm": "Confirmer la suppression ?"
|
||||
},
|
||||
"collection": {
|
||||
"collections": "Collection",
|
||||
@@ -25,12 +25,16 @@
|
||||
"no-description": "Aucune description",
|
||||
"create": "Créer une collection",
|
||||
"edit": "Modifier une collection",
|
||||
"remove": "Supprimer une collection",
|
||||
"remove-confirm": "Confirmer la suppression ?",
|
||||
"remove-description": "Vous devez supprimer tous les liens de cette collection avant de pouvoir supprimer cette collection"
|
||||
"delete": "Supprimer une collection",
|
||||
"delete-confirm": "Confirmer la suppression ?",
|
||||
"delete-description": "Vous devez supprimer tous les liens de cette collection avant de pouvoir supprimer cette collection"
|
||||
},
|
||||
"favorite": "Favoris",
|
||||
"add-favorite": "Ajouter aux favoris",
|
||||
"remove-favorite": "Retirer des favoris",
|
||||
"favorites-appears-here": "Vos favoris apparaîtront ici",
|
||||
"no-item-found": "Aucun élément trouvé",
|
||||
"admin": "Administrateur",
|
||||
"search": "Rechercher",
|
||||
"avatar": "Avatar de {{name}}",
|
||||
"generic-error": "Une erreur est survenue",
|
||||
|
||||
@@ -4,12 +4,14 @@ import FormCollection, {
|
||||
FormCollectionData,
|
||||
} from '~/components/form/form_collection';
|
||||
import { Visibility } from '../../../app/enums/visibility';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export default function CreateCollectionPage({
|
||||
disableHomeLink,
|
||||
}: {
|
||||
disableHomeLink: boolean;
|
||||
}) {
|
||||
const { t } = useTranslation('common');
|
||||
const { data, setData, post, processing } = useForm<FormCollectionData>({
|
||||
name: '',
|
||||
description: '',
|
||||
@@ -24,7 +26,7 @@ export default function CreateCollectionPage({
|
||||
|
||||
return (
|
||||
<FormCollection
|
||||
title="Create a collection"
|
||||
title={t('collection.create')}
|
||||
canSubmit={!isFormDisabled}
|
||||
disableHomeLink={disableHomeLink}
|
||||
data={data}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type Collection from '#models/collection';
|
||||
import { useForm } from '@inertiajs/react';
|
||||
import { ChangeEvent, FormEvent, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import FormField from '~/components/common/form/_form_field';
|
||||
import TextBox from '~/components/common/form/textbox';
|
||||
import BackToDashboard from '~/components/common/navigation/back_to_dashboard';
|
||||
@@ -13,6 +14,7 @@ export default function CreateLinkPage({
|
||||
}: {
|
||||
collections: Collection[];
|
||||
}) {
|
||||
const { t } = useTranslation('common');
|
||||
const collectionId = useSearchParam('collectionId') ?? collections[0].id;
|
||||
const { data, setData, post, processing } = useForm({
|
||||
name: '',
|
||||
@@ -50,8 +52,8 @@ export default function CreateLinkPage({
|
||||
>
|
||||
<BackToDashboard>
|
||||
<TextBox
|
||||
label="Link name"
|
||||
placeholder="Link name"
|
||||
label={t('link.name')}
|
||||
placeholder={t('link.name')}
|
||||
name="name"
|
||||
onChange={setData}
|
||||
value={data.name}
|
||||
@@ -67,8 +69,8 @@ export default function CreateLinkPage({
|
||||
required
|
||||
/>
|
||||
<TextBox
|
||||
label="Link description"
|
||||
placeholder="Link description"
|
||||
label={t('link.description')}
|
||||
placeholder={t('link.description')}
|
||||
name="description"
|
||||
onChange={setData}
|
||||
value={data.description}
|
||||
@@ -84,7 +86,7 @@ export default function CreateLinkPage({
|
||||
))}
|
||||
</select>
|
||||
<FormField required>
|
||||
<label htmlFor="favorite">Favorite</label>
|
||||
<label htmlFor="favorite">{t('favorite')}</label>
|
||||
<input
|
||||
type="checkbox"
|
||||
onChange={handleOnCheck}
|
||||
|
||||
8
package-lock.json
generated
8
package-lock.json
generated
@@ -26,7 +26,7 @@
|
||||
"@vinejs/vine": "^2.0.0",
|
||||
"edge.js": "^6.0.2",
|
||||
"hex-rgb": "^5.0.0",
|
||||
"i18next": "^23.11.3",
|
||||
"i18next": "^23.11.4",
|
||||
"luxon": "^3.4.4",
|
||||
"node-html-parser": "^6.1.13",
|
||||
"pg": "^8.11.5",
|
||||
@@ -6539,9 +6539,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/i18next": {
|
||||
"version": "23.11.3",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.3.tgz",
|
||||
"integrity": "sha512-Pq/aSKowir7JM0rj+Wa23Kb6KKDUGno/HjG+wRQu0PxoTbpQ4N89MAT0rFGvXmLkRLNMb1BbBOKGozl01dabzg==",
|
||||
"version": "23.11.4",
|
||||
"resolved": "https://registry.npmjs.org/i18next/-/i18next-23.11.4.tgz",
|
||||
"integrity": "sha512-CCUjtd5TfaCl+mLUzAA0uPSN+AVn4fP/kWCYt/hocPUwusTpMVczdrRyOBUwk6N05iH40qiKx6q1DoNJtBIwdg==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "individual",
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
"@vinejs/vine": "^2.0.0",
|
||||
"edge.js": "^6.0.2",
|
||||
"hex-rgb": "^5.0.0",
|
||||
"i18next": "^23.11.3",
|
||||
"i18next": "^23.11.4",
|
||||
"luxon": "^3.4.4",
|
||||
"node-html-parser": "^6.1.13",
|
||||
"pg": "^8.11.5",
|
||||
|
||||
Reference in New Issue
Block a user