diff --git a/docs/data/languages.json b/docs/data/languages.json index cc3952d0e..65e53ea0d 100644 --- a/docs/data/languages.json +++ b/docs/data/languages.json @@ -1 +1 @@ -{"defaults":{"language":{"display":"English","locale":"en"},"namespace":"portal"},"namespaces":["portal"],"languages":[{"display":"English","locale":"en","namespaces":["portal"],"fallbacks":["en"]},{"display":"Arabic","locale":"ar","namespaces":["portal"],"fallbacks":["en"]},{"display":"Arabic (Saudi Arabia)","locale":"ar-SA","namespaces":["portal"],"fallbacks":["ar","en"]},{"display":"Czech","locale":"cs","namespaces":["portal"],"fallbacks":["en"]},{"display":"Czech (Czechia)","locale":"cs-CZ","namespaces":["portal"],"fallbacks":["cs","en"]},{"display":"Danish","locale":"da","namespaces":["portal"],"fallbacks":["en"]},{"display":"Danish (Denmark)","locale":"da-DK","namespaces":["portal"],"fallbacks":["da","en"]},{"display":"German","locale":"de","namespaces":["portal"],"fallbacks":["en"]},{"display":"Greek","locale":"el","namespaces":["portal"],"fallbacks":["en"]},{"display":"Greek (Greece)","locale":"el-GR","namespaces":["portal"],"fallbacks":["el","en"]},{"display":"Spanish","locale":"es","namespaces":["portal"],"fallbacks":["en"]},{"display":"Finnish","locale":"fi","namespaces":["portal"],"fallbacks":["en"]},{"display":"French","locale":"fr","namespaces":["portal"],"fallbacks":["en"]},{"display":"Italian","locale":"it","namespaces":["portal"],"fallbacks":["en"]},{"display":"Japanese","locale":"ja","namespaces":["portal"],"fallbacks":["en"]},{"display":"Japanese (Japan)","locale":"ja-JP","namespaces":["portal"],"fallbacks":["ja","en"]},{"display":"Norwegian Bokmål","locale":"nb","namespaces":["portal"],"fallbacks":["en"]},{"display":"Norwegian Bokmål (Norway)","locale":"nb-NO","namespaces":["portal"],"fallbacks":["nb","en"]},{"display":"Dutch","locale":"nl","namespaces":["portal"],"fallbacks":["en"]},{"display":"Norwegian Bokmål","locale":"no","namespaces":["portal"],"fallbacks":["en"]},{"display":"Polish","locale":"pl","namespaces":["portal"],"fallbacks":["en"]},{"display":"Portuguese","locale":"pt","namespaces":["portal"],"fallbacks":["en"]},{"display":"Brazilian Portuguese","locale":"pt-BR","namespaces":["portal"],"fallbacks":["en"]},{"display":"Romanian","locale":"ro","namespaces":["portal"],"fallbacks":["en"]},{"display":"Russian","locale":"ru","namespaces":["portal"],"fallbacks":["en"]},{"display":"Swedish","locale":"sv","namespaces":["portal"],"fallbacks":["en"]},{"display":"Swedish (Sweden)","locale":"sv-SE","namespaces":["portal"],"fallbacks":["sv","en"]},{"display":"Ukrainian","locale":"uk","namespaces":["portal"],"fallbacks":["en"]},{"display":"Ukrainian (Ukraine)","locale":"uk-UA","namespaces":["portal"],"fallbacks":["uk","en"]},{"display":"Chinese","locale":"zh","namespaces":["portal"],"fallbacks":["en"]},{"display":"Chinese (China)","locale":"zh-CN","namespaces":["portal"],"fallbacks":["zh","en"]},{"display":"Chinese (Taiwan)","locale":"zh-TW","namespaces":["portal"],"fallbacks":["en"]}]} \ No newline at end of file +{"defaults":{"language":{"display":"English","locale":"en"},"namespace":"portal"},"namespaces":["portal","settings"],"languages":[{"display":"English","locale":"en","namespaces":["portal","settings"],"fallbacks":["en"]},{"display":"Arabic","locale":"ar","namespaces":["portal"],"fallbacks":["en"]},{"display":"Arabic (Saudi Arabia)","locale":"ar-SA","namespaces":["portal"],"fallbacks":["ar","en"]},{"display":"Czech","locale":"cs","namespaces":["portal"],"fallbacks":["en"]},{"display":"Czech (Czechia)","locale":"cs-CZ","namespaces":["portal"],"fallbacks":["cs","en"]},{"display":"Danish","locale":"da","namespaces":["portal"],"fallbacks":["en"]},{"display":"Danish (Denmark)","locale":"da-DK","namespaces":["portal"],"fallbacks":["da","en"]},{"display":"German","locale":"de","namespaces":["portal"],"fallbacks":["en"]},{"display":"Greek","locale":"el","namespaces":["portal"],"fallbacks":["en"]},{"display":"Greek (Greece)","locale":"el-GR","namespaces":["portal"],"fallbacks":["el","en"]},{"display":"Spanish","locale":"es","namespaces":["portal"],"fallbacks":["en"]},{"display":"Finnish","locale":"fi","namespaces":["portal"],"fallbacks":["en"]},{"display":"French","locale":"fr","namespaces":["portal"],"fallbacks":["en"]},{"display":"Italian","locale":"it","namespaces":["portal"],"fallbacks":["en"]},{"display":"Japanese","locale":"ja","namespaces":["portal"],"fallbacks":["en"]},{"display":"Japanese (Japan)","locale":"ja-JP","namespaces":["portal"],"fallbacks":["ja","en"]},{"display":"Norwegian Bokmål","locale":"nb","namespaces":["portal"],"fallbacks":["en"]},{"display":"Norwegian Bokmål (Norway)","locale":"nb-NO","namespaces":["portal"],"fallbacks":["nb","en"]},{"display":"Dutch","locale":"nl","namespaces":["portal"],"fallbacks":["en"]},{"display":"Norwegian Bokmål","locale":"no","namespaces":["portal"],"fallbacks":["en"]},{"display":"Polish","locale":"pl","namespaces":["portal"],"fallbacks":["en"]},{"display":"Portuguese","locale":"pt","namespaces":["portal"],"fallbacks":["en"]},{"display":"Brazilian Portuguese","locale":"pt-BR","namespaces":["portal"],"fallbacks":["en"]},{"display":"Romanian","locale":"ro","namespaces":["portal"],"fallbacks":["en"]},{"display":"Russian","locale":"ru","namespaces":["portal"],"fallbacks":["en"]},{"display":"Swedish","locale":"sv","namespaces":["portal"],"fallbacks":["en"]},{"display":"Swedish (Sweden)","locale":"sv-SE","namespaces":["portal"],"fallbacks":["sv","en"]},{"display":"Ukrainian","locale":"uk","namespaces":["portal"],"fallbacks":["en"]},{"display":"Ukrainian (Ukraine)","locale":"uk-UA","namespaces":["portal"],"fallbacks":["uk","en"]},{"display":"Chinese","locale":"zh","namespaces":["portal"],"fallbacks":["en"]},{"display":"Chinese (China)","locale":"zh-CN","namespaces":["portal"],"fallbacks":["zh","en"]},{"display":"Chinese (Taiwan)","locale":"zh-TW","namespaces":["portal"],"fallbacks":["en"]}]} \ No newline at end of file diff --git a/internal/server/locales/en/settings.json b/internal/server/locales/en/settings.json new file mode 100644 index 000000000..e9d784812 --- /dev/null +++ b/internal/server/locales/en/settings.json @@ -0,0 +1,28 @@ +{ + "Actions": "Actions", + "Add": "Add", + "Add new Security Key": "Add new Security Key", + "Attestation Type": "Attestation Type", + "Authenticator Attestation GUID": "Authenticator Attestation GUID", + "Cancel": "Cancel", + "Clone Warning": "Clone Warning", + "Created": "Created", + "Delete": "Delete", + "Details": "Details", + "Edit": "Edit", + "Enabled": "Enabled", + "Last Used": "Last Used", + "Manage your security keys": "Manage your security keys", + "Name": "Name", + "No": "No", + "Provide the details for the new security key": "Provide the details for the new security key", + "Relying Party ID": "Relying Party ID", + "Security Keys": "Security Keys", + "Settings": "Settings", + "Show Details": "Show Details", + "Transports": "Transports", + "Usage Count": "Usage Count", + "Webauthn Credential Identifier": "Credential Identifier: {{id}}", + "Webauthn Public Key": "Public Key: {{key}}", + "Yes": "Yes" +} diff --git a/web/src/i18n/index.ts b/web/src/i18n/index.ts index 63cfd5edf..605477c37 100644 --- a/web/src/i18n/index.ts +++ b/web/src/i18n/index.ts @@ -31,7 +31,7 @@ i18n.use(Backend) loadPath: basePath + "/locales/{{lng}}/{{ns}}.json", }, load: "all", - ns: ["portal"], + ns: ["portal", "settings"], defaultNS: "portal", fallbackLng: { default: ["en"], diff --git a/web/src/views/Settings/AddSecurityDialog.tsx b/web/src/views/Settings/AddSecurityDialog.tsx index 3cda17d6e..659e53bef 100644 --- a/web/src/views/Settings/AddSecurityDialog.tsx +++ b/web/src/views/Settings/AddSecurityDialog.tsx @@ -10,10 +10,13 @@ import { DialogTitle, TextField, } from "@mui/material"; +import { useTranslation } from "react-i18next"; interface Props extends DialogProps {} export default function AddSecurityKeyDialog(props: Props) { + const { t: translate } = useTranslation("settings"); + const handleAddClick = () => { if (props.onClose) { props.onClose({}, "backdropClick"); @@ -28,22 +31,22 @@ export default function AddSecurityKeyDialog(props: Props) { return ( - Add new Security Key + {translate("Add new Security Key")} - Provide the details for the new security key. + {translate("Provide the details for the new security key")}. - - + + ); diff --git a/web/src/views/Settings/SettingsView.tsx b/web/src/views/Settings/SettingsView.tsx index 0617bb380..853e898ff 100644 --- a/web/src/views/Settings/SettingsView.tsx +++ b/web/src/views/Settings/SettingsView.tsx @@ -31,6 +31,7 @@ import { Tooltip, Typography, } from "@mui/material"; +import { useTranslation } from "react-i18next"; import { WebauthnDevice } from "@root/models/Webauthn"; import { getWebauthnDevices } from "@root/services/UserWebauthnDevices"; @@ -42,6 +43,8 @@ interface Props {} const drawerWidth = 240; export default function SettingsView(props: Props) { + const { t: translate } = useTranslation("settings"); + const [webauthnDevices, setWebauthnDevices] = useState(); const [addKeyOpen, setAddKeyOpen] = useState(false); const [webauthnShowDetails, setWebauthnShowDetails] = useState(-1); @@ -73,7 +76,7 @@ export default function SettingsView(props: Props) { theme.zIndex.drawer + 1 }}> - Settings + {translate("Settings")} - + @@ -101,12 +104,12 @@ export default function SettingsView(props: Props) { - Manage your security keys + {translate("Manage your security keys")} @@ -116,9 +119,9 @@ export default function SettingsView(props: Props) { - Name - Enabled - Actions + {translate("Name")} + {translate("Enabled")} + {translate("Actions")} @@ -131,7 +134,10 @@ export default function SettingsView(props: Props) { key={x.kid.toString()} > - + - + - + @@ -196,7 +205,7 @@ export default function SettingsView(props: Props) { gutterBottom component="div" > - Details + {translate("Details")} @@ -218,7 +227,14 @@ export default function SettingsView(props: Props) { lg={12} xl={12} > - Key ID: {x.kid} + + {translate( + "Webauthn Credential Identifier", + { + id: x.kid.toString(), + }, + )} + Public Key: {x.public_key} + {translate("Webauthn Public Key", { + key: x.public_key.toString(), + })} - Relying Party ID + + {translate("Relying Party ID")} + {x.rpid} - Authenticator Attestation GUID + {translate( + "Authenticator Attestation GUID", + )} {x.aaguid} - Attestation Type + + {translate("Attestation Type")} + {x.attestation_type} - Transports + + {translate("Transports")} + {x.transports.length === 0 ? "N/A" @@ -265,30 +292,40 @@ export default function SettingsView(props: Props) { - Clone Warning - {x.clone_warning ? "Yes" : "No"} + {translate("Clone Warning")} + + + {x.clone_warning + ? translate("Yes") + : translate("No")} - Created + + {translate("Created")} + {x.created_at.toString()} - Last Used + + {translate("Last Used")} + {x.last_used_at === undefined - ? "Never" + ? translate("Never") : x.last_used_at.toString()} - Usage Count + + {translate("Usage Count")} + {x.sign_count === 0 - ? "Never" + ? translate("Never") : x.sign_count}