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
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:
@@ -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");
|
||||
|
||||
@@ -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,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 {
|
||||
|
||||
@@ -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 () => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user