Two review catches (#264), both verified.
The sample's placeholder substitution in intl/initial_sync.py is
r'/_core_name_(?=[/.])]' -- a stray ']' after the lookahead, asserting
the next character is both '/'-or-'.' and ']'. It matches nothing:
as-shipped regex changed anything? False
without stray ']' changed anything? True
So '_core_name_' survived into crowdin.yaml and the documented initial
setup would have uploaded to a Crowdin path literally named
'_core_name_'. The reset path further down the same file got the same
tightening right, and older copies (nestopia) use a working
r'/_core_name_', so it is an upstream typo rather than intent.
Second: the vendored scripts call subprocess.run() without check=True
throughout, so a failed Crowdin CLI invocation exits 0 and the workflow
step reports success -- meaning an unset secret gave a green run that
did nothing, contradicting this PR's claim that the not-set-up state is
visible. Each workflow now fails on an empty CROWDIN_API_KEY as its
first step.
That guard lives in our workflow files rather than as check=True edits
across five upstream scripts: it covers the failure that actually
happens, cannot be clobbered by the sync workflow's own
`git add intl/*_workflow.py`, and does not risk failing runs on benign
non-zero exits from the Crowdin CLI that we cannot characterise without
a working token.
Co-Authored-By: Claude Opus 5 <[email protected]>
libretro_core_options_intl.h has been included behind HAVE_NO_LANGEXTRA
all along but is an empty stub -- no arrays, just RETRO_LANGUAGE_*
placeholder comments -- so option labels have never been translatable.
This adds the standard libretro Crowdin pipeline that fills it.
The intl/ toolchain and the three workflows are copies of the RetroArch
example_translation sample. Placeholders are filled for this repo:
core name virtualjaguar-libretro, both headers at the repo root.
Three deliberate deviations from the sample:
- The workflows watch and write develop, not the default branch. This
repo is GitFlow and master is release-only; the sample assumes one
default branch, so on a schedule it would check out and commit
straight to master.
- The `on:` blocks are rewritten. The sample ships `on:`,
`workflow_dispatch` and `schedule:` as sibling lines, which is not
valid YAML -- the manual-dispatch trigger is silently lost.
- intl/activate.py is dropped. It is a one-shot placeholder filler that
targets the older crowdin_prep.yml / crowdin_translate.yml names and
raises against the current sample's filenames. The placeholders here
are already filled, so it had no remaining use.
The sync step also gained a `git diff --cached --quiet ||` guard: the
generator only rewrites the header when a translation actually changed,
so a quiet week would otherwise fail the run on an empty commit.
options_intl[] stays all-NULL. The generator writes only the intl
header; enabling a language means replacing its NULL with &options_xx
by hand once translations exist. That is manual upstream too, and is
documented rather than pre-empted -- referencing symbols that do not
exist yet would not compile.
This unblocks now that #257 froze the option strings, so translators
are not handed text that is about to change.
Timing: sync runs Fridays 06:35 UTC.
docs/core-option-translations.md covers the pipeline, the
enable-a-language step, and the four setup steps that need libretro org
access (Crowdin token -> CROWDIN_API_KEY secret -> initial setup run ->
sync run). Until that secret exists both workflows fail on an empty
key, which is the intended visible "not set up yet" state.
Co-Authored-By: Claude Opus 5 <[email protected]>