Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update mui-language-picker and font scripts #3060

Merged
merged 11 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions maintenance/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,10 @@ WORKDIR ${HOME}

ENV PATH ${PATH}:${SCRIPT_DIR}

RUN mkdir -p ${SCRIPT_DIR}/font_lists

COPY --chown=user:user requirements.txt .

RUN pip3 install -r requirements.txt

COPY --chown=user:user scripts/*.py ${SCRIPT_DIR}
COPY --chown=user:user scripts/*.sh ${SCRIPT_DIR}
COPY --chown=user:user scripts/font_lists/* ${SCRIPT_DIR}/font_lists
COPY --chown=user:user scripts/mui_language_picker_fonts.txt ${SCRIPT_DIR}
19 changes: 0 additions & 19 deletions maintenance/scripts/font_lists/mui_language_picker_font_map.json

This file was deleted.

188 changes: 0 additions & 188 deletions maintenance/scripts/font_lists/mui_language_picker_fonts.txt

This file was deleted.

86 changes: 37 additions & 49 deletions maintenance/scripts/get_fonts.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,7 @@

scripts_dir = Path(__file__).resolve().parent
file_name_fallback = "fallback.json"
font_lists_dir = scripts_dir / "font_lists"
mlp_font_list = font_lists_dir / "mui_language_picker_fonts.txt"
mlp_font_map = font_lists_dir / "mui_language_picker_font_map.json"
mlp_fonts_known_unavailable = ["NotoSansLeke", "NotoSansShuishu", "SimSun"]
mlp_font_list = scripts_dir / "mui_language_picker_fonts.txt"
url_font_families_info = "https://github.com/silnrsi/fonts/raw/main/families.json"
url_lang_tags_list = "https://ldml.api.sil.org/en?query=langtags"
url_script_font_table = (
Expand All @@ -48,6 +45,13 @@ def parse_args() -> argparse.Namespace:
metavar="LANG",
help="List of language tags for which fonts should be downloaded.",
)
parser.add_argument(
"--scripts",
"-s",
nargs="*",
metavar="SCRIPT",
help="List of script tags for which fonts should be downloaded.",
)
parser.add_argument(
"--url",
"-u",
Expand Down Expand Up @@ -142,10 +146,10 @@ def fetch_scripts_for_langs(langs: List[str]) -> List[str]:

def fetch_fonts_for_scripts(scripts: List[str]) -> List[str]:
"""Given a list of script tags, look up the default fonts used with those scripts."""
scripts = [script.capitalize() for script in scripts]
scripts = list({script.capitalize() for script in scripts})

# Always have the Mui-Language-Picker default/safe fonts (except proprietary "SimSun").
fonts = ["AnnapurnaSIL", "CharisSIL", "DoulosSIL", "NotoSans", "ScheherazadeNew"]
# Always have the Mui-Language-Picker default/safe fonts.
fonts = ["Annapurna SIL", "Charis SIL", "Noto Sans TC", "Scheherazade New"]

logging.debug(f"Downloading script font table from {url_script_font_table}")
req = requests.get(url_script_font_table)
Expand Down Expand Up @@ -174,7 +178,7 @@ def fetch_fonts_for_scripts(scripts: List[str]) -> List[str]:
if len(row) == 0 or row[0] not in scripts:
continue
for i in font_indices:
font = row[i].replace(" ", "")
font = row[i]
if font != "" and font not in fonts:
fonts.append(font)

Expand All @@ -200,19 +204,25 @@ def main() -> None:
logging.error(f"Invalid output directory: '{args.output}'")
exit(1)

is_for_offline: bool = args.langs or args.scripts

with open(mlp_font_list, "r") as mlp_fonts_list:
# MLP use of spaces in fonts is inconsistent, so remove all spaces for simplicity.
fonts = [f.strip().replace(" ", "") for f in mlp_fonts_list.readlines()]
fonts = [f.strip() for f in mlp_fonts_list.readlines()]

if args.langs:
logging.info(f"Language tags: {', '.join(args.langs)}")
if is_for_offline:
scripts: List[str] = []
if args.langs:
logging.info(f"Specified languages: {', '.join(args.langs)}")
scripts = fetch_scripts_for_langs(args.langs)
logging.info(f"Scripts for specified languages: {', '.join(scripts)}")

scripts = fetch_scripts_for_langs(args.langs)
logging.info(f"Scripts used for specified language tags: {', '.join(scripts)}")
if args.scripts:
logging.info(f"Specified scripts: {', '.join(args.scripts)}")
scripts.extend(args.scripts)

script_fonts = fetch_fonts_for_scripts(scripts)
logging.info(
f"Default fonts and fonts used for specified language tags: {', '.join(script_fonts)}"
f"Fonts (default and those for specified languages/scripts): {', '.join(script_fonts)}"
)

if args.clean:
Expand All @@ -227,30 +237,20 @@ def main() -> None:

families = fetch_font_families_info()

with open(mlp_font_map, "r") as mlp_map_file:
mlp_map: dict[str, str] = json.load(mlp_map_file)
# Assumes no two keys map to the same value.
mlp_map_rev = {val: key for key, val in mlp_map.items()}

# Fonts for which the frontend will get css files from Google's font API.
google_fallback: dict[str, str] = {}

for font in fonts:
logging.debug(f"Font: {font}")
font_id: str = font.lower()
if font in mlp_map.keys():
font_id = mlp_map[font].lower()
font_id: str = font.replace(" ", "").lower()

# Get font family info from font families info, using fallback font if necessary.
while font_id != "" and font_id in families.keys():
font_info = families[font_id]
family: str = font_info["family"]
from_google = (
(not args.langs)
and "source" in font_info.keys()
and font_info["source"] == "Google"
)
if check_font_info(font_info) or from_google:
source_is_google = "source" in font_info.keys() and font_info["source"] == "Google"
get_from_google = source_is_google and not is_for_offline
if check_font_info(font_info) or get_from_google:
# Font available.
break
if "fallback" in font_info.keys():
Expand All @@ -261,22 +261,20 @@ def main() -> None:
font_id = ""

# When downloading, only download fonts used for scripts of the specified languages.
if args.langs and family.replace(" ", "") not in script_fonts:
logging.debug(f"Skipping font {font} as irrelevant for specified languages.")
if is_for_offline and family not in script_fonts:
logging.debug(f'Skipping font "{font}" as irrelevant for specified languages/scripts.')
continue

# Check if font was determined available.
if font_id == "" or font_id not in families.keys():
if font in mlp_fonts_known_unavailable:
logging.debug(f"Font {font} not available (but we knew that already)")
elif args.langs:
logging.warning(f"Font {font} not available for download")
if is_for_offline:
logging.warning(f'Font "{font}" not available for download')
else:
logging.warning(f"Font {font} css info not available")
logging.warning(f'Font "{font}" css info not available')
continue

# When not downloading, prefer fetching css info from Google when available.
if from_google:
if get_from_google:
google_fallback[font] = family
logging.debug(f"Using Google fallback for {font}: {google_fallback[font]}")
continue
Expand Down Expand Up @@ -305,7 +303,7 @@ def main() -> None:
logging.warning(f"{file_name}: No 'flourl' or 'url' for this file")
continue

if args.langs:
if is_for_offline:
# With the https://fonts.languagetechnology.org "flourl" urls,
# urllib.request.urlretrieve() is denied (403), but requests.get() works.
req = requests.get(src)
Expand All @@ -326,17 +324,7 @@ def main() -> None:
with open(css_file_path, "w") as css_file:
css_file.writelines(css_lines)

# If the font corresponds to a different MPL font name,
# create a css file for that font name too.
if font in mlp_map_rev.keys():
font = mlp_map_rev[font]
css_lines[2] = f" font-family: '{font}';\n"
css_file_path = args.output / f"{font}.css"
logging.debug(f"Writing {css_file_path}")
with open(css_file_path, "w") as css_file:
css_file.writelines(css_lines)

if not args.langs:
if not is_for_offline:
fallback_lines = ['{\n "google": {\n']
for key, val in google_fallback.items():
fallback_lines.append(f' "{key}": "{val}",\n')
Expand Down
Loading
Loading