diff options
| author | erdgeist <erdgeist@erdgeist.org> | 2026-07-13 16:36:38 +0200 |
|---|---|---|
| committer | erdgeist <erdgeist@erdgeist.org> | 2026-07-13 16:36:38 +0200 |
| commit | 0b6ae26f3b4c3c8278e569fa6644a544e996c25d (patch) | |
| tree | 6c0e8dd23fa243e6bf7e6473aebae3f13ea20dea /app/models | |
| parent | e2705119ba718d40ff4f29c00027c2dfecef01ce (diff) | |
Add per-node translation management: list, edit, destroy, compare
Replaces the old locale-switch-and-edit-the-same-screen workflow,
which conflated presentation locale with content locale and let an
editor silently drift into editing the wrong language with no
persistent signal that anything had changed. Non-default-locale
content now has its own explicit routes and screens, never sharing
a route param with the ambient chrome locale.
- PageTranslationsController: index/show/edit/update/destroy,
scoped to Page.non_default_locales; update handles first-time
creation too, so there's no separate new/create step.
- Reads go through the actual PageTranslation row
(Page#translation_summary), never through the Globalize
fallback-bearing accessor -- fallback is correct for public
rendering but wrong for editing, where a missing translation
needs to look empty, not borrowed from another locale.
- Translations ride on the page's own draft/head cycle; no
independent publish state.
- nodes#show gains a Translations section (per-locale Lock+Edit /
Create+Lock, Destroy, a link into the read-only Compare view) and
a locale indicator on its own default-locale content; nodes#edit,
nodes#update, and nodes#autosave are pinned to the default locale
via Globalize.with_locale regardless of the ambient route locale.
- nodes#show no longer double-loads the node or calls wipe_draft!
on every view (see previous commit for why that's now safe).
- .preview_link_row is renamed .aligned_action_row now that it has
a second real consumer.
Diffstat (limited to 'app/models')
| -rw-r--r-- | app/models/page.rb | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/app/models/page.rb b/app/models/page.rb index db5b688..f796228 100644 --- a/app/models/page.rb +++ b/app/models/page.rb | |||
| @@ -87,6 +87,27 @@ class Page < ApplicationRecord | |||
| 87 | end | 87 | end |
| 88 | end | 88 | end |
| 89 | 89 | ||
| 90 | def self.non_default_locales | ||
| 91 | I18n.available_locales - [:root, I18n.default_locale] | ||
| 92 | end | ||
| 93 | |||
| 94 | # One row per non-default locale, read from the actual translation | ||
| 95 | # row -- never through the locale-dependent accessor, so a locale | ||
| 96 | # with no real translation yet reports as absent rather than quietly | ||
| 97 | # showing a fallback value borrowed from another locale. | ||
| 98 | def translation_summary | ||
| 99 | Page.non_default_locales.map do |locale| | ||
| 100 | translation = translations.find_by(:locale => locale) | ||
| 101 | { | ||
| 102 | :locale => locale, | ||
| 103 | :exists => translation.present?, | ||
| 104 | :title => translation&.title, | ||
| 105 | :updated_at => translation&.updated_at, | ||
| 106 | :outdated => translation.present? && outdated_translations?(:locale => locale) | ||
| 107 | } | ||
| 108 | end | ||
| 109 | end | ||
| 110 | |||
| 90 | def self.untranslated(options = {:locale => :de}) | 111 | def self.untranslated(options = {:locale => :de}) |
| 91 | PageTranslation.all.group_by(&:page_id).select do |k,v| | 112 | PageTranslation.all.group_by(&:page_id).select do |k,v| |
| 92 | v.size == 1 && v.map{|x| x.locale}.include?(options[:locale]) | 113 | v.size == 1 && v.map{|x| x.locale}.include?(options[:locale]) |
