@@ -4,6 +4,65 @@ import path from 'path';
44import fs from 'fs' ;
55import { buildSearchIndex } from './src/utils/search/build-search-index' ;
66
7+ /** ----- i18n translation-removal + Jaen recreation config ----- */
8+ const DEFAULT_LOCALE = 'en-US' ;
9+ /** These are the locale URL prefixes you configured in gatsby-plugin-i18n-l10n */
10+ const LOCALE_PREFIXES = [ 'en' , 'de' , 'tr' , 'ar' ] ;
11+ /** Remove *translations* for these URL roots (and all their children) */
12+ const URL_BLACKLIST = [ '/cms/' , '/login/' , '/mailpress/' , '/settings/' , '/logout/' ] ;
13+
14+ /** Normalize path to have leading slash, no duplicate slashes */
15+ const normalizePath = ( p : string ) => {
16+ if ( ! p ) return '/' ;
17+ let s = p . trim ( ) ;
18+ if ( ! s . startsWith ( '/' ) ) s = '/' + s ;
19+ // collapse multiple slashes
20+ s = s . replace ( / \/ { 2 , } / g, '/' ) ;
21+ return s ;
22+ } ;
23+
24+ /** Strip any known locale prefix like /de or /tr from the start of the path */
25+ const stripLocalePrefix = ( p : string ) => {
26+ const norm = normalizePath ( p ) ;
27+ // build regex like ^/(en|de|tr|ar)(/|$)
28+ const re = new RegExp ( `^/(?:${ LOCALE_PREFIXES . join ( '|' ) } )(?=/|$)` , 'i' ) ;
29+ const stripped = norm . replace ( re , '' ) ;
30+ return stripped || '/' ;
31+ } ;
32+
33+ /** True if path is under any blacklisted URL root (exact or child) */
34+ const isUnderBlacklistedRoot = ( p : string ) => {
35+ const norm = normalizePath ( p ) ;
36+ // drop trailing slash for compare
37+ const trimmed = norm . replace ( / \/ + $ / , '' ) ;
38+ return URL_BLACKLIST . some ( root => {
39+ const r = normalizePath ( root ) . replace ( / \/ + $ / , '' ) ;
40+ return trimmed === r || trimmed . startsWith ( r + '/' ) ;
41+ } ) ;
42+ } ;
43+
44+ const detectLocaleFromPath = ( p : string ) : string | undefined => {
45+ const norm = normalizePath ( p ) ;
46+ const seg = norm . split ( '/' ) [ 1 ] ; // first segment after leading slash
47+ return LOCALE_PREFIXES . includes ( seg ) ? seg : undefined ;
48+ } ;
49+
50+ /** Try to detect locale from page.context or from URL */
51+ const getPageLocale = ( page : any ) : string | undefined => {
52+ const ctx = page ?. context ?? { } ;
53+ return (
54+ ctx . locale ??
55+ ctx . language ??
56+ ctx . lang ??
57+ ctx ?. i18n ?. locale ??
58+ ctx ?. intl ?. locale ??
59+ ctx ?. intl ?. language ??
60+ detectLocaleFromPath ( page . path )
61+ ) ;
62+ } ;
63+
64+ /** ----------------------------------------------------- */
65+
766export const onCreateWebpackConfig : GatsbyNode [ 'onCreateWebpackConfig' ] = ( {
867 actions
968} ) => {
@@ -16,6 +75,62 @@ export const onCreateWebpackConfig: GatsbyNode['onCreateWebpackConfig'] = ({
1675 } ) ;
1776} ;
1877
78+ /**
79+ * Goal:
80+ * - Recreate every *non-blacklisted* page (default + translated) as a Jaen page so metadata is editable per locale.
81+ * - For blacklisted URL roots, keep default locale and remove translations.
82+ * - Use a per-locale stable Jaen id: `path:<path-without-locale>::<locale>`
83+ * - Avoid infinite loops with `__jaenRecreated`.
84+ */
85+ export const onCreatePage : GatsbyNode [ 'onCreatePage' ] = async ( { page, actions } ) => {
86+ const { deletePage, createPage } = actions ;
87+
88+ // Prevent infinite reprocessing
89+ if ( ( page . context as any ) ?. __jaenRecreated ) {
90+ return ;
91+ }
92+
93+ const locale = getPageLocale ( page ) || DEFAULT_LOCALE ;
94+ const isTranslated = locale !== DEFAULT_LOCALE ;
95+
96+ // figure out the effective "base" path without locale prefix
97+ const pathNoLocale = stripLocalePrefix ( page . path ) ;
98+ const matchNoLocale = page . matchPath ? stripLocalePrefix ( page . matchPath ) : undefined ;
99+
100+ const isBlacklisted =
101+ isUnderBlacklistedRoot ( pathNoLocale ) ||
102+ ( matchNoLocale && isUnderBlacklistedRoot ( matchNoLocale ) ) ;
103+
104+ // 1) Blacklisted: keep default, remove translations; don't recreate
105+ if ( isBlacklisted ) {
106+ if ( isTranslated ) {
107+ deletePage ( page ) ;
108+ }
109+ return ;
110+ }
111+
112+ // 2) Not blacklisted: recreate **every** locale (default + translated) as a Jaen page
113+ // Per-locale Jaen id so each locale has its own editable metadata
114+ const stableJaenId = `path:${ pathNoLocale } ::${ locale } ` ;
115+
116+ // Recreate with augmented context for Jaen
117+ deletePage ( page ) ;
118+ createPage ( {
119+ ...page ,
120+ context : {
121+ ...page . context ,
122+ __jaenRecreated : true ,
123+ locale,
124+ // Jaen identifiers; keep both keys for compatibility
125+ jaenPageId : stableJaenId ,
126+ jaenId : stableJaenId ,
127+ // useful helper if you need to map back to base path in components
128+ originalPath : pathNoLocale ,
129+ ...( matchNoLocale ? { matchPathNoLocale : matchNoLocale } : { } )
130+ }
131+ } ) ;
132+ } ;
133+
19134export const onPostBuild : GatsbyNode [ 'onPostBuild' ] = async ( {
20135 graphql,
21136 reporter
@@ -82,7 +197,6 @@ export const onPostBuild: GatsbyNode['onPostBuild'] = async ({
82197 reporter . panicOnBuild (
83198 `Error while running GraphQL query. ${ result . errors } `
84199 ) ;
85-
86200 return ;
87201 }
88202
@@ -121,7 +235,6 @@ async function preparePagesAndBuildSearch(allJaenPage: {
121235 const originPath = node . buildPath ;
122236
123237 let type = node . template ;
124-
125238 if ( type && path . extname ( type ) ) {
126239 type = path . basename ( type , path . extname ( type ) ) ;
127240 }
0 commit comments