🌐 Multi-language support: Danish, Swedish, Norwegian, German, French and Spanish (#22)

* :globe_with_meridians: Add multi-language support (da, sv, no, de, fr, es) Localises the site into Danish, Swedish, Norwegian, German, French and Spanish alongside English, using Rails' own i18n rather than a gem. URLs English keeps its existing unprefixed paths, so no URL moves and no redirects are needed. The other languages are served from a `/da/...` prefix via `scope "(:locale)"`. Admin, the API and sitemaps opt out. Locale resolution URL > signed-in user's profile > cookie > Accept-Language > English. The URL always wins so a shared or crawled link renders the language it was shared in. Visitors who prefer another language are redirected once from an unprefixed path, keeping one canonical URL per language. Routes without a `(:locale)` segment never redirect. This matters for the OmniAuth callbacks, which live on fixed paths: redirecting them discards the auth hash and breaks sign-in. SEO `<html lang>`, canonical, hreflang for all seven languages plus x-default, og:locale and its alternates, and translated titles and descriptions. The sitemap emits per-entry alternates rather than duplicating rows per language. Language selector Footer dropdown reusing the existing dropdown controller. Saves to the user's profile when signed in and to a cookie otherwise. Language is also editable on the profile form. Content Navigation, forms, flash messages, emails and meta tags, plus the home, search, about, press, help, FAQ and MobilePay pages. Emails render in the recipient's saved language, including their links. Region names and descriptions are translatable per locale from the admin. Terms and privacy stay English-only for now and reach other locales through the fallback; they are keyed and ready for a reviewed translation. Fixes found along the way - charities#show declared format.rss with no template, so the request 500'd. Added the feed. - `xml.language I18n.locale` passed a Symbol, which Builder reads as a namespace prefix and emitted `<language:en/>`. - FAQ answers moved into locale data still contained ERB, which rendered as literal text. Links now use placeholders resolved in a helper so they stay locale-correct. Query efficiency Fixed N+1s on donation cards (donor avatars, charity logos, regions), charity logos on the home/MobilePay/country/region pages, comment authors, leaderboard donors, and notifications in both the navbar and the notifications page. The sitemap no longer loads each user's donations separately. Covered by tests that fail if the count grows with the number of records. Adds one gem, rails-i18n, for Rails' own date, number and validation strings in the new languages. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * :green_heart: Fix CI: trailing newline and HTTP verb confusion Both failures predate this branch and reproduce on develop, but they make the build red, so they are fixed here. Rubocop flagged a trailing blank line in admin/users_controller_test.rb. Autocorrected; the file is otherwise untouched. Brakeman flagged `request.get?` in Authentication#store_location: HEAD is routed like GET, so a HEAD request skipped storing the return path. It now treats the two alike. The locale redirect had the same divergence, without being flagged. A crawler checking an unprefixed URL with HEAD would have seen a different answer than the GET that followed, so it redirects on HEAD as well. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> :arrow_up: Update version

Peter Theill
Deployed by Peter Theill
959 total
3 this month
3 this month
Back to feed