internationalize 0.3.0 → 0.4.0

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: '0808602c10b51ee1884f04c5b9fd66d05381d07c0f86d284517dce7f02ebb6cd'
4
- data.tar.gz: fe0c214e9c386b191d4e8f06e1ddee136d9e7a15b25a59d4dd0c9a4860a6589a
3
+ metadata.gz: 0a7c08fb66904ff4e73e13f590f4546af940ce8f9adc59d870adf60e71f54fc0
4
+ data.tar.gz: e6e5b34d18588fc2b8d1fd18b182d73f39bffe2ad67c7f383976eaa30d8b6ee2
5
5
  SHA512:
6
- metadata.gz: 18cf19554d3187476b26505e555e7f181fb6c31edc100e054a2a96f8eafbdb09fa1ad424544973abc349a8f68c62ec0d5634216c6d4fd4cfd029221331d620ed
7
- data.tar.gz: d998cbcd3ede8f8a1574e3adcec37ae3afb6216772de801ed0693199bbe70befe398f89a0ff001a66f149cc10f226ed5fd93721c44067e3ebd0ba62ad6e6643d
6
+ metadata.gz: 6bf2d4d4e0cfcb36adbd787f3a839dd6bbe4290468eb2934b99af4c4541d948aef7d3f5ea71329e2f99aabe1f2530c83af8955d544d8991e0a9341b4abd393cb
7
+ data.tar.gz: 5ccafbadb398e1ad9b956990b10334c80577f248d32b4e788a94dc5ad39fffdb47fa1c22eb892216af71784ea4770b4d0bfac43ceeaac951cff63575a4ce1152
data/CHANGELOG.md CHANGED
@@ -5,6 +5,19 @@ 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
+ ## [0.4.0] - 2025-12-02
9
+
10
+ ### Added
11
+
12
+ - `i18n_where` query method as a short, convenient alias for querying translated attributes
13
+ - `Article.i18n_where(title: "Hello")` - exact match
14
+ - `Article.i18n_where(title: "hello", match: :partial)` - LIKE match
15
+
16
+ ### Deprecated
17
+
18
+ - Using `international` for querying is now deprecated; use `i18n_where` or `international_where` instead
19
+ - A deprecation warning is now emitted when using `international` for queries
20
+
8
21
  ## [0.3.0] - 2024-12-01
9
22
 
10
23
  ### Added
@@ -13,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
13
26
  - `uniqueness: true` - validates uniqueness per-locale (requires JSON column querying)
14
27
  - `presence: { locales: [:en, :de] }` - requires translations for specific locales (useful for admin interfaces)
15
28
  - Standard Rails validations (`validates :title, presence: true`) now work with virtual accessors
29
+ - `international_where` query method as a clearer alternative to `international` for queries
16
30
 
17
31
  ## [0.2.4] - 2024-11-29
18
32
 
data/README.md CHANGED
@@ -119,13 +119,12 @@ All query methods default to the current `I18n.locale` and return ActiveRecord r
119
119
 
120
120
  ```ruby
121
121
  # Exact match on translation (uses current locale by default)
122
- Article.international(title: "Hello World")
123
- Article.international(title: "Hallo Welt", locale: :de)
122
+ Article.i18n_where(title: "Hello World")
123
+ Article.i18n_where(title: "Hallo Welt", locale: :de)
124
124
 
125
125
  # Partial match / search (case-insensitive LIKE)
126
- Article.international(title: "hello", match: :partial)
127
- Article.international(title: "Hello", match: :partial, case_sensitive: true)
128
- Article.international(title: "hallo", match: :partial, locale: :de)
126
+ Article.i18n_where(title: "hello", match: :partial)
127
+ Article.i18n_where(title: "Hello", match: :partial, case_sensitive: true)
129
128
 
130
129
  # Exclude matches
131
130
  Article.international_not(title: "Draft")
@@ -142,19 +141,15 @@ Article.translated(:title, locale: :de)
142
141
  Article.untranslated(:title, locale: :de)
143
142
 
144
143
  # Chain with ActiveRecord methods
145
- Article.international(title: "Hello World")
144
+ Article.i18n_where(title: "Hello World")
146
145
  .where(published: true)
147
146
  .includes(:author)
148
147
  .limit(10)
149
148
 
150
149
  # Combine queries
151
- Article.international(title: "hello", match: :partial)
150
+ Article.i18n_where(title: "hello", match: :partial)
152
151
  .where(status: "published")
153
152
  .merge(Article.international_order(:title, :desc))
154
-
155
- # Query across multiple locales
156
- Article.international(title: "Hello World", locale: :en)
157
- .merge(Article.international(title: "Hallo Welt", locale: :de))
158
153
  ```
159
154
 
160
155
  ### Helper Methods
@@ -71,10 +71,10 @@ article.title_translations # => {"en" => "Hello World", "de" => "Hallo Welt"}
71
71
 
