mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 05:32:47 +00:00
Reduce noise and drop dataclasses
This commit is contained in:
parent
f7a9b3eec8
commit
3008bfed61
@ -1,11 +1,8 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
""" Create an TRF translation for GodMode9 from a translation JSON. """
|
""" Create a TRF translation for GodMode9 from a translation JSON. """
|
||||||
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import dataclasses
|
|
||||||
import json
|
import json
|
||||||
import math
|
import math
|
||||||
import pathlib
|
import pathlib
|
||||||
@ -16,36 +13,6 @@ import sys
|
|||||||
LANGUAGE_NAME = "GM9_LANGUAGE"
|
LANGUAGE_NAME = "GM9_LANGUAGE"
|
||||||
|
|
||||||
|
|
||||||
def read_args() -> argparse.Namespace:
|
|
||||||
"""
|
|
||||||
Parse command-line args.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The parsed command-line args.
|
|
||||||
"""
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description="Create an TRF translation for GodMode9 from a translation JSON."
|
|
||||||
)
|
|
||||||
|
|
||||||
parser.add_argument(
|
|
||||||
"source",
|
|
||||||
type=pathlib.Path,
|
|
||||||
help="JSON to convert from"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"dest",
|
|
||||||
type=pathlib.Path,
|
|
||||||
help="TRF file to write"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"version",
|
|
||||||
type=int,
|
|
||||||
help="translation version, from language.yml"
|
|
||||||
)
|
|
||||||
|
|
||||||
return parser.parse_args()
|
|
||||||
|
|
||||||
|
|
||||||
def ceil_to_multiple(num: int, base: int) -> int:
|
def ceil_to_multiple(num: int, base: int) -> int:
|
||||||
"""
|
"""
|
||||||
Return the ceiling of num which is a multiple of base.
|
Return the ceiling of num which is a multiple of base.
|
||||||
@ -75,7 +42,7 @@ def get_language(data: dict) -> bytes:
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return data[LANGUAGE_NAME].encode("utf-8")
|
return data[LANGUAGE_NAME].encode("utf-8")
|
||||||
except AttributeError as exception:
|
except KeyError as exception:
|
||||||
raise ValueError("invalid language data") from exception
|
raise ValueError("invalid language data") from exception
|
||||||
|
|
||||||
|
|
||||||
@ -96,180 +63,60 @@ def load_translations(data: dict) -> dict[str, bytearray]:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
def strings_to_trf(mapping: dict[str, bytearray], version: int, language: str) -> bytearray:
|
||||||
class TRFMetadata:
|
|
||||||
"""
|
"""
|
||||||
A TRF file's metadata section.
|
Create a TRF file from translated strings.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
mapping: Mapping between labels and translated strings.
|
||||||
version: Translation version.
|
version: Translation version.
|
||||||
nstrings: Total strings in the translation.
|
|
||||||
language: Translation language.
|
language: Translation language.
|
||||||
"""
|
|
||||||
version: int
|
|
||||||
nstrings: int
|
|
||||||
language: bytes
|
|
||||||
|
|
||||||
def as_bytearray(self) -> bytearray:
|
|
||||||
"""
|
|
||||||
Return a bytearray representation of this TRF section.
|
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The TRF metadata section as a bytearray.
|
The translation strings as TRF data.
|
||||||
"""
|
"""
|
||||||
return (
|
# File header.
|
||||||
bytearray(b"META")
|
trfdata = bytearray(b"RIFF\0\0\0\0")
|
||||||
+ struct.pack("<LLL32s", 40, self.version, self.nstrings, self.language)
|
|
||||||
|
# Metadata section.
|
||||||
|
trfdata += (
|
||||||
|
b"META"
|
||||||
|
+ struct.pack("<LLL32s", 40, version, len(mapping), language)
|
||||||
)
|
)
|
||||||
|
|
||||||
def __len__(self) -> int:
|
# String data section.
|
||||||
return len(self.as_bytearray())
|
data = bytearray().join(mapping.values())
|
||||||
|
size = ceil_to_multiple(len(data), 4)
|
||||||
|
padding = size - len(data)
|
||||||
|
|
||||||
|
trfdata += (
|
||||||
@dataclasses.dataclass
|
b"SDAT"
|
||||||
class TRFCharacterData:
|
|
||||||
"""
|
|
||||||
A TRF file's character data section.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
data: Translation strings.
|
|
||||||
"""
|
|
||||||
data: bytearray
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_mapping(cls, mapping: dict[str, bytearray]) -> TRFCharacterData:
|
|
||||||
"""
|
|
||||||
Construct an instance of this class from a translation mapping.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
mapping: Mapping between translation labels and strings.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
An instance of TRFCharacterData.
|
|
||||||
"""
|
|
||||||
return cls(bytearray().join(mapping.values()))
|
|
||||||
|
|
||||||
def as_bytearray(self) -> bytearray:
|
|
||||||
"""
|
|
||||||
Return a bytearray representation of this TRF section.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
This TRF character data section as a bytearray.
|
|
||||||
"""
|
|
||||||
size = ceil_to_multiple(len(self.data), 4)
|
|
||||||
padding = size - len(self.data)
|
|
||||||
|
|
||||||
return (
|
|
||||||
bytearray(b"SDAT")
|
|
||||||
+ struct.pack("<L", size)
|
+ struct.pack("<L", size)
|
||||||
+ self.data
|
+ data
|
||||||
+ b"\0" * padding
|
+ b"\0" * padding
|
||||||
)
|
)
|
||||||
|
|
||||||
def __len__(self) -> int:
|
# String map section.
|
||||||
return len(self.as_bytearray())
|
|
||||||
|
|
||||||
|
|
||||||
@dataclasses.dataclass
|
|
||||||
class TRFCharacterMap:
|
|
||||||
"""
|
|
||||||
A TRF file's character map section.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
data: Translation strings' offsets.
|
|
||||||
"""
|
|
||||||
data: bytearray
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_mapping(cls, mapping: dict[str, bytearray]) -> TRFCharacterMap:
|
|
||||||
"""
|
|
||||||
Construct an instance of this class from a translation mapping.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
mapping: Mapping between translation labels and strings.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
An instance of TRFCharacterMap.
|
|
||||||
"""
|
|
||||||
data = bytearray()
|
data = bytearray()
|
||||||
offset = 0
|
offset = 0
|
||||||
|
|
||||||
for item in mapping.values():
|
for item in mapping.values():
|
||||||
data.extend(struct.pack("<H", offset))
|
data += struct.pack("<H", offset)
|
||||||
offset += len(item)
|
offset += len(item)
|
||||||
|
|
||||||
return cls(data)
|
size = ceil_to_multiple(len(data), 4)
|
||||||
|
padding = size - len(data)
|
||||||
|
|
||||||
def as_bytearray(self) -> bytearray:
|
trfdata += (
|
||||||
"""
|
b"SMAP"
|
||||||
Return a bytearray representation of this TRF section.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
This TRF character map section as a bytearray.
|
|
||||||
"""
|
|
||||||
size = ceil_to_multiple(len(self.data), 4)
|
|
||||||
padding = size - len(self.data)
|
|
||||||
|
|
||||||
return (
|
|
||||||
bytearray(b"SMAP")
|
|
||||||
+ struct.pack("<L", size)
|
+ struct.pack("<L", size)
|
||||||
+ self.data
|
+ data
|
||||||
+ b"\0" * padding
|
+ b"\0" * padding
|
||||||
)
|
)
|
||||||
|
|
||||||
def __len__(self) -> int:
|
# Fill in cumulative section size.
|
||||||
return len(self.as_bytearray())
|
trfdata[4:8] = struct.pack("<L", len(trfdata) - 8)
|
||||||
|
|
||||||
|
return trfdata
|
||||||
@dataclasses.dataclass
|
|
||||||
class TRFFile:
|
|
||||||
"""
|
|
||||||
A TRF file.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
metadata: The TRF META section.
|
|
||||||
chardata: The TRF SDAT section.
|
|
||||||
charmap: The TRF SMAP section.
|
|
||||||
"""
|
|
||||||
metadata: TRFMetadata
|
|
||||||
chardata: TRFCharacterData
|
|
||||||
charmap: TRFCharacterMap
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def new(cls, version: int, mapping: dict, language: bytes) -> TRFFile:
|
|
||||||
"""
|
|
||||||
Construct an instance of this class and its attributes.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
version: Translation version.
|
|
||||||
mapping: Mapping between translation labels and strings.
|
|
||||||
language: Translation language.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
An instance of TRFFile.
|
|
||||||
"""
|
|
||||||
return cls(
|
|
||||||
TRFMetadata(version, len(mapping), language),
|
|
||||||
TRFCharacterData.from_mapping(mapping),
|
|
||||||
TRFCharacterMap.from_mapping(mapping)
|
|
||||||
)
|
|
||||||
|
|
||||||
def as_bytearray(self) -> bytearray:
|
|
||||||
"""
|
|
||||||
Return a bytearray representation of this TRF file.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
This TRF file as a bytearray.
|
|
||||||
"""
|
|
||||||
size = len(self.metadata) + len(self.chardata) + len(self.charmap)
|
|
||||||
|
|
||||||
return (
|
|
||||||
bytearray(b"RIFF")
|
|
||||||
+ struct.pack("<L", size)
|
|
||||||
+ self.metadata.as_bytearray()
|
|
||||||
+ self.chardata.as_bytearray()
|
|
||||||
+ self.charmap.as_bytearray()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def main(source: pathlib.Path, dest: pathlib.Path, version: int) -> None:
|
def main(source: pathlib.Path, dest: pathlib.Path, version: int) -> None:
|
||||||
@ -287,14 +134,35 @@ def main(source: pathlib.Path, dest: pathlib.Path, version: int) -> None:
|
|||||||
language = get_language(data)
|
language = get_language(data)
|
||||||
except ValueError as exception:
|
except ValueError as exception:
|
||||||
sys.exit(f"Fatal: {exception}.")
|
sys.exit(f"Fatal: {exception}.")
|
||||||
strings = load_translations(data)
|
mapping = load_translations(data)
|
||||||
|
|
||||||
trf_file = TRFFile.new(version, strings, language)
|
trf_file = strings_to_trf(mapping, version, language)
|
||||||
|
|
||||||
dest.write_bytes(trf_file.as_bytearray())
|
dest.write_bytes(trf_file)
|
||||||
print(f"Info: {dest.as_posix()} created with {len(strings)} strings.")
|
print(f"Info: {dest.as_posix()} created with {len(mapping)} strings.")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
args = read_args()
|
parser = argparse.ArgumentParser(
|
||||||
|
description="Create an TRF translation for GodMode9 from a translation JSON."
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"source",
|
||||||
|
type=pathlib.Path,
|
||||||
|
help="JSON to convert from"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"dest",
|
||||||
|
type=pathlib.Path,
|
||||||
|
help="TRF file to write"
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"version",
|
||||||
|
type=int,
|
||||||
|
help="translation version, from language.yml"
|
||||||
|
)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
main(args.source, args.dest, args.version)
|
main(args.source, args.dest, args.version)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user