mark most of the game text for translation

pull/205/head
Jon Eugster 11 months ago
parent 1a54edffd4
commit d60dc3fcb2

@ -214,6 +214,7 @@ export function WelcomeAppBar({pageNumber, setPageNumber, gameInfo, toggleImpres
toggleInfo: any,
togglePreferencesPopup: () => void;
}) {
const { t } = useTranslation()
const gameId = React.useContext(GameIdContext)
const gameProgress = useAppSelector(selectProgress(gameId))
const {mobile} = React.useContext(PreferencesContext)
@ -225,7 +226,7 @@ export function WelcomeAppBar({pageNumber, setPageNumber, gameInfo, toggleImpres
<span className="app-bar-title"></span>
</div>
<div>
{!mobile && <span className="app-bar-title">{gameInfo?.title}</span>}
{!mobile && <span className="app-bar-title">{t(gameInfo?.title, {ns: gameId})}</span>}
</div>
<div className="nav-btns">
{mobile && <MobileNavButtons pageNumber={pageNumber} setPageNumber={setPageNumber} />}
@ -288,7 +289,7 @@ export function LevelAppBar({isLoading, levelTitle, toggleImpressum, toggleInfo,
{/* DESKTOP VERSION */}
<div className='app-bar-left'>
<HomeButton isDropdown={false} />
<span className="app-bar-title">{worldTitle && `${t("World")}: ${worldTitle}`}</span>
<span className="app-bar-title">{worldTitle && `${t("World")}: ${t(worldTitle, {ns: gameId})}`}</span>
</div>
<div>
<span className="app-bar-title">{levelTitle}</span>

@ -5,22 +5,25 @@ import { DeletedChatContext, ProofContext } from "./infoview/context";
import { lastStepHasErrors } from "./infoview/goals";
import { Button } from "./button";
import { useTranslation } from "react-i18next";
import { GameIdContext } from "../app";
/** Plug-in the variable names in a hint. We do this client-side to prepare
* for i18n in the future. i.e. one should be able translate the `rawText`
* and have the variables substituted just before displaying.
*/
function getHintText(hint: GameHint): string {
const gameId = React.useContext(GameIdContext)
let { t } = useTranslation()
if (hint.rawText) {
// Replace the variable names used in the hint with the ones used by the player
// variable names are marked like `«{g}»` inside the text.
return hint.rawText.replaceAll(/«\{(.*?)\}»/g, ((_, v) =>
return t(hint.rawText, {ns: gameId}).replaceAll(/«\{(.*?)\}»/g, ((_, v) =>
// `hint.varNames` contains tuples `[oldName, newName]`
(hint.varNames.find(x => x[0] == v))[1]))
} else {
// hints created in the frontend do not have a `rawText`
// TODO: `hint.text` could be removed in theory.
return hint.text
return t(hint.text, {ns: gameId})
}
}

@ -136,12 +136,15 @@ function DualEditorMain({ worldId, levelId, level, worldSize }: { worldId: strin
* If `showLeanStatement` is true, it will additionally display the lean code.
*/
function ExerciseStatement({ data, showLeanStatement = false }) {
let { t } = useTranslation()
const gameId = React.useContext(GameIdContext)
if (!(data?.descrText || data?.descrFormat)) { return <></> }
return <>
<div className="exercise-statement">
{data?.descrText &&
<Markdown>
{(data?.displayName ? `**Theorem** \`${data?.displayName}\`: ` : '') + data?.descrText}
{(data?.displayName ? `**Theorem** \`${data?.displayName}\`: ` : '') + t(data?.descrText, {ns: gameId})}
</Markdown>
}
{data?.descrFormat && showLeanStatement &&

@ -140,7 +140,7 @@ export function Documentation({name, type, handleClose}) {
<h1 className="doc">{doc.data?.displayName}</h1>
<p><code>{doc.data?.statement}</code></p>
{/* <code>docstring: {doc.data?.docstring}</code> */}
<Markdown>{doc.data?.content}</Markdown>
<Markdown>{t(doc.data?.content, {ns: gameId})}</Markdown>
</div>
}

@ -173,11 +173,11 @@ function ChatPanel({lastLevel, visible = true}) {
{proof?.completed &&
<>
<div className={`message information recent step-${k}${selectedStep == k ? ' selected' : ''}`} onClick={toggleSelection(k)}>
Level completed! 🎉
{t("Level completed! 🎉")}
</div>
{level?.data?.conclusion?.trim() &&
<div className={`message information recent step-${k}${selectedStep == k ? ' selected' : ''}`} onClick={toggleSelection(k)}>
<Markdown>{level?.data?.conclusion}</Markdown>
<Markdown>{t(level?.data?.conclusion, {ns: gameId})}</Markdown>
</div>
}
</>
@ -186,10 +186,10 @@ function ChatPanel({lastLevel, visible = true}) {
<div className="button-row">
{proof?.completed && (lastLevel ?
<Button to={`/${gameId}`}>
<FontAwesomeIcon icon={faHome} />&nbsp;Leave World
<FontAwesomeIcon icon={faHome} />&nbsp;{t("Leave World")}
</Button> :
<Button to={`/${gameId}/world/${worldId}/level/${levelId + 1}`}>
Next&nbsp;<FontAwesomeIcon icon={faArrowRight} />
{t("Next")}&nbsp;<FontAwesomeIcon icon={faArrowRight} />
</Button>)
}
<MoreHelpButton />

@ -4,6 +4,8 @@
import * as React from 'react'
import { Typography } from '@mui/material'
import Markdown from '../markdown'
import { useTranslation } from 'react-i18next'
import { GameIdContext } from '../../app'
/** Pop-up that is displaying the Game Info.
*
@ -11,12 +13,15 @@ import Markdown from '../markdown'
* controlled by the containing element.
*/
export function InfoPopup ({info, handleClose}: {info: string, handleClose: () => void}) {
let { t } = useTranslation()
const gameId = React.useContext(GameIdContext)
return <div className="modal-wrapper">
<div className="modal-backdrop" onClick={handleClose} />
<div className="modal">
<div className="codicon codicon-close modal-close" onClick={handleClose}></div>
<Typography variant="body1" component="div" className="welcome-text">
<Markdown>{info}</Markdown>
<Markdown>{t(info, {ns: gameId})}</Markdown>
</Typography>
</div>
</div>

@ -113,6 +113,7 @@ export function WorldIcon({world, title, position, completedLevels, difficulty,
difficulty: number,
worldSize: number
}) {
const { t } = useTranslation()
// See level icons. Match radius computed there minus `1.2*r`
const N = Math.max(worldSize, NMIN)
@ -151,7 +152,7 @@ export function WorldIcon({world, title, position, completedLevels, difficulty,
width={1.42*R} height={1.42*R} transform={"translate("+ -.71*R +","+ -.71*R +")"}>
<div className={unlocked && !completed ? "playable-world" : ''}>
<p className="world-title" style={{fontSize: fontSize + "px"}}>
{title ? title : world}
{title ? t(title, {ns: gameId}) : world}
</p>
</div>
</foreignObject>
@ -162,7 +163,7 @@ export function WorldIcon({world, title, position, completedLevels, difficulty,
>
<div className='world-label' style={{backgroundColor: completed ? darkgreen : unlocked ? darkblue : darkgrey}}>
<p className='world-title' style={{fontSize: MINFONT + "px"}}>
{title ? title : world}
{title ? t(title, {ns: gameId}) : world}
</p>
</div>
</foreignObject>}

Loading…
Cancel
Save