There currently exists no gem which adds model translations to ActiveRecord models while supporting Rails 7’s Active Record Encryption :
Work on Globalize has stopped, and
The maintainer of the more recent Mobility does not wish to go as deep as it would be required for this feature.
Given that I18n is only becoming more important as the world is becoming a village, do you agree that it makes sense to integrate model translations into Rails?
sdubois
(Sébastien Dubois)
May 17, 2022, 9:04am
#2
do you agree that it makes sense to integrate model translations into Rails?
It is already possible to translate models using Mobility, or maybe I misunderstood the question? Is the question about specifically translating encrypted attributes?
NB: I wrote the Mobility Action Text gem to translate rich text.
Hi Sébastien,
yes, sorry, slight misunderstanding:
The issue is that Mobility fails to work as soon as (Rails 7’s) encrypted attributes come into play. (And the maintainer does not intend to support Rails 7 on this level .)
sdubois
(Sébastien Dubois)
May 19, 2022, 8:11am
#4
Actually the maintainer wrote “this is not a bug but a feature request”. So if you provide a PR to Mobility with the feature, he could be willing to merge it; or alternately, it could be added as a gem, like I did for ActionText translations as suggested by the maintainer. And he was willing to support the feature by making the necessary adaptations to the API.
opened 08:26AM - 30 May 20 UTC
closed 06:20PM - 15 Jan 21 UTC
feature
active_record
I would like the `:key_value` backend to be configurable in order to support tra… nslating ActionText rich text.
## Context
It [appears](https://github.com/globalize/globalize/issues/753) Mobility is becoming the new "Rails I18n de-facto standard library for ActiveRecord model/data translation", to re-use Globalize's description 😉 I also guess that many apps, including my own bilingual content-centric app, use rich text rather than plain text, where ActionText is supposed to be the ad-hoc Rails solution. Additionally, Mobility describes itself as adapting to different storage needs. I would thus like Mobility and ActionText to work elegantly together.
## Expected Behavior
Being able to store and query translated ActionText rich text using a single table join using the existing Mobility API.
## Actual Behavior
I am not aware of a way to make ActionText and Mobility work together without requiring two levels of joining. [This example](https://github.com/rails/actiontext/issues/32#issuecomment-450653800) shows that translating ActionText can be done, however it requires two nested joins and fragile patches of code.
## Possible Fix
Similar to the `:key_value` backend, ActionText also works by establishing a polymorphic relation on the model. This raises an opportunity to translate ActionText rich text "for free", i.e. at no extra performance cost compared to untranslated rich text, by directly using the `action_text_rich_texts` table as a `:key_value` translation backend instead of the `mobility_text_translations` table.
Consider the Mobility and ActionText schemas, they already have a 1:1 mapping, except for the `locale` column: `key <=> name`, `value <=> body`, `translatable_id <=> record_id`, `translatable_type <=> record_type`:
<details>
```rb
create_table "mobility_text_translations", force: :cascade do |t|
t.string "locale"
t.string "key"
t.text "value"
t.integer "translatable_id"
t.string "translatable_type"
...
end
```
```rb
create_table "action_text_rich_texts", force: :cascade do |t|
t.string "name", null: false
t.text "body"
t.bigint "record_id", null: false
t.string "record_type", null: false
...
end
```
</details>
Whereas for the example above, ActionText would normally store:
```rb
{ record_type: 'Post', record_id: 1, name: 'content', body: '<h1>hello world!</h1>' }
```
... it would instead store:
```rb
{ record_type: 'Post', record_id: 1, name: 'content', locale: 'en', body: '<h1>hello world!</h1>' }
{ record_type: 'Post', record_id: 1, name: 'content', locale: 'fr', body: '<h1>bonjour le monde !</h1>' }
```
So if Mobility offered a way to configure the table name and columns for the `:key_value` backend, in theory everything should "just work" 🤞😄
Mobility could be instructed to achieve it with something like this:
```rb
Mobility.configure do |config|
config.default_backend = :key_value
config.backends.key_value.text.table = :action_text_rich_texts
config.backends.key_value.text.translatable = :record
config.backends.key_value.text.key = :name
config.backends.key_value.text.value = :text
end
```
Or with a shorthand:
```rb
Mobility.configure do |config|
config.default_backend = :key_value
config.key_value_text_backend = :action_text
end
```
The migration should be adapted to first check if the table exists, and if it exists, to insert the required columns/indices.
Then at the model level the following (existing) API should suffice:
```rb
# app/models/post.rb
class Post < ApplicationRecord
has_rich_text :content
translates :content
end
```
__________
@shioyama I understand that you do not have much bandwidth, but would you consider a PR? In that case I would be willing to give it a try with your guidance.
shioyama:master
← sedubois:keyvalue-config
opened 09:10AM - 30 Dec 20 UTC
In preparation for #385.
Also see #412.
(I have only basic web app developer skills, which means me attempting to produce a PR is unfortunately not something anybody in this community is going to want to see…)