@@ -725,6 +725,8 @@ export default async function build(
725
725
// n.b. we cannot handle this above in combinedPages because the dynamic
726
726
// page must be in the `pages` array, but not in the mapping.
727
727
exportPathMap : ( defaultMap : any ) => {
728
+ const { i18n } = config . experimental
729
+
728
730
// Dynamically routed pages should be prerendered to be used as
729
731
// a client-side skeleton (fallback) while data is being fetched.
730
732
// This ensures the end-user never sees a 500 or slow response from the
@@ -738,7 +740,14 @@ export default async function build(
738
740
if ( ssgStaticFallbackPages . has ( page ) ) {
739
741
// Override the rendering for the dynamic page to be treated as a
740
742
// fallback render.
741
- defaultMap [ page ] = { page, query : { __nextFallback : true } }
743
+ if ( i18n ) {
744
+ defaultMap [ `/${ i18n . defaultLocale } ${ page } ` ] = {
745
+ page,
746
+ query : { __nextFallback : true } ,
747
+ }
748
+ } else {
749
+ defaultMap [ page ] = { page, query : { __nextFallback : true } }
750
+ }
742
751
} else {
743
752
// Remove dynamically routed pages from the default path map when
744
753
// fallback behavior is disabled.
@@ -760,6 +769,39 @@ export default async function build(
760
769
}
761
770
}
762
771
772
+ if ( i18n ) {
773
+ for ( const page of [
774
+ ...staticPages ,
775
+ ...ssgPages ,
776
+ ...( useStatic404 ? [ '/404' ] : [ ] ) ,
777
+ ] ) {
778
+ const isSsg = ssgPages . has ( page )
779
+ const isDynamic = isDynamicRoute ( page )
780
+ const isFallback = isSsg && ssgStaticFallbackPages . has ( page )
781
+
782
+ for ( const locale of i18n . locales ) {
783
+ if ( ! isSsg && locale === i18n . defaultLocale ) continue
784
+ // skip fallback generation for SSG pages without fallback mode
785
+ if ( isSsg && isDynamic && ! isFallback ) continue
786
+ const outputPath = `/${ locale } ${ page === '/' ? '' : page } `
787
+
788
+ defaultMap [ outputPath ] = {
789
+ page : defaultMap [ page ] . page ,
790
+ query : { __nextLocale : locale } ,
791
+ }
792
+
793
+ if ( isFallback ) {
794
+ defaultMap [ outputPath ] . query . __nextFallback = true
795
+ }
796
+ }
797
+
798
+ if ( isSsg && ! isFallback ) {
799
+ // remove non-locale prefixed variant from defaultMap
800
+ delete defaultMap [ page ]
801
+ }
802
+ }
803
+ }
804
+
763
805
return defaultMap
764
806
} ,
765
807
trailingSlash : false ,
@@ -786,7 +828,8 @@ export default async function build(
786
828
page : string ,
787
829
file : string ,
788
830
isSsg : boolean ,
789
- ext : 'html' | 'json'
831
+ ext : 'html' | 'json' ,
832
+ additionalSsgFile = false
790
833
) => {
791
834
file = `${ file } .${ ext } `
792
835
const orig = path . join ( exportOptions . outdir , file )
@@ -820,8 +863,58 @@ export default async function build(
820
863
if ( ! isSsg ) {
821
864
pagesManifest [ page ] = relativeDest
822
865
}
823
- await promises . mkdir ( path . dirname ( dest ) , { recursive : true } )
824
- await promises . rename ( orig , dest )
866
+
867
+ const { i18n } = config . experimental
868
+
869
+ // for SSG files with i18n the non-prerendered variants are
870
+ // output with the locale prefixed so don't attempt moving
871
+ // without the prefix
872
+ if ( ! i18n || ! isSsg || additionalSsgFile ) {
873
+ await promises . mkdir ( path . dirname ( dest ) , { recursive : true } )
874
+ await promises . rename ( orig , dest )
875
+ }
876
+
877
+ if ( i18n ) {
878
+ if ( additionalSsgFile ) return
879
+
880
+ for ( const locale of i18n . locales ) {
881
+ // auto-export default locale files exist at root
882
+ // TODO: should these always be prefixed with locale
883
+ // similar to SSG prerender/fallback files?
884
+ if ( ! isSsg && locale === i18n . defaultLocale ) {
885
+ continue
886
+ }
887
+
888
+ const localeExt = page === '/' ? path . extname ( file ) : ''
889
+ const relativeDestNoPages = relativeDest . substr ( 'pages/' . length )
890
+
891
+ const updatedRelativeDest = path . join (
892
+ 'pages' ,
893
+ locale + localeExt ,
894
+ // if it's the top-most index page we want it to be locale.EXT
895
+ // instead of locale/index.html
896
+ page === '/' ? '' : relativeDestNoPages
897
+ )
898
+ const updatedOrig = path . join (
899
+ exportOptions . outdir ,
900
+ locale + localeExt ,
901
+ page === '/' ? '' : file
902
+ )
903
+ const updatedDest = path . join (
904
+ distDir ,
905
+ isLikeServerless ? SERVERLESS_DIRECTORY : SERVER_DIRECTORY ,
906
+ updatedRelativeDest
907
+ )
908
+
909
+ if ( ! isSsg ) {
910
+ pagesManifest [
911
+ `/${ locale } ${ page === '/' ? '' : page } `
912
+ ] = updatedRelativeDest
913
+ }
914
+ await promises . mkdir ( path . dirname ( updatedDest ) , { recursive : true } )
915
+ await promises . rename ( updatedOrig , updatedDest )
916
+ }
917
+ }
825
918
}
826
919
827
920
// Only move /404 to /404 when there is no custom 404 as in that case we don't know about the 404 page
@@ -877,13 +970,13 @@ export default async function build(
877
970
const extraRoutes = additionalSsgPaths . get ( page ) || [ ]
878
971
for ( const route of extraRoutes ) {
879
972
const pageFile = normalizePagePath ( route )
880
- await moveExportedPage ( page , route , pageFile , true , 'html' )
881
- await moveExportedPage ( page , route , pageFile , true , 'json' )
973
+ await moveExportedPage ( page , route , pageFile , true , 'html' , true )
974
+ await moveExportedPage ( page , route , pageFile , true , 'json' , true )
882
975
883
976
if ( hasAmp ) {
884
977
const ampPage = `${ pageFile } .amp`
885
- await moveExportedPage ( page , ampPage , ampPage , true , 'html' )
886
- await moveExportedPage ( page , ampPage , ampPage , true , 'json' )
978
+ await moveExportedPage ( page , ampPage , ampPage , true , 'html' , true )
979
+ await moveExportedPage ( page , ampPage , ampPage , true , 'json' , true )
887
980
}
888
981
889
982
finalPrerenderRoutes [ route ] = {
0 commit comments