{
v{SANDIFY_VERSION}
- create patterns for robots that draw in sand with ball bearings
+ {t("about.tagline")}
Sandify turns your cold, empty-hearted, emotionless sand tables
diff --git a/src/features/app/Header.js b/src/features/app/Header.js
index 9c75e1a7..eb5ebe96 100644
--- a/src/features/app/Header.js
+++ b/src/features/app/Header.js
@@ -1,5 +1,6 @@
import React, { useState } from "react"
import { useDispatch } from "react-redux"
+import { useTranslation } from "react-i18next"
import Nav from "react-bootstrap/Nav"
import Navbar from "react-bootstrap/Navbar"
import NavDropdown from "react-bootstrap/NavDropdown"
@@ -8,10 +9,12 @@ import ImageUploader from "@/features/import/ImageUploader"
import LayerUploader from "@/features/import/LayerUploader"
import SandifyDownloader from "@/features/file/SandifyDownloader"
import SandifyUploader from "@/features/file/SandifyUploader"
+import LanguageSelector from "@/components/LanguageSelector"
import logo from "./logo.svg"
import "./Header.scss"
const Header = ({ eventKey, setEventKey }) => {
+ const { t } = useTranslation()
const [showExport, setShowExport] = useState(false)
const [showImportLayer, setShowImportLayer] = useState(0)
const [showImportImage, setShowImportImage] = useState(0)
@@ -48,36 +51,37 @@ const Header = ({ eventKey, setEventKey }) => {
+
{
+ const { t } = useTranslation()
const dispatch = useDispatch()
const layer = useSelector(selectSelectedLayer)
const images = useSelector(selectAllImages)
@@ -26,7 +28,7 @@ const Sidebar = () => {
@@ -34,7 +36,7 @@ const Sidebar = () => {
@@ -42,7 +44,7 @@ const Sidebar = () => {
diff --git a/src/features/effects/CopyEffect.js b/src/features/effects/CopyEffect.js
index 177a2967..66d6255f 100644
--- a/src/features/effects/CopyEffect.js
+++ b/src/features/effects/CopyEffect.js
@@ -5,10 +5,12 @@ import Col from "react-bootstrap/Col"
import Row from "react-bootstrap/Row"
import Form from "react-bootstrap/Form"
import { useDispatch, useSelector } from "react-redux"
+import { useTranslation } from "react-i18next"
import { selectSelectedEffect } from "./effectsSlice"
import { addEffect } from "@/features/layers/layersSlice"
const CopyEffect = ({ toggleModal, showModal }) => {
+ const { t } = useTranslation()
const dispatch = useDispatch()
const selectedEffect = useSelector(selectSelectedEffect)
const namedInputRef = useRef(null)
@@ -53,13 +55,13 @@ const CopyEffect = ({ toggleModal, showModal }) => {
onEntered={handleInitialFocus}
>
- Copy {selectedEffect?.name || ""}
+ {t('copyEffect.title', { name: selectedEffect?.name || "" })}
diff --git a/src/features/effects/EffectEditor.js b/src/features/effects/EffectEditor.js
index a92c20ef..7d113f9d 100644
--- a/src/features/effects/EffectEditor.js
+++ b/src/features/effects/EffectEditor.js
@@ -14,8 +14,11 @@ import ModelOption from "@/components/ModelOption"
import { updateEffect } from "./effectsSlice"
import EffectLayer from "./EffectLayer"
import { selectSelectedEffect } from "./effectsSlice"
+import { useTranslation } from "react-i18next"
+
const EffectEditor = ({ id }) => {
+ const { t } = useTranslation()
const dispatch = useDispatch()
const effect = useSelector(selectSelectedEffect)
const type = effect?.type || "mask" // guard zombie child
@@ -69,7 +72,7 @@ const EffectEditor = ({ id }) => {
{renderedModelOptions}
{model.canTransform(effect) && (
- Transform
+ {t('layer.transform')}
diff --git a/src/features/effects/EffectLayer.js b/src/features/effects/EffectLayer.js
index b94e5df4..7c5d2bae 100644
--- a/src/features/effects/EffectLayer.js
+++ b/src/features/effects/EffectLayer.js
@@ -1,26 +1,27 @@
import { getEffect } from "@/features/effects/effectFactory"
+import i18n from "@/i18n"
-export const effectOptions = {
+export const effectOptions = () => ({
name: {
- title: "Name",
+ title: i18n.t("effects.effectLayer.name"),
type: "text",
},
x: {
- title: "X",
+ title: i18n.t("effects.effectLayer.x"),
inline: true,
isVisible: (model, state) => {
return model.canMove(state)
},
},
y: {
- title: "Y",
+ title: i18n.t("effects.effectLayer.y"),
inline: true,
isVisible: (model, state) => {
return model.canMove(state)
},
},
width: {
- title: "W",
+ title: i18n.t("effects.effectLayer.w"),
min: 1,
inline: true,
isVisible: (model, state) => {
@@ -36,7 +37,7 @@ export const effectOptions = {
},
},
height: {
- title: "H",
+ title: i18n.t("effects.effectLayer.h"),
min: 1,
inline: true,
onChange: (model, changes, state) => {
@@ -49,17 +50,17 @@ export const effectOptions = {
},
},
maintainAspectRatio: {
- title: "Lock aspect ratio",
+ title: i18n.t("effects.effectLayer.lockAspectRatio"),
type: "checkbox",
},
rotation: {
- title: "Rotate (degrees)",
+ title: i18n.t("effects.effectLayer.rotateDegrees"),
inline: true,
isVisible: (model, state) => {
return model.canRotate(state)
},
},
-}
+})
export default class EffectLayer {
constructor(type) {
@@ -93,7 +94,7 @@ export default class EffectLayer {
}
getOptions() {
- return effectOptions
+ return effectOptions()
}
getVertices(effect, layer, vertices) {
diff --git a/src/features/effects/EffectManager.js b/src/features/effects/EffectManager.js
index fabf1c10..82a784f6 100644
--- a/src/features/effects/EffectManager.js
+++ b/src/features/effects/EffectManager.js
@@ -20,8 +20,11 @@ import EffectList from "./EffectList"
import EffectLayer from "./EffectLayer"
import NewEffect from "./NewEffect"
import CopyEffect from "./CopyEffect"
+import { useTranslation } from "react-i18next"
+
const EffectManager = () => {
+ const { t } = useTranslation()
const dispatch = useDispatch()
const selectedLayer = useSelector(selectSelectedLayer)
const selectedEffect = useSelector(selectSelectedEffect)
@@ -69,7 +72,7 @@ const EffectManager = () => {
variant="secondary"
onClick={toggleNewEffectModal}
>
- Add effect
+ {t('effects.effectLayer.addEffect')}
)}
{numEffects > 0 && (
@@ -77,8 +80,8 @@ const EffectManager = () => {
defaultActiveKey={1}
className="mt-3"
>
-
- Effects
+
+ {t('effectManager.effects')}
{
className="ms-2 layer-button"
variant="light"
size="sm"
- data-tooltip-content="Create new effect"
+ data-tooltip-content={t('effectManager.createEffect')}
data-tooltip-id="tooltip-new-layer"
onClick={toggleNewEffectModal}
>
@@ -101,7 +104,7 @@ const EffectManager = () => {