Localization & i18n
InterGenOS is built entirely from source, and that extends to how the system handles language, region, and translation. This page describes how localization works in the current release and how contributors can help expand it.
The project is at version 1.0-dev (build id v1.0-dev1). Today the desktop is
GNOME 49 on Wayland, which carries its own mature internationalization stack.
The notes below distinguish what ships today from what is open for
contribution.
How localization works today
Localization in InterGenOS rides on the standard components that the from-source toolchain produces and the desktop consumes:
- Locale data comes from the C library’s locale definitions, generated at build time. Region, date, number, and currency formatting all derive from the active locale.
- The desktop environment is GNOME 49, which uses gettext message catalogs for its translations. Most user-visible GNOME strings are already translated upstream by the GNOME translation community.
- Per-application translations ship with each application package, in the catalogs that upstream provides.
Because the system is assembled package by package, the set of available languages reflects what the included packages carry. As the package set grows across the seven tiers (toolchain, core, base, desktop, extra, compute, and ai), so does the breadth of available translations.
The image ships the full set of locale definitions (several hundred under
/usr/share/i18n/locales) while only a small default set is compiled
out of the box. The installer’s keyboard-and-locale screen offers the full
definition set, writes the chosen locale to /etc/locale.conf, and compiles it
on the installed system — so a non-default locale selected at install time works
without any manual generation step.
InterGenOS-authored components
A few components are written for InterGenOS rather than pulled from upstream. These are where project-specific localization matters most:
- pkm — the package manager
- Forge — the installer
- InterGen — the tiered, hardware-detected, offline-first local assistant (built on an on-device model, with zero telemetry)
- InterGen Sentinel — the pluggable security scanner, which defaults to Local-Rules plus Local-Qwen and offers six built-in opt-in cloud providers plus a user-configured endpoint, including the Phone-A-Friend (Frontier/Cloud Escalation) path
User-facing text in these components is the highest-value target for translation work, because it is unique to the project and not covered by any upstream translation community.
Today none of the project-authored components externalize their strings — there are no gettext catalogs or message files in the package manager, the installer, or the assistant. That makes string externalization itself the first task of any translation effort for these components: the highest-value contribution is wiring a catalog mechanism in, not translating strings that are still embedded in code.
Contributing translations
There is no separate translation submission process. Translation contributions follow the same path as any other code contribution, and the general workflow from the project’s contributing guidelines applies.
- Open an issue first to discuss the language or component you want to work on. InterGenOS is maintained by a single developer, so coordinating up front avoids duplicated effort.
- Fork the repository and create a branch.
- Follow the existing code style. No surprises, no restructuring beyond the change at hand.
- Test your changes. If you cannot verify that a translation renders correctly, do not submit it. The build must remain reproducible.
- Submit a pull request with a clear description of what you translated and how you verified it.
Every commit must carry a Signed-off-by: trailer certifying the Developer
Certificate of Origin (DCO) 1.1. Add it with:
git commit -s
Pull requests whose commits are not all signed off will fail the audit workflow and cannot merge.
Translations and packages
For applications pulled from upstream, translations live with the package and
are updated when the package is updated. Package templates are the most
impactful contribution to the project, and each one lives under
packages/<tier>/<name>/ with two files:
package.yml— metadata: source URL, SHA256, dependencies, and build stylebuild.sh— the bash functionsconfigure(),build(),check(), anddo_install()
If a package’s upstream catalogs are out of date or missing a language, the right fix is usually upstream. Coordinate through an issue before changing how a package handles its own translations, so the build stays reproducible and the package stays close to its source.
The recipe format exposes no locale- or translation-specific keys — a package’s locale data is whatever its own upstream build installs. Selecting or stripping message catalogs per package would be new recipe-schema work, not an existing option.
The public-content audit
Every pull request to master is scanned by an automated public-content audit.
Translation contributions are no exception: keep host-specific paths, internal
file references, and credential-like strings out of message catalogs and commit
messages. If the audit flags a file, amend it and push again. Legitimate public
content that happens to match a flagged pattern can be added to the audit
allowlist.
What we value
The same standards that govern all contributions govern translations:
- Transparency — no hidden behavior, no surprising defaults.
- Simplicity over cleverness — if there is a simpler way to handle a string or a locale, use it.
- Tested changes — verify that text renders correctly before you submit.
These standards exist because the project’s purpose is a machine you understand, can modify, and can trust. In that posture, security is not first. It is only: translation work must never weaken the system’s integrity, and the audit and review gates apply to localized strings exactly as they apply to code.