5.5 KiB
Contributing to Shadowbroker
Thank you for taking the time to contribute. This document covers things specific to this project — for general open-source contribution etiquette, see the GitHub docs.
Code contributions
- Fork the repo on GitHub (
bigbodycobain/Shadowbroker) or GitLab (bigbodycobain/Shadowbrokermirror). - Make your changes on a feature branch.
- Run the local test suite:
- Backend:
pytest backend/tests/ - Frontend:
cd frontend && npx vitest run
- Backend:
- Open a Pull Request against
main.
CI runs on every PR. If CI fails, that's blocking — please push fixes rather than asking for it to be merged anyway.
Reporting security issues
Do not file security issues as public GitHub issues. Email the maintainer or use a private security advisory on GitHub. Public disclosure of an exploitable vulnerability without prior coordination will be rejected from the project.
Translation contributions
Shadowbroker supports UI localization (frontend/src/i18n/). Translation contributions are welcome but held to a stricter standard than most code changes, because translations can subtly reshape user perception in ways that are hard to spot during review. Read this section before submitting one.
The neutrality requirement
Translations must be technically faithful to the English source. That means:
- Each
t('key')entry should mean approximately the same thing in the target language as in English, modulo idiom. - Technical terms with established meanings (e.g. "GPS jamming," "military flight," "Tor," "onion routing," "encryption") should be translated using the corresponding established technical term in the target language — not softened, rebranded, or politically reframed.
- The set of UI strings should be the same between languages. Don't omit features from one locale that are visible in another.
What will get a translation PR rejected
Translation choices that align the project with the framing or terminology of state propaganda — from any country — will be rejected. This applies symmetrically:
| Country / source | Examples of substitutions we will reject |
|---|---|
| PRC / CCP | Calling Taiwan a "province" or "renegade province"; reframing protest layers as "riots"; using softened or euphemistic terms for surveillance, internment, or jamming when the source text is direct |
| Russia | Calling the Ukraine war a "special military operation"; relabeling occupied territories as Russian; softening sanctions/jamming/disinfo terminology |
| United States / EU | Reframing adversaries with editorial labels not in the source (e.g. inserting "regime" where the English says "government"); applying labels like "terrorist" or "rogue state" to entities the English source describes neutrally |
| Israel / Palestine / any active conflict | Substituting one side's preferred terminology when the source uses the other side's or a neutral term |
| Any government | Adding political slogans, omitting features that government finds inconvenient, or inserting terminology associated with a specific political faction |
The test is "would a translator working strictly from the English source produce this rendering?" If the answer requires assuming a political stance the source does not take, the substitution does not belong in the translation.
How translation PRs are reviewed
Changes to frontend/src/i18n/** are owned by the maintainer (see CODEOWNERS) and require explicit approval. We will:
- Diff the translation against the English source key-by-key.
- Spot-check a sample of entries with a native speaker of the target language when possible.
- Look for the patterns above.
- Look for suspicious additions to the i18n infrastructure itself (e.g. a remote translation fetcher, telemetry on language choice) — the i18n layer is supposed to be 100% client-side static JSON.
A PR that adds a new language is harder to review than one that fixes typos in an existing language. For new languages, please be patient and expect a real review window. For typo fixes, please describe each change in the PR body so the reviewer can verify intent.
What about adding a new language?
We welcome new languages. The mechanical setup is documented in the header comment of frontend/src/i18n/index.tsx. Beyond that:
- Register the locale in
backend/services/telegram_translate.py(_LOCALE_TO_GOOGLEand_SOURCE_LANG_LABELS) and the matching fallback labels infrontend/src/components/MaplibreViewer/popups/TelegramOsintPopup.tsx. Simple codes likefaalready pass through to Google Translate, but without the labels the UI shows raw codes (e.g.FA) for source language, and aliases likezh→zh-CNneed an explicit map entry. - For RTL languages, add the locale to
RTL_LOCALESinfrontend/src/i18n/index.tsxand smoke-test the map chrome (sidebar, modals, popups) with that locale selected —dir="rtl"can mirror flex layouts that were designed LTR. - We are more likely to merge a new language quickly if at least one reviewer in the maintainer's network speaks it.
- If you are the only speaker of the target language reading this repo, your translation is welcome but the merge timeline will be longer while a reviewer is found.
- Partial translations are fine — the system falls back to English for any missing key.
Anything else
If you have a question that isn't a security report, opening a GitHub Discussion or a draft PR with a question in the body is the fastest way to get a response. Direct emails are read but not always replied to promptly.