From 71d5d88a4906c4bf6efc5a631d6f1a62dd93a4cb Mon Sep 17 00:00:00 2001 From: evemartin Date: Thu, 9 May 2024 15:27:48 +0100 Subject: [PATCH 1/5] feat: add language dropdown (#1606) * feat: add language dropdown * feat: improve language dropdown * feat: add language dropdown test * remove test file to debug * debug tests * debug tests * debug tests * debug tests * debug tests * debug tests * debug tests * Simplify callback * debug tests * debug tests * testing * testing * debug tests * debug tests * add dropdown with dummy onchange function * add loadLanguage functions for updating language * add other languages * debug tests * added loadLanguages file to html * test removal of Blockly.Msg references * test addition of en.js script tag * test removal of custom block labels * test removal of extra css * debug tests, remove css * add back removed things except for css * test addition of en.js tag * test removal of custom block labels * testing addition of loadLanguage at startup, removal of en.js script * test addition of en.js script * testing small changes * test reloading workspace instead of containing everything in callback * test if reloading the workspace works if nothing else happens * more tests to see if just reloading will work * debug tests, reload * add back what I changed * removing any reloading * testing out reload again * testing if navigator is causing bug * try calling loadLanguage without reloading * adding some logging * moving loadLanguage function * try moving function again * fix logic negate error * add back other things now that logic negate issue fixed * add back some removed css * update css and some text * test removing test * debug tests * debug tests * debug tests * address PR comments * address PR comment - show dropdown symbol on language dropdown * begin adding translations * add black to pipfile * add remaining translations * comment out untranslated languages * add hindi * address PR comments --------- Co-authored-by: faucomte97 --- Pipfile | 2 + Pipfile.lock | 81 +++++++++++++++- game/end_to_end_tests/base_game_test.py | 3 - game/end_to_end_tests/game_page.py | 2 + .../test_language_dropdown.py | 14 +++ game/static/game/css/backgrounds.css | 18 ++-- game/static/game/css/game_screen.css | 11 +++ game/static/game/js/blockly/msg/js/en-gb.js | 51 +++++++++- game/static/game/js/blockly/msg/js/en.js | 51 +++++++++- game/static/game/js/blockly/msg/js/fr.js | 51 +++++++++- game/static/game/js/blockly/msg/js/hi.js | 51 +++++++++- game/static/game/js/blocklyControl.js | 3 +- game/static/game/js/blocklyCustomBlocks.js | 92 +++++++++---------- game/static/game/js/blocklyCustomisations.js | 4 +- game/static/game/js/game.js | 80 +++++++++------- game/static/game/js/loadLanguages.js | 21 +++++ game/templates/game/game.html | 22 ++++- game/views/language_code_conversions.py | 90 ++++++++++++++++++ game/views/level.py | 2 + 19 files changed, 544 insertions(+), 105 deletions(-) create mode 100644 game/end_to_end_tests/test_language_dropdown.py create mode 100644 game/static/game/js/loadLanguages.js create mode 100644 game/views/language_code_conversions.py diff --git a/Pipfile b/Pipfile index a8ef335c1..afdb4bb73 100644 --- a/Pipfile +++ b/Pipfile @@ -9,11 +9,13 @@ ipython = "*" rapid-router = {path = ".", editable = true} [dev-packages] +black = "*" codeforlife-portal = "*" django-import-export = "*" django-selenium-clean = "==1.0.0" django-test-migrations = "==1.2.0" importlib-metadata = "<5" # Using version 5 causes an issue when trying to run pytest. Not sure why, linked to: https://stackoverflow.com/questions/73929564/entrypoints-object-has-no-attribute-get-digital-ocean +isort = "*" pytest = "==7.*" pytest-django = "==4.5.2" pytest-order = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 51d84816a..7937ea228 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "f226d4b94222f73959f2d2a2ca01b487d4d58f7f188553141389208e98bce1ca" + "sha256": "95dccb04c57f2209160bd30a130b5eaaf58cbaaf038d32faf7f0fe919a3db538" }, "pipfile-spec": 6, "requires": { @@ -464,7 +464,7 @@ "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.9.0.post0" }, "pytz": { @@ -499,7 +499,7 @@ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, "sqlparse": { @@ -589,6 +589,35 @@ "markers": "python_version >= '3.7'", "version": "==23.2.0" }, + "black": { + "hashes": [ + "sha256:257d724c2c9b1660f353b36c802ccece186a30accc7742c176d29c146df6e474", + "sha256:37aae07b029fa0174d39daf02748b379399b909652a806e5708199bd93899da1", + "sha256:415e686e87dbbe6f4cd5ef0fbf764af7b89f9057b97c908742b6008cc554b9c0", + "sha256:48a85f2cb5e6799a9ef05347b476cce6c182d6c71ee36925a6c194d074336ef8", + "sha256:7768a0dbf16a39aa5e9a3ded568bb545c8c2727396d063bbaf847df05b08cd96", + "sha256:7e122b1c4fb252fd85df3ca93578732b4749d9be076593076ef4d07a0233c3e1", + "sha256:88c57dc656038f1ab9f92b3eb5335ee9b021412feaa46330d5eba4e51fe49b04", + "sha256:8e537d281831ad0e71007dcdcbe50a71470b978c453fa41ce77186bbe0ed6021", + "sha256:98e123f1d5cfd42f886624d84464f7756f60ff6eab89ae845210631714f6db94", + "sha256:accf49e151c8ed2c0cdc528691838afd217c50412534e876a19270fea1e28e2d", + "sha256:b1530ae42e9d6d5b670a34db49a94115a64596bc77710b1d05e9801e62ca0a7c", + "sha256:b9176b9832e84308818a99a561e90aa479e73c523b3f77afd07913380ae2eab7", + "sha256:bdde6f877a18f24844e381d45e9947a49e97933573ac9d4345399be37621e26c", + "sha256:be8bef99eb46d5021bf053114442914baeb3649a89dc5f3a555c88737e5e98fc", + "sha256:bf10f7310db693bb62692609b397e8d67257c55f949abde4c67f9cc574492cc7", + "sha256:c872b53057f000085da66a19c55d68f6f8ddcac2642392ad3a355878406fbd4d", + "sha256:d36ed1124bb81b32f8614555b34cc4259c3fbc7eec17870e8ff8ded335b58d8c", + "sha256:da33a1a5e49c4122ccdfd56cd021ff1ebc4a1ec4e2d01594fef9b6f267a9e741", + "sha256:dd1b5a14e417189db4c7b64a6540f31730713d173f0b63e55fabd52d61d8fdce", + "sha256:e151054aa00bad1f4e1f04919542885f89f5f7d086b8a59e5000e6c616896ffb", + "sha256:eaea3008c281f1038edb473c1aa8ed8143a5535ff18f978a318f10302b254063", + "sha256:ef703f83fc32e131e9bcc0a5094cfe85599e7109f896fe8bc96cc402f3eb4b6e" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==24.4.2" + }, "cachetools": { "hashes": [ "sha256:0abad1021d3f8325b2fc1d2e9c8b9c9d57b04c3932657a72465447332c24d945", @@ -708,6 +737,14 @@ "markers": "python_full_version >= '3.7.0'", "version": "==3.3.2" }, + "click": { + "hashes": [ + "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28", + "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de" + ], + "markers": "python_version >= '3.7'", + "version": "==8.1.7" + }, "codeforlife-portal": { "hashes": [ "sha256:64c51f8a42c488930fc5e0b3a0b9d740d7e6c52b69f0f524cb80162a9d36c4db", @@ -878,6 +915,7 @@ "sha256:27ae41fad9deed9bbf4166f3e3b65acc15d524d42210a518e5877da85a6b8c5d", "sha256:b36ec2ecc003de87fc87b93197d77fea528aa0f9204a34fdf3b2f8d0f01e017b" ], + "markers": "python_version >= '3.7'", "version": "==0.31.0" }, "exceptiongroup": { @@ -1009,6 +1047,15 @@ "markers": "python_version >= '3.7'", "version": "==2.0.0" }, + "isort": { + "hashes": [ + "sha256:48fdfcb9face5d58a4f6dde2e72a1fb8dcaf8ab26f95ab49fab84c2ddefb0109", + "sha256:8ca5e72a8d85860d5a3fa69b8745237f2939afe12dbf656afbcb47fe72d947a6" + ], + "index": "pypi", + "markers": "python_full_version >= '3.8.0'", + "version": "==5.13.2" + }, "kubernetes": { "hashes": [ "sha256:5854b0c508e8d217ca205591384ab58389abdae608576f9c9afc35a3c76a366c", @@ -1037,6 +1084,14 @@ "markers": "python_version >= '3.5'", "version": "==8.7.0" }, + "mypy-extensions": { + "hashes": [ + "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d", + "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.0" + }, "numpy": { "hashes": [ "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f", @@ -1126,6 +1181,14 @@ "markers": "python_version >= '3.8'", "version": "==2.0.3" }, + "pathspec": { + "hashes": [ + "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", + "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712" + ], + "markers": "python_version >= '3.8'", + "version": "==0.12.1" + }, "pgeocode": { "hashes": [ "sha256:07995d4cd2d7fec1f82afb14d6025e83bbc156b6f225fa3e0b3417da2ec020c8", @@ -1216,6 +1279,14 @@ "markers": "python_version >= '3.8'", "version": "==10.3.0" }, + "platformdirs": { + "hashes": [ + "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf", + "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1" + ], + "markers": "python_version >= '3.8'", + "version": "==4.2.1" + }, "pluggy": { "hashes": [ "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", @@ -1312,7 +1383,7 @@ "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==2.9.0.post0" }, "pytz": { @@ -1466,7 +1537,7 @@ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", "version": "==1.16.0" }, "sniffio": { diff --git a/game/end_to_end_tests/base_game_test.py b/game/end_to_end_tests/base_game_test.py index e03398826..d555196f5 100644 --- a/game/end_to_end_tests/base_game_test.py +++ b/game/end_to_end_tests/base_game_test.py @@ -87,14 +87,12 @@ def go_to_homepage(self): def go_to_level(self, level_name): path = reverse("play_default_level", kwargs={"levelName": str(level_name)}) self._go_to_path(path) - self.selenium.execute_script("ocargo.animation.FAST_ANIMATION_DURATION = 1;") return GamePage(self.selenium) def go_to_custom_level(self, level): path = reverse("play_custom_level", kwargs={"levelId": str(level.id)}) self._go_to_path(path) - self.selenium.execute_script("ocargo.animation.FAST_ANIMATION_DURATION = 1;") return GamePage(self.selenium) @@ -106,7 +104,6 @@ def go_to_level_editor(self): def go_to_episode(self, episodeId): path = reverse("start_episode", kwargs={"episodeId": str(episodeId)}) self._go_to_path(path) - self.selenium.execute_script("ocargo.animation.FAST_ANIMATION_DURATION = 1;") return GamePage(self.selenium) diff --git a/game/end_to_end_tests/game_page.py b/game/end_to_end_tests/game_page.py index 804c37ed0..e76a7d7d8 100644 --- a/game/end_to_end_tests/game_page.py +++ b/game/end_to_end_tests/game_page.py @@ -19,6 +19,8 @@ class GamePage(BasePage): def __init__(self, browser): super(GamePage, self).__init__(browser) + self.browser.execute_script("ocargo.animation.FAST_ANIMATION_DURATION = 1;") + assert self.on_correct_page("game_page") self._dismiss_initial_dialog() diff --git a/game/end_to_end_tests/test_language_dropdown.py b/game/end_to_end_tests/test_language_dropdown.py new file mode 100644 index 000000000..4c9d43418 --- /dev/null +++ b/game/end_to_end_tests/test_language_dropdown.py @@ -0,0 +1,14 @@ +from game.end_to_end_tests.base_game_test import BaseGameTest + +from selenium.webdriver.common.by import By + +class TestLanguageDropdown(BaseGameTest): + def test_level_language_dropdown(self): + page = self.go_to_level(1) + assert page.element_exists_by_id("language_dropdown") + + self.selenium.find_element(By.ID, "language_dropdown").click() + self.selenium.find_element(By.ID, "language_dropdown_fr").click() + + text_count = len(self.selenium.find_elements(By.XPATH, ("//*[contains(text(),'Move forwards')]"))) + assert text_count == 0 diff --git a/game/static/game/css/backgrounds.css b/game/static/game/css/backgrounds.css index b661f5e86..69c7e1c07 100644 --- a/game/static/game/css/backgrounds.css +++ b/game/static/game/css/backgrounds.css @@ -1,37 +1,37 @@ /* Background colours for episodes and game sidebar */ .bg--easy { - background: #86ae18; + background-color: #86ae18; } .bg--medium { - background: #00a3e0; + background-color: #00a3e0; } .bg--medium-hard { - background: #008cc1; + background-color: #008cc1; } .bg--brainteasers { - background: #c90548; + background-color: #c90548; } .bg--hard { - background: #8967d3; + background-color: #8967d3; } .bg--advanced { - background: #754fc8; + background-color: #754fc8; } .bg--shared-levels { - background: #f6be00; + background-color: #f6be00; } .bg--loops { - background: #3F3F3F; + background-color: #3F3F3F; } .bg--loops-coming-soon { - background: #CBCBCB; + background-color: #CBCBCB; } diff --git a/game/static/game/css/game_screen.css b/game/static/game/css/game_screen.css index 549667581..79e371a74 100644 --- a/game/static/game/css/game_screen.css +++ b/game/static/game/css/game_screen.css @@ -430,6 +430,17 @@ div.no-print div.tab label { background: rgba(255, 255, 255, 0.25); } +.tab select:hover { + background: rgba(255, 255, 255, 0.25); +} + +.tab select { + color: black; + border: none; + font-weight: bold; + padding-right: 20px; +} + #console { z-index: 100; display: flex; diff --git a/game/static/game/js/blockly/msg/js/en-gb.js b/game/static/game/js/blockly/msg/js/en-gb.js index e22384b06..9f49d8360 100755 --- a/game/static/game/js/blockly/msg/js/en-gb.js +++ b/game/static/game/js/blockly/msg/js/en-gb.js @@ -433,4 +433,53 @@ Blockly.Msg["VARIABLES_HUE"] = "330"; Blockly.Msg["TEXTS_HUE"] = "160"; Blockly.Msg["PROCEDURES_HUE"] = "290"; Blockly.Msg["COLOUR_HUE"] = "20"; -Blockly.Msg["VARIABLES_DYNAMIC_HUE"] = "310"; \ No newline at end of file +Blockly.Msg["VARIABLES_DYNAMIC_HUE"] = "310"; + +Blockly.Msg["START_TITLE"] = "Start"; +Blockly.Msg["START_TOOLTIP"] = "The beginning of the program" +Blockly.Msg["MOVE_FORWARDS_TITLE"] = "move forwards"; +Blockly.Msg["MOVE_FORWARDS_TOOLTIP"] = "Move the van forwards"; +Blockly.Msg["TURN_LEFT_TITLE"] = "turn left"; +Blockly.Msg["TURN_LEFT_TOOLTIP"] = "Turn the van left"; +Blockly.Msg["TURN_RIGHT_TITLE"] = "turn right"; +Blockly.Msg["TURN_RIGHT_TOOLTIP"] = "Turn the van right"; +Blockly.Msg["TURN_AROUND_TITLE"] = "turn around"; +Blockly.Msg["TURN_AROUND_TOOLTIP"] = "Turn the van around"; + +Blockly.Msg["WAIT_TITLE"] = "wait"; +Blockly.Msg["WAIT_TOOLTIP"] = "Keep the van stationary"; +Blockly.Msg["DELIVER_TITLE"] = "deliver"; +Blockly.Msg["DELIVER_TOOLTIP"] = "Deliver the goods from the van"; +Blockly.Msg["SOUND_HORN_TITLE"] = "sound horn"; +Blockly.Msg["SOUND_HORN_TOOLTIP"] = "Sound the horn to scare away the cows"; + +Blockly.Msg["ROAD_EXISTS_FORWARD_TITLE"] = "road exists forward"; +Blockly.Msg["ROAD_EXISTS_LEFT_TITLE"] = "road exists left"; +Blockly.Msg["ROAD_EXISTS_RIGHT_TITLE"] = "road exists right"; +Blockly.Msg["TRAFFIC_LIGHT_RED_TITLE"] = "traffic light red"; +Blockly.Msg["TRAFFIC_LIGHT_GREEN_TITLE"] = "traffic light green"; +Blockly.Msg["DEAD_END_TITLE"] = "is dead end"; +Blockly.Msg["AT_DESTINATION_TITLE"] = "at destination"; +Blockly.Msg["COW_CROSSING_TITLE"] = "cows"; + +Blockly.Msg["CALL_PROC_TITLE"] = "Call"; +Blockly.Msg["CALL_PROC_TOOLTIP"] = "Calls a procedure"; +Blockly.Msg["DECLARE_PROC_TITLE"] = "Define"; +Blockly.Msg["DECLARE_PROC_TOOLTIP"] = "Declares a procedure"; +Blockly.Msg["CONTROLS_REPEAT_WHILE_TITLE"] = "repeat while"; +Blockly.Msg["CONTROLS_REPEAT_WHILE_SUBTITLE"] = "do"; +Blockly.Msg["CONTROLS_REPEAT_WHILE_TOOLTIP"] = "While a value is true, do some statements"; +Blockly.Msg["CONTROLS_REPEAT_UNTIL_TITLE"] = "repeat until"; +Blockly.Msg["CONTROLS_REPEAT_UNTIL_SUBTITLE"] = "do"; +Blockly.Msg["CONTROLS_REPEAT_UNTIL_TOOLTIP"] = "Until a value is true, do some statements"; + +Blockly.Msg["VARIABLES_GET_TOOLTIP"] = "A variable"; +Blockly.Msg["VARIABLES_SET_TITLE"] = "set"; +Blockly.Msg["VARIABLES_SET_SUBTITLE"] = "to"; +Blockly.Msg["VARIABLES_SET_TOOLTIP"] = "Set a variable"; +Blockly.Msg["VARIABLES_NUMERIC_SET_TOOLTIP"] = "Set a variable to a number"; +Blockly.Msg["VARIABLES_INCREMENT_TITLE"] = "increment"; +Blockly.Msg["VARIABLES_INCREMENT_SUBTITLE"] = "by"; +Blockly.Msg["VARIABLES_INCREMENT_TOOLTIP"] = "Increment a variable"; +Blockly.Msg["NUMBER_TITLE"] = "Number"; +Blockly.Msg["NUMBER_TOOLTIP"] = "A number"; \ No newline at end of file diff --git a/game/static/game/js/blockly/msg/js/en.js b/game/static/game/js/blockly/msg/js/en.js index 24afa59b7..c71af5cc2 100755 --- a/game/static/game/js/blockly/msg/js/en.js +++ b/game/static/game/js/blockly/msg/js/en.js @@ -433,4 +433,53 @@ Blockly.Msg["VARIABLES_HUE"] = "330"; Blockly.Msg["TEXTS_HUE"] = "160"; Blockly.Msg["PROCEDURES_HUE"] = "290"; Blockly.Msg["COLOUR_HUE"] = "20"; -Blockly.Msg["VARIABLES_DYNAMIC_HUE"] = "310"; \ No newline at end of file +Blockly.Msg["VARIABLES_DYNAMIC_HUE"] = "310"; + +Blockly.Msg["START_TITLE"] = "Start"; +Blockly.Msg["START_TOOLTIP"] = "The beginning of the program" +Blockly.Msg["MOVE_FORWARDS_TITLE"] = "move forwards"; +Blockly.Msg["MOVE_FORWARDS_TOOLTIP"] = "Move the van forwards"; +Blockly.Msg["TURN_LEFT_TITLE"] = "turn left"; +Blockly.Msg["TURN_LEFT_TOOLTIP"] = "Turn the van left"; +Blockly.Msg["TURN_RIGHT_TITLE"] = "turn right"; +Blockly.Msg["TURN_RIGHT_TOOLTIP"] = "Turn the van right"; +Blockly.Msg["TURN_AROUND_TITLE"] = "turn around"; +Blockly.Msg["TURN_AROUND_TOOLTIP"] = "Turn the van around"; + +Blockly.Msg["WAIT_TITLE"] = "wait"; +Blockly.Msg["WAIT_TOOLTIP"] = "Keep the van stationary"; +Blockly.Msg["DELIVER_TITLE"] = "deliver"; +Blockly.Msg["DELIVER_TOOLTIP"] = "Deliver the goods from the van"; +Blockly.Msg["SOUND_HORN_TITLE"] = "sound horn"; +Blockly.Msg["SOUND_HORN_TOOLTIP"] = "Sound the horn to scare away the cows"; + +Blockly.Msg["ROAD_EXISTS_FORWARD_TITLE"] = "road exists forward"; +Blockly.Msg["ROAD_EXISTS_LEFT_TITLE"] = "road exists left"; +Blockly.Msg["ROAD_EXISTS_RIGHT_TITLE"] = "road exists right"; +Blockly.Msg["TRAFFIC_LIGHT_RED_TITLE"] = "traffic light red"; +Blockly.Msg["TRAFFIC_LIGHT_GREEN_TITLE"] = "traffic light green"; +Blockly.Msg["DEAD_END_TITLE"] = "is dead end"; +Blockly.Msg["AT_DESTINATION_TITLE"] = "at destination"; +Blockly.Msg["COW_CROSSING_TITLE"] = "cows"; + +Blockly.Msg["CALL_PROC_TITLE"] = "Call"; +Blockly.Msg["CALL_PROC_TOOLTIP"] = "Calls a procedure"; +Blockly.Msg["DECLARE_PROC_TITLE"] = "Define"; +Blockly.Msg["DECLARE_PROC_TOOLTIP"] = "Declares a procedure"; +Blockly.Msg["CONTROLS_REPEAT_WHILE_TITLE"] = "repeat while"; +Blockly.Msg["CONTROLS_REPEAT_WHILE_SUBTITLE"] = "do"; +Blockly.Msg["CONTROLS_REPEAT_WHILE_TOOLTIP"] = "While a value is true, do some statements"; +Blockly.Msg["CONTROLS_REPEAT_UNTIL_TITLE"] = "repeat until"; +Blockly.Msg["CONTROLS_REPEAT_UNTIL_SUBTITLE"] = "do"; +Blockly.Msg["CONTROLS_REPEAT_UNTIL_TOOLTIP"] = "Until a value is true, do some statements"; + +Blockly.Msg["VARIABLES_GET_TOOLTIP"] = "A variable"; +Blockly.Msg["VARIABLES_SET_TITLE"] = "set"; +Blockly.Msg["VARIABLES_SET_SUBTITLE"] = "to"; +Blockly.Msg["VARIABLES_SET_TOOLTIP"] = "Set a variable"; +Blockly.Msg["VARIABLES_NUMERIC_SET_TOOLTIP"] = "Set a variable to a number"; +Blockly.Msg["VARIABLES_INCREMENT_TITLE"] = "increment"; +Blockly.Msg["VARIABLES_INCREMENT_SUBTITLE"] = "by"; +Blockly.Msg["VARIABLES_INCREMENT_TOOLTIP"] = "Increment a variable"; +Blockly.Msg["NUMBER_TITLE"] = "Number"; +Blockly.Msg["NUMBER_TOOLTIP"] = "A number"; \ No newline at end of file diff --git a/game/static/game/js/blockly/msg/js/fr.js b/game/static/game/js/blockly/msg/js/fr.js index dce0fe18a..d9fe11e81 100755 --- a/game/static/game/js/blockly/msg/js/fr.js +++ b/game/static/game/js/blockly/msg/js/fr.js @@ -433,4 +433,53 @@ Blockly.Msg["VARIABLES_HUE"] = "330"; Blockly.Msg["TEXTS_HUE"] = "160"; Blockly.Msg["PROCEDURES_HUE"] = "290"; Blockly.Msg["COLOUR_HUE"] = "20"; -Blockly.Msg["VARIABLES_DYNAMIC_HUE"] = "310"; \ No newline at end of file +Blockly.Msg["VARIABLES_DYNAMIC_HUE"] = "310"; + +Blockly.Msg["START_TITLE"] = "Départ"; +Blockly.Msg["START_TOOLTIP"] = "Le début du programme" +Blockly.Msg["MOVE_FORWARDS_TITLE"] = "avancer"; +Blockly.Msg["MOVE_FORWARDS_TOOLTIP"] = "Faire avancer le camion"; +Blockly.Msg["TURN_LEFT_TITLE"] = "tourner à gauche"; +Blockly.Msg["TURN_LEFT_TOOLTIP"] = "Faire tourner le camion à gauche"; +Blockly.Msg["TURN_RIGHT_TITLE"] = "tourner à droite"; +Blockly.Msg["TURN_RIGHT_TOOLTIP"] = "Faire tourner le camion à droite"; +Blockly.Msg["TURN_AROUND_TITLE"] = "faire demi-tour"; +Blockly.Msg["TURN_AROUND_TOOLTIP"] = "Faire demi-tour avec le camion"; + +Blockly.Msg["WAIT_TITLE"] = "attendre"; +Blockly.Msg["WAIT_TOOLTIP"] = "Faire arrêter le camion pour attendre"; +Blockly.Msg["DELIVER_TITLE"] = "livrer"; +Blockly.Msg["DELIVER_TOOLTIP"] = "Livrer la commande du camion"; +Blockly.Msg["SOUND_HORN_TITLE"] = "klaxonner"; +Blockly.Msg["SOUND_HORN_TOOLTIP"] = "Klaxonner pour effrayer les vaches"; + +Blockly.Msg["ROAD_EXISTS_FORWARD_TITLE"] = "la route existe en face"; +Blockly.Msg["ROAD_EXISTS_LEFT_TITLE"] = "la route existe à gauche"; +Blockly.Msg["ROAD_EXISTS_RIGHT_TITLE"] = "la route existe à droite"; +Blockly.Msg["TRAFFIC_LIGHT_RED_TITLE"] = "feu rouge"; +Blockly.Msg["TRAFFIC_LIGHT_GREEN_TITLE"] = "feu vert"; +Blockly.Msg["DEAD_END_TITLE"] = "cul-de-sac"; +Blockly.Msg["AT_DESTINATION_TITLE"] = "arrivé à destination"; +Blockly.Msg["COW_CROSSING_TITLE"] = "vaches"; + +Blockly.Msg["CALL_PROC_TITLE"] = "Appeler"; +Blockly.Msg["CALL_PROC_TOOLTIP"] = "Appeler une fonction"; +Blockly.Msg["DECLARE_PROC_TITLE"] = "Définir"; +Blockly.Msg["DECLARE_PROC_TOOLTIP"] = "Déclarer une fonction"; +Blockly.Msg["CONTROLS_REPEAT_WHILE_TITLE"] = "répéter tant que"; +Blockly.Msg["CONTROLS_REPEAT_WHILE_SUBTITLE"] = "faire"; +Blockly.Msg["CONTROLS_REPEAT_WHILE_TOOLTIP"] = "Tant qu’une valeur est vraie, faire des instructions"; +Blockly.Msg["CONTROLS_REPEAT_UNTIL_TITLE"] = "répéter jusqu’à ce que"; +Blockly.Msg["CONTROLS_REPEAT_UNTIL_SUBTITLE"] = "faire"; +Blockly.Msg["CONTROLS_REPEAT_UNTIL_TOOLTIP"] = "Jusqu’à ce qu’une valeur soit vraie, faire des instructions"; + +Blockly.Msg["VARIABLES_GET_TOOLTIP"] = "Une variable"; +Blockly.Msg["VARIABLES_SET_TITLE"] = "définir"; +Blockly.Msg["VARIABLES_SET_SUBTITLE"] = "à"; +Blockly.Msg["VARIABLES_SET_TOOLTIP"] = "Définir une variable"; +Blockly.Msg["VARIABLES_NUMERIC_SET_TOOLTIP"] = "Définir une variable à un nombre"; +Blockly.Msg["VARIABLES_INCREMENT_TITLE"] = "incrémenter"; +Blockly.Msg["VARIABLES_INCREMENT_SUBTITLE"] = "de"; +Blockly.Msg["VARIABLES_INCREMENT_TOOLTIP"] = "Incrémenter une variable"; +Blockly.Msg["NUMBER_TITLE"] = "nombre"; +Blockly.Msg["NUMBER_TOOLTIP"] = "Un nombre"; \ No newline at end of file diff --git a/game/static/game/js/blockly/msg/js/hi.js b/game/static/game/js/blockly/msg/js/hi.js index 177b255cb..a783b7c24 100755 --- a/game/static/game/js/blockly/msg/js/hi.js +++ b/game/static/game/js/blockly/msg/js/hi.js @@ -433,4 +433,53 @@ Blockly.Msg["VARIABLES_HUE"] = "330"; Blockly.Msg["TEXTS_HUE"] = "160"; Blockly.Msg["PROCEDURES_HUE"] = "290"; Blockly.Msg["COLOUR_HUE"] = "20"; -Blockly.Msg["VARIABLES_DYNAMIC_HUE"] = "310"; \ No newline at end of file +Blockly.Msg["VARIABLES_DYNAMIC_HUE"] = "310"; + +Blockly.Msg["START_TITLE"] = "शुरू"; +Blockly.Msg["START_TOOLTIP"] = "कार्यक्रम की शुरुआत"; +Blockly.Msg["MOVE_FORWARDS_TITLE"] = "आगे बढ़ें"; +Blockly.Msg["MOVE_FORWARDS_TOOLTIP"] = "वैन को आगे बढ़ाएं"; +Blockly.Msg["TURN_LEFT_TITLE"] = "बाएँ मुड़ें"; +Blockly.Msg["TURN_LEFT_TOOLTIP"] = "वैन को बाएँ मोड़ें"; +Blockly.Msg["TURN_RIGHT_TITLE"] = "दाएं मुड़ें"; +Blockly.Msg["TURN_RIGHT_TOOLTIP"] = "वैन को दाएं मोड़ें)"; +Blockly.Msg["TURN_AROUND_TITLE"] = "मुड़ो"; +Blockly.Msg["TURN_AROUND_TOOLTIP"] = "वैन को घुमाओ"; + +Blockly.Msg["WAIT_TITLE"] = "इंतज़ार"; +Blockly.Msg["WAIT_TOOLTIP"] = "वैन को स्थिर रखें"; +Blockly.Msg["DELIVER_TITLE"] = "बाँटना"; +Blockly.Msg["DELIVER_TOOLTIP"] = "वैन से सामान पहुंचाएं"; +Blockly.Msg["SOUND_HORN_TITLE"] = "हॉर्न बजाओ"; +Blockly.Msg["SOUND_HORN_TOOLTIP"] = "गायों को डराने के लिए हॉर्न बजाएं"; + +Blockly.Msg["ROAD_EXISTS_FORWARD_TITLE"] = "सड़क आगे मौजूद है"; +Blockly.Msg["ROAD_EXISTS_LEFT_TITLE"] = "सड़क बाएँ मौजूद है"; +Blockly.Msg["ROAD_EXISTS_RIGHT_TITLE"] = "सड़क दाएँ मौजूद है"; +Blockly.Msg["TRAFFIC_LIGHT_RED_TITLE"] = "ट्रैफिक लाइट लाल"; +Blockly.Msg["TRAFFIC_LIGHT_GREEN_TITLE"] = "ट्रैफिक लाइट हरा"; +Blockly.Msg["DEAD_END_TITLE"] = "आगे का रास्ता बंद है"; +Blockly.Msg["AT_DESTINATION_TITLE"] = "मंजिल /गंतव्य पर"; +Blockly.Msg["COW_CROSSING_TITLE"] = "गायों"; + +Blockly.Msg["CALL_PROC_TITLE"] = "पुकारना"; +Blockly.Msg["CALL_PROC_TOOLTIP"] = "एक प्रक्रिया बुलाना"; +Blockly.Msg["DECLARE_PROC_TITLE"] = "परिभाषित करना"; +Blockly.Msg["DECLARE_PROC_TOOLTIP"] = "प्रक्रिया की घोषणा करता है"; +Blockly.Msg["CONTROLS_REPEAT_WHILE_TITLE"] = "दोहराएँ जबकि"; +Blockly.Msg["CONTROLS_REPEAT_WHILE_SUBTITLE"] = "करो"; +Blockly.Msg["CONTROLS_REPEAT_WHILE_TOOLTIP"] = "जबकि कोई मान सत्य है, कुछ कथन करें"; +Blockly.Msg["CONTROLS_REPEAT_UNTIL_TITLE"] = "जब तक"; +Blockly.Msg["CONTROLS_REPEAT_UNTIL_SUBTITLE"] = "न करें तब तक दोहराएँ"; +Blockly.Msg["CONTROLS_REPEAT_UNTIL_TOOLTIP"] = "जब तक कोई मान सत्य न हो, कुछ कथन करें"; + +Blockly.Msg["VARIABLES_GET_TOOLTIP"] = "एक परिवर्तनीय"; +Blockly.Msg["VARIABLES_SET_TITLE"] = "तय करना"; +Blockly.Msg["VARIABLES_SET_SUBTITLE"] = "को"; +Blockly.Msg["VARIABLES_SET_TOOLTIP"] = "एक परिवर्तनीय तय करना"; +Blockly.Msg["VARIABLES_NUMERIC_SET_TOOLTIP"] = "एक परिवर्तनीय को एक संख्या पर तय करें"; +Blockly.Msg["VARIABLES_INCREMENT_TITLE"] = "बढ़ाई"; +Blockly.Msg["VARIABLES_INCREMENT_SUBTITLE"] = "द्वारा"; +Blockly.Msg["VARIABLES_INCREMENT_TOOLTIP"] = "एक वेरिएबल बढ़ाएँ"; +Blockly.Msg["NUMBER_TITLE"] = "संख्या"; +Blockly.Msg["NUMBER_TOOLTIP"] = "एक संख्या"; \ No newline at end of file diff --git a/game/static/game/js/blocklyControl.js b/game/static/game/js/blocklyControl.js index f3ade14ba..21149ab9f 100644 --- a/game/static/game/js/blocklyControl.js +++ b/game/static/game/js/blocklyControl.js @@ -8,6 +8,7 @@ ocargo.BlocklyControl = function () { this.blocklyCustomisations.setupLimitedBlocks(); this.blocklyDiv = document.getElementById("blockly_holder"); this.toolbox = document.getElementById("blockly_toolbox"); + Blockly.inject(this.blocklyDiv, { path: "/static/game/js/blockly/", toolbox: BLOCKLY_XML, @@ -434,4 +435,4 @@ ocargo.BlockHandler.prototype.deselectCurrent = function () { this.setBlockSelected(this.selectedBlock, false); this.selectedBlock = null; } -}; +}; \ No newline at end of file diff --git a/game/static/game/js/blocklyCustomBlocks.js b/game/static/game/js/blocklyCustomBlocks.js index 7818a4e89..8f5458b06 100644 --- a/game/static/game/js/blocklyCustomBlocks.js +++ b/game/static/game/js/blocklyCustomBlocks.js @@ -15,7 +15,7 @@ function initCustomBlocksDescription() { ocargo.blocklyControl.numStartBlocks++; this.setColour(50); this.appendDummyInput() - .appendField(gettext("Start")) + .appendField(Blockly.Msg.START_TITLE) .appendField(new Blockly.FieldImage( new Date().getMonth() === 11 && CHARACTER_NAME === "Van" ? ocargo.Drawing.imageDir + "characters/top_view/Sleigh.svg" @@ -25,7 +25,7 @@ function initCustomBlocksDescription() { ) ); this.setNextStatement(true, "Action"); - this.setTooltip(gettext("The beginning of the program")); + this.setTooltip(Blockly.Msg.START_TOOLTIP); this.setDeletable(false); }, }; @@ -39,7 +39,7 @@ function initCustomBlocksDescription() { init: function () { this.setColour(160); this.appendDummyInput() - .appendField(gettext("move forwards")) + .appendField(Blockly.Msg.MOVE_FORWARDS_TITLE) .appendField( new Blockly.FieldImage( ocargo.Drawing.imageDir + "actions/forward.svg", @@ -49,7 +49,7 @@ function initCustomBlocksDescription() { ); this.setPreviousStatement(true, "Action"); this.setNextStatement(true, "Action"); - this.setTooltip(gettext("Move the van forwards")); + this.setTooltip(Blockly.Msg.MOVE_FORWARDS_TOOLTIP); }, }; @@ -58,7 +58,7 @@ function initCustomBlocksDescription() { init: function () { this.setColour(160); this.appendDummyInput() - .appendField(gettext("turn left")) + .appendField(Blockly.Msg.TURN_LEFT_TITLE) .appendField( new Blockly.FieldImage( ocargo.Drawing.imageDir + "empty.svg", @@ -75,7 +75,7 @@ function initCustomBlocksDescription() { ); this.setPreviousStatement(true, "Action"); this.setNextStatement(true, "Action"); - this.setTooltip(gettext("Turn the van left")); + this.setTooltip(Blockly.Msg.TURN_LEFT_TOOLTIP); }, }; @@ -84,7 +84,7 @@ function initCustomBlocksDescription() { init: function () { this.setColour(160); this.appendDummyInput() - .appendField(gettext("turn right")) + .appendField(Blockly.Msg.TURN_RIGHT_TITLE) .appendField( new Blockly.FieldImage( ocargo.Drawing.imageDir + "empty.svg", @@ -101,7 +101,7 @@ function initCustomBlocksDescription() { ); this.setPreviousStatement(true, "Action"); this.setNextStatement(true, "Action"); - this.setTooltip(gettext("Turn the van right")); + this.setTooltip(Blockly.Msg.TURN_RIGHT_TOOLTIP); }, }; @@ -110,7 +110,7 @@ function initCustomBlocksDescription() { init: function () { this.setColour(160); this.appendDummyInput() - .appendField(gettext("turn around")) + .appendField(Blockly.Msg.TURN_AROUND_TITLE) .appendField( new Blockly.FieldImage( ocargo.Drawing.imageDir + "empty.svg", @@ -127,7 +127,7 @@ function initCustomBlocksDescription() { ); this.setPreviousStatement(true, "Action"); this.setNextStatement(true, "Action"); - this.setTooltip(gettext("Turn the van around")); + this.setTooltip(Blockly.Msg.TURN_AROUND_TOOLTIP); }, }; @@ -136,7 +136,7 @@ function initCustomBlocksDescription() { init: function () { this.setColour(160); this.appendDummyInput() - .appendField(gettext("wait")) + .appendField(Blockly.Msg.WAIT_TITLE) .appendField( new Blockly.FieldImage( ocargo.Drawing.imageDir + "empty.svg", @@ -153,7 +153,7 @@ function initCustomBlocksDescription() { ); this.setPreviousStatement(true, "Action"); this.setNextStatement(true, "Action"); - this.setTooltip(gettext("Keep the van stationary")); + this.setTooltip(Blockly.Msg.WAIT_TOOLTIP); }, }; @@ -162,7 +162,7 @@ function initCustomBlocksDescription() { init: function () { this.setColour(160); this.appendDummyInput() - .appendField(gettext("deliver")) + .appendField(Blockly.Msg.DELIVER_TITLE) .appendField( new Blockly.FieldImage( ocargo.Drawing.imageDir + "empty.svg", @@ -179,7 +179,7 @@ function initCustomBlocksDescription() { ); this.setPreviousStatement(true, "Action"); this.setNextStatement(true, "Action"); - this.setTooltip(gettext("Deliver the goods from the van")); + this.setTooltip(Blockly.Msg.DELIVER_TOOLTIP); }, }; @@ -187,7 +187,7 @@ function initCustomBlocksDescription() { init: function() { this.setColour(160); this.appendDummyInput() - .appendField(gettext('sound horn')) + .appendField(Blockly.Msg.SOUND_HORN_TITLE) .appendField(new Blockly.FieldImage(ocargo.Drawing.imageDir + 'empty.svg', 43, ocargo.BlocklyControl.BLOCK_HEIGHT)) @@ -196,7 +196,7 @@ function initCustomBlocksDescription() { ocargo.BlocklyControl.BLOCK_HEIGHT)); this.setPreviousStatement(true, 'Action'); this.setNextStatement(true, 'Action'); - this.setTooltip(gettext('Sound the horn to scare away the cows')); + this.setTooltip(Blockly.Msg.SOUND_HORN_TOOLTIP); } }; @@ -207,9 +207,9 @@ function initCustomBlocksDescription() { Blockly.Blocks["road_exists"] = { init: function () { var BOOLEANS = [ - [gettext("road exists forward"), "FORWARD"], - [gettext("road exists left"), "LEFT"], - [gettext("road exists right"), "RIGHT"], + [Blockly.Msg.ROAD_EXISTS_FORWARD_TITLE, "FORWARD"], + [Blockly.Msg.ROAD_EXISTS_LEFT_TITLE, "LEFT"], + [Blockly.Msg.ROAD_EXISTS_RIGHT_TITLE, "RIGHT"], ]; this.setColour(210); this.setOutput(true, "Boolean"); @@ -228,8 +228,8 @@ function initCustomBlocksDescription() { Blockly.Blocks["traffic_light"] = { init: function () { var BOOLEANS = [ - [gettext("traffic light red"), ocargo.TrafficLight.RED], - [gettext("traffic light green"), ocargo.TrafficLight.GREEN], + [Blockly.Msg.TRAFFIC_LIGHT_RED_TITLE, ocargo.TrafficLight.RED], + [Blockly.Msg.TRAFFIC_LIGHT_GREEN_TITLE, ocargo.TrafficLight.GREEN], ]; this.setColour(210); this.setOutput(true, "Boolean"); @@ -250,7 +250,7 @@ function initCustomBlocksDescription() { this.setColour(210); this.setOutput(true, "Boolean"); this.appendDummyInput() - .appendField(gettext("is dead end")) + .appendField(Blockly.Msg.DEAD_END_TITLE) .appendField( new Blockly.FieldImage( ocargo.Drawing.imageDir + "empty.svg", @@ -266,7 +266,7 @@ function initCustomBlocksDescription() { this.setColour(210); this.setOutput(true, "Boolean"); this.appendDummyInput() - .appendField(gettext("at destination")) + .appendField(Blockly.Msg.AT_DESTINATION_TITLE) .appendField( new Blockly.FieldImage( ocargo.Drawing.imageDir + "empty.svg", @@ -282,7 +282,7 @@ function initCustomBlocksDescription() { this.setColour(210); this.setOutput(true, 'Boolean'); this.appendDummyInput() - .appendField(gettext('cows')) + .appendField(Blockly.Msg.COW_CROSSING_TITLE) .appendField(new Blockly.FieldImage(ocargo.Drawing.imageDir + ocargo.Drawing.whiteCowUrl, ocargo.BlocklyControl.COW_WIDTH, ocargo.BlocklyControl.BLOCK_HEIGHT), 'IMAGE'); @@ -298,7 +298,7 @@ function initCustomBlocksDescription() { var name = ""; this.setColour(260); this.appendDummyInput() - .appendField(gettext("Call")) + .appendField(Blockly.Msg.CALL_PROC_TITLE) .appendField( new Blockly.FieldImage( ocargo.Drawing.imageDir + "empty.svg", @@ -309,7 +309,7 @@ function initCustomBlocksDescription() { .appendField(new Blockly.FieldTextInput(name), "NAME"); this.setPreviousStatement(true, "Action"); this.setNextStatement(true, "Action"); - this.setTooltip(gettext("Call")); + this.setTooltip(Blockly.Msg.CALL_PROC_TOOLTIP); }, }; @@ -319,12 +319,12 @@ function initCustomBlocksDescription() { var name = ""; this.setColour(260); this.appendDummyInput() - .appendField(gettext("Define")) + .appendField(Blockly.Msg.DECLARE_PROC_TITLE) .appendField(new Blockly.FieldTextInput(name), "NAME"); this.appendStatementInput("DO") .setCheck("Action") .appendField(gettext("Do")); - this.setTooltip(gettext("Declares the procedure")); + this.setTooltip(Blockly.Msg.DECLARE_PROC_TOOLTIP); this.statementConnection_ = null; }, }; @@ -378,13 +378,13 @@ function initCustomBlocksDescription() { this.setColour(120); this.appendValueInput("condition") .setCheck("Boolean") - .appendField(gettext("repeat while")); + .appendField(Blockly.Msg.CONTROLS_REPEAT_WHILE_TITLE); this.appendStatementInput("body") .setCheck("Action") - .appendField(gettext("do")); + .appendField(Blockly.Msg.CONTROLS_REPEAT_WHILE_SUBTITLE); this.setPreviousStatement(true, "Action"); this.setNextStatement(true, "Action"); - this.setTooltip(gettext("While a value is true, do some statements")); + this.setTooltip(Blockly.Msg.CONTROLS_REPEAT_WHILE_TOOLTIP); }, }; @@ -394,13 +394,13 @@ function initCustomBlocksDescription() { this.setColour(120); this.appendValueInput("condition") .setCheck("Boolean") - .appendField(gettext("repeat until")); + .appendField(Blockly.Msg.CONTROLS_REPEAT_UNTIL_TITLE); this.appendStatementInput("body") .setCheck("Action") - .appendField(gettext("do")); + .appendField(Blockly.Msg.CONTROLS_REPEAT_UNTIL_SUBTITLE); this.setPreviousStatement(true, "Action"); this.setNextStatement(true, "Action"); - this.setTooltip(gettext("Until a value is true, do some statements")); + this.setTooltip(Blockly.Msg.CONTROLS_REPEAT_UNTIL_TOOLTIP); }, }; @@ -416,7 +416,7 @@ function initCustomBlocksDescription() { ); this.setOutput(true, null); this.setColour(330); - this.setTooltip(gettext("A variable")); + this.setTooltip(Blockly.Msg.VARIABLES_GET_TOOLTIP); }, }; @@ -424,41 +424,41 @@ function initCustomBlocksDescription() { init: function () { this.appendValueInput("VALUE") .setCheck(null) - .appendField("set") + .appendField(Blockly.Msg.VARIABLES_SET_TITLE) .appendField(new Blockly.FieldTextInput(""), "VAR") - .appendField("to"); + .appendField(Blockly.Msg.VARIABLES_SET_SUBTITLE); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setColour(330); - this.setTooltip(gettext("Set a variable")); + this.setTooltip(Blockly.Msg.VARIABLES_SET_TOOLTIP); }, }; Blockly.Blocks["variables_numeric_set"] = { init: function () { this.appendDummyInput() - .appendField("set") + .appendField(Blockly.Msg.VARIABLES_SET_TITLE) .appendField(new Blockly.FieldTextInput(""), "NAME") - .appendField("to") + .appendField(Blockly.Msg.VARIABLES_SET_SUBTITLE) .appendField(new Blockly.FieldNumber(0), "VALUE"); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setColour(330); - this.setTooltip(gettext("Set a variable to a number")); + this.setTooltip(Blockly.Msg.VARIABLES_NUMERIC_SET_TOOLTIP); }, }; Blockly.Blocks["variables_increment"] = { init: function () { this.appendDummyInput() - .appendField("increment") + .appendField(Blockly.Msg.VARIABLES_INCREMENT_TITLE) .appendField(new Blockly.FieldTextInput(""), "NAME") - .appendField("by") + .appendField(Blockly.Msg.VARIABLES_INCREMENT_SUBTITLE) .appendField(new Blockly.FieldNumber(0), "VALUE"); this.setPreviousStatement(true, null); this.setNextStatement(true, null); this.setColour(330); - this.setTooltip(gettext("Increment a variable")); + this.setTooltip(Blockly.Msg.VARIABLES_INCREMENT_TOOLTIP); }, }; @@ -469,11 +469,11 @@ function initCustomBlocksDescription() { Blockly.Blocks["math_number"] = { init: function () { this.appendDummyInput() - .appendField("number") + .appendField(Blockly.Msg.NUMBER_TITLE) .appendField(new Blockly.FieldNumber(0), "NUM"); this.setOutput(true, null); this.setColour(230); - this.setTooltip(gettext("A number")); + this.setTooltip(Blockly.Msg.NUMBER_TOOLTIP); }, }; diff --git a/game/static/game/js/blocklyCustomisations.js b/game/static/game/js/blocklyCustomisations.js index bd9ba5979..355cce5c2 100644 --- a/game/static/game/js/blocklyCustomisations.js +++ b/game/static/game/js/blocklyCustomisations.js @@ -5,6 +5,7 @@ var ocargo = ocargo || {}; ocargo.BlocklyCustomisations = function () { const TOOLBOX_REMAINING_CAPACITY_TEXT_COLUMN_WIDTH = 50; + const QUANTITY_TEXT_OFFSET = 35; var limitedBlocks = false; var blockCount = {}; @@ -94,6 +95,7 @@ ocargo.BlocklyCustomisations = function () { flyoutWidth *= this.workspace_.scale; flyoutWidth += Blockly.Scrollbar.scrollbarThickness; flyoutWidth += TOOLBOX_REMAINING_CAPACITY_TEXT_COLUMN_WIDTH; + flyoutWidth += 50; if (this.width_ != flyoutWidth) { for (var i = 0, block; block = blocks[i]; i++) { @@ -173,7 +175,7 @@ ocargo.BlocklyCustomisations = function () { var attributes = { 'width': 30, 'height': 30, - 'x': this.width_ - TOOLBOX_REMAINING_CAPACITY_TEXT_COLUMN_WIDTH, + 'x': blockHW.width + QUANTITY_TEXT_OFFSET, 'y': cursorY + 22, 'class': 'quantity_text', 'value': block.type diff --git a/game/static/game/js/game.js b/game/static/game/js/game.js index be1fae43e..28682e081 100644 --- a/game/static/game/js/game.js +++ b/game/static/game/js/game.js @@ -10,6 +10,8 @@ ocargo.Game = function () { } ocargo.Game.prototype.setup = function () { + gameUpdateBlockLanguage(navigator.language.toLowerCase()) + if(new Date().getMonth() === 11) { $("#paper").css('background-color', '#eef7ff') } @@ -25,11 +27,11 @@ ocargo.Game.prototype.setup = function () { } -// Function being called when there is a change in game level. -ocargo.Game.prototype.onLevelChange = function() { - const currentLevelId = LEVEL_ID; - localStorage.setItem('currentEpisode', EPISODE); -} + // Function being called when there is a change in game level. + ocargo.Game.prototype.onLevelChange = function() { + const currentLevelId = LEVEL_ID; + localStorage.setItem('currentEpisode', EPISODE); + } restoreCmsLogin() initCustomBlocks() @@ -38,20 +40,21 @@ ocargo.Game.prototype.onLevelChange = function() { ocargo.pythonControl = new ocargo.PythonControl() ocargo.blocklyCompiler = new ocargo.BlocklyCompiler() ocargo.model = new ocargo.Model( - PATH, - ORIGIN, - DESTINATIONS, - TRAFFIC_LIGHTS, - COWS, - MAX_FUEL + PATH, + ORIGIN, + DESTINATIONS, + TRAFFIC_LIGHTS, + COWS, + MAX_FUEL ) + this.drawing = new ocargo.Drawing(ocargo.model.startingPosition()) this.drawing.preloadRoadTiles() ocargo.animation = new ocargo.Animation(ocargo.model, DECOR, this.drawing) this.saving = new ocargo.Saving() this.sharing = new ocargo.Sharing( - () => parseInt(LEVEL_ID), - () => true + () => parseInt(LEVEL_ID), + () => true ) // Setup the blockly workspace @@ -79,20 +82,20 @@ ocargo.Game.prototype.onLevelChange = function() { // Setup blockly to python Blockly.Python.init(Blockly.getMainWorkspace()) window.addEventListener( - 'unload', - function (event) { - ocargo.pythonControl.teardown() - ocargo.blocklyControl.teardown() - }.bind(this) + 'unload', + function (event) { + ocargo.pythonControl.teardown() + ocargo.blocklyControl.teardown() + }.bind(this) ) var loggedOutWarning = '' // Check if logged on if (USER_STATUS == 'UNTRACKED') { loggedOutWarning = - '
' + - gettext("You are not logged in. Your progress won't be saved.") + - '' + '
' + + gettext("You are not logged in. Your progress won't be saved.") + + '' } // Start the popup var title = gettext('Try solving this one...') @@ -113,11 +116,11 @@ ocargo.Game.prototype.onLevelChange = function() { var message if (NIGHT_MODE) { message = - '
' + - gettext( - 'In Night Mode you can only see a very short distance. ' + - "We've given you more blocks to help you find your way!" - ) + '
' + + gettext( + 'In Night Mode you can only see a very short distance. ' + + "We've given you more blocks to help you find your way!" + ) } else { message = loggedOutWarning } @@ -127,15 +130,15 @@ ocargo.Game.prototype.onLevelChange = function() { const showMascot = BLOCKLY_ENABLED && !PYTHON_VIEW_ENABLED && LEVEL_NAME <= 80; // show mascot on Blockly-only levels that are not above 80 ocargo.Drawing.startPopup( - title, - LESSON, - message, - showMascot, - [ - ocargo.button.dismissButtonHtml("prev_button", gettext("Previous level")), - ocargo.button.dismissButtonHtml('play_button', gettext('Play')), - ocargo.button.dismissButtonHtml("next_button", gettext("Next level")) - ] + title, + LESSON, + message, + showMascot, + [ + ocargo.button.dismissButtonHtml("prev_button", gettext("Previous level")), + ocargo.button.dismissButtonHtml('play_button', gettext('Play')), + ocargo.button.dismissButtonHtml("next_button", gettext("Next level")) + ] ) } @@ -624,6 +627,7 @@ ocargo.Game.prototype.isInPythonWorkspace = function () { ocargo.Game.prototype._setupTabs = function () { this.tabs = [] + this.tabs.blockly = new ocargo.Tab( $('#blockly_radio'), $('#blockly_radio + label'), @@ -1387,6 +1391,12 @@ function setMutedCookie(mute) { } } +function gameUpdateBlockLanguage(language_code) { + loadLanguage("/static/game/js/blockly/msg/js/", language_code, function() { + reloadWorkspace(Blockly.mainWorkspace); + }); +} + $(document).ready(function () { ocargo.game = new ocargo.Game() ocargo.game.setup() diff --git a/game/static/game/js/loadLanguages.js b/game/static/game/js/loadLanguages.js new file mode 100644 index 000000000..9fa0577f5 --- /dev/null +++ b/game/static/game/js/loadLanguages.js @@ -0,0 +1,21 @@ +function loadLanguage(path, langStr, callback) { + var xobj = new XMLHttpRequest(); + xobj.overrideMimeType("application/javascript"); + xobj.open('GET', path + langStr + '.js', true); + xobj.onreadystatechange = function () { + if (xobj.readyState == 4 && xobj.status == "200") { + eval(xobj.responseText); + callback(); + } else if (xobj.status == "404") { + loadLanguage(path, "en", callback); + } + }; + xobj.send(null); +}; + +function reloadWorkspace(workspace) { + var blocklyDom = Blockly.Xml.workspaceToDom(workspace); + workspace.clear(); + Blockly.Xml.domToWorkspace(blocklyDom, workspace); + workspace.updateToolbox(BLOCKLY_XML); +}; \ No newline at end of file diff --git a/game/templates/game/game.html b/game/templates/game/game.html index 72c6f2a5f..c4e8df780 100644 --- a/game/templates/game/game.html +++ b/game/templates/game/game.html @@ -104,6 +104,7 @@ + @@ -143,6 +144,7 @@ {% block content %} {{ block.super }} +
@@ -158,6 +160,16 @@ {% trans "Blockly" %} +
+ +
+ +
+