diff --git a/src/containers/blocks.jsx b/src/containers/blocks.jsx
index 98a01db1bf1cf1819da808b4d3c2e9b08129bdef..c982bfeccfed36055895a0a1dd3e117066734176 100644
--- a/src/containers/blocks.jsx
+++ b/src/containers/blocks.jsx
@@ -87,6 +87,7 @@ class Blocks extends React.Component {
     componentDidMount () {
         this.ScratchBlocks.FieldColourSlider.activateEyedropper_ = this.props.onActivateColorPicker;
         this.ScratchBlocks.Procedures.externalProcedureDefCallback = this.props.onActivateCustomProcedures;
+        this.ScratchBlocks.ScratchMsgs.setLocale(this.props.locale);
 
         const workspaceConfig = defaultsDeep({},
             Blocks.defaultOptions,
@@ -526,7 +527,7 @@ Blocks.propTypes = {
     extensionLibraryVisible: PropTypes.bool,
     isRtl: PropTypes.bool,
     isVisible: PropTypes.bool,
-    locale: PropTypes.string,
+    locale: PropTypes.string.isRequired,
     messages: PropTypes.objectOf(PropTypes.string),
     onActivateColorPicker: PropTypes.func,
     onActivateCustomProcedures: PropTypes.func,
diff --git a/test/integration/localization.test.js b/test/integration/localization.test.js
index 4fb1e8d59f085b93a8fe9d457e720dc5ff7f96e4..e7cc64e90b6127ac4ed993ca4450c54cb1b886b9 100644
--- a/test/integration/localization.test.js
+++ b/test/integration/localization.test.js
@@ -24,7 +24,7 @@ describe('Localization', () => {
         await driver.quit();
     });
 
-    test('Localization', async () => {
+    test('Switching languages', async () => {
         await loadUri(uri);
         await clickXpath('//button[@title="Try It"]');
 
@@ -52,4 +52,15 @@ describe('Localization', () => {
         const logs = await getLogs();
         await expect(logs).toEqual([]);
     });
+
+    // Regression test for #4476, blocks in wrong language when loaded with locale
+    test('Loading with locale shows correct blocks', async () => {
+        await loadUri(`${uri}?locale=de`);
+        await clickXpath('//button[@title="Ausprobieren!"]'); // "Try It"
+        await clickText('Fühlen'); // Sensing category in German
+        await new Promise(resolve => setTimeout(resolve, 1000)); // wait for blocks to scroll
+        await clickText('Antwort'); // Find the "answer" block in German
+        const logs = await getLogs();
+        await expect(logs).toEqual([]);
+    });
 });