automatically format/check ftl files

This commit is contained in:
Damien Elmes 2020-11-22 15:30:59 +10:00
parent 0b848eae56
commit 52617511b0
19 changed files with 162 additions and 76 deletions

View file

@ -1,3 +1,5 @@
load("@py_deps//:requirements.bzl", "requirement")
filegroup(
name = "ftl",
srcs = [
@ -7,6 +9,24 @@ filegroup(
visibility = ["//rslib:__subpackages__"],
)
py_binary(
name = "format",
srcs = ["format.py"],
deps = [requirement("fluent-syntax")],
)
py_test(
name = "format_check",
srcs = [
"format.py",
"format_check.py",
],
# so we can locate data files
args = ["$(location BUILD.bazel)"],
data = glob(["**/*.ftl"]) + ["BUILD.bazel"],
deps = [requirement("fluent-syntax")],
)
# export this file as a way of locating the top level folder in $(location ...)
exports_files(
["BUILD.bazel"],

View file

@ -22,4 +22,3 @@ card-stats-review-log-type-review = Review
card-stats-review-log-type-relearn = Relearn
card-stats-review-log-type-filtered = Filtered
card-stats-review-log-type-manual = Manual

View file

@ -4,39 +4,27 @@
# Label of link users can click on
card-template-rendering-more-info = More information
card-template-rendering-front-side-problem = Front template has a problem:
card-template-rendering-back-side-problem = Back template has a problem:
# when the user forgot to close a field reference,
# eg, Missing '}}' in '{{Field'
card-template-rendering-no-closing-brackets =
Missing '{$missing}' in '{$tag}'
card-template-rendering-no-closing-brackets = Missing '{ $missing }' in '{ $tag }'
# when the user opened a conditional, but forgot to close it
# eg, Missing '{{/Conditional}}'
card-template-rendering-conditional-not-closed =
Missing '{$missing}'
card-template-rendering-conditional-not-closed = Missing '{ $missing }'
# when the user closed the wrong conditional
# eg, Found '{{/Something}}', but expected '{{/SomethingElse}}'
card-template-rendering-wrong-conditional-closed =
Found '{$found}', but expected '{$expected}'
card-template-rendering-wrong-conditional-closed = Found '{ $found }', but expected '{ $expected }'
# when the user closed a conditional that wasn't open
# eg, Found '{{/Something}}', but missing '{{#Something}}' or '{{^Something}}'
card-template-rendering-conditional-not-open =
Found '{$found}', but missing '{$missing1}' or '{$missing2}'
card-template-rendering-conditional-not-open = Found '{ $found }', but missing '{ $missing1 }' or '{ $missing2 }'
# when the user referenced a field that doesn't exist
# eg, Found '{{Field}}', but there is not field called 'Field'
card-template-rendering-no-such-field =
Found '{$found}', but there is no field called '{$field}'
card-template-rendering-no-such-field = Found '{ $found }', but there is no field called '{ $field }'
# This message is shown when the front side of the card is blank,
# either due to a badly-designed template, or because required fields
# are missing.
card-template-rendering-empty-front = The front of this card is blank.
card-template-rendering-missing-cloze = No cloze { $number } found on card.
Please either add a cloze deletion, or use the Empty Cards tool.
card-template-rendering-missing-cloze =
No cloze { $number } found on card.
Please either add a cloze deletion, or use the Empty Cards tool.

View file

@ -31,7 +31,8 @@ decks-reschedule-cards-based-on-my-answers = Reschedule cards based on my answer
decks-study = Study
decks-study-deck = Study Deck
decks-the-provided-search-did-not-match = The provided search did not match any cards. Would you like to revise it?
decks-it-has-card = { $count ->
[one] It has { $count } card.
*[other] It has { $count } cards.
}
decks-it-has-card =
{ $count ->
[one] It has { $count } card.
*[other] It has { $count } cards.
}

View file

@ -1,14 +1,14 @@
empty-cards-for-note-type = Empty cards for { $notetype }:
empty-cards-count-line =
{ $empty_count } of { $existing_count } cards empty ({ $template_names }).
empty-cards-count-line = { $empty_count } of { $existing_count } cards empty ({ $template_names }).
empty-cards-window-title = Empty Cards
empty-cards-preserve-notes-checkbox = Keep notes with no valid cards
empty-cards-delete-button = Delete
empty-cards-not-found = No empty cards.
empty-cards-deleted-count = Deleted { $cards ->
[one] { $cards } card.
*[other] { $cards } cards.
}
empty-cards-deleted-count =
Deleted { $cards ->
[one] { $cards } card.
*[other] { $cards } cards.
}
empty-cards-delete-empty-cards = Delete Empty Cards
empty-cards-delete-empty-notes = Delete Empty Notes
empty-cards-deleting = Deleting...

View file

@ -15,15 +15,18 @@ exporting-include-scheduling-information = Include scheduling information
exporting-include-tags = Include tags
exporting-notes-in-plain-text = Notes in Plain Text
exporting-selected-notes = Selected Notes
exporting-card-exported = { $count ->
[one] { $count } card exported.
*[other] { $count } cards exported.
}
exporting-exported-media-file = { $count ->
[one] Exported { $count } media file
*[other] Exported { $count } media files
}
exporting-note-exported = { $count ->
[one] { $count } note exported.
*[other] { $count } notes exported.
}
exporting-card-exported =
{ $count ->
[one] { $count } card exported.
*[other] { $count } cards exported.
}
exporting-exported-media-file =
{ $count ->
[one] Exported { $count } media file
*[other] Exported { $count } media files
}
exporting-note-exported =
{ $count ->
[one] { $count } note exported.
*[other] { $count } notes exported.
}

View file

@ -1,4 +1,5 @@
findreplace-notes-updated = { $total ->
[one] {$changed} of {$total} note updated
*[other] {$changed} of {$total} notes updated
}
findreplace-notes-updated =
{ $total ->
[one] { $changed } of { $total } note updated
*[other] { $changed } of { $total } notes updated
}

View file

@ -1,7 +1,6 @@
## Shown at the top of the media check screen
media-check-window-title = Check Media
# the number of files, and the total space used by files
# that have been moved to the trash folder. eg,
# "Trash folder: 3 files, 3.47MB"

View file

@ -2,5 +2,4 @@ network-offline = Please check your internet connection.
network-timeout = Connection timed out. Please try again. If you see frequent timeouts, please try a different network connection.
network-proxy-auth = Your proxy requires authentication.
network-other = A network error occurred.
network-details = Error details: {$details}
network-details = Error details: { $details }

View file

@ -18,7 +18,6 @@ notetypes-cloze-name = Cloze
notetypes-card-1-name = Card 1
notetypes-card-2-name = Card 2
notetypes-add = Add: { $val }
notetypes-add-note-type = Add Note Type
notetypes-cards = Cards...

View file

@ -138,7 +138,8 @@ scheduling-steps-must-be-numbers = Steps must be numbers.
scheduling-tag-only = Tag Only
scheduling-the-default-configuration-cant-be-removed = The default configuration can't be removed.
scheduling-your-changes-will-affect-multiple-decks = Your changes will affect multiple decks. If you wish to change only the current deck, please add a new options group first.
scheduling-deck-updated = { $count ->
[one] { $count } deck updated.
*[other] { $count } decks updated.
}
scheduling-deck-updated =
{ $count ->
[one] { $count } deck updated.
*[other] { $count } decks updated.
}

View file

@ -6,3 +6,4 @@ search-note-modified = Note Modified
search-card-modified = Card Modified
##

View file

@ -42,15 +42,18 @@ studying-type-answer-unknown-field = Type answer: unknown field { $val }
studying-unbury = Unbury
studying-what-would-you-like-to-unbury = What would you like to unbury?
studying-you-havent-recorded-your-voice-yet = You haven't recorded your voice yet.
studying-card-studied-in = { $count ->
[one] { $count } card studied in
*[other] { $count } cards studied in
}
studying-minute = { $count ->
[one] { $count } minute.
*[other] { $count } minutes.
}
studying-note-and-its-card-deleted = { $count ->
[one] Note and its { $count } card deleted.
*[other] Note and its { $count } cards deleted.
}
studying-card-studied-in =
{ $count ->
[one] { $count } card studied in
*[other] { $count } cards studied in
}
studying-minute =
{ $count ->
[one] { $count } minute.
*[other] { $count } minutes.
}
studying-note-and-its-card-deleted =
{ $count ->
[one] Note and its { $count } card deleted.
*[other] Note and its { $count } cards deleted.
}

View file

@ -1,5 +1,6 @@
### Messages shown when synchronizing with AnkiWeb.
## Media synchronization
sync-media-added-count = Added: { $up }↑ { $down }↓

62
ftl/format.py Normal file
View file

@ -0,0 +1,62 @@
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
Parse and re-serialize ftl files to get them in a consistent form.
"""
import os
import json
import glob
import sys
from typing import List
from fluent.syntax import parse, serialize
from fluent.syntax.ast import Junk
def check_file(path: str, fix: bool) -> bool:
"True if file is ok."
orig_text = open(path).read()
obj = parse(orig_text, with_spans=False)
# make sure there's no junk
for ent in obj.body:
if isinstance(ent, Junk):
raise Exception(f"file had junk! {path} {ent}")
# serialize
new_text = serialize(obj)
# make sure serializing did not introduce new junk
obj = parse(new_text, with_spans=False)
for ent in obj.body:
if isinstance(ent, Junk):
raise Exception(f"file introduced junk! {path} {ent}")
if new_text == orig_text:
return True
if fix:
print(f"Fixing {path}")
open(path, "w", newline="\n", encoding="utf8").write(new_text)
return True
else:
print(f"Bad formatting in {path}")
return False
def check_files(files: List[str], fix: bool) -> bool:
"True if files ok."
found_bad = False
for path in files:
ok = check_file(path, fix)
if not ok:
found_bad = True
return True
if __name__ == "__main__":
template_root = os.environ["BUILD_WORKSPACE_DIRECTORY"]
template_files = glob.glob(
os.path.join(template_root, "ftl", "*", "*.ftl"), recursive=True
)
check_files(template_files, fix=True)

10
ftl/format_check.py Normal file
View file

@ -0,0 +1,10 @@
import os
import format
import sys
import glob
template_root = os.path.dirname(sys.argv[1])
template_files = glob.glob(os.path.join(template_root, "*", "*.ftl"), recursive=True)
if not format.check_files(template_files, fix=False):
sys.exit(1)

View file

@ -1,7 +1,6 @@
# shown instead of the 'night mode' option when night mode is forced on because
# macOS is in dark mode
preferences-dark-mode-active = macOS is in dark mode
preferences-dark-mode-disable =
To show Anki in light mode while macOS is in dark mode, please
see the Night Mode section of the manual.
To show Anki in light mode while macOS is in dark mode, please
see the Night Mode section of the manual.

View file

@ -3,7 +3,6 @@ profiles-folder-readme =
to make backups easy. To tell Anki to use a different location,
please see:
{$link}
{ $link }
# will appear as 'Downgrade & Quit'
profiles-downgrade-and-quit = Downgrade && Quit

View file

@ -61,7 +61,8 @@ qt-misc-would-you-like-to-download-it = Would you like to download it now?
qt-misc-your-collection-file-appears-to-be = Your collection file appears to be corrupt. This can happen when the file is copied or moved while Anki is open, or when the collection is stored on a network or cloud drive. If problems persist after restarting your computer, please open an automatic backup from the profile screen.
qt-misc-your-computers-storage-may-be-full = Your computer's storage may be full. Please delete some unneeded files, then try again.
qt-misc-your-firewall-or-antivirus-program-is = Your firewall or antivirus program is preventing Anki from creating a connection to itself. Please add an exception for Anki.
qt-misc-second = { $count ->
[one] { $count } second
*[other] { $count } seconds
}
qt-misc-second =
{ $count ->
[one] { $count } second
*[other] { $count } seconds
}