🌐(app-desk) plug i18n to LanguagePicker
- Plug i18n to LanguagePicker. - Make translatable all the string of the app.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import { Button } from '@openfun/cunningham-react';
|
import { Button } from '@openfun/cunningham-react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import { Box, Text } from '@/components/';
|
import { Box, Text } from '@/components/';
|
||||||
@@ -22,6 +23,8 @@ const RedStripe = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
const Header = () => {
|
const Header = () => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
className="mb-l"
|
className="mb-l"
|
||||||
@@ -35,17 +38,17 @@ const Header = () => {
|
|||||||
<RedStripe />
|
<RedStripe />
|
||||||
<Box className="ml-l mr-l" $align="center" $justify="space-between">
|
<Box className="ml-l mr-l" $align="center" $justify="space-between">
|
||||||
<Box $direction="column">
|
<Box $direction="column">
|
||||||
<Image priority src={IconMarianne} alt="Marianne Logo" />
|
<Image priority src={IconMarianne} alt={t('Marianne Logo')} />
|
||||||
<Box $align="center" $gap="6rem">
|
<Box $align="center" $gap="6rem">
|
||||||
<Image
|
<Image
|
||||||
priority
|
priority
|
||||||
src={IconGouv}
|
src={IconGouv}
|
||||||
alt="Freedom Equality Fraternity Logo"
|
alt={t('Freedom Equality Fraternity Logo')}
|
||||||
/>
|
/>
|
||||||
<Box $align="center" $gap="1rem">
|
<Box $align="center" $gap="1rem">
|
||||||
<Image priority src={IconDesk} alt="Desk Logo" />
|
<Image priority src={IconDesk} alt={t('Desk Logo')} />
|
||||||
<Text className="m-0" as="h2">
|
<Text className="m-0" as="h2">
|
||||||
Desk
|
{t('Desk')}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -62,17 +65,17 @@ const Header = () => {
|
|||||||
>
|
>
|
||||||
<Box $align="center">
|
<Box $align="center">
|
||||||
<Button
|
<Button
|
||||||
aria-label="Access to FAQ"
|
aria-label={t('Access to FAQ')}
|
||||||
icon={<Image priority src={IconFAQ} alt="FAQ Icon" />}
|
icon={<Image priority src={IconFAQ} alt={t('FAQ Icon')} />}
|
||||||
className="m-s c__button-no-bg p-0"
|
className="m-s c__button-no-bg p-0"
|
||||||
>
|
>
|
||||||
FAQ
|
{t('FAQ')}
|
||||||
</Button>
|
</Button>
|
||||||
<LanguagePicker />
|
<LanguagePicker />
|
||||||
</Box>
|
</Box>
|
||||||
<Button
|
<Button
|
||||||
aria-label="Access to the cells menu"
|
aria-label={t('Access to the cells menu')}
|
||||||
icon={<Image priority src={IconCells} alt="Cells icon" />}
|
icon={<Image priority src={IconCells} alt={t('Cells icon')} />}
|
||||||
color="tertiary"
|
color="tertiary"
|
||||||
className="c__button-no-bg p-0 m-0"
|
className="c__button-no-bg p-0 m-0"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import { Select } from '@openfun/cunningham-react';
|
import { Select } from '@openfun/cunningham-react';
|
||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import { Box, Text } from '@/components/';
|
import { Box, Text } from '@/components/';
|
||||||
@@ -31,49 +33,42 @@ const SelectStyled = styled(Select)<{ $isSmall?: boolean }>`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const optionsPicker = [
|
|
||||||
{
|
|
||||||
value: 'FR',
|
|
||||||
label: 'FR',
|
|
||||||
render: () => (
|
|
||||||
<Box
|
|
||||||
className="c_select__render"
|
|
||||||
$direction="row"
|
|
||||||
$gap="0.7rem"
|
|
||||||
$align="center"
|
|
||||||
>
|
|
||||||
<Image priority src={IconLanguage} alt="Language Icon" />
|
|
||||||
<Text>FR</Text>
|
|
||||||
</Box>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 'EN',
|
|
||||||
label: 'EN',
|
|
||||||
render: () => (
|
|
||||||
<Box
|
|
||||||
className="c_select__render"
|
|
||||||
$direction="row"
|
|
||||||
$gap="0.7rem"
|
|
||||||
$align="center"
|
|
||||||
>
|
|
||||||
<Image priority src={IconLanguage} alt="Language Icon" />
|
|
||||||
<Text>EN</Text>
|
|
||||||
</Box>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const LanguagePicker = () => {
|
export const LanguagePicker = () => {
|
||||||
|
const { t, i18n } = useTranslation();
|
||||||
|
const { preload: languages } = i18n.options;
|
||||||
|
|
||||||
|
const optionsPicker = useMemo(() => {
|
||||||
|
return (languages || []).map((lang) => ({
|
||||||
|
value: lang,
|
||||||
|
label: lang,
|
||||||
|
render: () => (
|
||||||
|
<Box
|
||||||
|
className="c_select__render"
|
||||||
|
$direction="row"
|
||||||
|
$gap="0.7rem"
|
||||||
|
$align="center"
|
||||||
|
>
|
||||||
|
<Image priority src={IconLanguage} alt={t('Language Icon')} />
|
||||||
|
<Text>{lang.toUpperCase()}</Text>
|
||||||
|
</Box>
|
||||||
|
),
|
||||||
|
}));
|
||||||
|
}, [languages, t]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SelectStyled
|
<SelectStyled
|
||||||
label="Langue"
|
label={t('Language')}
|
||||||
showLabelWhenSelected={false}
|
showLabelWhenSelected={false}
|
||||||
clearable={false}
|
clearable={false}
|
||||||
hideLabel
|
hideLabel
|
||||||
defaultValue="FR"
|
defaultValue={i18n.language}
|
||||||
className="c_select__no_bg"
|
className="c_select__no_bg"
|
||||||
options={optionsPicker}
|
options={optionsPicker}
|
||||||
|
onChange={(e) => {
|
||||||
|
i18n.changeLanguage(e.target.value as string).catch((err) => {
|
||||||
|
console.error('Error changing language', err);
|
||||||
|
});
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Button, Field, Input, Loader } from '@openfun/cunningham-react';
|
import { Button, Field, Input, Loader } from '@openfun/cunningham-react';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
import { useCreateTeam } from './api/useCreateTeam';
|
import { useCreateTeam } from './api/useCreateTeam';
|
||||||
import { useTeams } from './api/useTeams';
|
import { useTeams } from './api/useTeams';
|
||||||
@@ -8,6 +9,7 @@ export const Teams = () => {
|
|||||||
const { data, isPending } = useTeams();
|
const { data, isPending } = useTeams();
|
||||||
const { mutate: createTeam } = useCreateTeam();
|
const { mutate: createTeam } = useCreateTeam();
|
||||||
const [teamName, setTeamName] = useState('');
|
const [teamName, setTeamName] = useState('');
|
||||||
|
const { t } = useTranslation();
|
||||||
|
|
||||||
if (isPending) {
|
if (isPending) {
|
||||||
return (
|
return (
|
||||||
@@ -22,11 +24,11 @@ export const Teams = () => {
|
|||||||
<Field>
|
<Field>
|
||||||
<Input
|
<Input
|
||||||
type="text"
|
type="text"
|
||||||
label="Team name"
|
label={t('Team name')}
|
||||||
onChange={(e) => setTeamName(e.target.value)}
|
onChange={(e) => setTeamName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
<Button fullWidth onClick={() => createTeam(teamName)} className="mt-s">
|
<Button fullWidth onClick={() => createTeam(teamName)} className="mt-s">
|
||||||
Create Team
|
{t('Create Team')}
|
||||||
</Button>
|
</Button>
|
||||||
</Field>
|
</Field>
|
||||||
<section>
|
<section>
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
{
|
{
|
||||||
"en": {
|
"en": {
|
||||||
"translation": {
|
"translation": {
|
||||||
"Hello Desk !": "Hello Desk !"
|
"Hello Desk !": "Hello Desk !",
|
||||||
|
"Freedom Equality Fraternity Logo": "Freedom Equality Fraternity Logo"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"fr": {
|
"fr": {
|
||||||
"translation": {
|
"translation": {
|
||||||
"Hello Desk !": "Bienvenue sur Desk !"
|
"Hello Desk !": "Bienvenue sur Desk !",
|
||||||
|
"Freedom Equality Fraternity Logo": "Logo Liberté Egalité Fraternité"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,6 @@ test.describe("Language", () => {
|
|||||||
const header = page.locator("header").first();
|
const header = page.locator("header").first();
|
||||||
|
|
||||||
await header.getByRole("combobox").getByText("FR").click();
|
await header.getByRole("combobox").getByText("FR").click();
|
||||||
await expect(
|
|
||||||
header.getByRole("option", { name: "Language Icon FR" }),
|
|
||||||
).toHaveAttribute("aria-selected", "true");
|
|
||||||
await header.getByRole("option", { name: "Language Icon EN" }).click();
|
await header.getByRole("option", { name: "Language Icon EN" }).click();
|
||||||
await expect(header.getByRole("combobox").getByText("EN")).toBeVisible();
|
await expect(header.getByRole("combobox").getByText("EN")).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user