Document https://crowdin.com/project/drytrix-timetracker in CONTRIBUTING.md, docs/TRANSLATION_SYSTEM.md, and contributor guides. Update CONTRIBUTING_TRANSLATIONS.md with the public project URL, clearer translator vs maintainer onboarding, and an optional "Further Crowdin integration" section (GitHub app, automation, QA, glossary, notifications). Refresh crowdin.yml header comments (project URL, secrets pointers), normalize preserve_hierarchy to a boolean, and keep the nb→no languages_mapping quoted for YAML 1.1 compatibility.
10 KiB
Contributing translations (no Git required)
This project uses GNU gettext .po files under translations/<locale>/LC_MESSAGES/messages.po, compiled at app startup (see TRANSLATION_SYSTEM.md). You do not need Git or developer tools to suggest fixes.
How we accept help (channels)
Maintainers should pick what fits workload and community size. The default for this repository is A; scale up to B or C when needed.
| Channel | Best for | Git? |
|---|---|---|
| A. GitHub issue (recommended default) | Wrong/missing wording, one string or a small batch | No — use the “Translation improvement” template when creating an issue |
| B. Spreadsheet or form | Many rows at once, non-GitHub users | No — maintainer copies suggestions into .po |
| C. Hosted translation platform | Ongoing community, many languages, history and glossaries | No for translators; maintainer connects repo or uploads .po |
A. GitHub issue (primary)
- Open a new issue and choose Translation improvement.
- Fill in language, where you saw the text, current UI text, and your suggested wording.
- A maintainer updates the correct
messages.poand merges the change.
No repository access is required.
B. Spreadsheet or form (optional)
Use when contributors cannot or will not use GitHub:
- Maintainer shares a table with columns such as: Language code, Screen or page, Text as shown now, Should be (your suggestion), Notes.
- Contributors only edit the suggestion column.
- Maintainer applies changes to the
.pofiles and validates placeholders (see below).
C. Hosted platform (optional, higher volume)
Examples: Weblate (open source, can be self-hosted), Crowdin, POEditor, Transifex. Translators work in the browser; integration or export/import keeps .po in sync with the codebase. Setup is maintainer-owned.
TimeTracker on Crowdin: https://crowdin.com/project/drytrix-timetracker
Crowdin setup (maintainers)
This repo includes a root crowdin.yml that maps source translations/en/LC_MESSAGES/messages.po to translations under translations/<locale>/LC_MESSAGES/messages.po, with nb → no so Norwegian matches app/config.py (no, not nb). You may still have a legacy translations/nb/ tree locally; prefer no in Crowdin and in config so you do not maintain two Norwegian copies.
- Crowdin account and project — Sign up at Crowdin if needed. Translators work in Drytrix TimeTracker (ask a maintainer for access if the project is private). Maintainers configure API tokens and GitHub integration against that same project unless you intentionally use a separate test project.
- Source language: English. Treat the resource as Gettext PO (
.po). - Target languages: Add every locale you ship:
nl,de,fr,it,fi,es,no,ar,he(matchLANGUAGESinapp/config.py). For Norwegian, add Norwegian (Bokmål) in Crowdin; thecrowdin.ymlmapping writes files intotranslations/no/. - Sync with this repository (pick one):
- GitHub Action: In the GitHub repo, add Actions secrets
CROWDIN_PROJECT_IDandCROWDIN_PERSONAL_TOKEN(Crowdin project Details shows the numeric project ID; Account Settings → API creates the token with project access, typically Manager). Run Crowdin sync from the Actions tab → Run workflow. For a one-time import of existing.pofiles into Crowdin’s translation memory, temporarily setupload_translations: truein .github/workflows/crowdin-sync.yml, run it once, then set it back tofalse. - Crowdin’s GitHub integration: Crowdin → Integrations → GitHub → connect the repo and branch; point it at the same
crowdin.ymlso Crowdin can open PRs when translations are updated. - Crowdin CLI: Install the Crowdin CLI, export the same env vars, run
crowdin upload sources(and optionallycrowdin upload translationsonce) from the repository root.
- GitHub Action: In the GitHub repo, add Actions secrets
- When developers add or change
_()strings: Runpybabel extract/pybabel updatelocally (see TRANSLATION_SYSTEM.md), commit if you version those files, then upload sources to Crowdin again. - Landing translations: Approve in Crowdin if you use review, then download (workflow or integration PR), merge, and run the app so
.mofiles rebuild.
Translators only need a Crowdin account; they do not use git.
Further Crowdin integration (optional)
Pick what reduces manual work without duplicating automation (avoid running both the Crowdin GitHub app and the Crowdin sync Action on the same events unless you coordinate branches, or you may get competing PRs).
- Crowdin → Integrations → GitHub — Connect the repository and default branch (e.g.
mainordevelop). Crowdin can open PRs when translations are updated and can watch the repo for changes to configured source files. Use the samecrowdin.ymlpath the integration expects (usually repo root). This can replace manual Action runs for “download translations” if you prefer Crowdin-driven PRs. - Automate the existing Action — Extend .github/workflows/crowdin-sync.yml with triggers such as
schedule(e.g. weekly), orpushlimited totranslations/en/**andmessages.potso new English sources upload shortly after merge. Keepworkflow_dispatchfor on-demand full sync. - Pre-translate and QA — In the Drytrix TimeTracker project, enable Translation Memory, Machine translation (as a suggestion layer only), and QA checks (variables, HTML tags, duplicate translations). Add a Glossary for product names and fixed terminology.
- Context for translators — Upload screenshots or use Crowdin’s in-context / overlay tools where supported so ambiguous short strings (e.g. “Save”, “Project”) get the right meaning.
- Review before merge — Turn on proofreading / “Export only approved” in Crowdin if you want the GitHub Action or integration to pull only reviewed strings (match the Action’s
export_only_approved-style options to your Crowdin workflow). - CLI in release process — Add
crowdin upload sourcesafterpybabel extract/updatein a maintainer script or release checklist so Crowdin always matches the latest POT-derived English catalog. - Notifications — Slack, email, or webhooks in Crowdin when a language reaches 100% or when there are new strings to translate.
Official references: Crowdin + GitHub, GitHub Action, Crowdin CLI.
Other options (reference)
- Poedit: Maintainer can zip
translations/<lang>/LC_MESSAGES/messages.pofor a trusted translator; they edit in Poedit and send the file back. Avoid two people editing the same locale in parallel without coordination. - GitHub web editor on
.pofiles: Possible for experts only; easy to break quoting or plural blocks.
Rules for translators
Follow these so your suggestion can be applied without breaking the app:
- Do not change English source keys. In
.pofiles those aremsgidlines. In an issue or spreadsheet you describe what you see; maintainers map it to the file. Never invent a new English “key” string. - Preserve placeholders exactly. If the UI shows
Hello, %(username)sor similar, your translation must include the same placeholders (same names, same%(name)s-style segments). Same for%s,%d, or other format tokens. - Plurals: Some strings have one vs many forms. If you are unsure, describe the case in Notes and a maintainer will set
msgstr[0]/msgstr[1]correctly in the.pofile. - Context matters. Say which page, button, or dialog the text appears on, and attach a screenshot if possible. One English phrase can appear in multiple places with different meanings.
- Length and tone: Short labels (buttons, nav) should stay compact. Full sentences can be more natural in your language than literal word-for-word English.
Supported locale codes (see app/config.py LANGUAGES): en, nl, de, fr, it, fi, es, no, ar, he.
Maintainer workflow
Designate at least one person responsible for translation intake (issues, spreadsheet, or platform export).
Applying contributor suggestions
- Identify the locale file:
translations/<locale>/LC_MESSAGES/messages.po. - Find the entry (by
msgid/ English source or grep for the currentmsgstr). - Update
msgstr(and pluralmsgstr[n]if needed). Remove#, fuzzyif you are sure the translation is correct (fuzzy entries may be ignored at compile time depending on setup). - Restart the app or trigger your usual deploy so
.mois regenerated (see TRANSLATION_SYSTEM.md — compilation runs on startup viaapp/utils/i18n.py).
After new UI strings ship in code
When developers add or change translatable strings:
pybabel extract -F babel.cfg -o messages.pot .
pybabel update -i messages.pot -d translations
Then fill new empty entries in each messages.po, run the app, and smoke-test critical screens in a few locales.
Verification checklist
- Placeholders in
msgstrmatch themsgid/ source string. .pofile is valid UTF-8 and parses (Poedit ormsgfmt --check).- UI checked in the target language for overflow or clipping on small screens (especially for short buttons).
See also
- Technical overview: TRANSLATION_SYSTEM.md