scripts: add langmover

a tool to move strings between language file sections. Will be used to
move login strings from admin into their own "login" file section.
user-page
Harvey Tindall 1 year ago
parent 726acb9c29
commit a1af6e3892
No known key found for this signature in database
GPG Key ID: BBC65952848FB1A2

@ -0,0 +1,33 @@
# *langmover*
* Makes moving strings between language files a little easier.
# Usage
You'll need to create a template file. See example `template.json`:
```json
{
"meta": {
"explanation": "values here can either be folder, folder:section, or folder:section:subkey, and then either nothing, or /keyname. It all depends on whether the sections and keys match up, or if you want to pull a plural/singular only or not."
},
"strings": {
"inviteInfiniteUsesWarning": "admin", // Resolves to admin/strings/inviteInfiniteUsesWarning
"emailAddress": "form:strings/emailAddress", // Resolves to form/strings/emailAddress
"modifySettingsFor": "admin:quantityStrings:plural/", // Resolves to admin/quantityStrings/modifySettingsFor/plural
"deleteNUsers": "admin:quantityStrings:singular/deleteNUsers" // Resolves to admin/quantityStrings/deleteNUsers/singular
},
"quantityStrings": {
"reEnableUsers": "admin" // Resolves to admin/quantityStrings/reEnableUsers
}
}
```
Args:
* `--source`: Source `lang/` directory. **Always run on a copy, to avoid data loss**
* `--template`: Template JSON file.
* `--output`: Output directory. Will be filled with lang files (e.g. "en-us.json", "fa-ir.json", ...).
* `--extract`: Passing will remove the templated strings from their source file. **Modifies the source directory**.

@ -0,0 +1,127 @@
import json, argparse, os
from pathlib import Path
ROOT = "en-us.json"
# Tree structure: <lang-code.json>/<folder>/<json content>
def generateTree(src: Path):
tree = {}
langs = {}
directories = []
def readLangFile(path: Path):
with open(path, 'r') as f:
content = json.load(f)
return content
for directory in os.scandir(src):
if not directory.is_dir(): continue
directories.append(directory.name)
# tree[directory.name] = {}
for lang in os.scandir(directory.path):
if not lang.is_file(): continue
if not ".json" in lang.name: continue
if lang.name not in langs:
langs[lang.name] = True
if lang.name.lower() not in tree:
tree[lang.name.lower()] = {}
for lang in langs:
for directory in directories:
filepath = Path(src) / Path(directory) / Path(lang)
if not filepath.exists(): continue
tree[lang.lower()][directory] = readLangFile(filepath)
return tree
def parseKey(langTree, currentSection: str, fieldName: str, key: str, extract=False):
temp = key.split("/")
loc = temp[0]
k = ""
if len(temp) > 1:
k = temp[1]
sections = loc.split(":")
# folder, folder:section or folder:section:subkey
folder = sections[0]
section = currentSection
subkey = None
if len(sections) > 1:
section = sections[1]
if len(sections) > 2:
subkey = sections[2]
if k == '':
k = fieldName
value = ""
if folder in langTree and section in langTree[folder] and k in langTree[folder][section]:
value = langTree[folder][section][k]
if extract:
s = langTree[folder][section]
del s[k]
langTree[folder][section] = s
if subkey is not None and subkey in value:
value = value[subkey]
return (langTree, folder, value)
def generate(templ: Path, source: Path, output: Path, extract: bool, tree):
with open(templ, "r") as f:
template = json.load(f)
if not output.exists():
output.mkdir()
for lang in tree:
out = {}
for section in template:
if section == "meta":
# grab a meta section from the first file we find
for file in tree[lang]:
out["meta"] = tree[lang][file]["meta"]
break
continue
modifiedTree = {}
folder = ""
out[section] = {}
for key in template[section]:
(modifiedTree, folder, val) = parseKey(tree[lang], section, key, template[section][key], extract)
if val != "":
out[section][key] = val
if extract and val != "":
with open(source / folder / lang, "w") as f:
json.dump(modifiedTree[folder], f, indent=4)
with open(output / Path(lang), "w") as f:
json.dump(out, f, indent=4)
parser = argparse.ArgumentParser()
parser.add_argument("--source", help="source \"lang/\" folder.")
parser.add_argument("--template", help="template file. see template.json for an example of how it works.")
parser.add_argument("--output", help="output directory for new files.")
parser.add_argument("--extract", help="remove strings from original file as they are copied.", action="store_true")
args = parser.parse_args()
source = Path(args.source)
tree = generateTree(source)
generate(Path(args.template), source, Path(args.output), args.extract, tree)
# print(json.dumps(tree, sort_keys=True, indent=4))

@ -0,0 +1,15 @@
{
"meta": {
"explanation": "values here can either be folder, folder:section, or folder:section:subkey, and then either nothing, or /keyname. It all depends on whether the sections and keys match up, or if you want to pull a plural/singular only or not."
},
"strings": {
"inviteInfiniteUsesWarning": "admin",
"emailAddress": "form:strings/emailAddress",
"modifySettingsFor": "admin:quantityStrings:plural/",
"deleteNUsers": "admin:quantityStrings:singular/deleteNUsers"
},
"quantityStrings": {
"reEnableUsers": "admin"
}
}
Loading…
Cancel
Save