Files
gsc-web-kit/src/chrome/labels.ts
Claude 71bce1bd56 Add i18n factory + AdminShell My Profile + LogoutButton anchor
- src/i18n/server.ts: createI18nConfig factory consolidating the locale
  resolution chain (cookie → access_token preferred_language claim →
  Accept-Language → default). Reusable across apps; previously each
  frontend reimplemented it.
- AdminShell: thread signoutPath + myProfileUrl (default
  https://my.gosec.internal/profile) into the navbar; render My Profile
  link alongside logout.
- LogoutButton: replace two-step fetch+signOut+redirect with a plain
  anchor pointing at signoutPath — the NextAuth POST-only signout
  endpoint plus form-CSRF flow doesn't need client JS.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 20:50:37 +02:00

74 lines
2.0 KiB
TypeScript

"use client";
import { useTranslations } from "next-intl";
import type { ChromeLabels } from "./types";
/**
* Default English chrome labels. Used as fallback when next-intl namespace
* "chrome" doesn't resolve a key and no per-key override is passed in props.
*/
export const DEFAULT_CHROME_LABELS: ChromeLabels = {
navigation: "Navigation",
main: "MAIN",
dashboard: "Dashboard",
support: "Support",
settings: "Settings",
allSettings: "All Settings",
logout: "Logout",
myProfile: "My Profile",
docs: "Docs",
browseApps: "Browse apps",
viewAll: "View all",
activityTitle: "Activity",
newNotifications: "New notifications",
olderNotifications: "Older notifications",
noOlderNotifications: "No older notifications",
noNewNotifications: "No new notifications",
expandSidebar: "Expand sidebar",
collapseSidebar: "Collapse sidebar",
closeSidebar: "Close sidebar",
};
/**
* Resolve chrome labels with three-level precedence:
* 1. `overrides` prop (per-key escape hatch)
* 2. next-intl namespace "chrome" message
* 3. hardcoded English default
*
* Apps add `"chrome": { ... }` to their next-intl messages to translate.
*/
export function useChromeLabels(overrides?: Partial<ChromeLabels>): ChromeLabels {
let t: ((key: string) => string) | null = null;
try {
t = useTranslations("chrome");
} catch {
t = null;
}
const resolved = { ...DEFAULT_CHROME_LABELS };
if (t) {
for (const key of Object.keys(resolved) as (keyof ChromeLabels)[]) {
try {
const v = t(key);
// next-intl returns the key path when the message is missing — treat
// that as "no translation" so we fall back to the English default.
if (v && v !== key && !v.startsWith("chrome.")) {
resolved[key] = v;
}
} catch {
// Missing key — keep the default.
}
}
}
if (overrides) {
for (const k of Object.keys(overrides) as (keyof ChromeLabels)[]) {
const v = overrides[k];
if (v != null) resolved[k] = v;
}
}
return resolved;
}