-
-
Notifications
You must be signed in to change notification settings - Fork 420
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
485 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
name: Check Translations | ||
|
||
on: | ||
push: | ||
branches-ignore: | ||
- "dependabot/**" | ||
tags-ignore: | ||
- "**" | ||
paths: | ||
- "src/main/resources/assets/wurst/translations/**.json" | ||
- "src/main/resources/intentionally_untranslated.json" | ||
pull_request: | ||
paths: | ||
- "src/main/resources/assets/wurst/translations/**.json" | ||
- "src/main/resources/intentionally_untranslated.json" | ||
workflow_dispatch: | ||
|
||
jobs: | ||
check_translations: | ||
runs-on: ubuntu-latest | ||
steps: | ||
|
||
- name: Checkout repository | ||
uses: actions/checkout@v4 | ||
|
||
- name: Set up Python 3.12 | ||
uses: actions/setup-python@v5 | ||
with: | ||
python-version: "3.12" | ||
|
||
- name: Run check_translations.py | ||
run: python scripts/check_translations.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,154 @@ | ||
import util | ||
from pathlib import Path | ||
|
||
translations_dir = Path("src") / "main" / "resources" / "assets" / "wurst" / "translations" | ||
|
||
|
||
def show_translation_stats(en_us: dict, translations: dict): | ||
"""Render a table of the current translation progress for each language.""" | ||
util.add_github_summary("| Language | Translated | % |") | ||
util.add_github_summary("| --- | --- | --- |") | ||
util.add_github_summary(f"| en_us | {len(en_us)} | 100.00% |") | ||
for lang, data in translations.items(): | ||
util.add_github_summary(f"| {lang} | {len(data)} | {len(data) / len(en_us) * 100:.2f}% |") | ||
util.add_github_summary("") | ||
|
||
|
||
def check_extra_keys(en_us: dict, translations: dict): | ||
"""Check if any translation files contain keys that don't exist in the original.""" | ||
extra_keys_found = False | ||
for lang, data in translations.items(): | ||
extra_keys = set(data.keys()) - set(en_us.keys()) | ||
if extra_keys: | ||
extra_keys_found = True | ||
util.add_github_summary( | ||
f"⚠ {lang}.json contains translations that don't exist in en_us.json ({len(extra_keys)} found):" | ||
) | ||
for key in extra_keys: | ||
util.add_github_summary(f"- {key}") | ||
if extra_keys_found: | ||
raise Exception("Found extra keys in one or more translation files, see summary") | ||
util.add_github_summary("✅ No extra keys found") | ||
|
||
|
||
def check_untranslated_strings(en_us: dict, translations: dict): | ||
"""Check if any translation files contain untranslated strings.""" | ||
untranslated_strings_found = False | ||
intentionally_untranslated = util.read_json_file( | ||
Path("src") / "main" / "resources" / "intentionally_untranslated.json" | ||
) | ||
|
||
for lang, data in translations.items(): | ||
untranslated_strings = set() | ||
for key, value in data.items(): | ||
if value == en_us[key]: | ||
if lang in intentionally_untranslated and key in intentionally_untranslated[lang]: | ||
continue | ||
untranslated_strings.add(key) | ||
if untranslated_strings: | ||
untranslated_strings_found = True | ||
util.add_github_summary( | ||
f"⚠ {lang}.json contains strings that are identical to en_us.json ({len(untranslated_strings)} found):" | ||
) | ||
for key in untranslated_strings: | ||
util.add_github_summary(f"- {key}: {en_us[key]}") | ||
util.add_github_summary( | ||
"\nIf this is intentional, add the affected key(s) to intentionally_untranslated.json:" | ||
) | ||
util.add_github_summary("```json") | ||
util.add_github_summary(f' "{lang}": [') | ||
for key in untranslated_strings: | ||
util.add_github_summary(f' "{key}"') | ||
util.add_github_summary(" ]") | ||
util.add_github_summary("```") | ||
|
||
if untranslated_strings_found: | ||
raise Exception("Found untranslated strings in one or more translation files, see summary") | ||
util.add_github_summary("✅ No accidentally untranslated strings found") | ||
|
||
|
||
def check_order_of_strings(en_us: dict, translations: dict): | ||
"""Check if the strings in each translation file are in the same order as in en_us.json.""" | ||
for lang, data in translations.items(): | ||
en_us_keys_present_in_translation = [key for key in en_us.keys() if key in data.keys()] | ||
translation_keys_present_in_en_us = [key for key in data.keys() if key in en_us.keys()] | ||
if en_us_keys_present_in_translation != translation_keys_present_in_en_us: | ||
raise Exception(f"⚠ The order of strings in {lang}.json is different from en_us.json") | ||
util.add_github_summary("✅ The order of strings in each translation file matches en_us.json") | ||
|
||
|
||
def check_known_issues(en_us: dict, translations: dict): | ||
"""Check if any translation files contain known issues.""" | ||
issues_found = False | ||
|
||
# Typos | ||
known_typos = { | ||
"Anchoraura": "AnchorAura", | ||
"Autobuild": "AutoBuild", | ||
"Clickaura": "ClickAura", | ||
"KillAura": "Killaura", | ||
"LegitNuker": "Nuker", | ||
"LegitKillaura": "KillauraLegit", | ||
"Nofall": "NoFall", | ||
"Triggerbot": "TriggerBot", | ||
} | ||
for lang, data in translations.items(): | ||
for key, value in data.items(): | ||
for typo, correct in known_typos.items(): | ||
if typo in value: | ||
issues_found = True | ||
util.add_github_summary( | ||
f"⚠ In {lang}.json string {key}, the word '{correct}' is incorrectly translated as '{typo}':" | ||
) | ||
util.add_github_summary("```json") | ||
util.add_github_summary(f' "{key}": "{value}"') | ||
util.add_github_summary("```") | ||
|
||
# Difficult strings | ||
for lang, data in translations.items(): | ||
# Boatfly | ||
boatfly_key = "description.wurst.hack.boatfly" | ||
if boatfly_key in data and "shift" in data[boatfly_key].lower(): | ||
issues_found = True | ||
util.add_github_summary( | ||
f"⚠ In {lang}.json, the translation for {boatfly_key} incorrectly suggests using the shift (sneak) key instead of ctrl (sprint) to descend" | ||
) | ||
# Radar | ||
radar_key = "description.wurst.hack.radar" | ||
if radar_key in data and ( | ||
"§cred§r" in data[radar_key] | ||
# Not checking orange because it appears in the French translation | ||
or "§agreen§r" in data[radar_key] | ||
or "§7gray§r" in data[radar_key] | ||
): | ||
issues_found = True | ||
util.add_github_summary( | ||
f"⚠ In {lang}.json, the translation for {radar_key} contains untranslated colors:" | ||
) | ||
util.add_github_summary("```json") | ||
util.add_github_summary(f' "{radar_key}": "{data[radar_key]}"') | ||
util.add_github_summary("```") | ||
|
||
if issues_found: | ||
raise Exception("Found known issues in one or more translation files, see summary") | ||
util.add_github_summary("✅ No known issues found in any translation files") | ||
|
||
|
||
def main(): | ||
en_us = util.read_json_file(translations_dir / "en_us.json") | ||
translations = {} | ||
for path in sorted(translations_dir.rglob("*.json"), key=lambda x: x.name): | ||
if path.is_file() and path.name != "en_us.json": | ||
lang = path.name.removesuffix(".json") | ||
data = util.read_json_file(path) | ||
translations[lang] = data | ||
|
||
show_translation_stats(en_us, translations) | ||
check_extra_keys(en_us, translations) | ||
check_untranslated_strings(en_us, translations) | ||
check_order_of_strings(en_us, translations) | ||
check_known_issues(en_us, translations) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import json | ||
import os | ||
from pathlib import Path | ||
|
||
|
||
def read_json_file(path: Path) -> dict: | ||
"""Read a JSON data file.""" | ||
return json.loads(path.read_text(encoding="utf-8")) | ||
|
||
|
||
def add_github_summary(summary: str): | ||
"""Add a line to the GitHub Actions summary for the current step.""" | ||
if "GITHUB_STEP_SUMMARY" not in os.environ: | ||
print(summary) | ||
return | ||
with open(os.environ["GITHUB_STEP_SUMMARY"], "a") as summary_file: | ||
print(summary, file=summary_file) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
/* | ||
* Copyright (c) 2014-2024 Wurst-Imperium and contributors. | ||
* | ||
* This source code is subject to the terms of the GNU General Public | ||
* License, version 3. If a copy of the GPL was not distributed with this | ||
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt | ||
*/ | ||
package net.wurstclient.test; | ||
|
||
import static net.wurstclient.test.WurstClientTestHelper.*; | ||
|
||
import net.minecraft.block.Blocks; | ||
|
||
public enum AutoMineHackTest | ||
{ | ||
; | ||
|
||
public static void testAutoMineHack() | ||
{ | ||
System.out.println("Testing AutoMine hack"); | ||
runChatCommand("gamemode survival"); | ||
|
||
// Break a dirt block in survival mode | ||
runChatCommand("setblock ~ ~1 ~2 minecraft:dirt"); | ||
waitForBlock(0, 1, 2, Blocks.DIRT); | ||
runWurstCommand("t AutoMine on"); | ||
waitForBlock(0, 1, 2, Blocks.AIR); | ||
takeScreenshot("automine_survival"); | ||
|
||
// Clean up | ||
runWurstCommand("t AutoMine off"); | ||
runChatCommand("gamemode creative"); | ||
runChatCommand("kill @e[type=item]"); | ||
runChatCommand("clear"); | ||
clearChat(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
/* | ||
* Copyright (c) 2014-2024 Wurst-Imperium and contributors. | ||
* | ||
* This source code is subject to the terms of the GNU General Public | ||
* License, version 3. If a copy of the GPL was not distributed with this | ||
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt | ||
*/ | ||
package net.wurstclient.test; | ||
|
||
import static net.wurstclient.test.WurstClientTestHelper.*; | ||
|
||
import java.time.Duration; | ||
|
||
import net.wurstclient.mixinterface.IKeyBinding; | ||
|
||
public enum FreecamHackTest | ||
{ | ||
; | ||
|
||
public static void testFreecamHack() | ||
{ | ||
System.out.println("Testing Freecam hack"); | ||
|
||
// Enable Freecam with default settings | ||
runWurstCommand("setcheckbox Freecam tracer off"); | ||
runWurstCommand("t Freecam on"); | ||
takeScreenshot("freecam_default", Duration.ofMillis(100)); | ||
clearChat(); | ||
|
||
// Press shift to fly down a bit | ||
submitAndWait( | ||
mc -> IKeyBinding.get(mc.options.sneakKey).simulatePress(true)); | ||
waitForWorldTicks(5); | ||
submitAndWait( | ||
mc -> IKeyBinding.get(mc.options.sneakKey).simulatePress(false)); | ||
takeScreenshot("freecam_down", Duration.ofMillis(300)); | ||
clearChat(); | ||
|
||
// Tracer | ||
runWurstCommand("setcheckbox Freecam tracer on"); | ||
takeScreenshot("freecam_tracer", Duration.ofMillis(100)); | ||
clearChat(); | ||
|
||
// Clean up | ||
runWurstCommand("setcheckbox Freecam tracer off"); | ||
runWurstCommand("t Freecam off"); | ||
waitForWorldTicks(5); | ||
clearChat(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
/* | ||
* Copyright (c) 2014-2024 Wurst-Imperium and contributors. | ||
* | ||
* This source code is subject to the terms of the GNU General Public | ||
* License, version 3. If a copy of the GPL was not distributed with this | ||
* file, You can obtain one at: https://www.gnu.org/licenses/gpl-3.0.txt | ||
*/ | ||
package net.wurstclient.test; | ||
|
||
import static net.wurstclient.test.WurstClientTestHelper.*; | ||
|
||
import net.minecraft.block.Blocks; | ||
|
||
public enum PistonTest | ||
{ | ||
; | ||
|
||
public static void testPistonDoesntCrash() | ||
{ | ||
System.out.println( | ||
"Testing that a piston can extend and retract without crashing the game"); | ||
|
||
// Place a redstone block and piston | ||
runChatCommand("setblock ~ ~1 ~2 minecraft:piston[facing=up]"); | ||
waitForBlock(0, 1, 2, Blocks.PISTON); | ||
runChatCommand("setblock ~ ~ ~2 minecraft:redstone_block"); | ||
waitForBlock(0, 0, 2, Blocks.REDSTONE_BLOCK); | ||
takeScreenshot("piston_extending"); | ||
waitForWorldTicks(3); | ||
|
||
// Destroy the redstone block | ||
runChatCommand("setblock ~ ~ ~2 minecraft:air"); | ||
waitForBlock(0, 0, 2, Blocks.AIR); | ||
takeScreenshot("piston_retracting"); | ||
waitForWorldTicks(3); | ||
|
||
// Clean up | ||
runChatCommand("setblock ~ ~1 ~2 minecraft:air"); | ||
waitForBlock(0, 1, 2, Blocks.AIR); | ||
clearChat(); | ||
} | ||
} |
Oops, something went wrong.