72
72
  ```ruby
73
73
  # Exact match
74
- Article.international(title: "Hello World")
74
+ Article.i18n_where(title: "Hello World")
75
75
 
76
76
  # Partial match (LIKE)
77
- Article.international(title: "Hello", match: :partial)
77
+ Article.i18n_where(title: "Hello", match: :partial)
78
78
 
79
79
  # Order by translation
80
80
  Article.international_order(:title, :desc)
data/context/model-api.md CHANGED
@@ -49,17 +49,17 @@ All query methods default to current `I18n.locale` and return `ActiveRecord::Rel
49
49
 
50
50
  | Method | Description |
51
51
  |--------|-------------|
52
- | `international(**conditions, locale: nil)` | Exact match query |
52
+ | `i18n_where(**conditions, locale: nil, match: :exact)` | Query by translation (short alias) |
53
+ | `international_where(**conditions, locale: nil, match: :exact)` | Query by translation |
53
54
  | `international_not(**conditions, locale: nil)` | Exclude matching records |
54
- | `international_search(**conditions, locale: nil, case_sensitive: false)` | Substring search |
55
55
  | `international_order(attr, dir = :asc, locale: nil)` | Order by translation |
56
56
  | `translated(*attrs, locale: nil)` | Find records with translation |
57
57
  | `untranslated(*attrs, locale: nil)` | Find records missing translation |
58
58
 
59
59
  ```ruby
60
60
  # Examples
61
- Article.international(title: "Hello World")
62
- Article.international_search(title: "hello", locale: :de)
61
+ Article.i18n_where(title: "Hello World")
62
+ Article.i18n_where(title: "hello", match: :partial) # case-insensitive LIKE
63
63
  Article.international_order(:title, :desc)
64
64
  Article.translated(:title, locale: :de)
65
65
  ```
data/context/query-api.md CHANGED
@@ -8,47 +8,40 @@ All query methods default to the current `I18n.locale`. Use the `locale:` option
8
8
 
9
9
  ```ruby
10
10
  # Uses current I18n.locale
11
- Article.international(title: "Hello World")
11
+ Article.i18n_where(title: "Hello World")
12
12
 
13
13
  # Explicit locale
14
- Article.international(title: "Hallo Welt", locale: :de)
14
+ Article.i18n_where(title: "Hallo Welt", locale: :de)
15
15
  ```
16
16
 
17
17
  ## Query Methods
18
18
 
19
- ### international(**conditions, locale: nil)
19
+ ### i18n_where(**conditions, locale: nil, match: :exact, case_sensitive: false)
20
20
 
21
- Exact match on translated attributes:
21
+ Query by translated attributes. Also available as `international_where`.
22
+
23
+ Exact match (default):
22
24
 
23
25
  ```ruby
24
- Article.international(title: "Hello World")
25
- Article.international(title: "Hello", status: "published")
26
- Article.international(title: "Hallo Welt", locale: :de)
26
+ Article.i18n_where(title: "Hello World")
27
+ Article.i18n_where(title: "Hello", status: "published")
28
+ Article.i18n_where(title: "Hallo Welt", locale: :de)
27
29
  ```
28
30
 
29
- ### international_not(**conditions, locale: nil)
30
-
31
- Exclude records matching conditions:
31
+ Partial match (case-insensitive LIKE):
32
32
 
33
33
  ```ruby
34
- Article.international_not(title: "Draft")
35
- Article.international_not(title: "Entwurf", locale: :de)
34
+ Article.i18n_where(title: "hello", match: :partial)
35
+ Article.i18n_where(title: "Hello", match: :partial, case_sensitive: true)
36
36
  ```
37
37
 
38
- ### international_search(**conditions, locale: nil, case_sensitive: false)
38
+ ### international_not(**conditions, locale: nil)
39
39
 
40
- Substring search (LIKE/ILIKE):
40
+ Exclude records matching conditions:
41
41
 
42
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)
43
+ Article.international_not(title: "Draft")
44
+ Article.international_not(title: "Entwurf", locale: :de)
52
45
  ```
53
46
 
54
47
  ### international_order(attribute, direction = :asc, locale: nil)
@@ -85,7 +78,7 @@ Article.untranslated(:title, locale: :de)
85
78
  All methods return `ActiveRecord::Relation`, so they chain naturally with AR methods:
86
79
 
87
80
  ```ruby
88
- Article.international(title: "Hello World")
81
+ Article.i18n_where(title: "Hello World")
89
82
  .where(published: true)
90
83
  .order(created_at: :desc)
91
84
  .limit(10)
@@ -98,20 +91,20 @@ Use `merge` to combine multiple international queries:
98
91
 
99
92
  ```ruby
100
93
  # Search + filter + order
101
- Article.international_search(title: "hello")
102
- .merge(Article.international(status: "published"))
94
+ Article.i18n_where(title: "hello", match: :partial)
95
+ .merge(Article.i18n_where(status: "published"))
103
96
  .merge(Article.international_order(:title, :desc))
104
97
 
105
98
  # Query across multiple locales
106
- Article.international(title: "Hello World", locale: :en)
107
- .merge(Article.international(title: "Hallo Welt", locale: :de))
99
+ Article.i18n_where(title: "Hello World", locale: :en)
100
+ .merge(Article.i18n_where(title: "Hallo Welt", locale: :de))
108
101
  ```
