Skip to content
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
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ jobs:
run: node scripts/gen-ramps.mjs --check
- name: Build
run: pnpm build
- name: Bundle budget
run: node scripts/check-bundle.mjs

# The browser tests run against `next dev` on the in-memory mock (no cloud), at 375 and 1280 px.
e2e:
Expand Down
12 changes: 12 additions & 0 deletions apps/web/e2e/language.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,15 @@ test("the account area speaks the language too, and the long words fit", async (
const overflow = await page.evaluate(() => document.documentElement.scrollWidth - document.documentElement.clientWidth);
expect(overflow).toBe(0);
});

test("a public profile carries only its own words, and none is missing", async ({ page }) => {
const problems: string[] = [];
page.on("console", (m) => {
if (m.type() === "error" && /MISSING_MESSAGE|Could not resolve/.test(m.text())) problems.push(m.text());
});
await page.goto("/u/mira?lang=de");
await expect(page.locator("html")).toHaveAttribute("lang", "de");
await expect(page.getByRole("heading", { level: 1, name: "mira" })).toBeVisible();
await expect(page.getByRole("region").first()).toBeVisible();
expect(problems).toEqual([]);
});
6 changes: 1 addition & 5 deletions apps/web/messages/de/auth.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@
"toastParty": "kit ist deiner Party beigetreten",
"toastTrophy": "Trophäe erhalten · Into the Ember",
"help": "Brauchst du Hilfe?",
"helpLink": "Frag auf Discord",
"legalNav": "Rechtliches",
"legalNotice": "Impressum",
"privacyNotice": "Datenschutzhinweis",
"termsOfUse": "Nutzungsbedingungen"
"helpLink": "Frag auf Discord"
},
"step": {
"loading": "Wird geladen",
Expand Down
6 changes: 6 additions & 0 deletions apps/web/messages/de/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@
"rate_limited": "Zu viele Versuche. Warte einen Moment und versuche es erneut.",
"rate_limited_wait": "Zu viele Versuche. Warte {seconds, plural, one {# Sekunde} other {# Sekunden}} und versuche es erneut.",
"passkey_unsupported": "Dieser Browser unterstützt keine Passkeys. Verwende stattdessen den E-Mail-Code."
},
"legal": {
"nav": "Rechtliches",
"legal": "Impressum",
"privacy": "Datenschutzhinweis",
"terms": "Nutzungsbedingungen"
}
}
6 changes: 1 addition & 5 deletions apps/web/messages/en/auth.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@
"toastParty": "kit joined your party",
"toastTrophy": "Trophy earned · Into the Ember",
"help": "Need help?",
"helpLink": "Ask on Discord",
"legalNav": "Legal",
"legalNotice": "Legal notice",
"privacyNotice": "Privacy notice",
"termsOfUse": "Terms of use"
"helpLink": "Ask on Discord"
},
"step": {
"loading": "Loading",
Expand Down
6 changes: 6 additions & 0 deletions apps/web/messages/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@
"rate_limited": "Too many tries. Wait a moment and try again.",
"rate_limited_wait": "Too many tries. Wait {seconds, plural, one {# second} other {# seconds}} and try again.",
"passkey_unsupported": "This browser can’t use passkeys. Use the e-mail code instead."
},
"legal": {
"nav": "Legal",
"legal": "Legal notice",
"privacy": "Privacy notice",
"terms": "Terms of use"
}
}
6 changes: 1 addition & 5 deletions apps/web/messages/es/auth.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@
"toastParty": "kit se unió a tu party",
"toastTrophy": "Trofeo conseguido · Into the Ember",
"help": "¿Necesitas ayuda?",
"helpLink": "Pregunta en Discord",
"legalNav": "Legal",
"legalNotice": "Aviso legal",
"privacyNotice": "Aviso de privacidad",
"termsOfUse": "Condiciones de uso"
"helpLink": "Pregunta en Discord"
},
"step": {
"loading": "Cargando",
Expand Down
6 changes: 6 additions & 0 deletions apps/web/messages/es/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@
"rate_limited": "Demasiados intentos. Espera un momento e inténtalo de nuevo.",
"rate_limited_wait": "Demasiados intentos. Espera {seconds, plural, one {# segundo} other {# segundos}} e inténtalo de nuevo.",
"passkey_unsupported": "Este navegador no admite passkeys. Usa el código por correo electrónico."
},
"legal": {
"nav": "Legal",
"legal": "Aviso legal",
"privacy": "Aviso de privacidad",
"terms": "Condiciones de uso"
}
}
6 changes: 1 addition & 5 deletions apps/web/messages/fr/auth.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@
"toastParty": "kit a rejoint ta party",
"toastTrophy": "Trophée obtenu · Into the Ember",
"help": "Besoin d’aide ?",
"helpLink": "Demande sur Discord",
"legalNav": "Mentions légales",
"legalNotice": "Mentions légales",
"privacyNotice": "Avis de confidentialité",
"termsOfUse": "Conditions d’utilisation"
"helpLink": "Demande sur Discord"
},
"step": {
"loading": "Chargement",
Expand Down
6 changes: 6 additions & 0 deletions apps/web/messages/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@
"rate_limited": "Trop d’essais. Attends un instant et réessaie.",
"rate_limited_wait": "Trop d’essais. Attends {seconds, plural, one {# seconde} other {# secondes}} et réessaie.",
"passkey_unsupported": "Ce navigateur ne gère pas les clés d’accès. Utilise plutôt le code reçu par e-mail."
},
"legal": {
"nav": "Informations légales",
"legal": "Mentions légales",
"privacy": "Avis de confidentialité",
"terms": "Conditions d’utilisation"
}
}
14 changes: 7 additions & 7 deletions apps/web/messages/pt/account.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,9 +151,9 @@
"detail": "{platform} · Último uso: {used}",
"signOut": "Sair",
"empty": "Nenhum launcher conectado ainda.",
"confirmTitle": "Desconectar este launcher?",
"confirmTitle": "Sair deste launcher?",
"confirmDescription": "Ele fica offline até alguém entrar de novo nesse PC.",
"confirmLabel": "Desconectar launcher"
"confirmLabel": "Sair do launcher"
},
"browsers": {
"title": "Navegadores",
Expand All @@ -164,7 +164,7 @@
"detail": "Entrou {created} · Último uso: {used}",
"signOut": "Sair",
"confirmThisTitle": "Sair deste navegador?",
"confirmOtherTitle": "Desconectar aquele navegador?",
"confirmOtherTitle": "Sair daquele navegador?",
"confirmThisDescription": "Você volta ao início e entra de novo na próxima vez.",
"confirmOtherDescription": "Ele precisa entrar de novo para abrir sua conta.",
"confirmLabel": "Sair"
Expand All @@ -174,7 +174,7 @@
"description": "Todo launcher e todo navegador, este também. Use quando um dispositivo for perdido ou alguém mais puder ter entrado.",
"button": "Sair em todos os lugares",
"confirmTitle": "Sair em todos os lugares?",
"confirmDescription": "Todo launcher e navegador é desconectado de uma vez, este também.",
"confirmDescription": "Todo launcher e navegador sai de uma vez, este também.",
"confirmLabel": "Sair em todos os lugares"
}
},
Expand Down Expand Up @@ -280,7 +280,7 @@
},
"confirm": {
"title": "Excluir sua conta?",
"description": "Ela é excluída em 30 dias. Todo launcher e navegador é desconectado agora."
"description": "Ela é excluída em 30 dias. Todo launcher e navegador sai agora."
}
},
"compare": {
Expand Down Expand Up @@ -341,9 +341,9 @@
"editProfile": "Editar seu perfil",
"blocked": "Bloqueado",
"friends": "Amigos",
"requestSent": "Solicitação enviada",
"requestSent": "Pedido enviado",
"accepting": "Aceitando…",
"accept": "Aceitar solicitação",
"accept": "Aceitar pedido",
"sending": "Enviando…",
"addFriend": "Adicionar amigo",
"addInAnyPlay": "Adicionar amigo no AnyPlay",
Expand Down
6 changes: 1 addition & 5 deletions apps/web/messages/pt/auth.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@
"toastParty": "kit entrou na sua party",
"toastTrophy": "Troféu conquistado · Into the Ember",
"help": "Precisa de ajuda?",
"helpLink": "Pergunte no Discord",
"legalNav": "Legal",
"legalNotice": "Aviso legal",
"privacyNotice": "Aviso de privacidade",
"termsOfUse": "Termos de uso"
"helpLink": "Pergunte no Discord"
},
"step": {
"loading": "Carregando",
Expand Down
6 changes: 6 additions & 0 deletions apps/web/messages/pt/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@
"rate_limited": "Muitas tentativas. Aguarde um momento e tente de novo.",
"rate_limited_wait": "Muitas tentativas. Aguarde {seconds, plural, one {# segundo} other {# segundos}} e tente de novo.",
"passkey_unsupported": "Este navegador não oferece suporte a passkeys. Use o código por e-mail."
},
"legal": {
"nav": "Legal",
"legal": "Aviso legal",
"privacy": "Aviso de privacidade",
"terms": "Termos de uso"
}
}
32 changes: 16 additions & 16 deletions apps/web/messages/tr/account.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
"deletion": "Hesabın {date} tarihinde silinecek. <keep>Hesabımı koru</keep>",
"passkeys": "{count, plural, one {# geçiş anahtarı} other {# geçiş anahtarı}}",
"noPasskey": "Henüz geçiş anahtarı yok",
"launchersBrowsers": "{launchers, plural, one {# Launcher} other {# Launcher}} · {browsers, plural, one {# tarayıcı} other {# tarayıcı}}",
"launchersBrowsers": "{launchers, plural, one {# başlatıcı} other {# başlatıcı}} · {browsers, plural, one {# tarayıcı} other {# tarayıcı}}",
"trophiesAudience": "Kupalar: {audience}",
"pictureAudience": "Profil resmi: {audience}",
"audience": {
Expand All @@ -78,8 +78,8 @@
"dataValue": "Dışa aktar ya da sil",
"dataDetail": "Hakkında tuttuğumuz her şey",
"launcher": {
"title": "Launcher’ı indir",
"description": "Bu hesapla Launcher’a giriş yap; arkadaşların, partilerin ve kupaların orada olur."
"title": "Başlatıcıyı indir",
"description": "Bu hesapla başlatıcıya giriş yap; arkadaşların, partilerin ve kupaların orada olur."
}
},
"profile": {
Expand All @@ -102,7 +102,7 @@
},
"favourites": {
"title": "Favori oyunlar",
"description": "En fazla {max}, oyun kimliğiyle. Bu site kimliği gösterir. Launcher her oyunun adını kendi kopyandan gösterir.",
"description": "En fazla {max}, oyun kimliğiyle. Bu site kimliği gösterir. Başlatıcı her oyunun adını kendi kopyandan gösterir.",
"empty": "Henüz favori oyun yok. Aşağıdan bir oyun kimliği ekle.",
"listLabel": "Favori oyunların",
"remove": "{id} kaldır",
Expand All @@ -117,7 +117,7 @@
}
},
"security": {
"lead": "Nasıl giriş yaptığın ve hesabına giriş yapmış her Launcher ile tarayıcı.",
"lead": "Nasıl giriş yaptığın ve hesabına giriş yapmış her başlatıcı ile tarayıcı.",
"email": {
"title": "E-posta",
"description": "Giriş kodlarının gittiği adres. Değiştirmek için yeni adrese gönderilen bir kod gerekir.",
Expand Down Expand Up @@ -146,14 +146,14 @@
"thisDevice": "bu cihaz"
},
"devices": {
"title": "Launcher’lar",
"description": "Launcher’ın hesabınla giriş yaptığı tüm bilgisayarlar.",
"title": "Başlatıcılar",
"description": "Hesabınla başlatıcıya giriş yapılmış tüm bilgisayarlar.",
"detail": "{platform} · Son kullanım: {used}",
"signOut": "Çıkış yap",
"empty": "Henüz hiçbir Launcher’da giriş yapılmadı.",
"confirmTitle": "Bu Launcher’dan çıkış yapılsın mı?",
"empty": "Henüz hiçbir başlatıcıda giriş yapılmadı.",
"confirmTitle": "Bu başlatıcıdan çıkış yapılsın mı?",
"confirmDescription": "O bilgisayarda biri tekrar giriş yapana kadar çevrimdışı olur.",
"confirmLabel": "Launcher’dan çıkış yap"
"confirmLabel": "Başlatıcıdan çıkış yap"
},
"browsers": {
"title": "Tarayıcılar",
Expand All @@ -171,18 +171,18 @@
},
"everywhere": {
"title": "Her yerden çıkış yap",
"description": "Bu dahil her Launcher ve her tarayıcı. Bir cihaz kaybolduysa ya da başkası giriş yapmış olabilirse kullan.",
"description": "Bu dahil her başlatıcı ve her tarayıcı. Bir cihaz kaybolduysa ya da başkası giriş yapmış olabilirse kullan.",
"button": "Her yerden çıkış yap",
"confirmTitle": "Her yerden çıkış yapılsın mı?",
"confirmDescription": "Bu dahil her Launcher ve tarayıcıdan aynı anda çıkış yapılır.",
"confirmDescription": "Bu dahil her başlatıcı ve tarayıcıdan aynı anda çıkış yapılır.",
"confirmLabel": "Her yerden çıkış yap"
}
},
"privacy": {
"lead": "Profilini ve etkinliğini kimin gördüğü. Kullanıcı adın her zaman görünür; böylece arkadaşların seni bulabilir.",
"profile": {
"title": "Profilin",
"description": "Değişiklikler hemen geçerli olur, Launcher’da da."
"description": "Değişiklikler hemen geçerli olur, başlatıcıda da."
},
"parts": {
"trophies": {
Expand Down Expand Up @@ -215,13 +215,13 @@
},
"appearOffline": {
"title": "Çevrimiçi durumu",
"description": "Hesabına giriş yapmış her Launcher ve tarayıcı için geçerlidir.",
"description": "Hesabına giriş yapmış her başlatıcı ve tarayıcı için geçerlidir.",
"label": "Çevrimdışı görün",
"detail": "Arkadaşların seni çevrimdışı görür. Yine de oynayabilir, sohbet edebilir ve katılabilirsin."
},
"publicProfile": {
"title": "Herkese açık profil",
"description": "Sen açana kadar kapalıdır. Hesabına giriş yapmış her Launcher ve tarayıcı için geçerlidir.",
"description": "Sen açana kadar kapalıdır. Hesabına giriş yapmış her başlatıcı ve tarayıcı için geçerlidir.",
"label": "Herkese açık profil göster",
"detail": "Bağlantıya sahip herkes seviyeni, kupalarını ve oynadığın oyunları görür. Çevrimiçi olup olmadığını asla göstermez.",
"page": "Sayfan: <link>{url}</link>"
Expand Down Expand Up @@ -280,7 +280,7 @@
},
"confirm": {
"title": "Hesabın silinsin mi?",
"description": "Hesap 30 gün içinde silinir. Her Launcher ve tarayıcıdan şimdi çıkış yapılır."
"description": "Hesap 30 gün içinde silinir. Her başlatıcı ve tarayıcıdan şimdi çıkış yapılır."
}
},
"compare": {
Expand Down
6 changes: 1 addition & 5 deletions apps/web/messages/tr/auth.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,7 @@
"toastParty": "kit partine katıldı",
"toastTrophy": "Kupa kazanıldı · Into the Ember",
"help": "Yardım mı lazım?",
"helpLink": "Discord’da sor",
"legalNav": "Yasal",
"legalNotice": "Yasal bildirim",
"privacyNotice": "Gizlilik bildirimi",
"termsOfUse": "Kullanım koşulları"
"helpLink": "Discord’da sor"
},
"step": {
"loading": "Yükleniyor",
Expand Down
6 changes: 6 additions & 0 deletions apps/web/messages/tr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,11 @@
"rate_limited": "Çok fazla deneme. Biraz bekleyip yeniden dene.",
"rate_limited_wait": "Çok fazla deneme. {seconds, plural, one {# saniye} other {# saniye}} bekleyip yeniden dene.",
"passkey_unsupported": "Bu tarayıcı geçiş anahtarlarını kullanamıyor. Bunun yerine e-posta kodunu kullan."
},
"legal": {
"nav": "Yasal",
"legal": "Yasal bildirim",
"privacy": "Gizlilik bildirimi",
"terms": "Kullanım koşulları"
}
}
4 changes: 2 additions & 2 deletions apps/web/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts";
import "./.next/dev/types/root-params.d.ts";
import "./.next/types/routes.d.ts";
import "./.next/types/root-params.d.ts";

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
18 changes: 15 additions & 3 deletions apps/web/src/app/u/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,20 @@ import { NextIntlClientProvider } from "next-intl";
import { getMessages } from "next-intl/server";
import type { ReactNode } from "react";

