Skip to content

feat(i18n): open translation system to third-party paks - #1

Open
dalexanco wants to merge 5 commits into
foXaCe:feature/i18n-translation-systemfrom
dalexanco:feature-i18n-paks
Open

feat(i18n): open translation system to third-party paks#1
dalexanco wants to merge 5 commits into
foXaCe:feature/i18n-translation-systemfrom
dalexanco:feature-i18n-paks

Conversation

@dalexanco

Copy link
Copy Markdown

Extends the i18n system from LoveRetro#735 to third-party Tools paks, without touching NextUI's own .lang files or core translation flow.

  • I18N_load_extra(path) — append-only merge into the already-loaded table, for compiled paks that link i18n.c themselves.
  • i18n.elf — a small CLI (same family as nextval.elf) giving shell paks get/format/lang, since most Tools paks have no C to call T() from.
  • i18n.elf format interpolates %s only, via a custom scanner never handed to printf(3)/vprintf — a .lang value (possibly a third-party or community translation) can never control byte counts or trigger UB.
  • Repeatable -f (later wins) lets a pak layer a community-contributed translation on top of its own file, via one documented shared path — enabling pak-i18n-common-style translation-only paks for pak authors who don't want to maintain locales themselves.
  • No OS-side auto-scanning: a pak's vocabulary is pulled in on demand, only while it runs — nothing orphaned when the pak is removed, no cost for paks never opened.

Full design and conventions documented in I18N.md.

Documents I18N_load_extra() for compiled paks and the planned i18n.elf
CLI for shell paks, mirroring the nextval.elf / pak-hooks.sh precedents
already in the codebase. Implementation follows separately.
…anslation packs

- i18n.elf format: %s-only positional substitution, never handed to
  printf(1) directly, so a third-party-translated .lang value can't
  become a format-string footgun.
- Document a pak-i18n-common pattern: a shared
  .userdata/shared/i18n-community/<Pak>/<code>.lang path, merged via an
  extra -f, that lets a data-only pak translate someone else's pak
  without touching its code -- conditional on that pak already routing
  strings through T()/i18n.elf.
Exposes the existing parse_file() as a public, append-only entry point:
a pak (compiled, or i18n.elf on a shell pak's behalf) can merge its own
.lang file into the table already loaded by I18N_init()/I18N_reload()
without clearing the OS's own entries. No-op before I18N_init(); safe
to call repeatedly, later files win on key collisions.

Step 1 of I18N.md's pak-scoped i18n plan.
Cut repeated framing/rationale, keep the same technical content and
examples. 269 -> 179 lines.
New workspace/all/i18n_cli/, built and packaged like nextval.elf:

  i18n.elf lang                                prints active language code
  i18n.elf get <key> [-f <path>]...            resolves a key, T() fallback semantics
  i18n.elf format <key> [-f <path>]... -- args  %s-only positional interpolation

-f is repeatable (I18N_load_extra() per file, later wins) -- this is
what lets a shell pak merge its own res/lang/ file, and optionally a
second community-translation file on top, in one call.

format never hands the resolved template to printf(3)/vprintf: only
%s is recognized and substituted, any other specifier (%d, %u, %n...)
is left as literal text. A .lang value -- including a third-party or
community-contributed one -- can never control how many bytes get
written.

Wired into workspace/makefile (all + clean) and the root makefile's
system: target, same placement as nextval.elf.

Step 2 of I18N.md's pak-scoped i18n plan.
@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ff8d76bf-b8ec-407d-a540-d7cb6c6cd357

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant