internationalize 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +24 -1
- data/README.md +28 -8
- data/context/configuration.md +3 -20
- data/context/getting-started.md +1 -0
- data/context/model-api.md +34 -18
- data/lib/internationalize/model.rb +31 -33
- data/lib/internationalize/rich_text.rb +73 -0
- data/lib/internationalize/version.rb +1 -1
- data/lib/internationalize.rb +1 -11
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 25678f8238179260f1496807a1a68a20d86e09e72e7d7c4097c4b14f41b060ec
|
|
4
|
+
data.tar.gz: b713e70a91f521041975b86e6e22be2239ebfddbd3c9867691c55ecf8fbfb380
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 433cc8be47c2df3d5e48abf8eaa6cd0550cbe4ceaaf3fde9700ad08c82be24488eb5b7a52d8ec4b6555880119d8c961a451841ddeed9a52d2a455792ae5eb69d
|
|
7
|
+
data.tar.gz: e6656a5c811920e9e4b4b2184ee5b981496296f3588182d3ce2f53e6bcb9328b0051c210830c01d2eb23a9fea5fe3151181a5adb7d08c5222eac08a67c2661ac
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,29 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.2.0] - 2024-11-29
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- ActionText support via `international_rich_text` (optional, requires ActionText)
|
|
15
|
+
- Generates `has_rich_text` for each locale with unified accessor
|
|
16
|
+
- Full attachment support per locale
|
|
17
|
+
- Validation for `title_translations=` setter - rejects non-Hash values and invalid locales
|
|
18
|
+
|
|
19
|
+
### Removed
|
|
20
|
+
|
|
21
|
+
- `fallback: false` option - translations now always fallback to default locale
|
|
22
|
+
- `set_translation(attr, locale, value)` - use `title_de = "value"` instead
|
|
23
|
+
- `translation_for(attr, locale)` - use `title_de` instead
|
|
24
|
+
|
|
25
|
+
## [0.1.1] - 2024-11-29
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
|
|
29
|
+
- Include `context/` directory in gem for `bake agent:context:install` support
|
|
30
|
+
|
|
8
31
|
## [0.1.0] - 2024-11-29
|
|
9
32
|
|
|
10
33
|
### Added
|
|
@@ -28,7 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
28
51
|
- `translation_for(attr, locale)`
|
|
29
52
|
- `translated?(attr, locale)`
|
|
30
53
|
- `translated_locales(attr)`
|
|
31
|
-
- Fallback to default locale when translation missing
|
|
54
|
+
- Fallback to default locale when translation missing
|
|
32
55
|
- SQLite adapter using `json_extract()`
|
|
33
56
|
- PostgreSQL adapter using `->>` operator
|
|
34
57
|
- MySQL 8+ adapter using `->>` operator (supports mysql2 and trilogy gems)
|
data/README.md
CHANGED
|
@@ -4,10 +4,14 @@ Lightweight, performant internationalization for Rails with JSON column storage.
|
|
|
4
4
|
|
|
5
5
|
## Why Internationalize?
|
|
6
6
|
|
|
7
|
+
Internationalize is a focused, lightweight gem that does one thing well: JSON column translations. No backend abstraction layers, no plugin systems, no extra memory overhead.
|
|
8
|
+
|
|
7
9
|
Unlike Globalize or Mobility which use separate translation tables requiring JOINs, Internationalize stores translations inline using JSON columns. This means:
|
|
8
10
|
|
|
9
11
|
- **No JOINs** - translations live in the same table
|
|
10
12
|
- **No N+1 queries** - data is always loaded with the record
|
|
13
|
+
- **No backend overhead** - direct JSON column access, no abstraction layers
|
|
14
|
+
- **~50% less memory** - no per-instance backend objects or plugin chains
|
|
11
15
|
- **Direct method dispatch** - no `method_missing` overhead
|
|
12
16
|
- **Multi-database support** - works with SQLite, PostgreSQL, and MySQL
|
|
13
17
|
- **Visible in schema.rb** - translated fields appear directly in your model's schema
|
|
@@ -155,10 +159,6 @@ article.translated?(:title, :de) # => true/false
|
|
|
155
159
|
|
|
156
160
|
# Get all translated locales for an attribute
|
|
157
161
|
article.translated_locales(:title) # => [:en, :de]
|
|
158
|
-
|
|
159
|
-
# Set/get translation for specific locale
|
|
160
|
-
article.set_translation(:title, :de, "Hallo Welt")
|
|
161
|
-
article.translation_for(:title, :de) # => "Hallo Welt"
|
|
162
162
|
```
|
|
163
163
|
|
|
164
164
|
### Fallbacks
|
|
@@ -173,10 +173,29 @@ I18n.locale = :de
|
|
|
173
173
|
article.title # => "Hello" (falls back to :en)
|
|
174
174
|
```
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
### ActionText Support
|
|
177
|
+
|
|
178
|
+
For rich text with attachments, use `international_rich_text` (requires ActionText):
|
|
177
179
|
|
|
178
180
|
```ruby
|
|
179
|
-
|
|
181
|
+
require "internationalize/rich_text"
|
|
182
|
+
|
|
183
|
+
class Article < ApplicationRecord
|
|
184
|
+
include Internationalize::Model
|
|
185
|
+
include Internationalize::RichText
|
|
186
|
+
|
|
187
|
+
international_rich_text :content
|
|
188
|
+
end
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
This generates `has_rich_text :content_en`, `has_rich_text :content_de`, etc. for each locale, with a unified accessor:
|
|
192
|
+
|
|
193
|
+
```ruby
|
|
194
|
+
article.content = "<p>Hello</p>" # Sets for current locale
|
|
195
|
+
article.content # Gets for current locale (with fallback)
|
|
196
|
+
article.content_en # Direct access to English
|
|
197
|
+
article.content.body # ActionText::Content object
|
|
198
|
+
article.content.embeds # Attachments work per-locale
|
|
180
199
|
```
|
|
181
200
|
|
|
182
201
|
## Configuration
|
|
@@ -184,11 +203,12 @@ international :title, fallback: false
|
|
|
184
203
|
```ruby
|
|
185
204
|
# config/initializers/internationalize.rb
|
|
186
205
|
Internationalize.configure do |config|
|
|
187
|
-
config.
|
|
188
|
-
config.available_locales = [:en, :de, :fr]
|
|
206
|
+
config.available_locales = [:en, :de, :fr] # Defaults to I18n.available_locales
|
|
189
207
|
end
|
|
190
208
|
```
|
|
191
209
|
|
|
210
|
+
Fallback uses `I18n.default_locale` automatically.
|
|
211
|
+
|
|
192
212
|
## Performance Comparison
|
|
193
213
|
|
|
194
214
|
Benchmark with 1000 records, 2 translated attributes (title + body), 3 locales:
|
data/context/configuration.md
CHANGED
|
@@ -5,27 +5,12 @@
|
|
|
5
5
|
```ruby
|
|
6
6
|
# config/initializers/internationalize.rb
|
|
7
7
|
Internationalize.configure do |config|
|
|
8
|
-
# Override fallback locale (defaults to I18n.default_locale)
|
|
9
|
-
config.fallback_locale = :en
|
|
10
|
-
|
|
11
8
|
# Override available locales (defaults to I18n.available_locales)
|
|
12
9
|
config.available_locales = [:en, :de, :fr, :es]
|
|
13
10
|
end
|
|
14
11
|
```
|
|
15
12
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
```ruby
|
|
19
|
-
class Article < ApplicationRecord
|
|
20
|
-
include Internationalize::Model
|
|
21
|
-
|
|
22
|
-
# With fallback (default)
|
|
23
|
-
international :title
|
|
24
|
-
|
|
25
|
-
# Without fallback
|
|
26
|
-
international :description, fallback: false
|
|
27
|
-
end
|
|
28
|
-
```
|
|
13
|
+
Fallback locale is always `I18n.default_locale`.
|
|
29
14
|
|
|
30
15
|
## Database Setup
|
|
31
16
|
|
|
@@ -72,12 +57,10 @@ end
|
|
|
72
57
|
|
|
73
58
|
## I18n Integration
|
|
74
59
|
|
|
75
|
-
Internationalize
|
|
60
|
+
Internationalize uses Rails I18n settings directly:
|
|
76
61
|
|
|
77
62
|
```ruby
|
|
78
63
|
I18n.locale # Used for current locale
|
|
79
64
|
I18n.default_locale # Used for fallbacks
|
|
80
|
-
I18n.available_locales # Used for locale-specific accessors
|
|
65
|
+
I18n.available_locales # Used for locale-specific accessors (can be overridden)
|
|
81
66
|
```
|
|
82
|
-
|
|
83
|
-
Override these with the configuration options above if needed.
|
data/context/getting-started.md
CHANGED
|
@@ -86,6 +86,7 @@ Article.international_order(:title, :desc)
|
|
|
86
86
|
- No JOINs - data lives in the same table
|
|
87
87
|
- Automatic fallback to default locale
|
|
88
88
|
- Works with SQLite, PostgreSQL, and MySQL
|
|
89
|
+
- ActionText support via `international_rich_text` (see Model API)
|
|
89
90
|
|
|
90
91
|
## Important: Column Defaults
|
|
91
92
|
|
data/context/model-api.md
CHANGED
|
@@ -9,16 +9,6 @@ class Article < ApplicationRecord
|
|
|
9
9
|
end
|
|
10
10
|
```
|
|
11
11
|
|
|
12
|
-
## Options
|
|
13
|
-
|
|
14
|
-
```ruby
|
|
15
|
-
# With fallback (default: true)
|
|
16
|
-
international :title, fallback: true
|
|
17
|
-
|
|
18
|
-
# Without fallback - returns nil if translation missing
|
|
19
|
-
international :title, fallback: false
|
|
20
|
-
```
|
|
21
|
-
|
|
22
12
|
## Generated Instance Methods
|
|
23
13
|
|
|
24
14
|
For each `international :title` declaration:
|
|
@@ -31,7 +21,7 @@ For each `international :title` declaration:
|
|
|
31
21
|
| `title=` | Set translation for current `I18n.locale` |
|
|
32
22
|
| `title?` | Check if translation exists |
|
|
33
23
|
| `title_translations` | Get raw hash of all translations |
|
|
34
|
-
| `title_translations=` | Set all translations at once |
|
|
24
|
+
| `title_translations=` | Set all translations at once (validates locale keys) |
|
|
35
25
|
|
|
36
26
|
### Locale-Specific Accessors
|
|
37
27
|
|
|
@@ -50,8 +40,6 @@ For each locale in `I18n.available_locales`:
|
|
|
50
40
|
|
|
51
41
|
| Method | Description |
|
|
52
42
|
|--------|-------------|
|
|
53
|
-
| `set_translation(:title, :de, "Hallo")` | Set translation for attribute/locale |
|
|
54
|
-
| `translation_for(:title, :de)` | Get translation without fallback |
|
|
55
43
|
| `translated?(:title, :de)` | Check if translation exists |
|
|
56
44
|
| `translated_locales(:title)` | Array of locales with translations |
|
|
57
45
|
|
|
@@ -84,7 +72,7 @@ Article.international_attributes # => [:title, :description]
|
|
|
84
72
|
|
|
85
73
|
## Fallback Behavior
|
|
86
74
|
|
|
87
|
-
|
|
75
|
+
Translations automatically fall back to the default locale when missing:
|
|
88
76
|
|
|
89
77
|
```ruby
|
|
90
78
|
article.title_en = "Hello"
|
|
@@ -92,10 +80,38 @@ I18n.locale = :de
|
|
|
92
80
|
article.title # => "Hello" (falls back to default locale)
|
|
93
81
|
```
|
|
94
82
|
|
|
95
|
-
|
|
83
|
+
## ActionText Support
|
|
84
|
+
|
|
85
|
+
For rich text with attachments, use `international_rich_text` (requires ActionText):
|
|
96
86
|
|
|
97
87
|
```ruby
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
88
|
+
require "internationalize/rich_text"
|
|
89
|
+
|
|
90
|
+
class Article < ApplicationRecord
|
|
91
|
+
include Internationalize::Model
|
|
92
|
+
include Internationalize::RichText
|
|
93
|
+
|
|
94
|
+
international_rich_text :content
|
|
95
|
+
end
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
This generates `has_rich_text :content_en`, `has_rich_text :content_de`, etc. for each locale.
|
|
99
|
+
|
|
100
|
+
### Generated Methods
|
|
101
|
+
|
|
102
|
+
| Method | Description |
|
|
103
|
+
|--------|-------------|
|
|
104
|
+
| `content` | Get rich text for current locale (with fallback) |
|
|
105
|
+
| `content=` | Set rich text for current locale |
|
|
106
|
+
| `content?` | Check if rich text exists |
|
|
107
|
+
| `content_en` | Direct access to English rich text |
|
|
108
|
+
| `content_de` | Direct access to German rich text |
|
|
109
|
+
| `content_translated?(:de)` | Check if translation exists |
|
|
110
|
+
| `content_translated_locales` | Array of locales with content |
|
|
111
|
+
|
|
112
|
+
```ruby
|
|
113
|
+
article.content = "<p>Hello</p>" # Sets for current locale
|
|
114
|
+
article.content # Gets for current locale (with fallback)
|
|
115
|
+
article.content.body # ActionText::Content object
|
|
116
|
+
article.content.embeds # Attachments work per-locale
|
|
101
117
|
```
|
|
@@ -28,7 +28,6 @@ module Internationalize
|
|
|
28
28
|
#
|
|
29
29
|
# When called with Symbol arguments, declares attributes as internationalized:
|
|
30
30
|
# international :title, :description
|
|
31
|
-
# international :title, fallback: false
|
|
32
31
|
#
|
|
33
32
|
# When called with keyword arguments, queries translated attributes:
|
|
34
33
|
# Article.international(title: "Hello") # exact match
|
|
@@ -37,16 +36,15 @@ module Internationalize
|
|
|
37
36
|
# Article.international(title: "Hello", match: :partial, case_sensitive: true)
|
|
38
37
|
#
|
|
39
38
|
# @param attributes [Array<Symbol>] attributes to declare as internationalized
|
|
40
|
-
# @param fallback [Boolean] whether to fallback to default locale (default: true)
|
|
41
39
|
# @param locale [Symbol] locale to query (default: current locale)
|
|
42
40
|
# @param match [Symbol] :exact or :partial (default: :exact)
|
|
43
41
|
# @param case_sensitive [Boolean] for partial matching only (default: false)
|
|
44
42
|
# @param conditions [Hash] attribute => value pairs to query
|
|
45
43
|
#
|
|
46
|
-
def international(*attributes,
|
|
44
|
+
def international(*attributes, locale: nil, match: :exact, case_sensitive: false, **conditions)
|
|
47
45
|
if attributes.any? && attributes.first.is_a?(Symbol) && conditions.empty?
|
|
48
46
|
# Declaration mode: international :title, :description
|
|
49
|
-
declare_international_attributes(attributes
|
|
47
|
+
declare_international_attributes(attributes)
|
|
50
48
|
else
|
|
51
49
|
# Query mode: Article.international(title: "Hello")
|
|
52
50
|
international_query(conditions, locale: locale, match: match, case_sensitive: case_sensitive)
|
|
@@ -71,7 +69,7 @@ module Internationalize
|
|
|
71
69
|
"Use standard ActiveRecord methods for non-translated attributes."
|
|
72
70
|
end
|
|
73
71
|
|
|
74
|
-
locale ||=
|
|
72
|
+
locale ||= I18n.locale
|
|
75
73
|
direction = direction.to_s.upcase
|
|
76
74
|
direction = "ASC" unless VALID_DIRECTIONS.include?(direction)
|
|
77
75
|
|
|
@@ -91,7 +89,7 @@ module Internationalize
|
|
|
91
89
|
# Article.translated(:title, :description, locale: :de)
|
|
92
90
|
#
|
|
93
91
|
def translated(*attributes, locale: nil)
|
|
94
|
-
locale ||=
|
|
92
|
+
locale ||= I18n.locale
|
|
95
93
|
adapter = Adapters.resolve(connection)
|
|
96
94
|
scope = all
|
|
97
95
|
|
|
@@ -117,7 +115,7 @@ module Internationalize
|
|
|
117
115
|
# Article.untranslated(:title, locale: :de)
|
|
118
116
|
#
|
|
119
117
|
def untranslated(*attributes, locale: nil)
|
|
120
|
-
locale ||=
|
|
118
|
+
locale ||= I18n.locale
|
|
121
119
|
adapter = Adapters.resolve(connection)
|
|
122
120
|
scope = all
|
|
123
121
|
|
|
@@ -143,7 +141,7 @@ module Internationalize
|
|
|
143
141
|
# Article.international_not(title: "Entwurf", locale: :de)
|
|
144
142
|
#
|
|
145
143
|
def international_not(locale: nil, **conditions)
|
|
146
|
-
locale ||=
|
|
144
|
+
locale ||= I18n.locale
|
|
147
145
|
adapter = Adapters.resolve(connection)
|
|
148
146
|
scope = all
|
|
149
147
|
|
|
@@ -233,12 +231,12 @@ module Internationalize
|
|
|
233
231
|
end
|
|
234
232
|
|
|
235
233
|
# Declares attributes as internationalized
|
|
236
|
-
def declare_international_attributes(attributes
|
|
234
|
+
def declare_international_attributes(attributes)
|
|
237
235
|
self.international_attributes = international_attributes | attributes.map(&:to_sym)
|
|
238
236
|
|
|
239
237
|
attributes.each do |attr|
|
|
240
238
|
warn_if_missing_default(attr)
|
|
241
|
-
define_translation_accessors(attr
|
|
239
|
+
define_translation_accessors(attr)
|
|
242
240
|
define_locale_accessors(attr)
|
|
243
241
|
end
|
|
244
242
|
end
|
|
@@ -258,7 +256,7 @@ module Internationalize
|
|
|
258
256
|
|
|
259
257
|
# Query translated attributes with exact or partial matching
|
|
260
258
|
def international_query(conditions, locale:, match:, case_sensitive:)
|
|
261
|
-
locale ||=
|
|
259
|
+
locale ||= I18n.locale
|
|
262
260
|
adapter = Adapters.resolve(connection)
|
|
263
261
|
scope = all
|
|
264
262
|
|
|
@@ -288,20 +286,19 @@ module Internationalize
|
|
|
288
286
|
end
|
|
289
287
|
|
|
290
288
|
# Defines the main getter/setter for an attribute
|
|
291
|
-
def define_translation_accessors(attr
|
|
289
|
+
def define_translation_accessors(attr)
|
|
292
290
|
translations_column = "#{attr}_translations"
|
|
293
291
|
|
|
294
|
-
# Main getter - returns translation for current locale
|
|
295
|
-
|
|
296
|
-
default_locale_str = fallback ? Internationalize.default_locale.to_s : nil
|
|
292
|
+
# Main getter - returns translation for current locale with fallback to default locale
|
|
293
|
+
default_locale_str = I18n.default_locale.to_s
|
|
297
294
|
|
|
298
295
|
define_method(attr) do |locale = nil|
|
|
299
296
|
locale_str = (locale || I18n.locale).to_s
|
|
300
297
|
translations = read_attribute(translations_column)
|
|
301
298
|
value = translations[locale_str]
|
|
302
299
|
|
|
303
|
-
# Short-circuit: return early if value exists or
|
|
304
|
-
return value if !
|
|
300
|
+
# Short-circuit: return early if value exists or already querying default locale
|
|
301
|
+
return value if !value.nil? || locale_str == default_locale_str
|
|
305
302
|
|
|
306
303
|
translations[default_locale_str]
|
|
307
304
|
end
|
|
@@ -327,7 +324,21 @@ module Internationalize
|
|
|
327
324
|
|
|
328
325
|
# Set all translations at once
|
|
329
326
|
define_method("#{attr}_translations=") do |hash|
|
|
330
|
-
write_attribute(translations_column,
|
|
327
|
+
return write_attribute(translations_column, {}) if hash.nil?
|
|
328
|
+
|
|
329
|
+
unless hash.is_a?(Hash)
|
|
330
|
+
raise ArgumentError, "#{attr}_translations must be a Hash, got #{hash.class}"
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
allowed_locales = Internationalize.locales.map(&:to_s)
|
|
334
|
+
hash.each_key do |key|
|
|
335
|
+
unless allowed_locales.include?(key.to_s)
|
|
336
|
+
raise ArgumentError, "Invalid locale '#{key}' for #{attr}_translations. " \
|
|
337
|
+
"Allowed locales: #{allowed_locales.join(', ')}"
|
|
338
|
+
end
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
write_attribute(translations_column, hash.stringify_keys)
|
|
331
342
|
end
|
|
332
343
|
end
|
|
333
344
|
|
|
@@ -362,23 +373,10 @@ module Internationalize
|
|
|
362
373
|
|
|
363
374
|
# Instance methods
|
|
364
375
|
|
|
365
|
-
# Set translation for a specific locale
|
|
366
|
-
def set_translation(attr, locale, value)
|
|
367
|
-
column = "#{attr}_translations"
|
|
368
|
-
translations = read_attribute(column)
|
|
369
|
-
translations[locale.to_s] = value
|
|
370
|
-
write_attribute(column, translations)
|
|
371
|
-
end
|
|
372
|
-
|
|
373
|
-
# Get translation for a specific locale without fallback
|
|
374
|
-
def translation_for(attr, locale)
|
|
375
|
-
translations = read_attribute("#{attr}_translations")
|
|
376
|
-
translations[locale.to_s]
|
|
377
|
-
end
|
|
378
|
-
|
|
379
376
|
# Check if a translation exists for a specific locale
|
|
380
377
|
def translated?(attr, locale)
|
|
381
|
-
|
|
378
|
+
translations = read_attribute("#{attr}_translations")
|
|
379
|
+
translations[locale.to_s].present?
|
|
382
380
|
end
|
|
383
381
|
|
|
384
382
|
# Returns all locales that have a translation for an attribute
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Internationalize
|
|
4
|
+
# Adds internationalization support for ActionText rich text attributes
|
|
5
|
+
#
|
|
6
|
+
# @example
|
|
7
|
+
# class Article < ApplicationRecord
|
|
8
|
+
# include Internationalize::Model
|
|
9
|
+
# include Internationalize::RichText
|
|
10
|
+
# international_rich_text :content
|
|
11
|
+
# end
|
|
12
|
+
#
|
|
13
|
+
# article.content = "<p>Hello</p>" # Sets for current locale
|
|
14
|
+
# article.content # Gets for current locale (with fallback)
|
|
15
|
+
# article.content_de # Direct access to German content
|
|
16
|
+
#
|
|
17
|
+
module RichText
|
|
18
|
+
extend ActiveSupport::Concern
|
|
19
|
+
|
|
20
|
+
class_methods do
|
|
21
|
+
# Declares a rich text attribute as internationalized
|
|
22
|
+
#
|
|
23
|
+
# Creates a has_rich_text association for each available locale and
|
|
24
|
+
# provides locale-aware accessors.
|
|
25
|
+
#
|
|
26
|
+
# @param name [Symbol] the attribute name
|
|
27
|
+
#
|
|
28
|
+
def international_rich_text(name)
|
|
29
|
+
# Generate has_rich_text for each locale
|
|
30
|
+
Internationalize.locales.each do |locale|
|
|
31
|
+
rich_text_name = :"#{name}_#{locale}"
|
|
32
|
+
has_rich_text(rich_text_name)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
default_locale_str = I18n.default_locale.to_s
|
|
36
|
+
|
|
37
|
+
# Main getter - returns rich text for current locale with fallback to default locale
|
|
38
|
+
define_method(name) do
|
|
39
|
+
locale_str = I18n.locale.to_s
|
|
40
|
+
rich_text = send(:"#{name}_#{locale_str}")
|
|
41
|
+
|
|
42
|
+
if rich_text.blank? && locale_str != default_locale_str
|
|
43
|
+
send(:"#{name}_#{default_locale_str}")
|
|
44
|
+
else
|
|
45
|
+
rich_text
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Main setter - sets rich text for current locale
|
|
50
|
+
define_method(:"#{name}=") do |value|
|
|
51
|
+
send(:"#{name}_#{I18n.locale}=", value)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Predicate method
|
|
55
|
+
define_method(:"#{name}?") do
|
|
56
|
+
send(name).present?
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Check if translation exists for a specific locale
|
|
60
|
+
define_method(:"#{name}_translated?") do |locale|
|
|
61
|
+
send(:"#{name}_#{locale}").present?
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Get all locales that have this rich text
|
|
65
|
+
define_method(:"#{name}_translated_locales") do
|
|
66
|
+
Internationalize.locales.select do |locale|
|
|
67
|
+
send(:"#{name}_#{locale}").present?
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
data/lib/internationalize.rb
CHANGED
|
@@ -10,22 +10,12 @@ require_relative "internationalize/model"
|
|
|
10
10
|
module Internationalize
|
|
11
11
|
class << self
|
|
12
12
|
# Configuration
|
|
13
|
-
attr_accessor :
|
|
13
|
+
attr_accessor :available_locales
|
|
14
14
|
|
|
15
15
|
def configure
|
|
16
16
|
yield self
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
# Returns the current locale, defaulting to I18n.locale
|
|
20
|
-
def locale
|
|
21
|
-
I18n.locale
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# Returns the default locale for fallbacks
|
|
25
|
-
def default_locale
|
|
26
|
-
fallback_locale || I18n.default_locale
|
|
27
|
-
end
|
|
28
|
-
|
|
29
19
|
# Returns available locales, defaulting to I18n.available_locales
|
|
30
20
|
def locales
|
|
31
21
|
available_locales || I18n.available_locales
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: internationalize
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sampo Kuokkanen
|
|
@@ -63,6 +63,7 @@ files:
|
|
|
63
63
|
- lib/internationalize/adapters/postgresql.rb
|
|
64
64
|
- lib/internationalize/adapters/sqlite.rb
|
|
65
65
|
- lib/internationalize/model.rb
|
|
66
|
+
- lib/internationalize/rich_text.rb
|
|
66
67
|
- lib/internationalize/version.rb
|
|
67
68
|
homepage: https://github.com/sampokuokkanen/internationalize
|
|
68
69
|
licenses:
|