Enable anonymous downloads on the host and harden Strings.fmt
Host (applied with root@192.168.88.30) - [service] REQUIRE_SIGNIN_VIEW = false in /etc/gitea/app.ini (backup written alongside), Gitea restarted. Verified anonymously: repo page 200, API 200, and a release asset downloads at full size (50.8 MB AppImage). Localization safety (Open Polish) - Strings.placeholder_count() counts conversions and ignores %% escapes. - Strings.fmt() validates the count and fails safe (warns, returns the template) instead of raising an engine error when a key's placeholders drift. - Strings.validate() lints the table for a trailing %, unsupported conversions, and mixed positional/sequential placeholders. - Tests cover the counter, the fail-safe path, a clean table, and a formatting pass over every placeholder key with type-correct arguments. Docs - TODO: distribution, release-pipeline, and open-polish sections are complete and moved to DONE; the v0.2.4-v0.2.8 backfill is closed as superseded. - README/MEMORY updated. Version 0.2.14.
This commit is contained in:
1 parent
a2a0ded527
commit
74f14014b2
7 files changed
+182
-44
No files matched your search
@@ -23,6 +23,70 @@ func test_strings_json_backed_all_resolve() -> bool:
|
||||
return TestUtils.fail("key %s resolves to itself — table entry missing" % key)
|
||||
return true
|
||||
|
||||
func test_placeholder_count() -> bool:
|
||||
var a := TestUtils.check_eq(Strings.placeholder_count("no args"), 0, "plain text has no placeholders")
|
||||
var b := TestUtils.check_eq(Strings.placeholder_count("%s complies"), 1, "one %s")
|
||||
var c := TestUtils.check_eq(Strings.placeholder_count("%s: \"%s\""), 2, "two %s")
|
||||
var d := TestUtils.check_eq(Strings.placeholder_count("100%% sure"), 0, "%% is an escape, not an argument")
|
||||
var e := TestUtils.check_eq(Strings.placeholder_count("%.0f%% mood"), 1, "float plus percent sign")
|
||||
return a and b and c and d and e
|
||||
|
||||
func test_fmt_fails_safe_on_arg_mismatch() -> bool:
|
||||
## A drifting placeholder count must not raise an engine error at runtime.
|
||||
var result: String = Strings.fmt("react.comply", [])
|
||||
var a := TestUtils.check_eq(result, Strings.lookup("react.comply"), "wrong arg count returns the raw template")
|
||||
var extra: String = Strings.fmt("react.comply", ["A", "B"])
|
||||
var b := TestUtils.check_eq(extra, Strings.lookup("react.comply"), "too many args also fails safe")
|
||||
return a and b
|
||||
|
||||
func test_table_validates_cleanly() -> bool:
|
||||
var problems: Array = Strings.validate()
|
||||
if not problems.is_empty():
|
||||
return TestUtils.fail("string table format problems: %s" % str(problems))
|
||||
return true
|
||||
|
||||
func test_every_placeholder_key_formats() -> bool:
|
||||
## Feed each template one dummy arg per placeholder, with a type that matches
|
||||
## the conversion (%s text, %d int, %f float). Nothing may be left unformatted.
|
||||
var problems: Array[String] = []
|
||||
for key in Strings.TABLE.keys():
|
||||
var template: String = str(Strings.TABLE[key])
|
||||
var specs: Array[String] = _specifiers(template)
|
||||
if specs.is_empty():
|
||||
continue
|
||||
var args := []
|
||||
for spec in specs:
|
||||
var conv: String = spec.substr(spec.length() - 1)
|
||||
if conv == "d" or conv == "x" or conv == "X":
|
||||
args.append(7)
|
||||
elif conv == "f":
|
||||
args.append(1.5)
|
||||
else:
|
||||
args.append("x")
|
||||
var out: String = Strings.fmt(key, args)
|
||||
if out == template:
|
||||
problems.append("%s did not format (%s)" % [key, str(specs)])
|
||||
return TestUtils.check(problems.is_empty(), "all placeholder keys format (problems: %s)" % str(problems))
|
||||
|
||||
func _specifiers(template: String) -> Array[String]:
|
||||
var out: Array[String] = []
|
||||
var i := 0
|
||||
while i < template.length():
|
||||
if template[i] != "%":
|
||||
i += 1
|
||||
continue
|
||||
if i + 1 < template.length() and template[i + 1] == "%":
|
||||
i += 2
|
||||
continue
|
||||
var j := i + 1
|
||||
while j < template.length() and template[j] in "0123456789.$":
|
||||
j += 1
|
||||
if j < template.length():
|
||||
out.append(template.substr(i, j - i + 1))
|
||||
j += 1
|
||||
i = j
|
||||
return out
|
||||
|
||||
func test_strings_cover_ui_keys() -> bool:
|
||||
## Every key referenced by the HUD and game manager must exist.
|
||||
var required := [
|
||||
|
||||
Reference in new issue
Block a user