Skip to content

Commit bf5efb0

Browse files
committed
Update scripts to handle tranlsations
1 parent d7f0545 commit bf5efb0

File tree

3 files changed

+115
-110
lines changed

3 files changed

+115
-110
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,6 @@ doc/source/savefig/
145145

146146
# Web & Translations #
147147
##############################
148-
web/pandas-translations.tar.gz
149148
web/translations/
150149
web/pandas/pt/
151150
web/pandas/es/

web/pandas_translations.py

Lines changed: 28 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -5,85 +5,52 @@
55
Popen,
66
)
77
import tarfile
8-
98
import requests
10-
import yaml
9+
import io
10+
import shutil
1111

1212

13-
def download_translations(url, fname):
13+
def download_and_extract_translations(url, dir_name):
1414
"""
1515
Download the translations from the GitHub repository.
1616
"""
1717
response = requests.get(url)
1818
if response.status_code == 200:
19-
with open(fname, "wb") as f:
20-
f.write(response.content)
19+
doc = io.BytesIO(response.content)
20+
with tarfile.open(None, "r:gz", doc) as tar:
21+
tar.extractall(dir_name)
2122
else:
2223
raise Exception(f"Failed to download translations: {response.status_code}")
2324

2425

25-
def extract_translations(fpath, dir_name):
26-
"""
27-
Extract the translations from the tar file.
28-
"""
29-
with tarfile.open(fpath, "r:gz") as tar:
30-
tar.extractall(dir_name)
31-
print(f"Translations extracted to '{dir_name}' directory.")
32-
33-
34-
def load_translations_config(path):
35-
"""
36-
Load the translations configuration from the YAML file.
37-
"""
38-
with open(path) as f:
39-
config = yaml.safe_load(f)
40-
return config
41-
42-
43-
def load_status_config(path):
26+
def copy_translations(src_path, dest_path):
4427
"""
45-
Load the translations configuration from the YAML file.
28+
Copy the translations to the appropriate directory.
4629
"""
47-
with open(path) as f:
48-
config = yaml.safe_load(f)
49-
return config
30+
languages_path = f"{src_path}/pandas-translations-main/web/pandas/"
31+
en_path = f"{languages_path}/en/"
32+
if os.path.exists(en_path):
33+
shutil.rmtree(en_path)
5034

35+
languages = []
36+
37+
paths = os.listdir(languages_path)
38+
for path in paths:
39+
if os.path.isdir(f"{languages_path}/{path}"):
40+
languages.append(path)
5141

52-
def copy_translations(data, translation_percentage, dir_name, dest_dir):
53-
"""
54-
Copy the translations to the appropriate directory.
55-
"""
56-
for lang, value in data.items():
57-
if value["progress"] >= translation_percentage:
58-
language_code = lang[:2]
59-
src_path = (
60-
f"{dir_name}/pandas-translations-main/web/pandas/{language_code}/"
61-
)
62-
dest_path = f"{dest_dir}/{language_code}/"
63-
cmds = ["rsync", "-av", "--delete", src_path, dest_path]
64-
p = Popen(cmds, stdout=PIPE, stderr=PIPE)
65-
stdout, stderr = p.communicate()
66-
print(stdout.decode())
67-
print(stderr.decode())
42+
print(languages)
43+
cmds = ["rsync", "-av", "--delete", languages_path, dest_path]
44+
p = Popen(cmds, stdout=PIPE, stderr=PIPE)
45+
stdout, stderr = p.communicate()
46+
print(stdout.decode())
47+
print(stderr.decode())
6848

6949

7050
if __name__ == "__main__":
7151
os.chdir(Path(__file__).parent.parent)
7252
url = "https://github.com/Scientific-Python-Translations/pandas-translations/archive/refs/heads/main.tar.gz"
73-
fpath = "web/pandas-translations.tar.gz"
74-
dir_name = "web/translations"
75-
dest_dir = "web/pandas"
76-
config_path = (
77-
f"{dir_name}/pandas-translations-main/.github/workflows/sync_translations.yml"
78-
)
79-
status_path = f"{dir_name}/pandas-translations-main/status.yml"
80-
81-
download_translations(url, fpath)
82-
extract_translations(fpath, dir_name)
83-
config = load_translations_config(config_path)
84-
variables = config["jobs"]["sync_translations"]["steps"][0]["with"]
85-
translation_percentage = int(variables["translation-percentage"])
86-
status = load_status_config(status_path)
87-
copy_translations(
88-
status, translation_percentage, dir_name=dir_name, dest_dir=dest_dir
89-
)
53+
src_path = "web/translations"
54+
dest_path = "web/pandas"
55+
download_and_extract_translations(url, src_path)
56+
copy_translations(src_path, dest_path)

