Add Danish (da_DK) language support (#279)#283
Conversation
Adds Danish as a full, selectable language, from HansUwe52's translation. UI strings — locale/da_DK.json (6579 keys, exact parity + order with it_IT): - Repaired Uwe's file: 10 keys had their KEY text corrupted by his translation tool (e.g. "questo"→"este", stripped <style>, "(hk)"→"(hb)", altered markdown) — re-keyed to the canonical Italian, preserving the good Danish values. - Added the 8 keys missing from his file — including the 4 contributor-help strings he flagged (illustratore/traduttore/curatore/colorista, new in 0.7.40). - Restored inline <code>/<strong> markup and the <zip-release> placeholder that the machine translation had stripped from ~10 strings rendered raw in views. Fresh-install seed — installer/database/data_da_DK.sql (structural clone of data_it_IT.sql): 181 genres, 22 email templates (subjects + HTML bodies, placeholders/markup preserved), 2 CMS pages, home_content and settings prose in Danish; locale columns da_DK; languages row for da_DK. Installer.php requires a per-locale seed (it throws otherwise), so this is what lets a fresh Danish install work at all. Wiring: da_DK added to the installer language step (step0.php + normalizeInstaller Locale), the I18n available-locales fallback, and the languages INSERT in every data_*.sql; migrate_0.7.41.sql upserts the languages row on existing installs. locale/routes_da_DK.json added (RouteTranslator already falls back to English if absent). Emails fall back to en_US when a da_DK template is missing. Verified: da_DK.json↔it_IT key parity 6579/0/0, all inline tags restored, placeholders intact; routes parity (33); data_da_DK.sql structure matches data_it_IT per-table; php -l clean, PHPStan clean on the app change (I18n); REAL load test — schema + data_da_DK.sql into a fresh DB loads with zero errors, yielding 5 languages incl. da_DK, 22 Danish emails, 181 Danish genres.
|
Warning Review limit reached
Next review available in: 29 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (17)
📝 WalkthroughWalkthroughLa localizzazione danese ChangesLocalizzazione danese
Estimated code review effort: 3 (Moderate) | ~20 minuti Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@installer/database/data_da_DK.sql`:
- Around line 305-310: Update the privacy cookie-banner settings in the database
seed so cookie_banner_language uses “da” and cookie_banner_country uses “dk”,
matching the Danish installation configuration and avoiding Italian defaults.
- Around line 215-226: Update the Danish home_content seed entries for the hero
and cta sections to use the Danish routes defined in routes_da_DK.json: replace
the catalog link with /katalog and the registration link with /registrer,
leaving the remaining seeded content unchanged.
In `@installer/database/migrations/migrate_0.7.41.sql`:
- Around line 1-17: Align the migration version with the current release so it
is executed when upgrading to 0.7.40: rename migrate_0.7.41.sql to the 0.7.40
migration or update version.json to 0.7.41. Preserve the Danish language
registration and ensure the migration filename version remains less than or
equal to the release version.
In `@locale/da_DK.json`:
- Line 2120: Preserve the source HTML markup in the affected Danish translations
at the entries around the “Il codice verrà inserito…” key and the additional
affected entries. Restore each corresponding <style>, <a>, and <code> tag with
all attributes, while keeping the translated text, placeholders, and URLs
unchanged.
- Line 2314: Correggi le traduzioni danesi nelle voci di locale indicate: nella
voce con il messaggio sul prestito sostituisci il termine tedesco “Verfügbar”
con l’equivalente danese corretto; aggiorna inoltre la stringa alla riga 4105
correggendo l’errore grammaticale e sostituendo il testo corrotto
“analyseculies”, senza modificare le chiavi originali.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: e03dabef-4ddf-47b1-88d0-02fb32e70e36
📒 Files selected for processing (12)
app/Support/I18n.phpinstaller/database/data_da_DK.sqlinstaller/database/data_de_DE.sqlinstaller/database/data_en_US.sqlinstaller/database/data_fr_FR.sqlinstaller/database/data_it_IT.sqlinstaller/database/migrations/migrate_0.7.41.sqlinstaller/index.phpinstaller/steps/step0.phplocale/da_DK.jsonlocale/routes_da_DK.jsontests/full-test.spec.js
Selecting Danish in the install wizard produced an Italian catalogue: the UI localized correctly (step0/index + I18n already knew da_DK), but four locale maps in the backend Installer class — and two runtime maps in the app — still listed only it/en/de/fr, so da_DK silently fell through to it_IT. Found by running a real Danish install through the browser (the SQL-only load test couldn't catch it — the installer picks the seed file itself). Installer (installer/classes/Installer.php): - createEnvFile(): da/da_dk -> da_DK, and da_DK added to the fallback whitelist — otherwise .env is written APP_LOCALE=it_IT for a Danish install. - importInitialData(): da/da_dk -> da_DK in the seed-file map — this is the bug that loaded data_it_IT.sql (181 Italian genres + 22 it_IT emails) instead of data_da_DK.sql. Now seeds 181 Danish genres + 22 da_DK emails. - admin-user locale map: new admin row gets locale da_DK, so the admin lands on a Danish dashboard instead of reverting to Italian on first login (cf. #112). - getInstallerLocale(): da/da_dk -> da_DK. Runtime: - PrivateModeMiddleware::LOCALES: add da_DK so the Danish login/register route variants (registered dynamically in web.php from I18n::getAvailableLocales()) are recognized as public in private mode instead of being blocked. - Updater::isCustomLocalePath(): treat da_DK as a bundled locale, so future releases keep updating locale/da_DK.json instead of preserving it as a user-custom catalogue that never receives translation fixes. Verified with a full browser install on a disposable Apache vhost + fresh DB: Danish wizard end to end, .env APP_LOCALE=da_DK, 65 tables, 181 Danish genres ("Prosa"/"Poesi"/"Skønlitteratur"), 22 da_DK email templates ("👤 Ny registreringsanmodning"), public site and admin dashboard both Danish, admin login works, zero console errors.
Follow-up: fixed a real installer bug, found by installing Danish for realI ran the full Danish install through a browser (disposable Apache vhost + fresh DB), not just an SQL load test — and it surfaced a bug the SQL test structurally couldn't: selecting Danish produced an Italian catalogue. The wizard looked fully Danish (UI, steps, connection test), but four locale maps in
Plus two runtime maps the language branch hadn't touched:
Fixed in 3881535. Re-verified end to end on a fresh Danish install:
Takeaway for the next added language: it's not enough to add the locale files + the installer UI selector — every hardcoded |
…a_DK.php) de/en/fr each ship a mail_templates/<locale>.php that overrides the 22 email subjects+bodies over the in-code Italian base; da_DK had none, so any template not seeded in the DB fell back to Italian for Danish installs — concretely `user_registration_verification` (sent by NotificationService for the registration-verification email) would go out in Italian to Danish users. - app/Support/mail_templates/da_DK.php: 22 templates, exact key parity with en_US.php. 21 are generated from the Danish rows already seeded in data_da_DK.sql (so the override layer and the install seed stay identical); `user_registration_verification` — which lives only in the code base/override, not in the DB seed — is translated to Danish here. - SettingsMailTemplates::localeOverrides(): map da/da_DK -> da_DK so the file is actually loaded (it was previously unreachable).
Self-review — multi-lens passRan a structured review over the diff. The core wiring checks out: every installer locale map, Worth fixing before merge1. 🟠 Danish 2. 🟡 Migration/version coordination — 3. 🟡 Polish (low)4. 5. Stale comments that enumerate supported locales without Dismissed (checked, not issues)
|
… comments)
Follow-up to the multi-lens review of this PR.
- app/Support/mail_templates/da_DK.php + installer/database/data_da_DK.sql:
restore the loan_pickup_ready content the Danish translation had dropped —
the {{giorni_prestito}} loan-duration line and the amber "⏰ pickup deadline …
or the loan is automatically canceled" warning box that en_US/de_DE/fr_FR all
carry. Both the override file and the DB seed now match the sibling locales.
- app/Support/I18n.php: add fr_FR to the $availableLocales no-DB fallback map.
It listed it_IT/en_US/de_DE (and now da_DK) but omitted fr_FR, so in an
early-bootstrap / DB-unavailable state setLocale('fr_FR') returned false while
the other bundled locales worked. Pre-existing gap, fixed while touching the map.
- Refresh stale locale enumerations in comments to include da_DK: step0.php
(validation list + the multilingual language-select heading/description now
include a Danish line), installer/index.php, installer/classes/Installer.php.
Not addressed here (needs release coordination, not a code fix): migrate_0.7.41.sql
is named for 0.7.41 while version.json is still 0.7.40 — the release must be cut
at >= 0.7.41 (create-release.sh bumps version.json) or the migration is skipped
on upgrade per the migration-version rule.
…ntime The Code Quality workflow's migration-version guard failed because migrate_0.7.41.sql (0.7.41) was higher than version.json (0.7.40): the updater only runs migrations with version_compare(v, target, '<=') true, so as shipped the da_DK migration would be skipped on upgrade. This is the correct next release version for the Danish feature, so: - version.json 0.7.40 -> 0.7.41; README "What's New in v0.7.41" section. - tests/migration-0.7.41.unit.php: behavioural test that runs the REAL migration against a sandbox languages table and asserts da_DK is inserted with the canonical metadata, pre-existing locales are untouched, the upsert is idempotent on a second run, and a deactivated da_DK is re-activated. This also satisfies issue-237-regression's "release migration has a matching behavioural unit test" meta-check, which was the other latent CI failure waiting behind the version guard. - CI Node runtime: the deprecation warning flagged actions/checkout@v4 and actions/setup-node@v4 (Node 20 runtime, being retired). Bump ci-quality to actions/checkout@v6 + actions/setup-node@v5 + node 22, matching the versions codeql.yml/test-migrations.yml already use, and bump checkout@v4 -> v6 in ci-e2e.yml and ci-upgrade-smoke.yml. Verified locally against a real MySQL: migration guard passes, all tests/*.unit.php pass (incl. the new migration test + issue-237 32/32), route/tailwind/plugin-schema/autoloader static checks pass, PHPStan clean.
Closes #279. Adds Danish as a full, selectable language, built from @HansUwe52's translation file.
UI strings —
locale/da_DK.json(6579 keys, exact parity + order withit_IT)questo→este, stripped<style>,(hk)→(hb), altered markdown links) — re-keyed to the canonical Italian, keeping his good Danish values.<code>/<strong>markup and a<zip-release>placeholder that the machine translation had stripped from ~10 strings that are rendered raw in views (they'd have lost bold/code styling).Fresh-install seed —
installer/database/data_da_DK.sqlStructural clone of
data_it_IT.sql: 181 genres, 22 email templates (subjects + HTML bodies,{{placeholders}}/markup preserved), 2 CMS pages,home_contentand settings prose in Danish;localecolumns →da_DK; alanguagesrow forda_DK.Installer.phprequires a per-locale seed (it throws otherwise), so this is what makes a fresh Danish install work.Wiring
step0.php+normalizeInstallerLocale), theI18navailable-locales fallback, and thelanguagesINSERT in everydata_*.sql.migrate_0.7.41.sqlupserts theda_DKlanguages row on existing installs (Uwe just updates → Danish appears).locale/routes_da_DK.jsonadded (RouteTranslatoralready falls back to English if absent).en_USwhen ada_DKtemplate is missing.Verified
da_DK.json↔it_ITkey parity 6579 / 0 missing / 0 extra; all inline tags restored; placeholders intact.routes_da_DK.jsonparity (33 keys);data_da_DK.sqlstructure matchesdata_it_ITper table.php -lclean; PHPStan clean on the app change (I18n.php).schema.sql+data_da_DK.sqlinto a fresh DB loads with zero errors — 5 languages incl.da_DK, 22 Danish emails, 181 Danish genres.Built with a translate → assemble → verify workflow; the machine translation was reviewed and its tag-stripping defects fixed. The Danish prose would still benefit from @HansUwe52's native review, especially the 22 email templates and CMS pages.
Summary by CodeRabbit