feat: _() strings and screen texts become translatable strings; search looks in all states; stutter hint
show text _("...") and literal screen texts are listed in Names and menu; typing in search switches the filter from To do to All; the translator is told how stutters are spelled.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
262db2687e
commit
cc71050362
5 files changed
+73
-1
No files matched your search
@@ -62,6 +62,39 @@ class TextIndex:
|
||||
modules: list[tuple[str, int]] = field(default_factory=list)
|
||||
|
||||
|
||||
_WORD = re.compile(r"[^\W\d_]")
|
||||
_SCREEN_TEXT = {"text", "textbutton", "label"}
|
||||
|
||||
|
||||
def marked_strings(value: Any) -> list[str]:
|
||||
"""Texts that Ren'Py translates by their source: ``_("...")`` and the literal text of screen widgets.
|
||||
|
||||
``show text _("...")``, ``$ x = _("...")`` and screen ``text "..."`` carry no dialogue id, so they
|
||||
are keyed by the text itself, like menu items. Strings without a letter (numbers, markup) are skipped.
|
||||
"""
|
||||
out: list[str] = []
|
||||
stack = [value]
|
||||
while stack:
|
||||
item = stack.pop()
|
||||
if isinstance(item, list):
|
||||
stack.extend(reversed(item))
|
||||
continue
|
||||
if not isinstance(item, dict):
|
||||
continue
|
||||
func = item.get("f")
|
||||
if (item.get("k") == "call" and isinstance(func, dict) and func.get("k") == "name"
|
||||
and func.get("id") in ("_", "__") and len(item.get("a") or []) == 1):
|
||||
arg = item["a"][0]
|
||||
if isinstance(arg, dict) and arg.get("k") == "const" and isinstance(arg.get("v"), str):
|
||||
out.append(arg["v"])
|
||||
if item.get("w") in _SCREEN_TEXT and item.get("args"):
|
||||
arg = item["args"][0]
|
||||
if isinstance(arg, dict) and arg.get("k") == "const" and isinstance(arg.get("v"), str):
|
||||
out.append(arg["v"])
|
||||
stack.extend(reversed(list(item.values())))
|
||||
return [text for text in out if text.strip() and _WORD.search(text)]
|
||||
|
||||
|
||||
def text_index(manifest: dict[str, Any]) -> TextIndex:
|
||||
game_hash = manifest["files"]["game.json"]["hash"]
|
||||
game = blob_json(game_hash)
|
||||
@@ -109,7 +142,11 @@ def _build_index(game_hash: str, scripts: tuple[tuple[str, str], ...]) -> TextIn
|
||||
idx.lines.append(info)
|
||||
idx.by_tid[info.tid] = info
|
||||
count += 1
|
||||
for text in marked_strings(module["labels"]):
|
||||
idx.strings.setdefault(text, "text")
|
||||
idx.modules.append((path, count))
|
||||
for text in marked_strings(game.get("screens") or {}):
|
||||
idx.strings.setdefault(text, "text")
|
||||
return idx
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user