internationalize 0.1.0 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0ba5df71bafb02b68108aed602ac75ad4ced036109e49dbd40dc90354a7c351a
4
- data.tar.gz: d39b4232e8b76511d1a409d6848fa98e8f60f8f9523b62985c467cb2767ec7e3
3
+ metadata.gz: 3f85c4969fc4c969bf8ad61c4cbdb76a5364c90b4c7853a446aaeb6a4ac629ff
4
+ data.tar.gz: 83c19c5597f26d23634cc37f3aaede5d7a58c62460c6a2cd5295a1d3e43c3017
5
5
  SHA512:
6
- metadata.gz: 8ff4adb5021405380a123cc1cc06b8dd3818851e32570ae90e7bdf776f566bbc9ff6504ab26960dae909109550444875aaca42d3cf988ae4393b18c05628e292
7
- data.tar.gz: 8d2643b882281a39f0446d274b25321be03909c2ba41510a75a4e498918fc0ee37a59abae42e373e246a4d1b1f1ebeefdb5ec9e12e29d8a81a13c3d05f9478a6
6
+ metadata.gz: 02037bac922bbd2e7a7ccf82399e5892436a32f02970c87365935745ebc2858b16b4befbf11b26a9e70e54833ae0347a3d45a8450c839a95d93111dc92109035
7
+ data.tar.gz: 7dced1dca63327c7e66c527be390ac39bff028615f10696094b545514573000a52962fdbd807a77e7bb823b4c6151c56284b075e18be37bbea36d4140e10450d
@@ -0,0 +1,83 @@
1
+ # Internationalize: Configuration
2
+
3
+ ## Global Configuration
4
+
5
+ ```ruby
6
+ # config/initializers/internationalize.rb
7
+ Internationalize.configure do |config|
8
+ # Override fallback locale (defaults to I18n.default_locale)
9
+ config.fallback_locale = :en
10
+
11
+ # Override available locales (defaults to I18n.available_locales)
12
+ config.available_locales = [:en, :de, :fr, :es]
13
+ end
14
+ ```
15
+
16
+ ## Per-Attribute Configuration
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
+ ```
29
+
30
+ ## Database Setup
31
+
32
+ Use the generator to create migrations:
33
+
34
+ ```bash
35
+ rails generate internationalize:translation Article title description
36
+ ```
37
+
38
+ Or create migrations manually:
39
+
40
+ ### SQLite / MySQL
41
+
42
+ ```ruby
43
+ class AddTranslationsToArticles < ActiveRecord::Migration[7.1]
44
+ def change
45
+ add_column :articles, :title_translations, :json, default: {}
46
+ end
47
+ end
48
+ ```
49
+
50
+ ### PostgreSQL
51
+
52
+ For better query performance, use `jsonb`:
53
+
54
+ ```ruby
55
+ class AddTranslationsToArticles < ActiveRecord::Migration[7.1]
56
+ def change
57
+ add_column :articles, :title_translations, :jsonb, default: {}
58
+
59
+ # Optional: Add GIN index for faster queries
60
+ add_index :articles, :title_translations, using: :gin
61
+ end
62
+ end
63
+ ```
64
+
65
+ ## Supported Databases
66
+
67
+ | Database | Minimum Version | JSON Type | Query Syntax |
68
+ |----------|-----------------|-----------|--------------|
69
+ | SQLite | 3.38+ | `json` | `json_extract()` |
70
+ | PostgreSQL | 9.4+ | `json`/`jsonb` | `->>` operator |
71
+ | MySQL | 8.0+ | `json` | `->>` operator |
72
+
73
+ ## I18n Integration
74
+
75
+ Internationalize automatically uses Rails I18n settings:
76
+
77
+ ```ruby
78
+ I18n.locale # Used for current locale
79
+ I18n.default_locale # Used for fallbacks
80
+ I18n.available_locales # Used for locale-specific accessors
81
+ ```
82
+
83
+ Override these with the configuration options above if needed.
@@ -0,0 +1,98 @@
1
+ # Internationalize: Getting Started
2
+
3
+ Internationalize is a lightweight internationalization gem for Rails that stores translations in JSON columns instead of separate tables.
4
+
5
+ ## Installation
6
+
7
+ ```ruby
8
+ # Gemfile
9
+ gem "internationalize"
10
+ ```
11
+
12
+ ## Quick Setup
13
+
14
+ ### 1. Generate a migration for translation columns
15
+
16
+ ```bash
17
+ rails generate internationalize:translation Article title description
18
+ ```
19
+
20
+ This creates a migration adding `title_translations` and `description_translations` JSON columns.
21
+
22
+ Or write the migration manually:
23
+
24
+ ```ruby
25
+ class AddTranslationsToArticles < ActiveRecord::Migration[7.1]
26
+ def change
27
+ add_column :articles, :title_translations, :json, default: {}
28
+ add_column :articles, :description_translations, :json, default: {}
29
+ end
30
+ end
31
+ ```
32
+
33
+ ### 2. Include the mixin and declare translatable attributes
34
+
35
+ ```ruby
36
+ class Article < ApplicationRecord
37
+ include Internationalize::Model
38
+ international :title, :description
39
+ end
40
+ ```
41
+
42
+ ### 3. Use translations
43
+
44
+ ```ruby
45
+ # Create with translations (hash for multiple locales)
46
+ Article.international_create!(
47
+ title: { en: "Hello World", de: "Hallo Welt" },
48
+ status: "published"
49
+ )
50
+
51
+ # Or direct string for current locale
52
+ I18n.locale = :de
53
+ Article.international_create!(title: "Achtung!") # Sets title_de
54
+
55
+ # Set translation for current locale
56
+ article.title = "Hello World"
57
+
58
+ # Set for specific locale
59
+ article.title_en = "Hello World"
60
+ article.title_de = "Hallo Welt"
61
+
62
+ # Read translation
63
+ article.title # => uses I18n.locale
64
+ article.title_de # => "Hallo Welt"
65
+
66
+ # Access raw hash
67
+ article.title_translations # => {"en" => "Hello World", "de" => "Hallo Welt"}
68
+ ```
69
+
70
+ ### 4. Query translations
71
+
72
+ ```ruby
73
+ # Exact match
74
+ Article.international(title: "Hello World")
75
+
76
+ # Partial match (LIKE)
77
+ Article.international(title: "Hello", match: :partial)
78
+
79
+ # Order by translation
80
+ Article.international_order(:title, :desc)
81
+ ```
82
+
83
+ ## Key Concepts
84
+
85
+ - Translations stored in `*_translations` JSON columns
86
+ - No JOINs - data lives in the same table
87
+ - Automatic fallback to default locale
88
+ - Works with SQLite, PostgreSQL, and MySQL
89
+
90
+ ## Important: Column Defaults
91
+
92
+ JSON columns **must** have `default: {}` set in the migration. The generator does this automatically, but if writing migrations manually, ensure you include it:
93
+
94
+ ```ruby
95
+ add_column :articles, :title_translations, :json, default: {}
96
+ ```
97
+
98
+ This is required for optimal performance and correct behavior.
@@ -0,0 +1,14 @@
1
+ description: "Lightweight, performant internationalization for Rails using JSON columns"
2
+ files:
3
+ - path: getting-started.md
4
+ title: "Getting Started"
5
+ description: "Quick setup guide for Internationalize"
6
+ - path: model-api.md
7
+ title: "Model API"
8
+ description: "Model mixin methods and generated accessors"
9
+ - path: query-api.md
10
+ title: "Query API"
11
+ description: "Query methods for searching and filtering translations"
12
+ - path: configuration.md
13
+ title: "Configuration"
14
+ description: "Global and per-attribute configuration options"
@@ -0,0 +1,101 @@
1
+ # Internationalize: Model API
2
+
3
+ ## Including the Mixin
4
+
5
+ ```ruby
6
+ class Article < ApplicationRecord
7
+ include Internationalize::Model
8
+ international :title, :description
9
+ end
10
+ ```
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
+ ## Generated Instance Methods
23
+
24
+ For each `international :title` declaration:
25
+
26
+ ### Accessors
27
+
28
+ | Method | Description |
29
+ |--------|-------------|
30
+ | `title` | Get translation for current `I18n.locale` |
31
+ | `title=` | Set translation for current `I18n.locale` |
32
+ | `title?` | Check if translation exists |
33
+ | `title_translations` | Get raw hash of all translations |
34
+ | `title_translations=` | Set all translations at once |
35
+
36
+ ### Locale-Specific Accessors
37
+
38
+ For each locale in `I18n.available_locales`:
39
+
40
+ | Method | Description |
41
+ |--------|-------------|
42
+ | `title_en` | Get English translation directly |
43
+ | `title_en=` | Set English translation |
44
+ | `title_en?` | Check if English translation exists |
45
+ | `title_de` | Get German translation |
46
+ | `title_de=` | Set German translation |
47
+ | ... | etc. for all locales |
48
+
49
+ ### Instance Helper Methods
50
+
51
+ | Method | Description |
52
+ |--------|-------------|
53
+ | `set_translation(:title, :de, "Hallo")` | Set translation for attribute/locale |
54
+ | `translation_for(:title, :de)` | Get translation without fallback |
55
+ | `translated?(:title, :de)` | Check if translation exists |
56
+ | `translated_locales(:title)` | Array of locales with translations |
57
+
58
+ ## Class Methods (Querying)
59
+
60
+ All query methods default to current `I18n.locale` and return `ActiveRecord::Relation`:
61
+
62
+ | Method | Description |
63
+ |--------|-------------|
64
+ | `international(**conditions, locale: nil)` | Exact match query |
65
+ | `international_not(**conditions, locale: nil)` | Exclude matching records |
66
+ | `international_search(**conditions, locale: nil, case_sensitive: false)` | Substring search |
67
+ | `international_order(attr, dir = :asc, locale: nil)` | Order by translation |
68
+ | `translated(*attrs, locale: nil)` | Find records with translation |
69
+ | `untranslated(*attrs, locale: nil)` | Find records missing translation |
70
+
71
+ ```ruby
72
+ # Examples
73
+ Article.international(title: "Hello World")
74
+ Article.international_search(title: "hello", locale: :de)
75
+ Article.international_order(:title, :desc)
76
+ Article.translated(:title, locale: :de)
77
+ ```
78
+
79
+ ## Class Attributes
80
+
81
+ ```ruby
82
+ Article.international_attributes # => [:title, :description]
83
+ ```
84
+
85
+ ## Fallback Behavior
86
+
87
+ When `fallback: true` (default):
88
+
89
+ ```ruby
90
+ article.title_en = "Hello"
91
+ I18n.locale = :de
92
+ article.title # => "Hello" (falls back to default locale)
93
+ ```
94
+
95
+ When `fallback: false`:
96
+
97
+ ```ruby
98
+ article.title_en = "Hello"
99
+ I18n.locale = :de
100
+ article.title # => nil
101
+ ```
@@ -0,0 +1,129 @@
1
+ # Internationalize: Query API
2
+
3
+ All query methods are class methods on models that include `Internationalize::Model`. They return `ActiveRecord::Relation` objects that can be chained with standard AR methods.
4
+
5
+ ## Default Locale Behavior
6
+
7
+ All query methods default to the current `I18n.locale`. Use the `locale:` option to override:
8
+
9
+ ```ruby
10
+ # Uses current I18n.locale
11
+ Article.international(title: "Hello World")
12
+
13
+ # Explicit locale
14
+ Article.international(title: "Hallo Welt", locale: :de)
15
+ ```
16
+
17
+ ## Query Methods
18
+
19
+ ### international(**conditions, locale: nil)
20
+
21
+ Exact match on translated attributes:
22
+
23
+ ```ruby
24
+ Article.international(title: "Hello World")
25
+ Article.international(title: "Hello", status: "published")
26
+ Article.international(title: "Hallo Welt", locale: :de)
27
+ ```
28
+
29
+ ### international_not(**conditions, locale: nil)
30
+
31
+ Exclude records matching conditions:
32
+
33
+ ```ruby
34
+ Article.international_not(title: "Draft")
35
+ Article.international_not(title: "Entwurf", locale: :de)
36
+ ```
37
+
38
+ ### international_search(**conditions, locale: nil, case_sensitive: false)
39
+
40
+ Substring search (LIKE/ILIKE):
41
+
42
+ ```ruby
43
+ # Case-insensitive (default)
44
+ Article.international_search(title: "hello")
45
+ Article.international_search(title: "hello", description: "world")
46
+
47
+ # Case-sensitive
48
+ Article.international_search(title: "Hello", case_sensitive: true)
49
+
50
+ # With explicit locale
51
+ Article.international_search(title: "welt", locale: :de)
52
+ ```
53
+
54
+ ### international_order(attribute, direction = :asc, locale: nil)
55
+
56
+ Order by translated attribute:
57
+
58
+ ```ruby
59
+ Article.international_order(:title)
60
+ Article.international_order(:title, :desc)
61
+ Article.international_order(:title, :asc, locale: :de)
62
+ ```
63
+
64
+ ### translated(*attributes, locale: nil)
65
+
66
+ Find records with translations in specified locale:
67
+
68
+ ```ruby
69
+ Article.translated(:title)
70
+ Article.translated(:title, locale: :de)
71
+ Article.translated(:title, :description, locale: :de)
72
+ ```
73
+
74
+ ### untranslated(*attributes, locale: nil)
75
+
76
+ Find records missing translations:
77
+
78
+ ```ruby
79
+ Article.untranslated(:title)
80
+ Article.untranslated(:title, locale: :de)
81
+ ```
82
+
83
+ ## Chaining with ActiveRecord
84
+
85
+ All methods return `ActiveRecord::Relation`, so they chain naturally with AR methods:
86
+
87
+ ```ruby
88
+ Article.international(title: "Hello World")
89
+ .where(published: true)
90
+ .order(created_at: :desc)
91
+ .limit(10)
92
+ .includes(:author)
93
+ ```
94
+
95
+ ## Combining Multiple Queries
96
+
97
+ Use `merge` to combine multiple international queries:
98
+
99
+ ```ruby
100
+ # Search + filter + order
101
+ Article.international_search(title: "hello")
102
+ .merge(Article.international(status: "published"))
103
+ .merge(Article.international_order(:title, :desc))
104
+
105
+ # Query across multiple locales
106
+ Article.international(title: "Hello World", locale: :en)
107
+ .merge(Article.international(title: "Hallo Welt", locale: :de))
108
+ ```
109
+
110
+ ## Examples
111
+
112
+ ```ruby
113
+ # Find published articles with German title containing "Welt"
114
+ Article.international_search(title: "Welt", locale: :de)
115
+ .where(published: true)
116
+ .merge(Article.international_order(:title, locale: :de))
117
+ .limit(10)
118
+
119
+ # Find articles missing German translation
120
+ Article.untranslated(:title, locale: :de).count
121
+
122
+ # Complex multi-locale query - find articles with both EN and DE titles
123
+ Article.translated(:title, locale: :en)
124
+ .merge(Article.translated(:title, locale: :de))
125
+
126
+ # Exclude drafts and order by title
127
+ Article.international_not(status: "draft")
128
+ .merge(Article.international_order(:title))
129
+ ```
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Internationalize
4
- VERSION = "0.1.0"
4
+ VERSION = "0.1.1"
5
5
  end
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.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sampo Kuokkanen
@@ -49,6 +49,11 @@ files:
49
49
  - CHANGELOG.md
50
50
  - LICENSE.txt
51
51
  - README.md
52
+ - context/configuration.md
53
+ - context/getting-started.md
54
+ - context/index.yaml
55
+ - context/model-api.md
56
+ - context/query-api.md
52
57
  - lib/generators/internationalize/translation/templates/add_translations_migration.rb.erb
53
58
  - lib/generators/internationalize/translation_generator.rb
54
59
  - lib/internationalize.rb