Skip to content
Draft
41 changes: 41 additions & 0 deletions .github/workflows/localise.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Localisation

on: pull_request

jobs:
update-localisation:
# Don't run if this is a draft.
if: github.event.pull_request.draft == true
name: Update Localisation
runs-on: ubuntu-latest

steps:
- name: Checkout Git repository
uses: actions/checkout@v2
# Comply with git-auto-commit
with:
ref: ${{ github.head_ref }}

- name: Set up Python 3.9
uses: actions/setup-python@v2
with:
python-version: 3.9

- name: install dependencies
run: |
python -m pip install --upgrade pip
pip install --upgrade orjson

- name: run update_en_strings.py
# TODO: Find a git command that will run on other branches.
run: |
python ../../locale/update_en_strings.py ../data
git --no-pager diff --name-status $GITHUB_BASE_REF...$GITHUB_SHA | python ../../locale/handle_file_operations.py

- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: Automatically update english strings.
# This shouldn't matter, but just in case.
file_pattern: *.json
# Give blame where it is due.
commit_author: Author <[email protected]>
43 changes: 43 additions & 0 deletions locale/handle_file_operations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env python
import sys
import os
from pathlib import Path
import shutil

# Ensure that the path is correct.
PATH_TO_LOCALE = Path(__file__).parent.absolute()
LOCALES = tuple(
PATH_TO_LOCALE.joinpath(d) for d in os.scandir(PATH_TO_LOCALE) if d.is_dir()
)

for line in sys.stdin:
line = line.split("\t")
if len(line) == 3:
code, old_file, new_file = line.split("\t")
code = code[0]
else:
code, filepath = line

# We only handle deleted or renamed files.
if code not in ("D", "R"):
continue

# filepath starts relative to Community-Mod-Compilation/. Remove data/
filepath = Path(*Path(filepath).parts[1:])
old_file = Path(*Path(old_file).parts[1:])
new_file = Path(*Path(new_file).parts[1:])

if code == "D":
for locale in LOCALES:
path = Path(locale, filepath)
# It is quite probable that the translation does not exist.
if path.is_file():
path.unlink()

elif code == "R":
for locale in LOCALES:
locale_new = Path(locale, new_file)
locale_old = Path(locale, old_file)
if locale_old.is_file():
shutil.copy(locale_old, locale_new)
locale_old.unlink()
72 changes: 72 additions & 0 deletions locale/update_en_strings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#!/usr/bin/env python

import orjson
from orjson import OPT_APPEND_NEWLINE, OPT_INDENT_2
import os
from pathlib import Path
from stat import S_IXOTH

# TODO: Make a script that doesn't rely on recreating every file.
PRETTY_PRINT = OPT_APPEND_NEWLINE | OPT_INDENT_2


def generate_localisation_file(path: Path):
# Assume Community-Mod-Compilation/data/.
# Assume this script is in locale, and then make absolute.
locale_file = Path("en", *path.parts[2:]).resolve()

if not locale_file.is_file():
if not locale_file.parent.is_dir():
locale_file.parent.mkdir(mode=S_IXOTH, parents=True, exist_ok=True)
# Get every directory starting from Community-Mod-Compilation/locale/en/
# TODO: Replace this with a call to range().
for i, p in enumerate(locale_file.parts[3:-1], 4):
parent_dir = os.path.join(locale_file.parts[:i])
# Check if permission allows everybody to execute.
if os.stat(parent_dir)[0] != S_IXOTH:
os.chmod(parent_dir, S_IXOTH)
# Annoying, but this is the only file creation option on Windows and MacOS
with open(locale_file, "w"):
pass

# Return path to the new file.
return locale_file


def get_translation_strings(path: Path):
tr_file = []
try:
json = orjson.loads(path.read_bytes())
except orjson.JSONDecodeError:
raise orjson.JSONDecodeError(f"File: {path}")

if type(json) is not list:
return

for jo in json:
if type(jo) is not dict:
continue
# TODO: Check if there are things without descriptions to be translated.
if jo.get("description") and jo.get("name"):
tr_file.append({"name": jo["name"], "description": jo["description"]})

return tr_file


def main(directory):
for root, dirnames, filenames in os.walk(directory):
for filename in [f for f in filenames if f.endswith(".json")]:
path = Path(root, filename)
tr_file = get_translation_strings(path)
# No point in generating a new file if it's going to be empty.
if not tr_file:
continue
local = generate_localisation_file(path)
with open(local, "wb") as f:
f.write(orjson.dumps(tr_file, option=PRETTY_PRINT))


if __name__ == "__main__":
import sys

main(sys.argv[1])