/** Public profiles: the shared words and the account words, in the visitor's language. */
type Tree = Record<string, Record<string, unknown>>;

/**
* Public profiles: the shared words and only the account words this page uses (the profile, the
* compare card, the level meter, the trophy grades and the shared parts), not the security and
* data texts of the signed-in area. Anyone can open this page, so it carries as little as it can.
* A key missing here shows as a missing message in the profile e2e test.
*/
export default async function ProfileLayout({ children }: { children: ReactNode }) {
const { common, account } = (await getMessages()) as Record<string, Record<string, unknown>>;
return <NextIntlClientProvider messages={{ common, account }}>{children}</NextIntlClientProvider>;
const { common, account } = (await getMessages()) as Tree;
const { publicProfile, compare, level, state, ui, trophies } = account as Tree;
return (
<NextIntlClientProvider messages={{ common, account: { publicProfile, compare, level, state, ui, trophies: { grades: (trophies as Tree).grades } } }}>
{children}
</NextIntlClientProvider>
);
}
11 changes: 6 additions & 5 deletions apps/web/src/components/auth/auth-shell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { DitherField } from "../landing/shaders";
*/
export function AuthShell({ children, toasts = true }: { children: ReactNode; toasts?: boolean }) {
const t = useTranslations("auth.shell");
const legal = useTranslations("common.legal");
const { discord } = useSite();
return (
<LandingProviders>
Expand Down Expand Up @@ -88,18 +89,18 @@ export function AuthShell({ children, toasts = true }: { children: ReactNode; to
</a>
</p>
)}
<nav aria-label={t("legalNav")}>
<nav aria-label={legal("nav")}>
<ul className="flex flex-wrap gap-x-6">
{(
[
["legalNotice", LINKS.legal],
["privacyNotice", LINKS.privacy],
["termsOfUse", LINKS.terms],
["legal", LINKS.legal],
["privacy", LINKS.privacy],
["terms", LINKS.terms],
] as const
).map(([label, href]) => (
<li key={label}>
<a href={href} className="inline-flex min-h-11 items-center py-1 text-ink-2 underline-offset-4 [@media(hover:hover)]:hover:underline">
{t(label)}
{legal(label)}
</a>
</li>
))}
Expand Down
Loading
Loading