From 27abf1b0deb051268fec3aeddac0e1b39df1a0f7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Tr=C3=A8sAbhi?= <43380238+tresabhi@users.noreply.github.com>
Date: Tue, 13 Jan 2026 20:15:55 -0600
Subject: [PATCH] feat: string hooks
---
.../src/components/AvatarCard/index.css | 1 +
.../src/components/AvatarCard/index.tsx | 12 ++----
packages/website-ue/src/core/api/client.ts | 8 ++++
.../website-ue/src/hooks/useGameStrings.ts | 13 +++++++
packages/website-ue/src/hooks/useLocale.tsx | 39 +++++++++++++++++++
.../src/pages/[...locale]/avatars/_index.tsx | 17 +++++++-
.../src/pages/[...locale]/avatars/index.astro | 4 +-
7 files changed, 82 insertions(+), 12 deletions(-)
create mode 100644 packages/website-ue/src/hooks/useGameStrings.ts
create mode 100644 packages/website-ue/src/hooks/useLocale.tsx
diff --git a/packages/website-ue/src/components/AvatarCard/index.css b/packages/website-ue/src/components/AvatarCard/index.css
index e67b7aed0..6d7715603 100644
--- a/packages/website-ue/src/components/AvatarCard/index.css
+++ b/packages/website-ue/src/components/AvatarCard/index.css
@@ -20,5 +20,6 @@
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
+ white-space: nowrap;
}
}
diff --git a/packages/website-ue/src/components/AvatarCard/index.tsx b/packages/website-ue/src/components/AvatarCard/index.tsx
index 316848e87..4ddb4b6b3 100644
--- a/packages/website-ue/src/components/AvatarCard/index.tsx
+++ b/packages/website-ue/src/components/AvatarCard/index.tsx
@@ -1,5 +1,5 @@
-import { api } from "../../core/api/dynamic";
-import { useAwait } from "../../hooks/useAwait";
+import { useGameStrings } from "../../hooks/useGameStrings";
+import { useLocale } from "../../hooks/useLocale";
import type { Avatar } from "../../protos/avatar";
import { Text } from "../Text";
import "./index.css";
@@ -9,12 +9,8 @@ interface Props {
}
export function AvatarCard({ avatar }: Props) {
- // const { locale } = useLocale();
- const { locale } = { locale: "en" };
- const profileAvatarEntityStrings = useAwait(
- () => api.groupedGameStrings(locale, "ProfileAvatarEntity"),
- "profile-avatar-entity-strings"
- );
+ const { locale } = useLocale();
+ const profileAvatarEntityStrings = useGameStrings("ProfileAvatarEntity");
return (
diff --git a/packages/website-ue/src/core/api/client.ts b/packages/website-ue/src/core/api/client.ts
index fb8ec176f..d1ff4077c 100644
--- a/packages/website-ue/src/core/api/client.ts
+++ b/packages/website-ue/src/core/api/client.ts
@@ -1,4 +1,5 @@
import { fetchPB } from "@blitzkit/core";
+import type { Strings } from "@blitzkit/i18n";
import { Avatars } from "../../protos/avatars";
import { AbstractAPI } from "./abstract";
@@ -29,4 +30,11 @@ export class ClientAPI extends AbstractAPI {
return strings;
}
+
+ protected async _strings(locale: string) {
+ const response = await fetch(`/api/strings/${locale}.json`);
+ const json = (await response.json()) as Strings;
+
+ return json;
+ }
}
diff --git a/packages/website-ue/src/hooks/useGameStrings.ts b/packages/website-ue/src/hooks/useGameStrings.ts
new file mode 100644
index 000000000..998c2c597
--- /dev/null
+++ b/packages/website-ue/src/hooks/useGameStrings.ts
@@ -0,0 +1,13 @@
+import { api } from "../core/api/dynamic";
+import { useAwait } from "./useAwait";
+import { useLocale } from "./useLocale";
+
+export function useGameStrings(group: string) {
+ const { locale } = useLocale();
+ const strings = useAwait(
+ () => api.groupedGameStrings(locale, group),
+ `game-strings-${locale}-${group}`
+ );
+
+ return strings;
+}
diff --git a/packages/website-ue/src/hooks/useLocale.tsx b/packages/website-ue/src/hooks/useLocale.tsx
new file mode 100644
index 000000000..2bf4020e5
--- /dev/null
+++ b/packages/website-ue/src/hooks/useLocale.tsx
@@ -0,0 +1,39 @@
+import locales from "@blitzkit/i18n/locales.json";
+import { createContext, useContext, type ReactNode } from "react";
+import { api } from "../core/api/dynamic";
+import { useAwait } from "./useAwait";
+
+const LocaleContext = createContext<{
+ locale: string;
+} | null>(null);
+
+interface LocaleProviderProps extends LocaleAcceptorProps {
+ children: ReactNode;
+}
+
+export function LocaleProvider({ locale, children }: LocaleProviderProps) {
+ return (
+
+ {children}
+
+ );
+}
+
+export function useLocale() {
+ const context = useContext(LocaleContext);
+
+ if (!context) {
+ throw new Error("useLocale must be used within a LocaleProvider");
+ }
+
+ const strings = useAwait(
+ () => api.strings(context.locale),
+ `strings-${context.locale}`
+ );
+
+ return { locale: context.locale, strings };
+}
+
+export interface LocaleAcceptorProps {
+ locale: string | undefined;
+}
diff --git a/packages/website-ue/src/pages/[...locale]/avatars/_index.tsx b/packages/website-ue/src/pages/[...locale]/avatars/_index.tsx
index d8e0f0b2b..a7a30da17 100644
--- a/packages/website-ue/src/pages/[...locale]/avatars/_index.tsx
+++ b/packages/website-ue/src/pages/[...locale]/avatars/_index.tsx
@@ -1,12 +1,25 @@
import { AvatarCard } from "../../../components/AvatarCard";
import { api } from "../../../core/api/dynamic";
import { useAwait } from "../../../hooks/useAwait";
+import { LocaleProvider } from "../../../hooks/useLocale";
-interface Props {
+interface PageProps extends ContentProps {
+ locale: string;
+}
+
+export function Page({ locale, ...props }: PageProps) {
+ return (
+
+
+
+ );
+}
+
+interface ContentProps {
skeleton?: boolean;
}
-export function Page({ skeleton }: Props) {
+function Content({ skeleton }: ContentProps) {
const { avatars } = useAwait(() => api.avatars(), "avatars");
return (
diff --git a/packages/website-ue/src/pages/[...locale]/avatars/index.astro b/packages/website-ue/src/pages/[...locale]/avatars/index.astro
index fff0ba90f..d8b13960f 100644
--- a/packages/website-ue/src/pages/[...locale]/avatars/index.astro
+++ b/packages/website-ue/src/pages/[...locale]/avatars/index.astro
@@ -18,8 +18,8 @@ const { locale } = Astro.props;