Translate portal chrome and page strings
Replace the remaining hard-coded UI copy in the top bar, user menu, home hero, and the documents/subprocessors/updates/requests pages with i18next keys, and supply the en-US and fr-FR catalog entries for them. The home hero title uses value interpolation rather than string concatenation so word order stays correct across locales. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -1,5 +1,32 @@
|
||||
{
|
||||
"topBar": {
|
||||
"tagline": "Compliance Portal",
|
||||
"getAccess": "Get Access",
|
||||
"nav": {
|
||||
"documents": "Documents",
|
||||
"subprocessors": "Subprocessors",
|
||||
"updates": "Updates",
|
||||
"requests": "Requests"
|
||||
}
|
||||
},
|
||||
"userMenu": {
|
||||
"signOut": "Sign out"
|
||||
},
|
||||
"home": {
|
||||
"heroTitle": "Trust at {{name}}."
|
||||
},
|
||||
"documents": {
|
||||
"title": "Documents"
|
||||
},
|
||||
"subprocessors": {
|
||||
"title": "Subprocessors"
|
||||
},
|
||||
"updates": {
|
||||
"title": "Updates",
|
||||
"subscribe": "Subscribe to updates"
|
||||
},
|
||||
"requests": {
|
||||
"title": "Data Requests",
|
||||
"newRequest": "New Request"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,32 @@
|
||||
{
|
||||
"topBar": {
|
||||
"tagline": "Portail de conformité",
|
||||
"getAccess": "Obtenir l'accès",
|
||||
"nav": {
|
||||
"documents": "Documents",
|
||||
"subprocessors": "Sous-traitants",
|
||||
"updates": "Mises à jour",
|
||||
"requests": "Demandes"
|
||||
}
|
||||
},
|
||||
"userMenu": {
|
||||
"signOut": "Se déconnecter"
|
||||
},
|
||||
"home": {
|
||||
"heroTitle": "La confiance chez {{name}}."
|
||||
},
|
||||
"documents": {
|
||||
"title": "Documents"
|
||||
},
|
||||
"subprocessors": {
|
||||
"title": "Sous-traitants"
|
||||
},
|
||||
"updates": {
|
||||
"title": "Mises à jour",
|
||||
"subscribe": "S'abonner aux mises à jour"
|
||||
},
|
||||
"requests": {
|
||||
"title": "Demandes de données",
|
||||
"newRequest": "Nouvelle demande"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import { Avatar } from "@probo/ui/src/v2/Avatar/Avatar";
|
||||
import { Button } from "@probo/ui/src/v2/Button/Button";
|
||||
import { Link } from "@probo/ui/src/v2/Button/Link";
|
||||
import { Text } from "@probo/ui/src/v2/typography/Text";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { graphql, useFragment } from "react-relay";
|
||||
import { Link as RouterLink, useLocation } from "react-router";
|
||||
|
||||
@@ -25,10 +26,10 @@ import { TopBarUserMenu } from "./TopBarUserMenu";
|
||||
import { topBar } from "./variants";
|
||||
|
||||
const NAV_ITEMS = [
|
||||
{ to: "/documents", label: "Documents" },
|
||||
{ to: "/subprocessors", label: "Subprocessors" },
|
||||
{ to: "/updates", label: "Updates" },
|
||||
{ to: "/requests", label: "Requests" },
|
||||
{ to: "/documents", labelKey: "topBar.nav.documents" },
|
||||
{ to: "/subprocessors", labelKey: "topBar.nav.subprocessors" },
|
||||
{ to: "/updates", labelKey: "topBar.nav.updates" },
|
||||
{ to: "/requests", labelKey: "topBar.nav.requests" },
|
||||
] as const;
|
||||
|
||||
const topBarFragment = graphql`
|
||||
@@ -57,6 +58,7 @@ function isActive(pathname: string, to: string): boolean {
|
||||
}
|
||||
|
||||
export function TopBar({ queryKey }: TopBarProps) {
|
||||
const { t } = useTranslation();
|
||||
const data = useFragment(topBarFragment, queryKey);
|
||||
const { pathname } = useLocation();
|
||||
|
||||
@@ -83,7 +85,7 @@ export function TopBar({ queryKey }: TopBarProps) {
|
||||
{organizationName}
|
||||
</Text>
|
||||
<Text size={2} color="neutral">
|
||||
Compliance Portal
|
||||
{t("topBar.tagline")}
|
||||
</Text>
|
||||
</RouterLink>
|
||||
|
||||
@@ -99,13 +101,13 @@ export function TopBar({ queryKey }: TopBarProps) {
|
||||
size={2}
|
||||
active={isActive(pathname, item.to)}
|
||||
>
|
||||
{item.label}
|
||||
{t(item.labelKey)}
|
||||
</Link>
|
||||
))}
|
||||
{data.viewer == null
|
||||
? (
|
||||
<Button variant="solid" color="neutral" highContrast iconStart={<LockSimpleIcon />}>
|
||||
Get Access
|
||||
{t("topBar.getAccess")}
|
||||
</Button>
|
||||
)
|
||||
: <TopBarUserMenu identityKey={data.viewer} />}
|
||||
|
||||
@@ -21,6 +21,7 @@ import { DropdownPopup } from "@probo/ui/src/v2/Dropdown/DropdownPopup";
|
||||
import { DropdownSeparator } from "@probo/ui/src/v2/Dropdown/DropdownSeparator";
|
||||
import { DropdownTrigger } from "@probo/ui/src/v2/Dropdown/DropdownTrigger";
|
||||
import { Text } from "@probo/ui/src/v2/typography/Text";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { graphql, useFragment } from "react-relay";
|
||||
|
||||
import type { TopBarUserMenu_identity$key } from "./__generated__/TopBarUserMenu_identity.graphql";
|
||||
@@ -38,6 +39,7 @@ interface TopBarUserMenuProps {
|
||||
}
|
||||
|
||||
export function TopBarUserMenu({ identityKey }: TopBarUserMenuProps) {
|
||||
const { t } = useTranslation();
|
||||
const identity = useFragment(topBarUserMenuFragment, identityKey);
|
||||
|
||||
return (
|
||||
@@ -63,7 +65,7 @@ export function TopBarUserMenu({ identityKey }: TopBarUserMenuProps) {
|
||||
<DropdownGroupLabel>{identity.email}</DropdownGroupLabel>
|
||||
<DropdownSeparator />
|
||||
<DropdownItem color="error" iconStart={<SignOutIcon />}>
|
||||
Sign out
|
||||
{t("userMenu.signOut")}
|
||||
</DropdownItem>
|
||||
</DropdownPopup>
|
||||
</Dropdown>
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
import type { PreloadedQuery } from "react-relay";
|
||||
import { graphql, usePreloadedQuery } from "react-relay";
|
||||
|
||||
@@ -37,11 +38,15 @@ interface HomePageProps {
|
||||
}
|
||||
|
||||
export function HomePage({ queryRef }: HomePageProps) {
|
||||
const { t } = useTranslation();
|
||||
const data = usePreloadedQuery<HomePageQuery>(homePageQuery, queryRef);
|
||||
const { organization } = data.currentTrustCenter;
|
||||
|
||||
return (
|
||||
<Hero title={`Trust at ${organization.name}.`} description={organization.description}>
|
||||
<Hero
|
||||
title={t("home.heroTitle", { name: organization.name })}
|
||||
description={organization.description}
|
||||
>
|
||||
<OrganizationContactInfo organizationKey={organization} />
|
||||
</Hero>
|
||||
);
|
||||
|
||||
@@ -14,16 +14,18 @@
|
||||
|
||||
import { PlusIcon } from "@phosphor-icons/react";
|
||||
import { Button } from "@probo/ui/src/v2/Button/Button";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { PageHeader } from "#/components/PageHeader/PageHeader";
|
||||
|
||||
export default function RequestsPage() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<PageHeader
|
||||
title="Data Requests"
|
||||
title={t("requests.title")}
|
||||
actions={(
|
||||
<Button variant="soft" color="neutral" highContrast iconStart={<PlusIcon />}>
|
||||
New Request
|
||||
{t("requests.newRequest")}
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
|
||||
@@ -12,10 +12,13 @@
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { PageHeader } from "#/components/PageHeader/PageHeader";
|
||||
|
||||
// Toolbar (category/region filters, search, Download CSV) and the subprocessor
|
||||
// count are deferred until the v2 Select/TextField components exist.
|
||||
export default function SubprocessorsPage() {
|
||||
return <PageHeader title="Subprocessors" />;
|
||||
const { t } = useTranslation();
|
||||
return <PageHeader title={t("subprocessors.title")} />;
|
||||
}
|
||||
|
||||
@@ -14,16 +14,18 @@
|
||||
|
||||
import { BellIcon } from "@phosphor-icons/react";
|
||||
import { Button } from "@probo/ui/src/v2/Button/Button";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import { PageHeader } from "#/components/PageHeader/PageHeader";
|
||||
|
||||
export default function UpdatesPage() {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<PageHeader
|
||||
title="Updates"
|
||||
title={t("updates.title")}
|
||||
actions={(
|
||||
<Button variant="soft" color="neutral" highContrast iconStart={<BellIcon />}>
|
||||
Subscribe to updates
|
||||
{t("updates.subscribe")}
|
||||
</Button>
|
||||
)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user