109
102
 
110
103
  ## Examples
111
104
 
112
105
  ```ruby
113
106
  # Find published articles with German title containing "Welt"
114
- Article.international_search(title: "Welt", locale: :de)
107
+ Article.i18n_where(title: "Welt", match: :partial, locale: :de)
115
108
  .where(published: true)
116
109
  .merge(Article.international_order(:title, locale: :de))
117
110
  .limit(10)
@@ -12,8 +12,8 @@ module Internationalize
12
12
  # end
13
13
  #
14
14
  # # Querying
15
- # Article.international(title: "Hello")
16
- # Article.international(title: "hello", match: :partial)
15
+ # Article.i18n_where(title: "Hello")
16
+ # Article.i18n_where(title: "hello", match: :partial)
17
17
  # Article.international_order(:title, :desc)
18
18
  #
19
19
  module Model
@@ -27,33 +27,57 @@ module Internationalize
27
27
  end
28
28
 
29
29
  class_methods do
30
- # Declares attributes as internationalized OR queries by translated attributes
30
+ # Declares attributes as internationalized
31
31
  #
32
- # When called with Symbol arguments, declares attributes as internationalized:
32
+ # @example
33
33
  # international :title, :description
34
34
  #
35
- # When called with keyword arguments, queries translated attributes:
36
- # Article.international(title: "Hello") # exact match
37
- # Article.international(title: "Hello", locale: :de) # exact match in German
38
- # Article.international(title: "hello", match: :partial) # LIKE match (case-insensitive)
39
- # Article.international(title: "Hello", match: :partial, case_sensitive: true)
40
- #
41
35
  # @param attributes [Array<Symbol>] attributes to declare as internationalized
42
- # @param locale [Symbol] locale to query (default: current locale)
43
- # @param match [Symbol] :exact or :partial (default: :exact)
44
- # @param case_sensitive [Boolean] for partial matching only (default: false)
45
- # @param conditions [Hash] attribute => value pairs to query
36
+ #
37
+ # @deprecated Using this method for querying is deprecated.
38
+ # Use {#i18n_where} or {#international_where} instead.
46
39
  #
47
40
  def international(*attributes, locale: nil, match: :exact, case_sensitive: false, **conditions)
48
41
  if attributes.any? && attributes.first.is_a?(Symbol) && conditions.empty?
49
42
  # Declaration mode: international :title, :description
50
43
  declare_international_attributes(attributes)
51
44
  else
52
- # Query mode: Article.international(title: "Hello")
45
+ # Query mode: Article.international(title: "Hello") - DEPRECATED
46
+ warn("[Internationalize] DEPRECATION WARNING: Using `international` for querying is deprecated. " \
47
+ "Use `i18n_where` or `international_where` instead. " \
48
+ "(called from #{caller(1..1).first})")
53
49
  international_query(conditions, locale: locale, match: match, case_sensitive: case_sensitive)
54
50
  end
55
51
  end
56
52
 
53
+ # Query translated attributes
54
+ #
55
+ # @param conditions [Hash] attribute => value pairs to query
56
+ # @param locale [Symbol] locale to query (default: current locale)
57
+ # @param match [Symbol] :exact or :partial (default: :exact)
58
+ # @param case_sensitive [Boolean] for partial matching only (default: false)
59
+ # @return [ActiveRecord::Relation]
60
+ #
61
+ # @example
62
+ # Article.international_where(title: "Hello")
63
+ # Article.international_where(title: "hello", match: :partial)
64
+ #
65
+ def international_where(locale: nil, match: :exact, case_sensitive: false, **conditions)
66
+ international_query(conditions, locale: locale, match: match, case_sensitive: case_sensitive)
67
+ end
68
+
69
+ # Short alias for international_where
70
+ #
71
+ # @see #international_where
72
+ #
73
+ # @example
74
+ # Article.i18n_where(title: "Hello")
75
+ # Article.i18n_where(title: "hello", match: :partial)
76
+ #
77
+ def i18n_where(locale: nil, match: :exact, case_sensitive: false, **conditions)
78
+ international_query(conditions, locale: locale, match: match, case_sensitive: case_sensitive)
79
+ end
80
+
57
81
  # Order by translated attribute
58
82
  #
59
83
  # @param attribute [Symbol] attribute to order by
@@ -51,7 +51,7 @@ module Internationalize
51
51
  def validate_international_presence(attr, options)
52
52
  unless options.is_a?(Hash) && options[:locales]
53
53
  raise ArgumentError, "validates_international presence requires locales: option. " \
54
- "For current locale, use: validates :#{attr}, presence: true"
54
+ "For current locale, use: validates :#{attr}, presence: true"
55
55
  end
56
56
 
57
57
  locales = options[:locales].map(&:to_s)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Internationalize
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
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.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sampo Kuokkanen