web/pandas_web.py

Lines changed: 87 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -81,11 +81,14 @@ def navbar_add_info(context):
8181
``has_subitems`` that tells which one of them every element is. It
8282
also adds a ``slug`` field to be used as a CSS id.
8383
"""
84+
lang = context['language']
85+
prefix = f"{lang}/" if lang != "en" else ""
8486
for i, item in enumerate(context["navbar"]):
87+
# print("lang", lang, prefix + (item["name"].replace(" ", "-").lower()))
8588
context["navbar"][i] = dict(
8689
item,
8790
has_subitems=isinstance(item["target"], list),
88-
slug=(item["name"].replace(" ", "-").lower()),
91+
slug=prefix + (item["name"].replace(" ", "-").lower()),
8992
)
9093
return context
9194

@@ -202,12 +205,15 @@ def maintainers_add_info(context):
202205

203206
# save the data fetched from github to use it in case we exceed
204207
# git github api quota in the future
205-
with open(
206-
pathlib.Path(context["target_path"]) / "maintainers.json",
207-
"w",
208-
encoding="utf-8",
209-
) as f:
210-
json.dump(maintainers_info, f)
208+
try:
209+
with open(
210+
pathlib.Path(context["target_path"]) / "maintainers.json",
211+
"w",
212+
encoding="utf-8",
213+
) as f:
214+
json.dump(maintainers_info, f)
215+
except Exception:
216+
pass
211217

212218
return context
213219

@@ -396,6 +402,8 @@ def get_context(config_fname: str, **kwargs):
396402

397403
context["source_path"] = os.path.dirname(config_fname)
398404
context.update(kwargs)
405+
context["selected_language"] = context.get("language", "en")
406+
context["languages"] = context.get("languages", ["en"])
399407

400408
preprocessors = (
401409
get_callable(context_prep)
@@ -409,14 +417,25 @@ def get_context(config_fname: str, **kwargs):
409417
return context
410418

411419

412-
def get_source_files(source_path: str) -> typing.Generator[str, None, None]:
420+
def get_source_files(source_path: str, language, languages) -> typing.Generator[str, None, None]:
413421
"""
414422
Generate the list of files present in the source directory.
415423
"""
424+
paths = []
425+
all_languages = languages[:]
426+
all_languages.remove(language)
416427
for root, dirs, fnames in os.walk(source_path):
417428
root_rel_path = os.path.relpath(root, source_path)
418429
for fname in fnames:
419-
yield os.path.join(root_rel_path, fname)
430+
path = os.path.join(root_rel_path, fname)
431+
for language in all_languages:
432+
if path.startswith(language + "/"):
433+
break
434+
else:
435+
paths.append(path)
436+
437+
for path in paths:
438+
yield path
420439

421440

422441
def extend_base_template(content: str, base_template: str) -> str:
@@ -434,65 +453,85 @@ def extend_base_template(content: str, base_template: str) -> str:
434453
def main(
435454
source_path: str,
436455
target_path: str,
456+
languages: typing.List[str],
437457
) -> int:
438458
"""
439459
Copy every file in the source directory to the target directory.
440460
441461
For ``.md`` and ``.html`` files, render them with the context
442462
before copying them. ``.md`` files are transformed to HTML.
443463
"""
444-
config_fname = os.path.join(source_path, "config.yml")
464+
base_source_path = source_path
465+
base_target_path = target_path
466+
for language in languages:
467+
print(f"\n\nProcessing language: {language}\n\n")
468+
if language != "en":
469+
target_path = os.path.join(base_target_path, language)
470+
source_path = os.path.join(base_source_path, language)
445471

446-
shutil.rmtree(target_path, ignore_errors=True)
447-
os.makedirs(target_path, exist_ok=True)
472+
shutil.rmtree(target_path, ignore_errors=True)
473+
os.makedirs(target_path, exist_ok=True)
448474

449-
sys.stderr.write("Generating context...\n")
450-
context = get_context(config_fname, target_path=target_path)
451-
sys.stderr.write("Context generated\n")
475+
config_fname = os.path.join(source_path, "config.yml")
476+
sys.stderr.write("Generating context...\n")
452477

453-
templates_path = os.path.join(source_path, context["main"]["templates_path"])
454-
jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(templates_path))
478+
context = get_context(config_fname, target_path=target_path, languages=languages, language=language)
479+
sys.stderr.write("Context generated\n")
455480

456-
for fname in get_source_files(source_path):
457-
if os.path.normpath(fname) in context["main"]["ignore"]:
458-
continue
481+
templates_path = os.path.join(source_path, context["main"]["templates_path"])
482+
jinja_env = jinja2.Environment(loader=jinja2.FileSystemLoader(templates_path))
459483

460-
sys.stderr.write(f"Processing {fname}\n")
461-
dirname = os.path.dirname(fname)
462-
os.makedirs(os.path.join(target_path, dirname), exist_ok=True)
484+
for fname in get_source_files(source_path, language, languages):
485+
if os.path.normpath(fname) in context["main"]["ignore"]:
486+
continue
463487

464-
extension = os.path.splitext(fname)[-1]
465-
if extension in (".html", ".md"):
466-
with open(os.path.join(source_path, fname), encoding="utf-8") as f:
467-
content = f.read()
468-
if extension == ".md":
469-
body = markdown.markdown(
470-
content, extensions=context["main"]["markdown_extensions"]
488+
sys.stderr.write(f"Processing {fname}\n")
489+
dirname = os.path.dirname(fname)
490+
os.makedirs(os.path.join(target_path, dirname), exist_ok=True)
491+
492+
extension = os.path.splitext(fname)[-1]
493+
if extension in (".html", ".md"):
494+
with open(os.path.join(source_path, fname), encoding="utf-8") as f:
495+
content = f.read()
496+
if extension == ".md":
497+
body = markdown.markdown(
498+
content, extensions=context["main"]["markdown_extensions"]
499+
)
500+
# Apply Bootstrap's table formatting manually
501+
# Python-Markdown doesn't let us config table attributes by hand
502+
body = body.replace("<table>", '<table class="table table-bordered">')
503+
content = extend_base_template(body, context["main"]["base_template"])
504+
context["base_url"] = "".join(["../"] * os.path.normpath(fname).count("/"))
505+
content = jinja_env.from_string(content).render(**context)
506+
fname_html = os.path.splitext(fname)[0] + ".html"
507+
with open(
508+
os.path.join(target_path, fname_html), "w", encoding="utf-8"
509+
) as f:
510+
f.write(content)
511+
else:
512+
shutil.copy(
513+
os.path.join(source_path, fname), os.path.join(target_path, dirname)
471514
)
472-
# Apply Bootstrap's table formatting manually
473-
# Python-Markdown doesn't let us config table attributes by hand
474-
body = body.replace("<table>", '<table class="table table-bordered">')
475-
content = extend_base_template(body, context["main"]["base_template"])
476-
context["base_url"] = "".join(["../"] * os.path.normpath(fname).count("/"))
477-
content = jinja_env.from_string(content).render(**context)
478-
fname_html = os.path.splitext(fname)[0] + ".html"
479-
with open(
480-
os.path.join(target_path, fname_html), "w", encoding="utf-8"
481-
) as f:
482-
f.write(content)
483-
else:
484-
shutil.copy(
485-
os.path.join(source_path, fname), os.path.join(target_path, dirname)
486-
)
515+
return 0
487516

488517

489518
if __name__ == "__main__":
490519
parser = argparse.ArgumentParser(description="Documentation builder.")
520+
521+
# For each language, the output will be written in a subdirectory named
522+
# after the language (default: build/, build/es, etc...)
523+
parser.add_argument(
524+
"--target-path", default="build", help="directory where to write the output."
525+
)
526+
# e.g. python pandas_web.py --source_path pandas/ --languages en pt
491527
parser.add_argument(
492-
"source_path", help="path to the source directory (must contain config.yml)"
528+
"source_path",
529+
help="path to the source directory (must contain each language folder)",
493530
)
494531
parser.add_argument(
495-
"--target-path", default="build", help="directory where to write the output"
532+
"--languages",
533+
nargs="*",
534+
help="language codes to build",
496535
)
497536
args = parser.parse_args()
498-
sys.exit(main(args.source_path, args.target_path))
537+
sys.exit(main(args.source_path, args.target_path, args.languages))

0 commit comments

Comments
 (0)