@@ -1117,12 +1117,42 @@ const LanguageMapper = ({stack, uid} :{ stack : IDropDown, uid : string}) => {
11171117 const sourceLocaleValue = ( singleSourceLocale . value || singleSourceLocale . label || '' ) . toLowerCase ( ) ;
11181118 const destinationLocale = ( stack ?. master_locale || 'en-us' ) . toLowerCase ( ) ;
11191119
1120+ const hasExactDestination = allLocales . some ( dest => {
1121+ const destValue = ( dest . value || dest . label || '' ) . toLowerCase ( ) ;
1122+ return destValue === sourceLocaleValue ;
1123+ } ) ;
1124+
1125+ if ( ! hasExactDestination && sourceLocaleValue !== destinationLocale ) {
1126+ console . info ( '⚠️ [Single Locale] No exact destination match found. Leaving master locale unmapped.' , {
1127+ sourceLocaleValue,
1128+ destinationLocale,
1129+ allLocales : allLocales . map ( dest => dest . value || dest . label )
1130+ } ) ;
1131+
1132+ if ( cmsLocaleOptions ?. length === 0 ) {
1133+ setcmsLocaleOptions ( [ {
1134+ label : destinationLocale ,
1135+ value : destinationLocale
1136+ } ] ) ;
1137+ }
1138+
1139+ setAutoSelectedSourceLocale ( null ) ;
1140+ setMapperLocaleState ( { } ) ;
1141+ if ( isStackChanged ) {
1142+ setisStackChanged ( false ) ;
1143+ }
1144+ setTimeout ( ( ) => {
1145+ isProcessingRef . current = false ;
1146+ } , 0 ) ;
1147+ return ;
1148+ }
1149+
11201150 console . info ( '🔥 [Single Locale Auto-Map] Mapping single source to destination master:' , {
11211151 source : sourceLocaleValue ,
11221152 destination : destinationLocale ,
11231153 source_locale_object : singleSourceLocale ,
11241154 stack_master_locale : stack ?. master_locale ,
1125- reason : 'Single source locale - no other choice '
1155+ reason : hasExactDestination ? 'Exact destination match found' : 'Source equals master locale '
11261156 } ) ;
11271157
11281158 const autoMapping = {
@@ -1314,49 +1344,81 @@ const LanguageMapper = ({stack, uid} :{ stack : IDropDown, uid : string}) => {
13141344 autoMapping [ match . source ] = match . dest ;
13151345 } ) ;
13161346
1317- // 🔥 CRITICAL FIX: Update cmsLocaleOptions with master locale ALWAYS first
1318- const destinationLocalesInMapping = new Set < string > ( ) ;
1347+ const leftoverAssignments : Array < { source : string ; dest : string } > = [ ] ;
1348+ const assignedDestinations = new Set < string > ( ) ;
1349+ if ( masterLocaleMatch ) {
1350+ assignedDestinations . add ( masterLocaleMatch . dest ) ;
1351+ }
1352+ exactMatches . forEach ( match => {
1353+ if ( ! ( match . source === normalizedStackMaster && masterLocaleMatch ) ) {
1354+ assignedDestinations . add ( match . dest ) ;
1355+ }
1356+ } ) ;
1357+ assignedDestinations . add ( normalizedStackMaster ) ;
13191358
1320- // 🔥 Don't use Set for ordering - use array to maintain master-first order
1321- const orderedDestLocales : string [ ] = [ ] ;
1359+ const availableDestLocales = allLocales
1360+ . map ( dest => ( dest . value || dest . label || '' ) . toLowerCase ( ) )
1361+ . filter ( dest => dest && dest !== normalizedStackMaster && ! assignedDestinations . has ( dest ) ) ;
13221362
1323- // 🔥 STEP 1: ALWAYS add master locale first
1324- orderedDestLocales . push ( normalizedStackMaster ) ;
1363+ unmatchedSources . forEach ( ( sourceValue , idx ) => {
1364+ const candidateDest = availableDestLocales [ idx ] ;
1365+ if ( ! candidateDest ) {
1366+ console . info ( '⚠️ [TC-03/TC-08] No available destination locale to assign for:' , { sourceValue } ) ;
1367+ return ;
1368+ }
1369+ console . info ( '🎯 [TC-03] Assigning unmatched source to remaining destination:' , {
1370+ sourceValue,
1371+ candidateDest
1372+ } ) ;
1373+ autoMapping [ sourceValue ] = candidateDest ;
1374+ leftoverAssignments . push ( { source : sourceValue , dest : candidateDest } ) ;
1375+ assignedDestinations . add ( candidateDest ) ;
1376+ } ) ;
13251377
1326- // 🔥 STEP 2: Add all other exact match destinations (excluding master if already added)
1378+ const destinationLocalesInMapping = new Set < string > ( ) ;
1379+ destinationLocalesInMapping . add ( normalizedStackMaster ) ;
13271380 exactMatches . forEach ( match => {
1328- if ( match . dest !== normalizedStackMaster && ! orderedDestLocales . includes ( match . dest ) ) {
1329- orderedDestLocales . push ( match . dest ) ;
1330- }
1381+ destinationLocalesInMapping . add ( match . dest ) ;
1382+ } ) ;
1383+ leftoverAssignments . forEach ( assign => {
1384+ destinationLocalesInMapping . add ( assign . dest ) ;
13311385 } ) ;
13321386
13331387 setcmsLocaleOptions ( ( ) => {
13341388 const newList : { label : string ; value : string } [ ] = [ ] ;
1389+ const processedLocales = new Set < string > ( ) ;
13351390
1336- // Build list in order from orderedDestLocales array
1337- orderedDestLocales . forEach ( destLocale => {
1391+ if ( ! processedLocales . has ( normalizedStackMaster ) ) {
13381392 newList . push ( {
1339- label : destLocale ,
1340- value : destLocale
1393+ label : normalizedStackMaster ,
1394+ value : normalizedStackMaster
13411395 } ) ;
1396+ processedLocales . add ( normalizedStackMaster ) ;
1397+ }
1398+
1399+ destinationLocalesInMapping . forEach ( destLocale => {
1400+ if ( ! processedLocales . has ( destLocale ) ) {
1401+ newList . push ( {
1402+ label : destLocale ,
1403+ value : destLocale
1404+ } ) ;
1405+ processedLocales . add ( destLocale ) ;
1406+ }
13421407 } ) ;
13431408
13441409 console . info ( '🔥 [Multi-locale] Updated cmsLocaleOptions (master GUARANTEED first):' , {
13451410 newList,
13461411 first : newList [ 0 ] ,
13471412 second : newList [ 1 ] ,
13481413 length : newList . length ,
1349- orderedDestLocales,
1414+ orderedDestLocales : Array . from ( destinationLocalesInMapping ) ,
13501415 VERIFY_MASTER_IS_FIRST : newList [ 0 ] ?. label === normalizedStackMaster
13511416 } ) ;
13521417 return newList ;
13531418 } ) ;
13541419
1355- // 🔥 CRITICAL FIX: Update mapperLocaleState with proper keys
13561420 const updatedMapperState : ExistingFieldType = { } ;
13571421
1358- // 🔥 CRITICAL: Keys MUST be destination locale codes (what appears in cmsLocaleOptions)
1359- // Values MUST be source locale objects (what should appear in the source dropdown)
13601422 if ( masterLocaleMatch ) {
13611423 updatedMapperState [ normalizedStackMaster ] = {
13621424 label : masterLocaleMatch . source ,
@@ -1380,14 +1442,13 @@ const LanguageMapper = ({stack, uid} :{ stack : IDropDown, uid : string}) => {
13801442 } ) ;
13811443 }
13821444
1383- // 🔥 For other matched rows - use destination locale as key, source locale as value
13841445 exactMatches . forEach ( match => {
13851446 if ( match . dest === normalizedStackMaster ) {
13861447 console . info ( '🔥 [Multi-locale] Skipping duplicate master:' , {
13871448 match_dest : match . dest ,
13881449 normalizedStackMaster
13891450 } ) ;
1390- return ; // Already processed as master
1451+ return ;
13911452 }
13921453
13931454 updatedMapperState [ match . dest ] = {
@@ -1401,6 +1462,18 @@ const LanguageMapper = ({stack, uid} :{ stack : IDropDown, uid : string}) => {
14011462 } ) ;
14021463 } ) ;
14031464
1465+ leftoverAssignments . forEach ( assign => {
1466+ updatedMapperState [ assign . dest ] = {
1467+ label : assign . source ,
1468+ value : assign . source
1469+ } ;
1470+ console . info ( '🔥 [Multi-locale] Set leftover row:' , {
1471+ key : assign . dest ,
1472+ value : assign . source ,
1473+ full_object : updatedMapperState [ assign . dest ]
1474+ } ) ;
1475+ } ) ;
1476+
14041477 console . info ( '🔥 [Multi-locale] Final mapperLocaleState:' , {
14051478 updatedMapperState,
14061479 keys : Object . keys ( updatedMapperState ) ,
0 commit comments