@@ -35,6 +35,7 @@ import { type Context, createContext, provideContext } from '@openelement/elemen
3535import { escapeAttr , escapeHtml } from '@openelement/element' ;
3636import { createLogger } from '@openelement/element' ;
3737import { defineCustomElement } from '@openelement/element' ;
38+ import { normalizeLocalePath } from '@openelement/app/i18n' ;
3839import '@openelement/ui/open-theme-toggle' ;
3940
4041export const tagName = 'open-layout' ;
@@ -61,27 +62,22 @@ function isSafeLayoutUrl(url: string): boolean {
6162 }
6263}
6364
64- /* --- Locale/path helpers for the site shell --- */
65+ /* --- Locale/path helpers: thin wrappers over @openelement/app/i18n --- */
6566
6667const LOCALE_LABELS : Record < string , string > = { en : '中文' , zh : 'English' } ;
6768
68- function parsePathWithoutLocale ( pathname : string , locales : string [ ] ) : string {
69- const segs = pathname . split ( '/' ) . filter ( Boolean ) ;
70- if ( segs . length > 0 && locales . includes ( segs [ 0 ] ) ) {
71- return '/' + segs . slice ( 1 ) . join ( '/' ) || '/' ;
72- }
73- return pathname || '/' ;
74- }
75-
76- function detectLocale ( pathname : string , locales : string [ ] , defaultLocale : string ) : string {
77- const segs = pathname . split ( '/' ) . filter ( Boolean ) ;
78- if ( segs . length > 0 && locales . includes ( segs [ 0 ] ) ) return segs [ 0 ] ;
79- return defaultLocale ;
80- }
81-
82- function localizePath ( path : string , locale : string , defaultLocale : string ) : string {
69+ function localizePath (
70+ path : string ,
71+ locale : string ,
72+ locales : string [ ] ,
73+ defaultLocale : string ,
74+ ) : string {
8375 if ( isSafeLayoutUrl ( path ) && / ^ h t t p s ? : / i. test ( path ) ) return path ;
84- return locale === defaultLocale ? path : `/${ locale } ${ path } ` ;
76+ if ( locale === defaultLocale ) return path ;
77+ return normalizeLocalePath ( `/${ locale } ${ path === '/' ? '' : path } ` , {
78+ locales,
79+ defaultLocale,
80+ } ) . localizedPath ;
8581}
8682
8783function switchPath (
@@ -91,7 +87,8 @@ function switchPath(
9187 defaultLocale : string ,
9288) : string {
9389 const other = locales . find ( ( l ) => l !== currentLocale ) || currentLocale ;
94- return localizePath ( currentPath , other , defaultLocale ) ;
90+ const bare = normalizeLocalePath ( currentPath , { locales, defaultLocale } ) . path ;
91+ return localizePath ( bare , other , locales , defaultLocale ) ;
9592}
9693
9794function switchLabel ( currentLocale : string ) : string {
@@ -595,7 +592,10 @@ export class OpenLayout extends OpenElement {
595592 private get _currentLocale ( ) : string {
596593 try {
597594 if ( typeof globalThis . location !== 'undefined' ) {
598- return detectLocale ( location . pathname , this . _locales , this . _defaultLocale ) ;
595+ return normalizeLocalePath ( location . pathname , {
596+ locales : this . _locales ,
597+ defaultLocale : this . _defaultLocale ,
598+ } ) . locale ;
599599 }
600600 return this . _defaultLocale ;
601601 } catch {
@@ -606,7 +606,10 @@ export class OpenLayout extends OpenElement {
606606 private get _currentPathWithoutLocale ( ) : string {
607607 try {
608608 if ( typeof globalThis . location !== 'undefined' ) {
609- return parsePathWithoutLocale ( location . pathname , this . _locales ) ;
609+ return normalizeLocalePath ( location . pathname , {
610+ locales : this . _locales ,
611+ defaultLocale : this . _defaultLocale ,
612+ } ) . path ;
610613 }
611614 return this . getAttribute ( 'current-path' ) || '/' ;
612615 } catch {
@@ -649,7 +652,7 @@ export class OpenLayout extends OpenElement {
649652
650653 // _currentPathWithoutLocale, _currentLocale, _locales, _switchPath(),
651654 // _switchLabel(), _updateSwitch(), _localizePath()
652- // Site-local helpers keep the shell independent from application internals .
655+ // Locale path math goes through @openelement /app/i18n (normalizeLocalePath) .
653656
654657 private _currentPath ( ) : string {
655658 // SSR-safe: prefer attribute/prop set by renderDsd over URL detection
@@ -660,7 +663,10 @@ export class OpenLayout extends OpenElement {
660663 if ( attr && attr . length > 0 ) return attr ;
661664 try {
662665 if ( typeof globalThis . location !== 'undefined' ) {
663- return parsePathWithoutLocale ( location . pathname , this . _locales ) ;
666+ return normalizeLocalePath ( location . pathname , {
667+ locales : this . _locales ,
668+ defaultLocale : this . _defaultLocale ,
669+ } ) . path ;
664670 }
665671 return this . getAttribute ( 'current-path' ) || '/' ;
666672 } catch {
@@ -848,7 +854,7 @@ export class OpenLayout extends OpenElement {
848854 return {
849855 href : isExternal
850856 ? safeHref
851- : localizePath ( safeHref , this . _currentLocale , this . _defaultLocale ) ,
857+ : localizePath ( safeHref , this . _currentLocale , this . _locales , this . _defaultLocale ) ,
852858 isExternal,
853859 } ;
854860 }
@@ -867,7 +873,7 @@ export class OpenLayout extends OpenElement {
867873 const langHref = locales . length > 1
868874 ? switchPath ( currentPath , currentLocale , locales , defaultLocale )
869875 : '' ;
870- const localePath = ( path : string ) => localizePath ( path , currentLocale , defaultLocale ) ;
876+ const localePath = ( path : string ) => localizePath ( path , currentLocale , locales , defaultLocale ) ;
871877
872878 return (
873879 < div className = 'app-layout' part = 'container' home = { home || undefined } >
0 commit comments