update arabic to be default
Build & Push / Pipeline Tests (push) Successful in 1m56s
Test / Type Check (all packages) (push) Successful in 56s
Build & Push / Build & Push Docker Image (push) Successful in 3m39s
Test / API Unit Tests (push) Successful in 1m12s
Test / Homepage Unit Tests (push) Successful in 52s
Test / Carplace Unit Tests (push) Successful in 43s
Test / Admin Unit Tests (push) Successful in 52s
Test / Dashboard Unit Tests (push) Successful in 45s
Test / API Integration Tests (push) Successful in 1m8s

This commit is contained in:
root
2026-08-31 19:50:27 -04:00
parent f00d2a8aea
commit cb8bf63218
23 changed files with 58 additions and 77 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ export const metadata: Metadata = {
}
function resolveInitialLanguage(value: string | undefined): 'en' | 'fr' | 'ar' {
return value === 'fr' || value === 'ar' || value === 'en' ? value : 'en'
return value === 'fr' || value === 'ar' || value === 'en' ? value : 'ar'
}
export default async function RootLayout({ children }: { children: React.ReactNode }) {
@@ -86,7 +86,7 @@ describe("dashboard public auth pages", () => {
const text = collectText(page).join(" ");
const signInLink = findElement(
page,
(element) => element.props.href === "/en/dark/sign-in",
(element) => element.props.href === "/ar/dark/sign-in",
);
expect(text).toContain("Invitation accepted");
+4 -14
View File
@@ -1519,22 +1519,12 @@ const I18nContext = createContext<I18nContextValue | null>(null)
const DASHBOARD_LANGUAGE_KEY = 'dashboard-language'
function normalizeLanguage(value: string | null | undefined): DashboardLanguage {
return value === 'fr' || value === 'ar' || value === 'en' ? value : 'en'
}
function detectBrowserLanguage(): DashboardLanguage | null {
if (typeof navigator === 'undefined') return null
const langs = Array.from(navigator.languages ?? [navigator.language])
for (const lang of langs) {
const code = lang.split('-')[0].toLowerCase()
if (code === 'fr' || code === 'ar' || code === 'en') return code as DashboardLanguage
}
return null
return value === 'fr' || value === 'ar' || value === 'en' ? value : 'ar'
}
export function DashboardI18nProvider({
children,
initialLanguage = 'en',
initialLanguage = 'ar',
}: {
children: React.ReactNode
initialLanguage?: DashboardLanguage
@@ -1580,8 +1570,8 @@ export function DashboardI18nProvider({
const next = normalizeLanguage(stored)
if (next !== language) setLanguageState(next)
} else {
const detected = detectBrowserLanguage()
if (detected && detected !== language) setLanguageState(detected)
const defaultLanguage = normalizeLanguage(null)
if (defaultLanguage !== language) setLanguageState(defaultLanguage)
}
}, [])
@@ -135,8 +135,8 @@ describe('DashboardAccessGuard route helpers', () => {
})
it('builds sign-in redirects with public dashboard return paths', () => {
expect(buildSignInRedirect('/reservations')).toBe('/en/dark/sign-in?redirect=%2Fdashboard%2Freservations')
expect(buildSignInRedirect('/dashboard/fleet')).toBe('/en/dark/sign-in?redirect=%2Fdashboard%2Ffleet')
expect(buildSignInRedirect('/reservations')).toBe('/ar/dark/sign-in?redirect=%2Fdashboard%2Freservations')
expect(buildSignInRedirect('/dashboard/fleet')).toBe('/ar/dark/sign-in?redirect=%2Fdashboard%2Ffleet')
})
it('treats subscription as an owner-only recovery route independent of menu registration', () => {
@@ -21,8 +21,8 @@ describe('dashboard path normalization', () => {
})
it('builds the canonical homepage sign-in URL with a dashboard return path', () => {
expect(buildHomepageSignInPath('/reservations')).toBe('/en/dark/sign-in?redirect=%2Fdashboard%2Freservations')
expect(buildHomepageSignInPath('/reservations')).toBe('/ar/dark/sign-in?redirect=%2Fdashboard%2Freservations')
expect(buildHomepageSignInPath('/dashboard/fleet', { locale: 'fr', theme: 'dark' })).toBe('/fr/dark/sign-in?redirect=%2Fdashboard%2Ffleet')
expect(buildHomepageSignInPath()).toBe('/en/dark/sign-in')
expect(buildHomepageSignInPath()).toBe('/ar/dark/sign-in')
})
})
+1 -1
View File
@@ -1,5 +1,5 @@
const DASHBOARD_BASE_PATH = '/dashboard'
const DEFAULT_SIGN_IN_LOCALE = 'en'
const DEFAULT_SIGN_IN_LOCALE = 'ar'
const DEFAULT_SIGN_IN_THEME = 'dark'
export function toDashboardAppPath(path?: string | null): string {
+4 -4
View File
@@ -77,7 +77,7 @@ describe('dashboard proxy', () => {
const response = proxy(request('http://dashboard:3001/dashboard/team') as never)
expect(response).toEqual({ kind: 'redirect', url: 'https://rentaldrivego.example/en/dark/sign-in?redirect=%2Fdashboard%2Fteam' })
expect(response).toEqual({ kind: 'redirect', url: 'https://rentaldrivego.example/ar/dark/sign-in?redirect=%2Fdashboard%2Fteam' })
})
it('redirects unprefixed internal app paths with a public dashboard return path', async () => {
@@ -85,7 +85,7 @@ describe('dashboard proxy', () => {
const response = proxy(request('http://dashboard:3001/reservations') as never)
expect(response).toEqual({ kind: 'redirect', url: 'https://rentaldrivego.example/en/dark/sign-in?redirect=%2Fdashboard%2Freservations' })
expect(response).toEqual({ kind: 'redirect', url: 'https://rentaldrivego.example/ar/dark/sign-in?redirect=%2Fdashboard%2Freservations' })
})
it('ignores spoofed forwarded host/proto when building the dashboard sign-in redirect', async () => {
@@ -98,7 +98,7 @@ describe('dashboard proxy', () => {
},
}) as never)
expect(response).toEqual({ kind: 'redirect', url: 'https://market.example.com/en/dark/sign-in?redirect=%2Fdashboard%2Fbilling' })
expect(response).toEqual({ kind: 'redirect', url: 'https://market.example.com/ar/dark/sign-in?redirect=%2Fdashboard%2Fbilling' })
})
it('ignores internal forwarded hosts when building the dashboard sign-in redirect', async () => {
@@ -111,7 +111,7 @@ describe('dashboard proxy', () => {
},
}) as never)
expect(response).toEqual({ kind: 'redirect', url: 'https://market.example.com/en/dark/sign-in?redirect=%2Fdashboard%2Ffleet' })
expect(response).toEqual({ kind: 'redirect', url: 'https://market.example.com/ar/dark/sign-in?redirect=%2Fdashboard%2Ffleet' })
})
it('redirects legacy dashboard sign-in requests to the localized homepage sign-in route', async () => {
+1 -1
View File
@@ -4,7 +4,7 @@ import type { NextRequest } from 'next/server'
const WEBSITE_URL = process.env.NEXT_PUBLIC_WEBSITE_URL ?? 'http://localhost:3000'
const DASHBOARD_PUBLIC_URL = process.env.NEXT_PUBLIC_DASHBOARD_URL ?? `${WEBSITE_URL.replace(/\/$/, '')}/dashboard`
const DASHBOARD_BASE_PATH = '/dashboard'
const DEFAULT_SIGN_IN_LOCALE = 'en'
const DEFAULT_SIGN_IN_LOCALE = 'ar'
const DEFAULT_SIGN_IN_THEME = 'dark'
function toDashboardAppPath(pathname: string): string {