Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(web): convert most strings to translation keys #188

Merged
merged 1 commit into from
Jan 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ declare module "i18next" {
defaultNS: typeof defaultNS;
nsSeparator: "";
resources: { "": (typeof resources)["en"]["translations"] };
// the following should be working but has apparently been broken in i18next 23.x
// resources: (typeof resources)["en"];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,7 @@ declare module "i18next" {
defaultNS: typeof defaultNS;
nsSeparator: "";
resources: { "": (typeof resources)["en"]["translations"] };
// the following should be working but has apparently been broken in i18next 23.x
// resources: (typeof resources)["en"];
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import * as React from "react";
import { selectIsAuthenticated } from "@abrechnung/redux";
import { Link as RouterLink, Navigate, Outlet, useLocation, useParams } from "react-router-dom";
import { selectAuthSlice, useAppSelector } from "../../store";
import { selectAuthSlice, useAppSelector } from "@/store";
import { useRecoilValue } from "recoil";
import ListItemLink from "../../components/style/ListItemLink";
import SidebarGroupList from "../../app/authenticated-layout/SidebarGroupList";
import { ListItemLink } from "@/components/style/ListItemLink";
import { SidebarGroupList } from "@/app/authenticated-layout/SidebarGroupList";
import {
AppBar,
Box,
Expand Down Expand Up @@ -40,17 +40,19 @@ import {
Paid,
People,
} from "@mui/icons-material";
import { config } from "../../state/config";
import { config } from "@/state/config";
import { useTheme } from "@mui/material/styles";
import { Banner } from "../../components/style/Banner";
import Loading from "../../components/style/Loading";
import { Banner } from "@/components/style/Banner";
import { Loading } from "@/components/style/Loading";
import styles from "./AuthenticatedLayout.module.css";
import { LanguageSelect } from "@/components/LanguageSelect";
import { useTranslation } from "react-i18next";

const drawerWidth = 240;
const AUTH_FALLBACK = "/login";

export const AuthenticatedLayout: React.FC = () => {
const { t } = useTranslation();
const authenticated = useAppSelector((state) => selectIsAuthenticated({ state: selectAuthSlice(state) }));
const location = useLocation();
const params = useParams();
Expand Down Expand Up @@ -94,7 +96,7 @@ export const AuthenticatedLayout: React.FC = () => {
<ListItemIcon>
<Paid />
</ListItemIcon>
<ListItemText primary="Transactions" />
<ListItemText primary={t("navbar.transactions")} />
</ListItemLink>
<ListItemLink
to={`/groups/${groupId}/events`}
Expand All @@ -103,7 +105,7 @@ export const AuthenticatedLayout: React.FC = () => {
<ListItemIcon>
<EventIcon />
</ListItemIcon>
<ListItemText primary="Events" />
<ListItemText primary={t("navbar.events")} />
</ListItemLink>
<ListItemLink
to={`/groups/${groupId}/balances`}
Expand All @@ -112,7 +114,7 @@ export const AuthenticatedLayout: React.FC = () => {
<ListItemIcon>
<BarChart />
</ListItemIcon>
<ListItemText primary="Balances" />
<ListItemText primary={t("navbar.balances")} />
</ListItemLink>
<ListItemLink
to={`/groups/${groupId}/accounts`}
Expand All @@ -121,7 +123,7 @@ export const AuthenticatedLayout: React.FC = () => {
<ListItemIcon>
<AccountBalance />
</ListItemIcon>
<ListItemText primary="Accounts" />
<ListItemText primary={t("navbar.accounts")} />
</ListItemLink>
<ListItemLink
to={`/groups/${groupId}/detail`}
Expand All @@ -130,7 +132,7 @@ export const AuthenticatedLayout: React.FC = () => {
<ListItemIcon>
<AdminPanelSettings />
</ListItemIcon>
<ListItemText primary="Group Settings" />
<ListItemText primary={t("navbar.groupSettings")} />
</ListItemLink>
<ListItemLink
to={`/groups/${groupId}/members`}
Expand All @@ -139,7 +141,7 @@ export const AuthenticatedLayout: React.FC = () => {
<ListItemIcon>
<People />
</ListItemIcon>
<ListItemText primary="Group Members" />
<ListItemText primary={t("navbar.groupMembers")} />
</ListItemLink>
<ListItemLink
to={`/groups/${groupId}/invites`}
Expand All @@ -148,7 +150,7 @@ export const AuthenticatedLayout: React.FC = () => {
<ListItemIcon>
<Mail />
</ListItemIcon>
<ListItemText primary="Group Invites" />
<ListItemText primary={t("navbar.groupInvites")} />
</ListItemLink>
<ListItemLink
to={`/groups/${groupId}/log`}
Expand All @@ -157,7 +159,7 @@ export const AuthenticatedLayout: React.FC = () => {
<ListItemIcon>
<Message />
</ListItemIcon>
<ListItemText primary="Group Log" />
<ListItemText primary={t("navbar.groupLog")} />
</ListItemLink>
<Divider />
</List>
Expand All @@ -173,7 +175,7 @@ export const AuthenticatedLayout: React.FC = () => {
>
{cfg.imprintURL && (
<Link href={cfg.imprintURL} target="_blank" sx={{ mr: 2 }}>
imprint
{t("navbar.imprint")}
</Link>
)}
<Tooltip title="Source Code">
Expand Down Expand Up @@ -213,7 +215,7 @@ export const AuthenticatedLayout: React.FC = () => {
</IconButton>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
<RouterLink to="/" style={{ textDecoration: "none", color: "inherit" }}>
Abrechnung
{t("app.name")}
</RouterLink>
</Typography>
<div>
Expand Down Expand Up @@ -243,26 +245,26 @@ export const AuthenticatedLayout: React.FC = () => {
onClose={handleDotsMenuClose}
>
<MenuItem component={RouterLink} to="/profile">
Profile
{t("navbar.profile")}
</MenuItem>
<MenuItem component={RouterLink} to="/profile/settings">
Settings
{t("navbar.settings")}
</MenuItem>
<MenuItem component={RouterLink} to="/profile/sessions">
Sessions
{t("navbar.sessions")}
</MenuItem>
<MenuItem component={RouterLink} to="/profile/change-email">
Change E-Mail
{t("navbar.changeEmail")}
</MenuItem>
<MenuItem component={RouterLink} to="/profile/change-password">
Change Password
{t("navbar.changePassword")}
</MenuItem>
<Divider />
<MenuItem component={RouterLink} to="/logout">
<ListItemIcon>
<Logout fontSize="small" />
</ListItemIcon>
<ListItemText>Sign out</ListItemText>
<ListItemText>{t("navbar.signOut")}</ListItemText>
</MenuItem>
</Menu>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,3 @@ export const SidebarGroupList: React.FC<Props> = ({ activeGroupId }) => {
</>
);
};

export default SidebarGroupList;
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import * as React from "react";
import { Link as RouterLink, Outlet, Navigate } from "react-router-dom";
import { AppBar, Box, Button, Container, CssBaseline, Toolbar, Typography } from "@mui/material";
import { Banner } from "../../components/style/Banner";
import { Banner } from "@/components/style/Banner";
import { selectIsAuthenticated } from "@abrechnung/redux";
import { useAppSelector, selectAuthSlice } from "../../store";
import { LanguageSelect } from "@/components/LanguageSelect";
import { useTranslation } from "react-i18next";

export const UnauthenticatedLayout: React.FC = () => {
const { t } = useTranslation();
const authenticated = useAppSelector((state) => selectIsAuthenticated({ state: selectAuthSlice(state) }));

if (authenticated) {
Expand All @@ -25,12 +27,12 @@ export const UnauthenticatedLayout: React.FC = () => {
<Toolbar>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
<RouterLink to="/" style={{ textDecoration: "none", color: "inherit" }}>
Abrechnung
{t("app.name")}
</RouterLink>
</Typography>
<LanguageSelect />
<Button component={RouterLink} color="inherit" to="/login">
Login
{t("navbar.login")}
</Button>
</Toolbar>
</AppBar>
Expand Down
2 changes: 0 additions & 2 deletions frontend/apps/web/src/components/AccountSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,3 @@ export const AccountSelect: React.FC<AccountSelectProps> = ({
/>
);
};

export default AccountSelect;
10 changes: 6 additions & 4 deletions frontend/apps/web/src/components/AddNewTagDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from "react";
import { Dialog, DialogTitle, DialogContent, TextField, DialogActions, Button } from "@mui/material";
import { useTranslation } from "react-i18next";

interface Props {
open: boolean;
Expand All @@ -8,6 +9,7 @@ interface Props {
}

export const AddNewTagDialog: React.FC<Props> = ({ open, onCreate, onClose }) => {
const { t } = useTranslation();
const [tag, setTag] = React.useState("");
const [error, setError] = React.useState(false);

Expand Down Expand Up @@ -43,12 +45,12 @@ export const AddNewTagDialog: React.FC<Props> = ({ open, onCreate, onClose }) =>

return (
<Dialog open={open} onClose={handleCloseDialog}>
<DialogTitle>Add new tag</DialogTitle>
<DialogTitle>{t("common.addNewTag")}</DialogTitle>
<DialogContent>
<TextField
autoFocus
fullWidth
label="Tag name"
label={t("common.name")}
variant="standard"
value={tag}
error={error}
Expand All @@ -59,10 +61,10 @@ export const AddNewTagDialog: React.FC<Props> = ({ open, onCreate, onClose }) =>
</DialogContent>
<DialogActions>
<Button onClick={handleSave} color="primary">
Save
{t("common.save")}
</Button>
<Button onClick={handleCloseDialog} color="error">
Cancel
{t("common.cancel")}
</Button>
</DialogActions>
</Dialog>
Expand Down
6 changes: 4 additions & 2 deletions frontend/apps/web/src/components/DateInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { DatePicker } from "@mui/x-date-pickers";
import { DateTime } from "luxon";
import * as React from "react";
import { DisabledTextField } from "./style/DisabledTextField";
import { useTranslation } from "react-i18next";

interface Props {
value: string;
Expand All @@ -12,6 +13,7 @@ interface Props {
}

export const DateInput: React.FC<Props> = ({ value, onChange, helperText, error, disabled = false }) => {
const { t } = useTranslation();
const handleChange = (value: DateTime) => {
if (value.toISODate()) {
onChange(value.toISODate());
Expand All @@ -21,7 +23,7 @@ export const DateInput: React.FC<Props> = ({ value, onChange, helperText, error,
if (disabled) {
return (
<DisabledTextField
label="Date"
label={t("common.date")}
variant="standard"
fullWidth
value={DateTime.fromISO(value).toISODate()}
Expand All @@ -32,7 +34,7 @@ export const DateInput: React.FC<Props> = ({ value, onChange, helperText, error,

return (
<DatePicker
label="Date"
label={t("common.date")}
format="yyyy-MM-dd"
value={DateTime.fromISO(value)}
onChange={handleChange}
Expand Down
2 changes: 0 additions & 2 deletions frontend/apps/web/src/components/RequireAuth.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,3 @@ export const RequireAuth: React.FC<Props> = ({ authFallback = "/login", children

return children;
};

export default RequireAuth;
28 changes: 21 additions & 7 deletions frontend/apps/web/src/components/ShareSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { getAccountLink } from "../utils";
import { NumericInput } from "./NumericInput";
import { getAccountIcon } from "./style/AbrechnungIcons";
import { getAccountSortFunc } from "@abrechnung/core";
import { useTranslation } from "react-i18next";

interface RowProps {
account: Account;
Expand Down Expand Up @@ -127,6 +128,7 @@ export const ShareSelect: React.FC<ShareSelectProps> = ({
helperText,
editable = false,
}) => {
const { t } = useTranslation();
const theme = useTheme();
const isSmallScreen = useMediaQuery((theme: Theme) => theme.breakpoints.down("sm"));

Expand Down Expand Up @@ -214,8 +216,20 @@ export const ShareSelect: React.FC<ShareSelectProps> = ({
<Grid container direction="row" justifyContent="space-between">
<Box sx={{ display: "flex", flexDirection: "row", alignItems: "center", gap: "0.5em", marginY: 1 }}>
<Typography variant="subtitle1">{label}</Typography>
{nSelectedPeople > 0 && <Chip label={`${nSelectedPeople} People`} size="small" color="primary" />}
{nSelectedEvents > 0 && <Chip label={`${nSelectedEvents} Events`} size="small" color="primary" />}
{nSelectedPeople > 0 && (
<Chip
label={t("shareSelect.selectedPeople", "", { count: nSelectedPeople })}
size="small"
color="primary"
/>
)}
{nSelectedEvents > 0 && (
<Chip
label={t("shareSelect.selectedEvent", "", { count: nSelectedEvents })}
size="small"
color="primary"
/>
)}
</Box>
{editable && (
<Box>
Expand All @@ -225,15 +239,15 @@ export const ShareSelect: React.FC<ShareSelectProps> = ({
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
setShowEvents(event.target.checked)
}
label="Show Events"
label={t("shareSelect.showEvents")}
/>
<FormControlLabel
control={<Checkbox name="show-advanced" />}
checked={showAdvanced}
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
setShowAdvanced(event.target.checked)
}
label="Advanced"
label={t("common.advanced")}
/>
</Box>
)}
Expand All @@ -257,10 +271,10 @@ export const ShareSelect: React.FC<ShareSelectProps> = ({
<TableRow>
<TableCell>
{!showSearch ? (
"Account / Event"
t("shareSelect.accountSlashEvent")
) : (
<TextField
placeholder="Search ..."
placeholder={t("common.search")}
margin="none"
size="small"
value={searchValue}
Expand All @@ -287,7 +301,7 @@ export const ShareSelect: React.FC<ShareSelectProps> = ({
/>
)}
</TableCell>
<TableCell width="100px">Shares</TableCell>
<TableCell width="100px">{t("common.shares")}</TableCell>
{additionalShareInfoHeader ?? null}
</TableRow>
</TableHead>
Expand Down
Loading
Loading