@@ -47,6 +47,7 @@ import * as ChangeFramework from './blocks/utils/change_framework'
4747import { mutatorOpenListener } from './blocks/mrc_param_container'
4848import { TOOLBOX_UPDATE_EVENT } from './blocks/mrc_mechanism_component_holder' ;
4949import { antdThemeFromString } from './reactComponents/ThemeModal' ;
50+ import { useTranslation } from 'react-i18next' ;
5051
5152/** Storage key for shown toolbox categories. */
5253const SHOWN_TOOLBOX_CATEGORIES_KEY = 'shownPythonToolboxCategories' ;
@@ -86,6 +87,8 @@ const LAYOUT_BACKGROUND_COLOR = '#0F0';
8687 * project management, and user interface layout.
8788 */
8889const App : React . FC = ( ) : React . JSX . Element => {
90+ const { t, i18n } = useTranslation ( ) ;
91+
8992 const [ alertErrorMessage , setAlertErrorMessage ] = React . useState ( '' ) ;
9093 const [ storage , setStorage ] = React . useState < commonStorage . Storage | null > ( null ) ;
9194 const [ currentModule , setCurrentModule ] = React . useState < commonStorage . Module | null > ( null ) ;
@@ -101,7 +104,6 @@ const App: React.FC = (): React.JSX.Element => {
101104 const [ rightCollapsed , setRightCollapsed ] = React . useState ( false ) ;
102105 const [ theme , setTheme ] = React . useState ( 'dark' ) ;
103106
104-
105107 const blocksEditor = React . useRef < editor . Editor | null > ( null ) ;
106108 const generatorContext = React . useRef < GeneratorContext | null > ( null ) ;
107109 const blocklyComponent = React . useRef < BlocklyComponentType | null > ( null ) ;
@@ -232,7 +234,7 @@ const App: React.FC = (): React.JSX.Element => {
232234 const tabs : Tabs . TabItem [ ] = [
233235 {
234236 key : projectData . robot . modulePath ,
235- title : 'Robot' ,
237+ title : t ( 'ROBOT' ) ,
236238 type : TabType . ROBOT ,
237239 } ,
238240 ] ;
@@ -261,7 +263,7 @@ const App: React.FC = (): React.JSX.Element => {
261263 if ( blocksEditor . current && currentModule ) {
262264 blocksEditor . current . updateToolbox ( shownPythonToolboxCategories ) ;
263265 }
264- } , [ currentModule , shownPythonToolboxCategories ] ) ;
266+ } , [ currentModule , shownPythonToolboxCategories , i18n . language ] ) ;
265267
266268 // Add event listener for toolbox updates
267269 React . useEffect ( ( ) => {
@@ -290,7 +292,31 @@ const App: React.FC = (): React.JSX.Element => {
290292 if ( blocksEditor . current ) {
291293 blocksEditor . current . loadModuleBlocks ( currentModule ) ;
292294 }
293- } , [ currentModule ] ) ;
295+ } , [ currentModule ] ) ;
296+
297+ const setupWorkspace = ( newWorkspace : Blockly . WorkspaceSvg ) => {
298+ if ( ! blocklyComponent . current || ! storage ) {
299+ return ;
300+ }
301+ // Recreate workspace when Blockly component is ready
302+ ChangeFramework . setup ( newWorkspace ) ;
303+ newWorkspace . addChangeListener ( mutatorOpenListener ) ;
304+ newWorkspace . addChangeListener ( handleBlocksChanged ) ;
305+ generatorContext . current = createGeneratorContext ( ) ;
306+
307+ if ( currentModule ) {
308+ generatorContext . current . setModule ( currentModule ) ;
309+ }
310+
311+ blocksEditor . current = new editor . Editor ( newWorkspace , generatorContext . current , storage ) ;
312+
313+ // Set the current module in the editor after creating it
314+ if ( currentModule ) {
315+ blocksEditor . current . loadModuleBlocks ( currentModule ) ;
316+ }
317+
318+ blocksEditor . current . updateToolbox ( shownPythonToolboxCategories ) ;
319+ } ;
294320
295321 // Initialize Blockly workspace and editor when component and storage are ready
296322 React . useEffect ( ( ) => {
@@ -300,17 +326,8 @@ const App: React.FC = (): React.JSX.Element => {
300326
301327 const blocklyWorkspace = blocklyComponent . current . getBlocklyWorkspace ( ) ;
302328 if ( blocklyWorkspace ) {
303- ChangeFramework . setup ( blocklyWorkspace ) ;
304- blocklyWorkspace . addChangeListener ( mutatorOpenListener ) ;
305- blocklyWorkspace . addChangeListener ( handleBlocksChanged ) ;
329+ setupWorkspace ( blocklyWorkspace ) ;
306330 }
307-
308- generatorContext . current = createGeneratorContext ( ) ;
309- if ( currentModule ) {
310- generatorContext . current . setModule ( currentModule ) ;
311- }
312-
313- blocksEditor . current = new editor . Editor ( blocklyWorkspace , generatorContext . current , storage ) ;
314331 } , [ blocklyComponent , storage ] ) ;
315332
316333 // Generate code when module or regeneration trigger changes
@@ -342,6 +359,31 @@ const App: React.FC = (): React.JSX.Element => {
342359 }
343360 } , [ project ] ) ;
344361
362+ // Handle language changes with automatic saving
363+ React . useEffect ( ( ) => {
364+ const handleLanguageChange = async ( ) => {
365+ // Save current blocks before language change
366+ if ( currentModule && areBlocksModified ( ) ) {
367+ try {
368+ await saveBlocks ( ) ;
369+ } catch ( e ) {
370+ console . error ( 'Failed to save blocks before language change:' , e ) ;
371+ }
372+ }
373+
374+ // Update toolbox after language change
375+ if ( blocksEditor . current ) {
376+ blocksEditor . current . updateToolbox ( shownPythonToolboxCategories ) ;
377+ }
378+ } ;
379+
380+ i18n . on ( 'languageChanged' , handleLanguageChange ) ;
381+
382+ return ( ) => {
383+ i18n . off ( 'languageChanged' , handleLanguageChange ) ;
384+ } ;
385+ } , [ currentModule , shownPythonToolboxCategories , i18n ] ) ;
386+
345387 const { Sider, Content } = Antd . Layout ;
346388
347389 return (
@@ -392,6 +434,7 @@ const App: React.FC = (): React.JSX.Element => {
392434 < Content >
393435 < BlocklyComponent
394436 theme = { theme }
437+ onWorkspaceRecreated = { setupWorkspace }
395438 ref = { blocklyComponent }
396439 />
397440 </ Content >
0 commit comments