diff --git a/front/src/Components/AudioManager/AudioManager.svelte b/front/src/Components/AudioManager/AudioManager.svelte index b62d8fbe..5bf02fc9 100644 --- a/front/src/Components/AudioManager/AudioManager.svelte +++ b/front/src/Components/AudioManager/AudioManager.svelte @@ -5,6 +5,7 @@ import { get } from "svelte/store"; import type { Unsubscriber } from "svelte/store"; import { onDestroy, onMount } from "svelte"; + import { translator } from "../../Translator/Translator"; let HTMLAudioPlayer: HTMLAudioElement; let audioPlayerVolumeIcon: HTMLElement; @@ -144,7 +145,7 @@ </div> <div class="audio-manager-reduce-conversation"> <label> - reduce in conversations + {translator._("audio.manager.reduce")} <input type="checkbox" bind:checked={decreaseWhileTalking} on:change={setDecrease} /> </label> <section class="audio-manager-file"> diff --git a/front/src/Components/Chat/Chat.svelte b/front/src/Components/Chat/Chat.svelte index 6827dde4..2e60e43e 100644 --- a/front/src/Components/Chat/Chat.svelte +++ b/front/src/Components/Chat/Chat.svelte @@ -5,6 +5,7 @@ import ChatElement from "./ChatElement.svelte"; import { afterUpdate, beforeUpdate, onMount } from "svelte"; import { HtmlUtils } from "../../WebRtc/HtmlUtils"; + import { translator } from "../../Translator/Translator"; let listDom: HTMLElement; let chatWindowElement: HTMLElement; @@ -45,7 +46,7 @@ <p class="close-icon" on:click={closeChat}>×</p> <section class="messagesList" bind:this={listDom}> <ul> - <li><p class="system-text">Here is your chat history:</p></li> + <li><p class="system-text">{translator._("chat.intro")}</p></li> {#each $chatMessagesStore as message, i} <li><ChatElement {message} line={i} /></li> {/each} diff --git a/front/src/Components/Chat/ChatMessageForm.svelte b/front/src/Components/Chat/ChatMessageForm.svelte index d57eaf5c..6853d669 100644 --- a/front/src/Components/Chat/ChatMessageForm.svelte +++ b/front/src/Components/Chat/ChatMessageForm.svelte @@ -1,5 +1,6 @@ <script lang="ts"> import { chatMessagesStore, chatInputFocusStore } from "../../Stores/ChatStore"; + import { translator } from "../../Translator/Translator"; export const handleForm = { blur() { @@ -27,7 +28,7 @@ <input type="text" bind:value={newMessageText} - placeholder="Enter your message..." + placeholder={translator._("chat.enter")} on:focus={onFocus} on:blur={onBlur} bind:this={inputElement} diff --git a/front/src/Components/Chat/ChatSubMenu.svelte b/front/src/Components/Chat/ChatSubMenu.svelte index 5a04a1b9..48f59e65 100644 --- a/front/src/Components/Chat/ChatSubMenu.svelte +++ b/front/src/Components/Chat/ChatSubMenu.svelte @@ -1,6 +1,7 @@ <script lang="ts"> import type { PlayerInterface } from "../../Phaser/Game/PlayerInterface"; import { requestVisitCardsStore } from "../../Stores/GameStore"; + import { translator } from "../../Translator/Translator"; export let player: PlayerInterface; @@ -12,8 +13,12 @@ </script> <ul class="selectMenu" style="border-top: {player.color || 'whitesmoke'} 5px solid"> - <li><button class="text-btn" disabled={!player.visitCardUrl} on:click={openVisitCard}>Visit card</button></li> - <li><button class="text-btn" disabled>Add friend</button></li> + <li> + <button class="text-btn" disabled={!player.visitCardUrl} on:click={openVisitCard} + >{translator._("chat.menu.visit-card")}</button + > + </li> + <li><button class="text-btn" disabled>{translator._("chat.menu.add-friend")}</button></li> </ul> <style lang="scss"> diff --git a/front/src/Components/CustomCharacterScene/CustomCharacterScene.svelte b/front/src/Components/CustomCharacterScene/CustomCharacterScene.svelte index 70bd385b..c446ccbc 100644 --- a/front/src/Components/CustomCharacterScene/CustomCharacterScene.svelte +++ b/front/src/Components/CustomCharacterScene/CustomCharacterScene.svelte @@ -2,6 +2,7 @@ import type { Game } from "../../Phaser/Game/Game"; import { CustomizeScene, CustomizeSceneName } from "../../Phaser/Login/CustomizeScene"; import { activeRowStore } from "../../Stores/CustomCharacterStore"; + import { translator } from "../../Translator/Translator"; export let game: Game; @@ -34,7 +35,7 @@ <form class="customCharacterScene"> <section class="text-center"> - <h2>Customize your WOKA</h2> + <h2>{translator._("custom-character.title")}</h2> </section> <section class="action action-move"> <button @@ -53,26 +54,29 @@ <section class="action"> {#if $activeRowStore === 0} <button type="submit" class="customCharacterSceneFormBack nes-btn" on:click|preventDefault={previousScene} - >Return</button + >{translator._("custom-character.navigation.return")}</button > {/if} {#if $activeRowStore !== 0} <button type="submit" class="customCharacterSceneFormBack nes-btn" on:click|preventDefault={selectUp} - >Back <img src="resources/objects/arrow_up_black.png" alt="" /></button + >{translator._("custom-character.navigation.back")} + <img src="resources/objects/arrow_up_black.png" alt="" /></button > {/if} {#if $activeRowStore === 5} <button type="submit" class="customCharacterSceneFormSubmit nes-btn is-primary" - on:click|preventDefault={finish}>Finish</button + on:click|preventDefault={finish}>{translator._("custom-character.navigation.finish")}</button > {/if} {#if $activeRowStore !== 5} <button type="submit" class="customCharacterSceneFormSubmit nes-btn is-primary" - on:click|preventDefault={selectDown}>Next <img src="resources/objects/arrow_down.png" alt="" /></button + on:click|preventDefault={selectDown} + >{translator._("custom-character.navigation.next")} + <img src="resources/objects/arrow_down.png" alt="" /></button > {/if} </section> diff --git a/front/src/Components/EnableCamera/EnableCameraScene.svelte b/front/src/Components/EnableCamera/EnableCameraScene.svelte index 5993ee75..7dba267b 100644 --- a/front/src/Components/EnableCamera/EnableCameraScene.svelte +++ b/front/src/Components/EnableCamera/EnableCameraScene.svelte @@ -13,6 +13,7 @@ import cinemaCloseImg from "../images/cinema-close.svg"; import cinemaImg from "../images/cinema.svg"; import microphoneImg from "../images/microphone.svg"; + import { translator } from "../../Translator/Translator"; export let game: Game; let selectedCamera: string | undefined = undefined; @@ -76,7 +77,7 @@ <form class="enableCameraScene" on:submit|preventDefault={submit}> <section class="text-center"> - <h2>Turn on your camera and microphone</h2> + <h2>{translator._("camera.enable.title")}</h2> </section> {#if $localStreamStore.type === "success" && $localStreamStore.stream} <video class="myCamVideoSetup" use:srcObject={$localStreamStore.stream} autoplay muted playsinline /> @@ -121,7 +122,7 @@ {/if} </section> <section class="action"> - <button type="submit" class="nes-btn is-primary letsgo">Let's go!</button> + <button type="submit" class="nes-btn is-primary letsgo">{translator._("camera.enable.start")}</button> </section> </form> diff --git a/front/src/Components/FollowMenu/FollowMenu.svelte b/front/src/Components/FollowMenu/FollowMenu.svelte index aaa23b3e..b41e0fd4 100644 --- a/front/src/Components/FollowMenu/FollowMenu.svelte +++ b/front/src/Components/FollowMenu/FollowMenu.svelte @@ -6,11 +6,13 @@ vim: ft=typescript import followImg from "../images/follow.svg"; import { followStateStore, followRoleStore, followUsersStore } from "../../Stores/FollowStore"; + import { translator } from "../../Translator/Translator"; const gameScene = gameManager.getCurrentGameScene(); - function name(userId: number): string | undefined { - return gameScene.MapPlayersByKey.get(userId)?.PlayerValue; + function name(userId: number): string { + const user = gameScene.MapPlayersByKey.get(userId); + return user ? user.PlayerValue : ""; } function sendFollowRequest() { @@ -42,11 +44,15 @@ vim: ft=typescript {#if $followStateStore === "requesting" && $followRoleStore === "follower"} <div class="interact-menu nes-container is-rounded"> <section class="interact-menu-title"> - <h2>Do you want to follow {name($followUsersStore[0])}?</h2> + <h2>{translator._("follow.interact-menu.title.follow", { leader: name($followUsersStore[0]) })}</h2> </section> <section class="interact-menu-action"> - <button type="button" class="nes-btn is-success" on:click|preventDefault={acceptFollowRequest}>Yes</button> - <button type="button" class="nes-btn is-error" on:click|preventDefault={reset}>No</button> + <button type="button" class="nes-btn is-success" on:click|preventDefault={acceptFollowRequest} + >{translator._("follow.interact-menu.yes")}</button + > + <button type="button" class="nes-btn is-error" on:click|preventDefault={reset} + >{translator._("follow.interact-menu.no")}</button + > </section> </div> {/if} @@ -54,20 +60,24 @@ vim: ft=typescript {#if $followStateStore === "ending"} <div class="interact-menu nes-container is-rounded"> <section class="interact-menu-title"> - <h2>Interaction</h2> + <h2>{translator._("follow.interact-menu.title.interact")}</h2> </section> {#if $followRoleStore === "follower"} <section class="interact-menu-question"> - <p>Do you want to stop following {name($followUsersStore[0])}?</p> + <p>{translator._("follow.interact-menu.stop.follower", { leader: name($followUsersStore[0]) })}</p> </section> {:else if $followRoleStore === "leader"} <section class="interact-menu-question"> - <p>Do you want to stop leading the way?</p> + <p>{translator._("follow.interact-menu.stop.leader")}</p> </section> {/if} <section class="interact-menu-action"> - <button type="button" class="nes-btn is-success" on:click|preventDefault={reset}>Yes</button> - <button type="button" class="nes-btn is-error" on:click|preventDefault={abortEnding}>No</button> + <button type="button" class="nes-btn is-success" on:click|preventDefault={reset} + >{translator._("follow.interact-menu.yes")}</button + > + <button type="button" class="nes-btn is-error" on:click|preventDefault={abortEnding} + >{translator._("follow.interact-menu.no")}</button + > </section> </div> {/if} @@ -76,18 +86,24 @@ vim: ft=typescript <div class="interact-status nes-container is-rounded"> <section class="interact-status"> {#if $followRoleStore === "follower"} - <p>Following {name($followUsersStore[0])}</p> + <p>{translator._("follow.interact-status.following", { leader: name($followUsersStore[0]) })}</p> {:else if $followUsersStore.length === 0} - <p>Waiting for followers' confirmation</p> + <p>{translator._("follow.interact-status.waiting-followers")}</p> {:else if $followUsersStore.length === 1} - <p>{name($followUsersStore[0])} is following you</p> + <p>{translator._("follow.interact-status.followed.one", { follower: name($followUsersStore[0]) })}</p> {:else if $followUsersStore.length === 2} - <p>{name($followUsersStore[0])} and {name($followUsersStore[1])} are following you</p> + <p> + {translator._("follow.interact-status.followed.one", { + firstFollower: name($followUsersStore[0]), + secondFollower: name($followUsersStore[1]), + })} + </p> {:else} <p> - {$followUsersStore.slice(0, -1).map(name).join(", ")} and {name( - $followUsersStore[$followUsersStore.length - 1] - )} are following you + {translator._("follow.interact-status.followed.many", { + followers: $followUsersStore.slice(0, -1).map(name).join(", "), + lastFollower: name($followUsersStore[$followUsersStore.length - 1]), + })} </p> {/if} </section> diff --git a/front/src/Components/HelpCameraSettings/HelpCameraSettingsPopup.svelte b/front/src/Components/HelpCameraSettings/HelpCameraSettingsPopup.svelte index 78380174..c7cdb9aa 100644 --- a/front/src/Components/HelpCameraSettings/HelpCameraSettingsPopup.svelte +++ b/front/src/Components/HelpCameraSettings/HelpCameraSettingsPopup.svelte @@ -4,6 +4,7 @@ import firefoxImg from "./images/help-setting-camera-permission-firefox.png"; import chromeImg from "./images/help-setting-camera-permission-chrome.png"; import { getNavigatorType, isAndroid as isAndroidFct, NavigatorType } from "../../WebRtc/DeviceUtils"; + import { translator } from "../../Translator/Translator"; let isAndroid = isAndroidFct(); let isFirefox = getNavigatorType() === NavigatorType.firefox; @@ -24,14 +25,13 @@ transition:fly={{ y: -900, duration: 500 }} > <section> - <h2>Camera / Microphone access needed</h2> - <p class="err">Permission denied</p> - <p>You must allow camera and microphone access in your browser.</p> + <h2>{translator._("camera.help.title")}</h2> + <p class="err">{translator._("camera.help.permission-denied")}</p> + <p>{translator._("camera.help.content")}</p> <p> {#if isFirefox} <p class="err"> - Please click the "Remember this decision" checkbox, if you don't want Firefox to keep asking you the - authorization. + {translator._("camera.help.firefox-content")} </p> <img src={firefoxImg} alt="" /> {:else if isChrome && !isAndroid} @@ -40,9 +40,11 @@ </p> </section> <section> - <button class="helpCameraSettingsFormRefresh nes-btn" on:click|preventDefault={refresh}>Refresh</button> + <button class="helpCameraSettingsFormRefresh nes-btn" on:click|preventDefault={refresh} + >{translator._("camera.help.refresh")}</button + > <button type="submit" class="helpCameraSettingsFormContinue nes-btn is-primary" on:click|preventDefault={close} - >Continue without webcam</button + >{translator._("camera.help.continue")}</button > </section> </form> diff --git a/front/src/Components/Login/LoginScene.svelte b/front/src/Components/Login/LoginScene.svelte index bebc49b6..e4f47d60 100644 --- a/front/src/Components/Login/LoginScene.svelte +++ b/front/src/Components/Login/LoginScene.svelte @@ -4,6 +4,7 @@ import { DISPLAY_TERMS_OF_USE, MAX_USERNAME_LENGTH } from "../../Enum/EnvironmentVariable"; import logoImg from "../images/logo.png"; import { gameManager } from "../../Phaser/Game/GameManager"; + import { translator } from "../../Translator/Translator"; export let game: Game; @@ -27,7 +28,7 @@ <img src={logoImg} alt="WorkAdventure logo" /> </section> <section class="text-center"> - <h2>Enter your name</h2> + <h2>{translator._("login.input.name.placeholder")}</h2> </section> <!-- svelte-ignore a11y-autofocus --> <input @@ -44,22 +45,20 @@ /> <section class="error-section"> {#if name.trim() === "" && startValidating} - <p class="err">The name is empty</p> + <p class="err">{translator._("login.input.name.empty")}</p> {/if} </section> {#if DISPLAY_TERMS_OF_USE} <section class="terms-and-conditions"> + <a style="display: none;" href="traduction">Need for traduction</a> <p> - By continuing, you are agreeing our <a href="https://workadventu.re/terms-of-use" target="_blank" - >terms of use</a - >, <a href="https://workadventu.re/privacy-policy" target="_blank">privacy policy</a> and - <a href="https://workadventu.re/cookie-policy" target="_blank">cookie policy</a>. + {translator._("login.terms")} </p> </section> {/if} <section class="action"> - <button type="submit" class="nes-btn is-primary loginSceneFormSubmit">Continue</button> + <button type="submit" class="nes-btn is-primary loginSceneFormSubmit">{translator._("login.continue")}</button> </section> </form> diff --git a/front/src/Components/Menu/AboutRoomSubMenu.svelte b/front/src/Components/Menu/AboutRoomSubMenu.svelte index 2bbb4d3c..ee560340 100644 --- a/front/src/Components/Menu/AboutRoomSubMenu.svelte +++ b/front/src/Components/Menu/AboutRoomSubMenu.svelte @@ -1,6 +1,7 @@ <script lang="ts"> import { gameManager } from "../../Phaser/Game/GameManager"; import { onMount } from "svelte"; + import { translator } from "../../Translator/Translator"; let gameScene = gameManager.getCurrentGameScene(); @@ -11,7 +12,7 @@ let mapName: string = ""; let mapLink: string = ""; let mapDescription: string = ""; - let mapCopyright: string = "The map creator did not declare a copyright for the map."; + let mapCopyright: string = translator._("menu.about.copyrights.map.empty"); let tilesetCopyright: string[] = []; let audioCopyright: string[] = []; @@ -62,41 +63,37 @@ </script> <div class="about-room-main"> - <h2>Information on the map</h2> + <h2>{translator._("menu.about.map-info")}</h2> <section class="container-overflow"> <h3>{mapName}</h3> <p class="string-HTML">{mapDescription}</p> {#if mapLink} - <p class="string-HTML">> <a href={mapLink} target="_blank">link to this map</a> <</p> + <p class="string-HTML"> + > <a href={mapLink} target="_blank">{translator._("menu.about.map-link")}</a> < + </p> {/if} <h3 class="nes-pointer hoverable" on:click={() => (expandedMapCopyright = !expandedMapCopyright)}> - Copyrights of the map + {translator._("menu.about.copyrights.map.title")} </h3> <p class="string-HTML" hidden={!expandedMapCopyright}>{mapCopyright}</p> <h3 class="nes-pointer hoverable" on:click={() => (expandedTilesetCopyright = !expandedTilesetCopyright)}> - Copyrights of the tilesets + {translator._("menu.about.copyrights.tileset.title")} </h3> <section hidden={!expandedTilesetCopyright}> {#each tilesetCopyright as copyright} <p class="string-HTML">{copyright}</p> {:else} - <p> - The map creator did not declare a copyright for the tilesets. This doesn't mean that those tilesets - have no license. - </p> + <p>{translator._("menu.about.copyrights.tileset.empty")}</p> {/each} </section> <h3 class="nes-pointer hoverable" on:click={() => (expandedAudioCopyright = !expandedAudioCopyright)}> - Copyrights of audio files + {translator._("menu.about.copyrights.audio.title")} </h3> <section hidden={!expandedAudioCopyright}> {#each audioCopyright as copyright} <p class="string-HTML">{copyright}</p> {:else} - <p> - The map creator did not declare a copyright for audio files. This doesn't mean that those tilesets - have no license. - </p> + <p>{translator._("menu.about.copyrights.audio.empty")}</p> {/each} </section> </section> diff --git a/front/src/Components/Menu/AudioGlobalMessage.svelte b/front/src/Components/Menu/AudioGlobalMessage.svelte index 51caee17..edc9568d 100644 --- a/front/src/Components/Menu/AudioGlobalMessage.svelte +++ b/front/src/Components/Menu/AudioGlobalMessage.svelte @@ -4,6 +4,7 @@ import { AdminMessageEventTypes } from "../../Connexion/AdminMessagesService"; import uploadFile from "../images/music-file.svg"; import type { PlayGlobalMessageInterface } from "../../Connexion/ConnexionModels"; + import { translator } from "../../Translator/Translator"; interface EventTargetFiles extends EventTarget { files: Array<File>; @@ -76,7 +77,7 @@ <img class="nes-pointer" src={uploadFile} - alt="Upload a file" + alt={translator._("menu.global-audio.upload-info")} on:click|preventDefault={() => { fileInput.click(); }} @@ -85,7 +86,7 @@ <p>{fileName} : {fileSize}</p> {/if} {#if errorFile} - <p class="err">No file selected. You need to upload a file before sending it.</p> + <p class="err">{translator._("menu.global-audio.error")}</p> {/if} <input type="file" diff --git a/front/src/Components/Menu/ContactSubMenu.svelte b/front/src/Components/Menu/ContactSubMenu.svelte index a5bf0331..6eb7c963 100644 --- a/front/src/Components/Menu/ContactSubMenu.svelte +++ b/front/src/Components/Menu/ContactSubMenu.svelte @@ -1,4 +1,7 @@ <script lang="ts"> + import { contactPageStore } from "../../Stores/MenuStore"; + import { translator } from "../../Translator/Translator"; + function goToGettingStarted() { const sparkHost = "https://workadventu.re/getting-started"; window.open(sparkHost, "_blank"); @@ -8,25 +11,24 @@ const sparkHost = "https://workadventu.re/map-building/"; window.open(sparkHost, "_blank"); } - - import { contactPageStore } from "../../Stores/MenuStore"; </script> <div class="create-map-main"> <section class="container-overflow"> <section> - <h3>Getting started</h3> - <p> - WorkAdventure allows you to create an online space to communicate spontaneously with others. And it all - starts with creating your own space. Choose from a large selection of prefabricated maps by our team. - </p> - <button type="button" class="nes-btn is-primary" on:click={goToGettingStarted}>Getting started</button> + <h3>{translator._("menu.contact.getting-started.title")}</h3> + <p>{translator._("menu.contact.getting-started.description")}</p> + <button type="button" class="nes-btn is-primary" on:click={goToGettingStarted} + >{translator._("menu.contact.getting-started.title")}</button + > </section> <section> - <h3>Create your map</h3> - <p>You can also create your own custom map by following the step of the documentation.</p> - <button type="button" class="nes-btn" on:click={goToBuildingMap}>Create your map</button> + <h3>{translator._("menu.contact.create-map.title")}</h3> + <p>{translator._("menu.contact.create-map.description")}</p> + <button type="button" class="nes-btn" on:click={goToBuildingMap} + >{translator._("menu.contact.create-map.title")}</button + > </section> <iframe diff --git a/front/src/Components/Menu/GlobalMessagesSubMenu.svelte b/front/src/Components/Menu/GlobalMessagesSubMenu.svelte index e755a243..654c0449 100644 --- a/front/src/Components/Menu/GlobalMessagesSubMenu.svelte +++ b/front/src/Components/Menu/GlobalMessagesSubMenu.svelte @@ -1,6 +1,7 @@ <script lang="ts"> import TextGlobalMessage from "./TextGlobalMessage.svelte"; import AudioGlobalMessage from "./AudioGlobalMessage.svelte"; + import { translator } from "../../Translator/Translator"; let handleSendText: { sendTextMessage(broadcast: boolean): void }; let handleSendAudio: { sendAudioMessage(broadcast: boolean): Promise<void> }; @@ -35,14 +36,14 @@ <button type="button" class="nes-btn {inputSendTextActive ? 'is-disabled' : ''}" - on:click|preventDefault={activateInputText}>Text</button + on:click|preventDefault={activateInputText}>{translator._("menu.global-message.text")}</button > </section> <section> <button type="button" class="nes-btn {uploadAudioActive ? 'is-disabled' : ''}" - on:click|preventDefault={activateUploadAudio}>Audio</button + on:click|preventDefault={activateUploadAudio}>{translator._("menu.global-message.audio")}</button > </section> </div> @@ -57,10 +58,12 @@ <div class="global-message-footer"> <label> <input type="checkbox" class="nes-checkbox is-dark nes-pointer" bind:checked={broadcastToWorld} /> - <span>Broadcast to all rooms of the world</span> + <span>{translator._("menu.global-message.warning")}</span> </label> <section> - <button class="nes-btn is-primary" on:click|preventDefault={send}>Send</button> + <button class="nes-btn is-primary" on:click|preventDefault={send} + >{translator._("menu.global-message.send")}</button + > </section> </div> </div> diff --git a/front/src/Components/Menu/GuestSubMenu.svelte b/front/src/Components/Menu/GuestSubMenu.svelte index 408dcbce..e83cd682 100644 --- a/front/src/Components/Menu/GuestSubMenu.svelte +++ b/front/src/Components/Menu/GuestSubMenu.svelte @@ -1,4 +1,6 @@ <script lang="ts"> + import { translator } from "../../Translator/Translator"; + function copyLink() { const input: HTMLInputElement = document.getElementById("input-share-link") as HTMLInputElement; input.focus(); @@ -21,14 +23,18 @@ <div class="guest-main"> <section class="container-overflow"> <section class="share-url not-mobile"> - <h3>Share the link of the room!</h3> + <h3>{translator._("menu.invite.description")}</h3> <input type="text" readonly id="input-share-link" value={location.toString()} /> - <button type="button" class="nes-btn is-primary" on:click={copyLink}>Copy</button> + <button type="button" class="nes-btn is-primary" on:click={copyLink} + >{translator._("menu.invite.copy")}</button + > </section> <section class="is-mobile"> - <h3>Share the link of the room!</h3> + <h3>{translator._("menu.invite.description")}</h3> <input type="hidden" readonly id="input-share-link" value={location.toString()} /> - <button type="button" class="nes-btn is-primary" on:click={shareLink}>Share</button> + <button type="button" class="nes-btn is-primary" on:click={shareLink} + >{translator._("menu.invite.share")}</button + > </section> </section> </div> diff --git a/front/src/Components/Menu/Menu.svelte b/front/src/Components/Menu/Menu.svelte index b02df36d..a8606653 100644 --- a/front/src/Components/Menu/Menu.svelte +++ b/front/src/Components/Menu/Menu.svelte @@ -18,6 +18,7 @@ import { get } from "svelte/store"; import type { Unsubscriber } from "svelte/store"; import { sendMenuClickedEvent } from "../../Api/iframe/Ui/MenuItem"; + import { translator } from "../../Translator/Translator"; let activeSubMenu: string = SubMenusInterface.profile; let activeComponent: typeof ProfileSubMenu | typeof CustomSubMenu = ProfileSubMenu; @@ -82,18 +83,26 @@ function closeMenu() { menuVisiblilityStore.set(false); } + function onKeyDown(e: KeyboardEvent) { if (e.key === "Escape") { closeMenu(); } } + + function translateMenuName(menuName: string) { + const nameFormatted = "menu.sub." + menuName.toLowerCase().replaceAll(" ", "-"); + const translation = translator._(nameFormatted); + + return translation === nameFormatted ? menuName : translation; + } </script> <svelte:window on:keydown={onKeyDown} /> <div class="menu-container-main"> <div class="menu-nav-sidebar nes-container is-rounded" transition:fly={{ x: -1000, duration: 500 }}> - <h2>Menu</h2> + <h2>{translator._("menu.title")}</h2> <nav> {#each $subMenusStore as submenu} <button @@ -101,14 +110,14 @@ class="nes-btn {activeSubMenu === submenu ? 'is-disabled' : ''}" on:click|preventDefault={() => switchMenu(submenu)} > - {submenu} + {translateMenuName(submenu)} </button> {/each} </nav> </div> <div class="menu-submenu-container nes-container is-rounded" transition:fly={{ y: -1000, duration: 500 }}> <button type="button" class="nes-btn is-error close" on:click={closeMenu}>×</button> - <h2>{activeSubMenu}</h2> + <h2>{translateMenuName(activeSubMenu)}</h2> <svelte:component this={activeComponent} {...props} /> </div> </div> diff --git a/front/src/Components/Menu/MenuIcon.svelte b/front/src/Components/Menu/MenuIcon.svelte index 9d3f72dd..5c0a1304 100644 --- a/front/src/Components/Menu/MenuIcon.svelte +++ b/front/src/Components/Menu/MenuIcon.svelte @@ -9,6 +9,7 @@ import { get } from "svelte/store"; import { ADMIN_URL } from "../../Enum/EnvironmentVariable"; import { showShareLinkMapModalStore } from "../../Stores/ModalStore"; + import { translator } from "../../Translator/Translator"; function showMenu() { menuVisiblilityStore.set(!get(menuVisiblilityStore)); @@ -29,11 +30,31 @@ <main class="menuIcon"> {#if $limitMapStore} - <img src={logoInvite} alt="open menu" class="nes-pointer" on:click|preventDefault={showInvite} /> - <img src={logoRegister} alt="open menu" class="nes-pointer" on:click|preventDefault={register} /> + <img + src={logoInvite} + alt={translator._("menu.icon.open.invite")} + class="nes-pointer" + on:click|preventDefault={showInvite} + /> + <img + src={logoRegister} + alt={translator._("menu.icon.open.register")} + class="nes-pointer" + on:click|preventDefault={register} + /> {:else} - <img src={logoWA} alt="open menu" class="nes-pointer" on:click|preventDefault={showMenu} /> - <img src={logoTalk} alt="open menu" class="nes-pointer" on:click|preventDefault={showChat} /> + <img + src={logoWA} + alt={translator._("menu.icon.open.menu")} + class="nes-pointer" + on:click|preventDefault={showMenu} + /> + <img + src={logoTalk} + alt={translator._("menu.icon.open.chat")} + class="nes-pointer" + on:click|preventDefault={showChat} + /> {/if} </main> diff --git a/front/src/Components/Menu/ProfileSubMenu.svelte b/front/src/Components/Menu/ProfileSubMenu.svelte index 87bf57c9..621670ec 100644 --- a/front/src/Components/Menu/ProfileSubMenu.svelte +++ b/front/src/Components/Menu/ProfileSubMenu.svelte @@ -17,6 +17,7 @@ import btnProfileSubMenuCompanion from "../images/btn-menu-profile-companion.svg"; import Woka from "../Woka/Woka.svelte"; import Companion from "../Companion/Companion.svelte"; + import { translator } from "../../Translator/Translator"; function disableMenuStores() { menuVisiblilityStore.set(false); @@ -62,20 +63,20 @@ <div class="submenu"> <section> <button type="button" class="nes-btn" on:click|preventDefault={openEditNameScene}> - <img src={btnProfileSubMenuIdentity} alt="Edit your name" /> - <span class="btn-hover">Edit your name</span> + <img src={btnProfileSubMenuIdentity} alt={translator._("menu.profile.edit.name")} /> + <span class="btn-hover">{translator._("menu.profile.edit.name")}</span> </button> <button type="button" class="nes-btn" on:click|preventDefault={openEditSkinScene}> <Woka userId={-1} placeholderSrc="" width="26px" height="26px" /> - <span class="btn-hover">Edit your WOKA</span> + <span class="btn-hover">{translator._("menu.profile.edit.woka")}</span> </button> <button type="button" class="nes-btn" on:click|preventDefault={openEditCompanionScene}> <Companion userId={-1} placeholderSrc={btnProfileSubMenuCompanion} width="26px" height="26px" /> - <span class="btn-hover">Edit your companion</span> + <span class="btn-hover">{translator._("menu.profile.edit.companion")}</span> </button> <button type="button" class="nes-btn" on:click|preventDefault={openEnableCameraScene}> - <img src={btnProfileSubMenuCamera} alt="Edit your camera" /> - <span class="btn-hover">Edit your camera</span> + <img src={btnProfileSubMenuCamera} alt={translator._("menu.profile.edit.camera")} /> + <span class="btn-hover">{translator._("menu.profile.edit.camera")}</span> </button> </section> </div> @@ -88,11 +89,13 @@ {/if} </section> <section> - <button type="button" class="nes-btn" on:click|preventDefault={logOut}>Log out</button> + <button type="button" class="nes-btn" on:click|preventDefault={logOut} + >{translator._("menu.profile.logout")}</button + > </section> {:else} <section> - <a type="button" class="nes-btn" href="/login">Sign in</a> + <a type="button" class="nes-btn" href="/login">{translator._("menu.profile.login")}</a> </section> {/if} </div> diff --git a/front/src/Components/Menu/SettingsSubMenu.svelte b/front/src/Components/Menu/SettingsSubMenu.svelte index 1ad1ac8b..53503902 100644 --- a/front/src/Components/Menu/SettingsSubMenu.svelte +++ b/front/src/Components/Menu/SettingsSubMenu.svelte @@ -4,6 +4,7 @@ import { HtmlUtils } from "../../WebRtc/HtmlUtils"; import { isMobile } from "../../Enum/EnvironmentVariable"; import { menuVisiblilityStore } from "../../Stores/MenuStore"; +import { translator } from "../../Translator/Translator"; let fullscreen: boolean = localUserStore.getFullscreen(); let notification: boolean = localUserStore.getNotification() === "granted"; @@ -73,34 +74,64 @@ <div class="settings-main" on:submit|preventDefault={saveSetting}> <section> - <h3>Game quality</h3> + <h3>{translator._("menu.settings.game-quality.title")}</h3> <div class="nes-select is-dark"> <select bind:value={valueGame}> - <option value={120}>{isMobile() ? "High (120 fps)" : "High video quality (120 fps)"}</option> - <option value={60} - >{isMobile() ? "Medium (60 fps)" : "Medium video quality (60 fps, recommended)"}</option + <option value={120} + >{isMobile() + ? translator._("menu.settings.game-quality.short.high") + : translator._("menu.settings.game-quality.long.high")}</option + > + <option value={60} + >{isMobile() + ? translator._("menu.settings.game-quality.short.medium") + : translator._("menu.settings.game-quality.long.medium")}</option + > + <option value={40} + >{isMobile() + ? translator._("menu.settings.game-quality.short.minimum") + : translator._("menu.settings.game-quality.long.minimum")}</option + > + <option value={20} + >{isMobile() + ? translator._("menu.settings.game-quality.short.small") + : translator._("menu.settings.game-quality.long.small")}</option > - <option value={40}>{isMobile() ? "Minimum (40 fps)" : "Minimum video quality (40 fps)"}</option> - <option value={20}>{isMobile() ? "Small (20 fps)" : "Small video quality (20 fps)"}</option> </select> </div> </section> <section> - <h3>Video quality</h3> + <h3>{translator._("menu.settings.video-quality.title")}</h3> <div class="nes-select is-dark"> <select bind:value={valueVideo}> - <option value={30}>{isMobile() ? "High (30 fps)" : "High video quality (30 fps)"}</option> - <option value={20} - >{isMobile() ? "Medium (20 fps)" : "Medium video quality (20 fps, recommended)"}</option + <option value={30} + >{isMobile() + ? translator._("menu.settings.video-quality.short.high") + : translator._("menu.settings.video-quality.long.high")}</option + > + <option value={20} + >{isMobile() + ? translator._("menu.settings.video-quality.short.medium") + : translator._("menu.settings.video-quality.long.medium")}</option + > + <option value={10} + >{isMobile() + ? translator._("menu.settings.video-quality.short.minimum") + : translator._("menu.settings.video-quality.long.minimum")}</option + > + <option value={5} + >{isMobile() + ? translator._("menu.settings.video-quality.short.small") + : translator._("menu.settings.video-quality.long.small")}</option > - <option value={10}>{isMobile() ? "Minimum (10 fps)" : "Minimum video quality (10 fps)"}</option> - <option value={5}>{isMobile() ? "Small (5 fps)" : "Small video quality (5 fps)"}</option> </select> </div> </section> <section class="settings-section-save"> - <p>(Saving these settings will restart the game)</p> - <button type="button" class="nes-btn is-primary" on:click|preventDefault={saveSetting}>Save</button> + <p>{translator._("menu.settings.save.warning")}</p> + <button type="button" class="nes-btn is-primary" on:click|preventDefault={saveSetting} + >{translator._("menu.settings.save.button")}</button + > </section> <section class="settings-section-noSaveOption"> <label> @@ -110,7 +141,7 @@ bind:checked={fullscreen} on:change={changeFullscreen} /> - <span>Fullscreen</span> + <span>{translator._("menu.settings.fullscreen")}</span> </label> <label> <input @@ -119,7 +150,7 @@ bind:checked={notification} on:change={changeNotification} /> - <span>Notifications</span> + <span>{translator._("menu.settings.notifications")}</span> </label> <label> <input @@ -128,7 +159,7 @@ bind:checked={forceCowebsiteTrigger} on:change={changeForceCowebsiteTrigger} /> - <span>Always ask before opening websites and Jitsi Meet rooms</span> + <span>{translator._("menu.settings.cowebsite-trigger")}</span> </label> <label> <input @@ -137,7 +168,7 @@ bind:checked={ignoreFollowRequests} on:change={changeIgnoreFollowRequests} /> - <span>Ignore requests to follow other users</span> + <span>{translator._("menu.settings.ignore-follow-request")}</span> </label> </section> </div> diff --git a/front/src/Components/Menu/TextGlobalMessage.svelte b/front/src/Components/Menu/TextGlobalMessage.svelte index ed39d573..8f984f68 100644 --- a/front/src/Components/Menu/TextGlobalMessage.svelte +++ b/front/src/Components/Menu/TextGlobalMessage.svelte @@ -5,6 +5,7 @@ import { AdminMessageEventTypes } from "../../Connexion/AdminMessagesService"; import type { Quill } from "quill"; import type { PlayGlobalMessageInterface } from "../../Connexion/ConnexionModels"; + import { translator } from "../../Translator/Translator"; //toolbar const toolbarOptions = [ @@ -58,7 +59,7 @@ const { default: Quill } = await import("quill"); // eslint-disable-line @typescript-eslint/no-explicit-any quill = new Quill(QUILL_EDITOR, { - placeholder: "Enter your message here...", + placeholder: translator._("menu.global-message.enter"), theme: "snow", modules: { toolbar: toolbarOptions, diff --git a/front/src/Components/MyCamera.svelte b/front/src/Components/MyCamera.svelte index 5db9171c..6c259b54 100644 --- a/front/src/Components/MyCamera.svelte +++ b/front/src/Components/MyCamera.svelte @@ -4,6 +4,7 @@ import SoundMeterWidget from "./SoundMeterWidget.svelte"; import { onDestroy } from "svelte"; import { srcObject } from "./Video/utils"; + import { translator } from "../Translator/Translator"; let stream: MediaStream | null; @@ -32,5 +33,5 @@ <SoundMeterWidget {stream} /> {/if} </div> - <div class="is-silent" class:hide={isSilent}>Silent zone</div> + <div class="is-silent" class:hide={isSilent}>{translator._("camera.my.silent-zone")}</div> </div> diff --git a/front/src/Components/ReportMenu/BlockSubMenu.svelte b/front/src/Components/ReportMenu/BlockSubMenu.svelte index c27169bf..765b0202 100644 --- a/front/src/Components/ReportMenu/BlockSubMenu.svelte +++ b/front/src/Components/ReportMenu/BlockSubMenu.svelte @@ -2,6 +2,7 @@ import { blackListManager } from "../../WebRtc/BlackListManager"; import { showReportScreenStore, userReportEmpty } from "../../Stores/ShowReportScreenStore"; import { onMount } from "svelte"; + import { translator } from "../../Translator/Translator"; export let userUUID: string | undefined; export let userName: string; @@ -29,10 +30,10 @@ </script> <div class="block-container"> - <h3>Block</h3> - <p>Block any communication from and to {userName}. This can be reverted.</p> + <h3>{translator._("report.block.title")}</h3> + <p>{translator._("report.block.content", { userName })}</p> <button type="button" class="nes-btn is-error" on:click|preventDefault={blockUser}> - {userIsBlocked ? "Unblock this user" : "Block this user"} + {userIsBlocked ? translator._("report.block.unblock") : translator._("report.block.block")} </button> </div> diff --git a/front/src/Components/ReportMenu/ReportMenu.svelte b/front/src/Components/ReportMenu/ReportMenu.svelte index 92601774..0b482dc6 100644 --- a/front/src/Components/ReportMenu/ReportMenu.svelte +++ b/front/src/Components/ReportMenu/ReportMenu.svelte @@ -7,6 +7,7 @@ import { playersStore } from "../../Stores/PlayersStore"; import { connectionManager } from "../../Connexion/ConnectionManager"; import { get } from "svelte/store"; + import { translator } from "../../Translator/Translator"; let blockActive = true; let reportActive = !blockActive; @@ -59,7 +60,7 @@ <div class="report-menu-main nes-container is-rounded"> <section class="report-menu-title"> - <h2>Moderate {userName}</h2> + <h2>{translator._("moderate.title", { userName })}</h2> <section class="justify-center"> <button type="button" class="nes-btn" on:click|preventDefault={close}>X</button> </section> @@ -69,14 +70,14 @@ <button type="button" class="nes-btn {blockActive ? 'is-disabled' : ''}" - on:click|preventDefault={activateBlock}>Block</button + on:click|preventDefault={activateBlock}>{translator._("moderate.block")}</button > </section> <section class="justify-center"> <button type="button" class="nes-btn {reportActive ? 'is-disabled' : ''}" - on:click|preventDefault={activateReport}>Report</button + on:click|preventDefault={activateReport}>{translator._("moderate.report")}</button > </section> </section> @@ -86,7 +87,7 @@ {:else if reportActive} <ReportSubMenu {userUUID} /> {:else} - <p>ERROR : There is no action selected.</p> + <p>{translator._("moderate.no-select")}</p> {/if} </section> </div> diff --git a/front/src/Components/ReportMenu/ReportSubMenu.svelte b/front/src/Components/ReportMenu/ReportSubMenu.svelte index 379dd663..20a38a9b 100644 --- a/front/src/Components/ReportMenu/ReportSubMenu.svelte +++ b/front/src/Components/ReportMenu/ReportSubMenu.svelte @@ -1,6 +1,7 @@ <script lang="ts"> import { showReportScreenStore, userReportEmpty } from "../../Stores/ShowReportScreenStore"; import { gameManager } from "../../Phaser/Game/GameManager"; + import { translator } from "../../Translator/Translator"; export let userUUID: string | undefined; let reportMessage: string; @@ -22,18 +23,20 @@ </script> <div class="report-container-main"> - <h3>Report</h3> - <p>Send a report message to the administrators of this room. They may later ban this user.</p> + <h3>{translator._("report.title")}</h3> + <p>{translator._("report.message")}</p> <form> <section> <label> - <span>Your message: </span> + <span>{translator._("report.message.title")}</span> <textarea type="text" class="nes-textarea" bind:value={reportMessage} /> </label> - <p hidden={hiddenError}>Report message cannot to be empty.</p> + <p hidden={hiddenError}>{translator._("report.message.empty")}</p> </section> <section> - <button type="submit" class="nes-btn is-error" on:click={submitReport}>Report this user</button> + <button type="submit" class="nes-btn is-error" on:click={submitReport} + >{translator._("report.submit")}</button + > </section> </form> </div> diff --git a/front/src/Components/SelectCompanion/SelectCompanionScene.svelte b/front/src/Components/SelectCompanion/SelectCompanionScene.svelte index 99c654ce..94c1d9c6 100644 --- a/front/src/Components/SelectCompanion/SelectCompanionScene.svelte +++ b/front/src/Components/SelectCompanion/SelectCompanionScene.svelte @@ -1,6 +1,7 @@ <script lang="typescript"> import type { Game } from "../../Phaser/Game/Game"; import { SelectCompanionScene, SelectCompanionSceneName } from "../../Phaser/Login/SelectCompanionScene"; + import { translator } from "../../Translator/Translator"; export let game: Game; @@ -25,7 +26,7 @@ <form class="selectCompanionScene"> <section class="text-center"> - <h2>Select your companion</h2> + <h2>{translator._("companion.select.title")}</h2> <button class="selectCharacterButton selectCharacterButtonLeft nes-btn" on:click|preventDefault={selectLeft}> < </button> @@ -35,12 +36,12 @@ </section> <section class="action"> <button href="/" class="selectCompanionSceneFormBack nes-btn" on:click|preventDefault={noCompanion} - >No companion</button + >{translator._("companion.select.any")}</button > <button type="submit" class="selectCompanionSceneFormSubmit nes-btn is-primary" - on:click|preventDefault={selectCompanion}>Continue</button + on:click|preventDefault={selectCompanion}>{translator._("companion.select.continue")}</button > </section> </form> diff --git a/front/src/Components/TypeMessage/BanMessage.svelte b/front/src/Components/TypeMessage/BanMessage.svelte index ce230067..4b19523b 100644 --- a/front/src/Components/TypeMessage/BanMessage.svelte +++ b/front/src/Components/TypeMessage/BanMessage.svelte @@ -3,6 +3,7 @@ import { onMount } from "svelte"; import type { Message } from "../../Stores/TypeMessageStore/MessageStore"; import { banMessageStore } from "../../Stores/TypeMessageStore/BanMessageStore"; + import { translator } from "../../Translator/Translator"; export let message: Message; @@ -37,7 +38,8 @@ out:fade={{ duration: 200 }} > <h2 class="title-ban-message"> - <img src="resources/logos/report.svg" alt="***" /> Important message + <img src="resources/logos/report.svg" alt="***" /> + {translator._("important-message")} <img src="resources/logos/report.svg" alt="***" /> </h2> <div class="content-ban-message"> diff --git a/front/src/Components/UI/AudioPlaying.svelte b/front/src/Components/UI/AudioPlaying.svelte index a8d12ec9..bfe34157 100644 --- a/front/src/Components/UI/AudioPlaying.svelte +++ b/front/src/Components/UI/AudioPlaying.svelte @@ -3,6 +3,7 @@ import megaphoneImg from "./images/megaphone.svg"; import { soundPlayingStore } from "../../Stores/SoundPlayingStore"; import { afterUpdate } from "svelte"; + import { translator } from "../../Translator/Translator"; export let url: string; let audio: HTMLAudioElement; @@ -18,7 +19,7 @@ <div class="audio-playing" transition:fly={{ x: 210, duration: 500 }}> <img src={megaphoneImg} alt="Audio playing" /> - <p>Audio message</p> + <p>{translator._("audio.message")}</p> <audio bind:this={audio} src={url} on:ended={soundEnded}> <track kind="captions" /> </audio> diff --git a/front/src/Components/VisitCard/VisitCard.svelte b/front/src/Components/VisitCard/VisitCard.svelte index 5bf8c57e..df1342a8 100644 --- a/front/src/Components/VisitCard/VisitCard.svelte +++ b/front/src/Components/VisitCard/VisitCard.svelte @@ -2,6 +2,7 @@ import { fly } from "svelte/transition"; import { requestVisitCardsStore } from "../../Stores/GameStore"; import { onMount } from "svelte"; + import { translator } from "../../Translator/Translator"; export let visitCardUrl: string; let w = "500px"; @@ -40,7 +41,8 @@ /> {#if !hidden} <div class="buttonContainer"> - <button class="nes-btn is-popUpElement" on:click={closeCard}>Close</button> + <button class="nes-btn is-popUpElement" on:click={closeCard}>{translator._("menu.visit-card.close")}</button + > </div> {/if} </section> diff --git a/front/src/Components/WarningContainer/WarningContainer.svelte b/front/src/Components/WarningContainer/WarningContainer.svelte index f75050fc..2791d462 100644 --- a/front/src/Components/WarningContainer/WarningContainer.svelte +++ b/front/src/Components/WarningContainer/WarningContainer.svelte @@ -2,6 +2,7 @@ import { fly } from "svelte/transition"; import { userIsAdminStore, limitMapStore } from "../../Stores/GameStore"; import { ADMIN_URL } from "../../Enum/EnvironmentVariable"; + import { translator } from "../../Translator/Translator"; const upgradeLink = ADMIN_URL + "/pricing"; const registerLink = ADMIN_URL + "/second-step-register"; @@ -9,19 +10,17 @@ <main class="warningMain" transition:fly={{ y: -200, duration: 500 }}> {#if $userIsAdminStore} - <h2>Warning!</h2> + <h2>{translator._("warning.title")}</h2> <p> - This world is close to its limit!. You can upgrade its capacity <a href={upgradeLink} target="_blank" - >here</a - > + {translator._("warning.content", { upgradeLink })} </p> {:else if $limitMapStore} <p> This map is available for 2 days. You can register your domain <a href={registerLink}>here</a>! </p> {:else} - <h2>Warning!</h2> - <p>This world is close to its limit!</p> + <h2>{translator._("warning.title")}</h2> + <p>{translator._("warning.limit")}</p> {/if} </main> diff --git a/front/src/Components/selectCharacter/SelectCharacterScene.svelte b/front/src/Components/selectCharacter/SelectCharacterScene.svelte index 77db49e9..f7e3be5b 100644 --- a/front/src/Components/selectCharacter/SelectCharacterScene.svelte +++ b/front/src/Components/selectCharacter/SelectCharacterScene.svelte @@ -1,6 +1,7 @@ <script lang="typescript"> import type { Game } from "../../Phaser/Game/Game"; import { SelectCharacterScene, SelectCharacterSceneName } from "../../Phaser/Login/SelectCharacterScene"; + import { translator } from "../../Translator/Translator"; export let game: Game; @@ -25,7 +26,7 @@ <form class="selectCharacterScene"> <section class="text-center"> - <h2>Select your WOKA</h2> + <h2>{translator._("select-woka.title")}</h2> <button class="selectCharacterButton selectCharacterButtonLeft nes-btn" on:click|preventDefault={selectLeft}> < </button> @@ -37,12 +38,12 @@ <button type="submit" class="selectCharacterSceneFormSubmit nes-btn is-primary" - on:click|preventDefault={cameraScene}>Continue</button + on:click|preventDefault={cameraScene}>{translator._("select-woka.continue")}</button > <button type="submit" class="selectCharacterSceneFormCustomYourOwnSubmit nes-btn" - on:click|preventDefault={customizeScene}>Customize your WOKA</button + on:click|preventDefault={customizeScene}>{translator._("select-woka.customize")}</button > </section> </form> diff --git a/front/src/Phaser/Login/EntryScene.ts b/front/src/Phaser/Login/EntryScene.ts index 37b77048..b67b559a 100644 --- a/front/src/Phaser/Login/EntryScene.ts +++ b/front/src/Phaser/Login/EntryScene.ts @@ -13,7 +13,6 @@ export const EntrySceneName = "EntryScene"; * and to route to the next correct scene. */ export class EntryScene extends Scene { - constructor() { super({ key: EntrySceneName, @@ -48,20 +47,20 @@ export class EntryScene extends Scene { if (err.response && err.response.status == 404) { ErrorScene.showError( new WAError( - "Access link incorrect", - "Could not find map. Please check your access link.", - "If you want more information, you may contact administrator or contact us at: hello@workadventu.re" + translator._("error.access-link.title"), + translator._("error.access-link.sub-title"), + translator._("error.access-link.details") ), this.scene ); } else if (err.response && err.response.status == 403) { ErrorScene.showError( new WAError( - "Connection rejected", - "You cannot join the World. Try again later" + - (err.response.data ? ". \n\r \n\r" + `${err.response.data}` : "") + - ".", - "If you want more information, you may contact administrator or contact us at: hello@workadventu.re" + translator._("error.connection-rejected.title"), + translator._("error.connection-rejected.sub-title", { + error: err.response.data ? ". \n\r \n\r" + `${err.response.data}` : "", + }), + translator._("error.connection-rejected.details") ), this.scene ); diff --git a/front/src/Phaser/Reconnecting/ReconnectingScene.ts b/front/src/Phaser/Reconnecting/ReconnectingScene.ts index aa19bd21..08092488 100644 --- a/front/src/Phaser/Reconnecting/ReconnectingScene.ts +++ b/front/src/Phaser/Reconnecting/ReconnectingScene.ts @@ -1,3 +1,4 @@ +import { translator } from "../../Translator/Translator"; import { TextField } from "../Components/TextField"; import Image = Phaser.GameObjects.Image; import Sprite = Phaser.GameObjects.Sprite; @@ -38,7 +39,7 @@ export class ReconnectingScene extends Phaser.Scene { this, this.game.renderer.width / 2, this.game.renderer.height / 2, - "Connection lost. Reconnecting..." + translator._("connection-lost") ); const cat = this.add.sprite(this.game.renderer.width / 2, this.game.renderer.height / 2 - 32, "cat"); diff --git a/front/src/Translator/Translator.ts b/front/src/Translator/Translator.ts index 35785e95..7cae4c5f 100644 --- a/front/src/Translator/Translator.ts +++ b/front/src/Translator/Translator.ts @@ -224,7 +224,9 @@ class Translator { return params ? this.formatStringWithParams(fallbackLanguageValue, params) : fallbackLanguageValue; } - console.warn(`"${key}" key cannot be found in ${this.getStringByLanguage(this.fallbackLanguage)} fallback language`); + console.warn( + `"${key}" key cannot be found in ${this.getStringByLanguage(this.fallbackLanguage)} fallback language` + ); return key; } diff --git a/front/src/WebRtc/MediaManager.ts b/front/src/WebRtc/MediaManager.ts index 7b32699b..6302f217 100644 --- a/front/src/WebRtc/MediaManager.ts +++ b/front/src/WebRtc/MediaManager.ts @@ -13,6 +13,7 @@ import { layoutManagerActionStore, layoutManagerVisibilityStore } from "../Store import { get } from "svelte/store"; import { localUserStore } from "../Connexion/LocalUserStore"; import { MediaStreamConstraintsError } from "../Stores/Errors/MediaStreamConstraintsError"; +import { translator } from "../Translator/Translator"; export class MediaManager { startScreenSharingCallBacks: Set<StartScreenSharingCallback> = new Set<StartScreenSharingCallback>(); @@ -29,7 +30,7 @@ export class MediaManager { layoutManagerActionStore.addAction({ uuid: "cameraAccessDenied", type: "warning", - message: "Camera access denied. Click here and check your browser permissions.", + message: translator._("warning.access-denied.camera"), callback: () => { helpCameraSettingsVisibleStore.set(true); }, @@ -50,7 +51,7 @@ export class MediaManager { layoutManagerActionStore.addAction({ uuid: "screenSharingAccessDenied", type: "warning", - message: "Screen sharing denied. Click here and check your browser permissions.", + message: translator._("warning.access-denied.screen-sharing"), callback: () => { helpCameraSettingsVisibleStore.set(true); }, diff --git a/front/translations/en-US/audio.en-US.json b/front/translations/en-US/audio.en-US.json new file mode 100644 index 00000000..677b67b1 --- /dev/null +++ b/front/translations/en-US/audio.en-US.json @@ -0,0 +1,8 @@ +{ + "audio": { + "manager": { + "reduce": "reduce in conversations" + }, + "message": "Audio message" + } +} diff --git a/front/translations/en-US/camera.en-US.json b/front/translations/en-US/camera.en-US.json new file mode 100644 index 00000000..35d03221 --- /dev/null +++ b/front/translations/en-US/camera.en-US.json @@ -0,0 +1,19 @@ +{ + "camera": { + "enable": { + "title": "Turn on your camera and microphone", + "start": "Let's go!" + }, + "help": { + "title": "Camera / Microphone access needed", + "permission-denied": "Permission denied", + "content": "You must allow camera and microphone access in your browser.", + "firefox-content": "Please click the \"Remember this decision\" checkbox, if you don't want Firefox to keep asking you the authorization.", + "refresh": "Refresh", + "continue": "Continue without webcam" + }, + "my": { + "silent-zone": "Silent zone" + } + } +} diff --git a/front/translations/en-US/chat.en-US.json b/front/translations/en-US/chat.en-US.json new file mode 100644 index 00000000..1c05f15b --- /dev/null +++ b/front/translations/en-US/chat.en-US.json @@ -0,0 +1,10 @@ +{ + "chat": { + "intro": "Here is your chat history:", + "enter": "Enter your message...", + "menu": { + "visit-card": "Visit card", + "add-friend": "Add friend" + } + } +} diff --git a/front/translations/en-US/companion.en-US.json b/front/translations/en-US/companion.en-US.json new file mode 100644 index 00000000..8346c992 --- /dev/null +++ b/front/translations/en-US/companion.en-US.json @@ -0,0 +1,9 @@ +{ + "companion": { + "select": { + "title": "Select your companion", + "any": "No companion", + "continue": "Continue" + } + } +} diff --git a/front/translations/en-US/custom-character.en-US.json b/front/translations/en-US/custom-character.en-US.json new file mode 100644 index 00000000..56f7dac4 --- /dev/null +++ b/front/translations/en-US/custom-character.en-US.json @@ -0,0 +1,16 @@ +{ + "custom-character": { + "title": "Customize your WOKA", + "navigation": { + "return": "Return", + "back": "Back", + "finish": "Finish", + "next": "Next" + } + }, + "select-woka": { + "title": "Select your WOKA", + "continue": "Continue", + "customize": "Customize your WOKA" + } +} diff --git a/front/translations/en-US/error.en-US.json b/front/translations/en-US/error.en-US.json new file mode 100644 index 00000000..d91d7dd0 --- /dev/null +++ b/front/translations/en-US/error.en-US.json @@ -0,0 +1,14 @@ +{ + "error": { + "access-link": { + "title": "Access link incorrect", + "sub-title": "Could not find map. Please check your access link.", + "details": "If you want more information, you may contact administrator or contact us at: hello@workadventu.re" + }, + "connection-rejected": { + "title": "Connection rejected", + "sub-title": "You cannot join the World. Try again later {{error}}.", + "details": "If you want more information, you may contact administrator or contact us at: hello@workadventu.re" + } + } +} \ No newline at end of file diff --git a/front/translations/en-US/follow.en-US.json b/front/translations/en-US/follow.en-US.json new file mode 100644 index 00000000..baa32baf --- /dev/null +++ b/front/translations/en-US/follow.en-US.json @@ -0,0 +1,25 @@ +{ + "follow": { + "interact-status": { + "following": "Following {{leader}}", + "waiting-followers": "Waiting for followers confirmation", + "followed": { + "one": "{{follower}} is following you", + "two": "{{firstFollower}} and {{secondFollower}} are following you", + "many": "{{followers}} and {{lastFollower}} are following you" + } + }, + "interact-menu": { + "title": { + "interact": "Interaction", + "follow": "Do you want to follow {{leader}}?" + }, + "stop": { + "leader": "Do you want to stop leading the way?", + "follower": "Do you want to stop following {{leader}}?" + }, + "yes": "Yes", + "no": "No" + } + } +} diff --git a/front/translations/en-US/login.en-US.json b/front/translations/en-US/login.en-US.json new file mode 100644 index 00000000..8cb20637 --- /dev/null +++ b/front/translations/en-US/login.en-US.json @@ -0,0 +1,12 @@ +{ + "login": { + "input": { + "name": { + "placeholder": "Enter your name", + "empty": "The name is empty" + } + }, + "terms": "By continuing, you are agreeing our <a href=\"https://workadventu.re/terms-of-use\" target=\"_blank\">terms of use</a>, <a href=\"https://workadventu.re/privacy-policy\" target=\"_blank\">privacy policy</a> and <a href=\"https://workadventu.re/cookie-policy\" target=\"_blank\">cookie policy</a>.", + "continue": "Continue" + } +} diff --git a/front/translations/en-US/menu.en-US.json b/front/translations/en-US/menu.en-US.json new file mode 100644 index 00000000..f6170423 --- /dev/null +++ b/front/translations/en-US/menu.en-US.json @@ -0,0 +1,118 @@ +{ + "menu": { + "title": "Menu", + "icon": { + "open": { + "menu": "Open menu", + "invite": "Show invite", + "register": "Register", + "chat": "Open chat" + } + }, + "visit-card": { + "close": "Close" + }, + "profile": { + "edit": { + "name": "Edit your name", + "woka": "Edit your WOKA", + "companion": "Edit your companion", + "camera": "Edit your camera" + }, + "login": "Sign in", + "logout": "Log out" + }, + "settings": { + "game-quality": { + "title": "Game quality", + "short": { + "high": "High (120 fps)", + "medium": "Medium (60 fps)", + "minimum": "Minimum (40 fps)", + "small": "Small (20 fps)" + }, + "long": { + "high": "High video quality (120 fps)", + "medium": "Medium video quality (60 fps, recommended)", + "minimum": "Minimum video quality (40 fps)", + "small": "Small video quality (20 fps)" + } + }, + "video-quality": { + "title": "Video quality", + "short": { + "high": "High (30 fps)", + "medium": "Medium (20 fps)", + "minimum": "Minimum (10 fps)", + "small": "Small (5 fps)" + }, + "long": { + "high": "High video quality (30 fps)", + "medium": "Medium video quality (20 fps, recommended)", + "minimum": "Minimum video quality (10 fps)", + "small": "Small video quality (5 fps)" + } + }, + "save": { + "warning": "(Saving these settings will restart the game)", + "button": "Save" + }, + "fullscreen": "Fullscreen", + "notifications": "Notifications", + "cowebsite-trigger": "Always ask before opening websites and Jitsi Meet rooms", + "ignore-follow-request": "Ignore requests to follow other users" + }, + "invite": { + "description": "Share the link of the room!", + "copy": "Copy", + "share": "Share" + }, + "global-message": { + "text": "Text", + "audio": "Audio", + "warning": "Broadcast to all rooms of the world", + "enter": "Enter your message here...", + "send": "Send" + }, + "global-audio": { + "upload-info": "Upload a file", + "error": "No file selected. You need to upload a file before sending it." + }, + "contact": { + "getting-started": { + "title": "Getting started", + "description": "WorkAdventure allows you to create an online space to communicate spontaneously with others. And it all starts with creating your own space. Choose from a large selection of prefabricated maps by our team." + }, + "create-map": { + "title": "Create your map", + "description": "You can also create your own custom map by following the step of the documentation." + } + }, + "about": { + "map-info": "Information on the map", + "map-link": "link to this map", + "copyrights": { + "map": { + "title": "Copyrights of the map", + "empty": "The map creator did not declare a copyright for the map." + }, + "tileset": { + "title": "Copyrights of the tilesets", + "empty": "The map creator did not declare a copyright for the tilesets. This doesn't mean that those tilesets have no license." + }, + "audio": { + "title": "Copyrights of audio files", + "empty": "The map creator did not declare a copyright for audio files. This doesn't mean that those audio files have no license." + } + } + }, + "sub": { + "profile": "Profile", + "settings": "Settings", + "invite": "Invite", + "credit": "Credit", + "global-message": "Global Messages", + "contact": "Contact" + } + } +} diff --git a/front/translations/en-US/report.en-US.json b/front/translations/en-US/report.en-US.json new file mode 100644 index 00000000..97eafc1c --- /dev/null +++ b/front/translations/en-US/report.en-US.json @@ -0,0 +1,23 @@ +{ + "report": { + "block": { + "title": "Block", + "content": "Block any communication from and to {{userName}}. This can be reverted.", + "unblock": "Unblock this user", + "block": "Block this user" + }, + "title": "Report", + "content": "Send a report message to the administrators of this room. They may later ban this user.", + "message": { + "title": "Your message: ", + "empty": "Report message cannot to be empty." + }, + "submit": "Report this user" + }, + "moderate": { + "title": "Moderate {{userName}}", + "block": "Block", + "report": "Report", + "no-select": "ERROR : There is no action selected." + } +} diff --git a/front/translations/en-US/test.en-US.json b/front/translations/en-US/test.en-US.json deleted file mode 100644 index 5bc56b94..00000000 --- a/front/translations/en-US/test.en-US.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "test": { - "nolway": "Too mutch cofee" - } -} diff --git a/front/translations/en-US/warning.en-US.json b/front/translations/en-US/warning.en-US.json new file mode 100644 index 00000000..028e68a0 --- /dev/null +++ b/front/translations/en-US/warning.en-US.json @@ -0,0 +1,13 @@ +{ + "warning": { + "title": "Warning!", + "content": "This world is close to its limit!. You can upgrade its capacity <a href={{upgradeLink}} target=\"_blank\">here</a>", + "limit": "This world is close to its limit!", + "access-denied": { + "camera": "Camera access denied. Click here and check your browser permissions.", + "screen-sharing": "Screen sharing denied. Click here and check your browser permissions." + } + }, + "important-message": "Important message", + "connection-lost": "Connection lost. Reconnecting..." +}