mirror of
https://github.com/hrfee/jfa-go.git
synced 2024-12-22 09:00:10 +00:00
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.
This commit is contained in:
parent
726acb9c29
commit
a1af6e3892
33
scripts/langmover/README.md
Normal file
33
scripts/langmover/README.md
Normal file
@ -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**.
|
||||
|
||||
|
127
scripts/langmover/langmover.py
Normal file
127
scripts/langmover/langmover.py
Normal file
@ -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))
|
15
scripts/langmover/template.json
Normal file
15
scripts/langmover/template.json
Normal file
@ -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…
Reference in New Issue
Block a user