diff --git a/src/components/button/button.css b/src/components/button/button.css
index 9ce746c52140b73be1ba889fae9c028ab7cfe2bb..9ba2fbd93b4b48dd489f6249e2cafd8abcfc2eec 100644
--- a/src/components/button/button.css
+++ b/src/components/button/button.css
@@ -11,10 +11,17 @@
 }
 
 .icon {
-    margin-right: .5rem;
     height: 1.5rem;
 }
 
+[dir="ltr"] .icon {
+    margin-right: .5rem;
+}
+
+[dir="rtl"] .icon {
+    margin-left: .5rem;
+}
+
 .content {
     white-space: nowrap;
 }
diff --git a/src/components/camera-modal/camera-modal.css b/src/components/camera-modal/camera-modal.css
index 4ea962fbafd68bc7ecdf3736d96930070a46f0de..7522fbb2ec286f0491d62d1fd6a67a7ebb5b2ed4 100644
--- a/src/components/camera-modal/camera-modal.css
+++ b/src/components/camera-modal/camera-modal.css
@@ -135,6 +135,10 @@ $main-button-size: 2.75rem;
     color: $ui-white;
 }
 
+[dir="rtl"] .retake-button img {
+    transform: scaleX(-1);
+}
+
 @keyframes flash {
     0% { opacity: 1; }
     100% { opacity: 0; }
diff --git a/src/components/camera-modal/camera-modal.jsx b/src/components/camera-modal/camera-modal.jsx
index f115a6f8a75f1c77286f15365137509313a8783f..8c499c3624922e7d84ac1b00e75cf8f9205c29c0 100644
--- a/src/components/camera-modal/camera-modal.jsx
+++ b/src/components/camera-modal/camera-modal.jsx
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
 import React from 'react';
 import {defineMessages, injectIntl, intlShape} from 'react-intl';
 import Box from '../box/box.jsx';
-import Modal from '../modal/modal.jsx';
+import Modal from '../../containers/modal.jsx';
 import styles from './camera-modal.css';
 import backIcon from './icon--back.svg';
 import cameraIcon from '../action-menu/icon--camera.svg';
@@ -79,7 +79,7 @@ const CameraModal = ({intl, ...props}) => (
             {props.capture ?
                 <Box className={styles.buttonRow}>
                     <button
-                        className={styles.cancelButton}
+                        className={styles.retakeButton}
                         key="retake-button"
                         onClick={props.onBack}
                     >
diff --git a/src/components/connection-modal/connection-modal.css b/src/components/connection-modal/connection-modal.css
index b8ca0634b32c81d1504f6f6bd915e1f2dc6380ea..5660a44eb0834a8e0a25d3be015aa29a182d173e 100644
--- a/src/components/connection-modal/connection-modal.css
+++ b/src/components/connection-modal/connection-modal.css
@@ -51,10 +51,14 @@
     align-items: center;
 }
 
-.device-tile-image {
+[dir="ltr"] .device-tile-image {
     margin-right: 0.5rem;
 }
 
+[dir="rtl"] .device-tile-image {
+    margin-left: 0.5rem;
+}
+
 .device-tile-name-wrapper {
     display: flex;
     flex-direction: column;
@@ -89,9 +93,16 @@
     align-items: flex-end;
     width: 22px;
     height: 16px;
+}
+
+[dir="ltr"] .signal-strength-meter {
     margin-right: 1rem;
 }
 
+[dir="rtl"] .signal-strength-meter {
+    margin-left: 1rem;
+}
+
 .signal-bar {
     width: 4px;
     border-radius: 4px;
@@ -110,17 +121,23 @@
 .radar {
     width: 40px;
     height: 40px;
-    margin-right: 0.5rem;
     animation: spin 4s linear infinite;
 }
 
+[dir="ltr"] .radar {
+    margin-right: .5rem;
+}
+
+[dir="rtl"] .radar {
+    margin-left: .5rem;
+}
+
 @keyframes spin {
     100% {
         transform: rotate(360deg);
     }
 }
 
-
 .device-activity {
     position: relative;
 }
@@ -134,6 +151,7 @@
     position: absolute;
     top: -5px;
     right: -15px;
+    left: -15px;
     padding: 5px 5px;
     background-color: $motion-primary;
     border-radius: 100%;
@@ -199,14 +217,26 @@
     margin-left: 3rem;
 }
 
+[dir="ltr"] .scratch-link-help-step {
+    margin-left: 3rem;
+}
+
+[dir="rtl"] .scratch-link-help-step {
+    margin-right: 3rem;
+}
+
 .scratch-link-icon {
     max-width: 50px;
 }
 
-.help-step-image {
+[dir="ltr"] .help-step-image {
     margin-right: 0.5rem;
 }
 
+[dir="rtl"] .help-step-image {
+    margin-left: 0.5rem;
+}
+
 .help-step-number {
     background: $pen-primary;
     border-radius: 100%;
@@ -215,11 +245,18 @@
     align-items: center;
     color: $ui-white;
     font-weight: bold;
-    margin-right: 0.5rem;
     min-width: 2rem;
     height: 2rem;
 }
 
+[dir="ltr"] .help-step-number {
+    margin-right: 0.5rem;
+}
+
+[dir="rtl"] .help-step-number {
+    margin-left: 0.5rem;
+}
+
 .button-row {
     font-weight: bolder;
     text-align: center;
@@ -265,14 +302,26 @@
     border-bottom-left-radius: 0;
 }
 
-.button-icon-right {
+[dir="ltr"] .button-icon-right {
     margin-left: 0.5rem;
 }
+[dir="rtl"] .button-icon-right {
+    margin-right: 0.5rem;
+}
 
-.button-icon-left {
+[dir="ltr"] .button-icon-left {
     margin-right: 0.5rem;
 }
 
+[dir="rtl"] .button-icon-left {
+    margin-left: 0.5rem;
+}
+
+/* reverse back arrow icon for RTL, don't reverse other connection icons */
+[dir="rtl"] .button-icon-back {
+    transform: scaleX(-1);
+}
+
 .red-button {
     background: $red-primary;
 }
diff --git a/src/components/connection-modal/connection-modal.jsx b/src/components/connection-modal/connection-modal.jsx
index c6566e954db7c3b5de3b32a8de3a2d6439115838..b8a5feea7d84137816923816377ee114592f1836 100644
--- a/src/components/connection-modal/connection-modal.jsx
+++ b/src/components/connection-modal/connection-modal.jsx
@@ -3,7 +3,7 @@ import React from 'react';
 import keyMirror from 'keymirror';
 
 import Box from '../box/box.jsx';
-import Modal from '../modal/modal.jsx';
+import Modal from '../../containers/modal.jsx';
 
 import ScanningStep from '../../containers/scanning-step.jsx';
 import ConnectingStep from './connecting-step.jsx';
diff --git a/src/components/connection-modal/error-step.jsx b/src/components/connection-modal/error-step.jsx
index 194e95678fed2fae311e583c35f0a676acc58aa8..a5a5ce1b70085d66bfd351599673da58da171821 100644
--- a/src/components/connection-modal/error-step.jsx
+++ b/src/components/connection-modal/error-step.jsx
@@ -1,5 +1,6 @@
 import {FormattedMessage} from 'react-intl';
 import PropTypes from 'prop-types';
+import classNames from 'classnames';
 import React from 'react';
 
 import Box from '../box/box.jsx';
@@ -39,7 +40,7 @@ const ErrorStep = props => (
                     onClick={props.onScanning}
                 >
                     <img
-                        className={styles.buttonIconLeft}
+                        className={classNames(styles.buttonIconLeft, styles.buttonIconBack)}
                         src={backIcon}
                     />
                     <FormattedMessage
diff --git a/src/components/connection-modal/unavailable-step.jsx b/src/components/connection-modal/unavailable-step.jsx
index 975a66debe7d0b14b25a87c632c04a494775ac4d..ae89404a1952d8ccded43103dc0b1b6af50cf036 100644
--- a/src/components/connection-modal/unavailable-step.jsx
+++ b/src/components/connection-modal/unavailable-step.jsx
@@ -1,5 +1,6 @@
 import {FormattedMessage} from 'react-intl';
 import PropTypes from 'prop-types';
+import classNames from 'classnames';
 import React from 'react';
 
 import Box from '../box/box.jsx';
@@ -64,7 +65,7 @@ const UnavailableStep = props => (
                     onClick={props.onScanning}
                 >
                     <img
-                        className={styles.buttonIconLeft}
+                        className={classNames(styles.buttonIconLeft, styles.buttonIconBack)}
                         src={backIcon}
                     />
                     <FormattedMessage
diff --git a/src/components/custom-procedures/custom-procedures.css b/src/components/custom-procedures/custom-procedures.css
index 6c8967a12d513023f337c3b58d5070281a761170..1716baab306a5b5b4a877831aaff8ee8dfbe5dda 100644
--- a/src/components/custom-procedures/custom-procedures.css
+++ b/src/components/custom-procedures/custom-procedures.css
@@ -91,6 +91,10 @@
     color: white;
 }
 
-.button-row button + button {
+[dir="ltr"] .button-row button + button {
     margin-left: 0.5rem;
 }
+
+[dir="rtl"] .button-row button + button {
+    margin-right: 0.5rem;
+}
diff --git a/src/components/custom-procedures/custom-procedures.jsx b/src/components/custom-procedures/custom-procedures.jsx
index 81756e762ee9e8ffd64492a35b59b2849aada0a7..7d2f3e1a5352afb855d6f5e59bae83164e37ff6a 100644
--- a/src/components/custom-procedures/custom-procedures.jsx
+++ b/src/components/custom-procedures/custom-procedures.jsx
@@ -1,6 +1,6 @@
 import PropTypes from 'prop-types';
 import React from 'react';
-import Modal from '../modal/modal.jsx';
+import Modal from '../../containers/modal.jsx';
 import Box from '../box/box.jsx';
 import {defineMessages, injectIntl, intlShape, FormattedMessage} from 'react-intl';
 
diff --git a/src/components/filter/filter.css b/src/components/filter/filter.css
index b67e60795c29a100c7e67982b8dafeb8bb46c28b..fffef4812eca008d8d3e3dc30c9a540e75192eef 100644
--- a/src/components/filter/filter.css
+++ b/src/components/filter/filter.css
@@ -18,13 +18,22 @@
 .filter-icon {
     position: absolute;
     top: 0;
-    left: 0;
 
     height: 1rem;
     width: 1rem;
+}
+
+[dir="ltr"] .filter-icon {
+    left: 0;
     margin: 0.75rem 0.75rem 0.75rem 1rem;
 }
 
+[dir="rtl"] .filter-icon {
+    right: 0;
+    margin: 0.75rem 1rem 0.75rem 0.75rem;
+    transform: scaleX(-1);
+}
+
 .filter:focus-within {
     box-shadow: 0 0 0 .25rem $motion-transparent;
 }
@@ -36,7 +45,6 @@
     opacity: 0;
     position: absolute;
     top: 0;
-    right: 0;
 
     display: flex;
     justify-content: center;
@@ -53,6 +61,14 @@
     transition: opacity 0.05s linear;
 }
 
+[dir="ltr"] .x-icon-wrapper {
+    right: 0;
+}
+
+[dir="rtl"] .x-icon-wrapper {
+    left: 0;
+}
+
 /*
     Shown state
 */
@@ -96,13 +112,27 @@
     font-size: 0.75rem;
     letter-spacing: 0.15px;
     cursor: text;
+}
+
+[dir="ltr"] .filter-input {
     padding: .625rem 2rem .625rem 3rem;
 }
 
+[dir="rtl"] .filter-input {
+    padding: .625rem 3rem .625rem 2rem;
+}
+
 .filter-input::placeholder {
     opacity: .5;
-    padding: 0 0 0 0.25rem;
     color: $text-primary;
     font-size: 0.875rem;
     letter-spacing: 0.15px;
 }
+
+[dir="ltr"] .filter-input::placeholder {
+    padding: 0 0 0 0.25rem;
+}
+
+[dir="rtl"] .filter-input::placeholder {
+    padding: 0 0.25rem 0 0;
+}
diff --git a/src/components/modal/modal.css b/src/components/modal/modal.css
index 3b318f40ddd7b0697e33d90aa31b505c519a0394..1bb4f196343e94658a56c140447ee91ce4a739aa 100644
--- a/src/components/modal/modal.css
+++ b/src/components/modal/modal.css
@@ -100,13 +100,24 @@ $sides: 20rem;
     user-select: none;
     letter-spacing: 0.4px;
     cursor: default;
+}
+
+[dir="ltr"] .header-item-title {
     margin: 0 -$sides 0 0;
 }
 
-.full-screen .header-item-title {
+[dir="rtl"] .header-item-title {
+    margin: 0 0 0 -$sides;
+}
+
+.full-screen [dir="ltr"] .header-item-title {
     margin: 0 0 0 -$sides;
 }
 
+.full-screen [dir="rtl"] .header-item-title {
+    margin: 0 -$sides 0 0;
+}
+
 .header-item-close {
     flex-basis: $sides;
     justify-content: flex-end;
@@ -120,17 +131,36 @@ $sides: 20rem;
 
 .back-button {
     font-weight: normal;
+    padding-right: 0;
     padding-left: 0;
 }
 
+[dir="rtl"] .back-button img {
+    transform: scaleX(-1);
+}
+
 .header-item-help {
     padding: 0;
-    margin-right: -4.75rem;
     z-index: 1;
 }
 
+[dir="ltr"] .header-item-help {
+    margin-right: -4.75rem;
+}
+
+[dir="rtl"] .header-item-help {
+    margin-left: -4.75rem;
+}
+
 .help-button {
     font-weight: normal;
-    padding-right: 0;
     font-size: 0.75rem;
 }
+
+[dir="ltr"] .help-button {
+    padding-right: 0;
+}
+
+[dir="rtl"] .help-button {
+    padding-left: 0;
+}
diff --git a/src/components/modal/modal.jsx b/src/components/modal/modal.jsx
index acce21993d86b23137104f5f7bddc1215c1d26bf..32fe0502854d4676a2b617f5ccb04f46660a00d0 100644
--- a/src/components/modal/modal.jsx
+++ b/src/components/modal/modal.jsx
@@ -24,6 +24,7 @@ const ModalComponent = props => (
         onRequestClose={props.onRequestClose}
     >
         <Box
+            dir={props.isRtl ? 'rtl' : 'ltr'}
             direction="column"
             grow={1}
         >
@@ -103,6 +104,7 @@ ModalComponent.propTypes = {
     fullScreen: PropTypes.bool,
     headerClassName: PropTypes.string,
     headerImage: PropTypes.string,
+    isRtl: PropTypes.bool,
     onHelp: PropTypes.func,
     onRequestClose: PropTypes.func
 };
diff --git a/src/components/prompt/prompt.css b/src/components/prompt/prompt.css
index 78e3ecb27c6b3d2583528ed1dc6b1df6f36dca6e..ae523e188013ad9c79433ed908f4623665551a50 100644
--- a/src/components/prompt/prompt.css
+++ b/src/components/prompt/prompt.css
@@ -60,10 +60,14 @@
     color: white;
 }
 
-.button-row button + button {
+[dir="ltr"] .button-row button + button {
     margin-left: 0.5rem;
 }
 
+[dir="rtl"] .button-row button + button {
+    margin-right: 0.5rem;
+}
+
 .more-options {
     border-top: 1px dashed hsla(0, 0%, 0%, .25);
     overflow: visible;
diff --git a/src/components/prompt/prompt.jsx b/src/components/prompt/prompt.jsx
index 3e5ec7950fc1be25a4e5cc89297a9828237fd649..42de1599939801b8896374f032525be7c77982a9 100644
--- a/src/components/prompt/prompt.jsx
+++ b/src/components/prompt/prompt.jsx
@@ -4,7 +4,7 @@ import React from 'react';
 
 import Box from '../box/box.jsx';
 import {ComingSoonTooltip} from '../coming-soon/coming-soon.jsx';
-import Modal from '../modal/modal.jsx';
+import Modal from '../../containers/modal.jsx';
 
 import styles from './prompt.css';
 
diff --git a/src/components/record-modal/playback-step.jsx b/src/components/record-modal/playback-step.jsx
index 40167172deac8f7167c88d2046b89a92d5162886..8f76b506f33e8e38c00869c0a2d06bf6f6fcc471 100644
--- a/src/components/record-modal/playback-step.jsx
+++ b/src/components/record-modal/playback-step.jsx
@@ -87,7 +87,7 @@ const PlaybackStep = props => (
         </Box>
         <Box className={styles.buttonRow}>
             <button
-                className={styles.cancelButton}
+                className={styles.rerecordButton}
                 onClick={props.onBack}
             >
                 <img
diff --git a/src/components/record-modal/record-modal.css b/src/components/record-modal/record-modal.css
index 79ce9c606a995d69642eabc76b064ba06cc50aa1..ae9d8afcc0d0b2d8b5235b7c86b30c5fa3bb15b6 100644
--- a/src/components/record-modal/record-modal.css
+++ b/src/components/record-modal/record-modal.css
@@ -118,3 +118,7 @@
     opacity: 0.2;
     transition: 0.1s;
 }
+
+[dir="rtl"] .rerecord-button img {
+    transform: scaleX(-1);
+}
diff --git a/src/components/record-modal/record-modal.jsx b/src/components/record-modal/record-modal.jsx
index 2adc9c14774b9fcf8992c78a53a531c26328429d..5f4086c1c60a35f7a46e011d49248f3849d93de6 100644
--- a/src/components/record-modal/record-modal.jsx
+++ b/src/components/record-modal/record-modal.jsx
@@ -4,7 +4,7 @@ import Box from '../box/box.jsx';
 import {defineMessages, injectIntl, intlShape} from 'react-intl';
 import RecordingStep from '../../containers/recording-step.jsx';
 import PlaybackStep from '../../containers/playback-step.jsx';
-import Modal from '../modal/modal.jsx';
+import Modal from '../../containers/modal.jsx';
 import styles from './record-modal.css';
 
 const messages = defineMessages({
diff --git a/src/containers/custom-procedures.jsx b/src/containers/custom-procedures.jsx
index 879800aae880313299ab53601e6a1f9f0f667d54..525422720a8324b69d47ccad362943f7f8a6e988 100644
--- a/src/containers/custom-procedures.jsx
+++ b/src/containers/custom-procedures.jsx
@@ -32,7 +32,8 @@ class CustomProcedures extends React.Component {
         this.blocks = blocksRef;
         const workspaceConfig = defaultsDeep({},
             CustomProcedures.defaultOptions,
-            this.props.options
+            this.props.options,
+            {rtl: this.props.isRtl}
         );
 
         // @todo This is a hack to make there be no toolbox.
@@ -117,6 +118,7 @@ class CustomProcedures extends React.Component {
 }
 
 CustomProcedures.propTypes = {
+    isRtl: PropTypes.bool,
     mutator: PropTypes.instanceOf(Element),
     onRequestClose: PropTypes.func.isRequired,
     options: PropTypes.shape({
@@ -147,6 +149,7 @@ CustomProcedures.defaultProps = {
 };
 
 const mapStateToProps = state => ({
+    isRtl: state.locales.isRtl,
     mutator: state.scratchGui.customProcedures.mutator
 });
 
diff --git a/src/containers/modal.jsx b/src/containers/modal.jsx
index 67b14c9ff4494b1e5f354f7befb0b6b0faa9946b..30dc4277b56a8a7aabcf2dd204d3be9c14c5b072 100644
--- a/src/containers/modal.jsx
+++ b/src/containers/modal.jsx
@@ -1,6 +1,7 @@
 import bindAll from 'lodash.bindall';
 import PropTypes from 'prop-types';
 import React from 'react';
+import {connect} from 'react-redux';
 
 import ModalComponent from '../components/modal/modal.jsx';
 
@@ -47,8 +48,15 @@ class Modal extends React.Component {
 
 Modal.propTypes = {
     id: PropTypes.string.isRequired,
+    isRtl: PropTypes.bool,
     onRequestClose: PropTypes.func,
     onRequestOpen: PropTypes.func
 };
 
-export default Modal;
+const mapStateToProps = state => ({
+    isRtl: state.locales.isRtl
+});
+
+export default connect(
+    mapStateToProps
+)(Modal);