para-i18n 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 +4 -4
- data/README.md +77 -1
- data/app/controllers/para/admin/translations_controller.rb +13 -5
- data/lib/generators/para/i18n/translate/templates/model_migration.rb.erb +1 -1
- data/lib/generators/para/i18n/translate/translate_generator.rb +1 -5
- data/lib/para/i18n/engine.rb +7 -3
- data/lib/para/i18n/friendly_id.rb +22 -9
- data/lib/para/i18n/i18n_input.rb +34 -9
- data/lib/para/i18n/model.rb +41 -7
- data/lib/para/i18n/resources_table.rb +1 -1
- data/lib/para/i18n/translations_helper.rb +2 -1
- data/lib/para/i18n/version.rb +1 -1
- data/lib/para/i18n.rb +3 -0
- metadata +2 -3
- data/app/views/para/inputs/_i18n.html.haml +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ca0ae98159f636ad5cf97f4481d066819e4daf2
|
4
|
+
data.tar.gz: e2bd232647bd4edee8c06fc82a931fad40ef7211
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 79e0910d8bf7ec05871b8721f547ee29b4fd4e5192f2aaf1d8ae7bd1f825dd8a79040d144c538e3c2b1677d1cd8f420d2137d6db0d9ba37ffa6e907bdf876330
|
7
|
+
data.tar.gz: b19299a63bb9eff4690854f285eda67dab0c5df3bbd1cbbd703ab5139b71fede3425b49d97abc1bb048390b4b8c6b4372be2cb23cb3937db61de40cab638ad62
|
data/README.md
CHANGED
@@ -57,7 +57,7 @@ end
|
|
57
57
|
Now, any `crud` component managing the `Page` model will show a button to access
|
58
58
|
the translation interface for existing entries.
|
59
59
|
|
60
|
-
|
60
|
+
### Overriding the translations form
|
61
61
|
|
62
62
|
The translation form can be overriden by generating it with the `para:i18n:form`
|
63
63
|
generator. This is useful to delete or add fields to translate that are not
|
@@ -73,6 +73,82 @@ rails g para:i18n:form page
|
|
73
73
|
This will create a partial at `app/views/admin/pages/_translations_form.html.haml`
|
74
74
|
that you can override.
|
75
75
|
|
76
|
+
### Translation fields customization
|
77
|
+
|
78
|
+
This gem uses a special [Simple Form](https://github.com/plataformatec/simple_form)
|
79
|
+
input to manage translations.
|
80
|
+
|
81
|
+
Example :
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
= form.input :title, as: :i18n, locale: @target_locale
|
85
|
+
```
|
86
|
+
|
87
|
+
When generating the translations form, you can edit those inputs, remove or add
|
88
|
+
some inputs.
|
89
|
+
|
90
|
+
#### Managing nested resources
|
91
|
+
|
92
|
+
You can simply manage nested resources by using the `simple_fields_for` form
|
93
|
+
helper :
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
= form.simple_fields_for :nested_resources do |fields|
|
97
|
+
= fields.input :nested_title, as: :i18n, locale: @target_locale
|
98
|
+
```
|
99
|
+
|
100
|
+
#### Passing options to the translation field
|
101
|
+
|
102
|
+
The I18n field generates a plain HTML section with the original contents of the
|
103
|
+
field (in the `I18n.default_locale` locale), and a sub-input, which uses the
|
104
|
+
default type that Para infers from the attribute.
|
105
|
+
|
106
|
+
You can override the generated field type or pass other options by using the
|
107
|
+
`:input_html` option :
|
108
|
+
|
109
|
+
```ruby
|
110
|
+
= form.input :value, as: :i18n, locale: @target_locale, input_html: { as: :numeric, spinner: false }
|
111
|
+
```
|
112
|
+
|
113
|
+
Also, if your original content contains useful HTML, you can use the `:html_safe`
|
114
|
+
to be applied to the original content by using the `:original_html` option :
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
= form.input :value, as: :i18n, locale: @target_locale, original_html: { html_safe: true }
|
118
|
+
```
|
119
|
+
|
120
|
+
### Locales fallbacks support
|
121
|
+
|
122
|
+
The gem fully supports Rails' I18n fallbacks and will try to fallback to any
|
123
|
+
available translation using the `I18n.fallbacks` hash if you enable them.
|
124
|
+
|
125
|
+
If not enabled, any untranslated content will be empty.
|
126
|
+
|
127
|
+
### Friendly id support
|
128
|
+
|
129
|
+
The gem comes with friendly_id i18n support, with a dedicated `:i18n` module to
|
130
|
+
include instead of the `:slugged` module into your models friendly_id options.
|
131
|
+
|
132
|
+
For example, for the page :
|
133
|
+
|
134
|
+
```ruby
|
135
|
+
class Page < ActiveRecord::Base
|
136
|
+
translates :title, :slug
|
137
|
+
|
138
|
+
friendly_id :title, use: [:finders, :i18n]
|
139
|
+
end
|
140
|
+
```
|
141
|
+
|
142
|
+
> **Warning** : You always need to put the `:i18n` fiendly_id module after all
|
143
|
+
other modules, so the finder methods included in this module take the current
|
144
|
+
locale into account.
|
145
|
+
|
146
|
+
This will automatically build localized slugs when updating the `title` in any
|
147
|
+
locale, and will allow you to find the resources with the translated slugs.
|
148
|
+
|
149
|
+
Note that if I18n fallbacks are enabled, it will try to fall back to the next
|
150
|
+
locale if no resource was found for the given slug and locale.
|
151
|
+
|
76
152
|
## Contributing
|
77
153
|
|
78
154
|
Bug reports and pull requests are welcome on GitHub at https://github.com/para-cms/para-i18n.
|
@@ -1,7 +1,11 @@
|
|
1
1
|
module Para
|
2
2
|
module Admin
|
3
|
-
class TranslationsController < ::Para::Admin::
|
3
|
+
class TranslationsController < ::Para::Admin::ResourcesController
|
4
|
+
include Para::Admin::ResourceControllerConcerns
|
5
|
+
|
6
|
+
before_action :load_and_authorize_crud_resource
|
4
7
|
before_action :load_locales
|
8
|
+
before_action :add_breadcrumbs
|
5
9
|
|
6
10
|
def edit
|
7
11
|
end
|
@@ -19,10 +23,14 @@ module Para
|
|
19
23
|
private
|
20
24
|
|
21
25
|
def load_and_authorize_crud_resource
|
22
|
-
|
23
|
-
|
24
|
-
|
26
|
+
options = { class: resource_model }
|
27
|
+
|
28
|
+
options.merge!(
|
29
|
+
singleton: true,
|
30
|
+
through: :component
|
31
|
+
) unless params.key?(:resource_id)
|
25
32
|
|
33
|
+
loader = self.class.cancan_resource_class.new(self, :resource, options)
|
26
34
|
loader.load_and_authorize_resource
|
27
35
|
end
|
28
36
|
|
@@ -36,7 +44,7 @@ module Para
|
|
36
44
|
end
|
37
45
|
|
38
46
|
def add_breadcrumbs
|
39
|
-
|
47
|
+
add_breadcrumb(resource_title_for(resource), @component.relation_path(resource, action: :show)) if resource
|
40
48
|
add_breadcrumb(t('para.i18n.translation'))
|
41
49
|
end
|
42
50
|
end
|
@@ -15,7 +15,7 @@ module Para
|
|
15
15
|
desc "I18nAdmin translation generator"
|
16
16
|
|
17
17
|
def generate_migration
|
18
|
-
migration_template 'model_migration.rb.erb', "db/migrate/translate_#{
|
18
|
+
migration_template 'model_migration.rb.erb', "db/migrate/translate_#{ table_name }.rb"
|
19
19
|
end
|
20
20
|
|
21
21
|
def migrate
|
@@ -31,10 +31,6 @@ module Para
|
|
31
31
|
def plural_class_name
|
32
32
|
@plural_class_name ||= class_name.pluralize
|
33
33
|
end
|
34
|
-
|
35
|
-
def table_name
|
36
|
-
@table_name ||= plural_class_name.underscore
|
37
|
-
end
|
38
34
|
end
|
39
35
|
end
|
40
36
|
end
|
data/lib/para/i18n/engine.rb
CHANGED
@@ -9,7 +9,11 @@ module Para
|
|
9
9
|
|
10
10
|
initializer 'para.i18n.extend_para_routes' do
|
11
11
|
::Para.config.routes.extend_routes_for(:crud_component) do
|
12
|
-
resource :translation, only: [:edit, :update]
|
12
|
+
resource :translation, only: [:edit, :update], controller: '/para/admin/translations'
|
13
|
+
end
|
14
|
+
|
15
|
+
::Para.config.routes.extend_routes_for(:form_component) do
|
16
|
+
resource :translation, only: [:edit, :update], controller: '/para/admin/translations'
|
13
17
|
end
|
14
18
|
end
|
15
19
|
|
@@ -26,12 +30,12 @@ module Para
|
|
26
30
|
end
|
27
31
|
|
28
32
|
initializer 'para.i18n.add_translate_actions' do
|
29
|
-
Para.config.add_actions_for('crud/edit') do
|
33
|
+
Para.config.add_actions_for('crud/edit', 'form/show') do
|
30
34
|
{
|
31
35
|
icon: 'globe',
|
32
36
|
label: ::I18n.t('para.i18n.translate'),
|
33
37
|
url: @component.relation_path(resource, :translation, action: :edit)
|
34
|
-
}
|
38
|
+
} if resource.class.translates?
|
35
39
|
end
|
36
40
|
end
|
37
41
|
end
|
@@ -9,6 +9,15 @@ module FriendlyId
|
|
9
9
|
|
10
10
|
def included(model_class)
|
11
11
|
model_class.extend(ClassMethods)
|
12
|
+
|
13
|
+
# Support for friendly finds on associations for Rails 4.0.1 and above.
|
14
|
+
#
|
15
|
+
# Borrowed from FriendlyId::Finders module
|
16
|
+
#
|
17
|
+
if ::ActiveRecord.const_defined?('AssociationRelation')
|
18
|
+
association_relation_delegate_class = model_class.relation_delegate_class(::ActiveRecord::AssociationRelation)
|
19
|
+
association_relation_delegate_class.send(:include, ClassMethods)
|
20
|
+
end
|
12
21
|
end
|
13
22
|
end
|
14
23
|
|
@@ -31,21 +40,25 @@ module FriendlyId
|
|
31
40
|
end
|
32
41
|
|
33
42
|
module ClassMethods
|
34
|
-
def exists_by_friendly_id?(id)
|
35
|
-
if (exists = by_friendly_id(id).exists?)
|
43
|
+
def exists_by_friendly_id?(id, locale = ::I18n.locale)
|
44
|
+
if (exists = by_friendly_id(id, locale).exists?)
|
36
45
|
exists
|
37
|
-
elsif (fallback_locale = Para::I18n::Fallbacks.i18n_fallback_for(
|
38
|
-
|
46
|
+
elsif (fallback_locale = Para::I18n::Fallbacks.i18n_fallback_for(locale)) &&
|
47
|
+
fallback_locale != locale
|
48
|
+
then
|
49
|
+
exists_by_friendly_id?(id, fallback_locale)
|
39
50
|
end
|
40
51
|
end
|
41
52
|
|
42
53
|
private
|
43
54
|
|
44
|
-
def first_by_friendly_id(id)
|
45
|
-
if (first = by_friendly_id(id).first)
|
55
|
+
def first_by_friendly_id(id, locale = ::I18n.locale)
|
56
|
+
if (first = by_friendly_id(id, locale).first)
|
46
57
|
first
|
47
|
-
elsif (fallback_locale = Para::I18n::Fallbacks.i18n_fallback_for(
|
48
|
-
|
58
|
+
elsif (fallback_locale = Para::I18n::Fallbacks.i18n_fallback_for(locale)) &&
|
59
|
+
fallback_locale != locale
|
60
|
+
then
|
61
|
+
first_by_friendly_id(id, fallback_locale)
|
49
62
|
end
|
50
63
|
end
|
51
64
|
|
@@ -53,7 +66,7 @@ module FriendlyId
|
|
53
66
|
if locale == ::I18n.default_locale
|
54
67
|
where(friendly_id_config.query_field => id)
|
55
68
|
else
|
56
|
-
json_path = "{#{
|
69
|
+
json_path = "{#{ locale },#{ friendly_id_config.query_field }}"
|
57
70
|
where("_translations#>>'#{ json_path }' = ?", id)
|
58
71
|
end
|
59
72
|
end
|
data/lib/para/i18n/i18n_input.rb
CHANGED
@@ -1,18 +1,26 @@
|
|
1
1
|
module Para
|
2
2
|
module Inputs
|
3
3
|
class I18nInput < SimpleForm::Inputs::Base
|
4
|
+
delegate :content_tag, to: :template
|
5
|
+
|
4
6
|
def input(wrapper_options = nil)
|
5
7
|
model = object.class
|
8
|
+
render
|
9
|
+
end
|
6
10
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
def render
|
12
|
+
content_tag(:div, class: 'row') do
|
13
|
+
content_tag(:div, class: 'col-md-6') do
|
14
|
+
::I18n.with_locale(::I18n.default_locale) do
|
15
|
+
original_content
|
16
|
+
end
|
17
|
+
end +
|
18
|
+
content_tag(:div, class: 'col-md-6') do
|
19
|
+
::I18n.with_locale(locale) do
|
20
|
+
@builder.input_field(attribute_name, input_options)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
16
24
|
end
|
17
25
|
|
18
26
|
private
|
@@ -24,6 +32,23 @@ module Para
|
|
24
32
|
raise 'Missing `:locale` option passed to :i18n input.'
|
25
33
|
end
|
26
34
|
end
|
35
|
+
|
36
|
+
def original_content
|
37
|
+
value = template.value_for(object, attribute_name)
|
38
|
+
value = value.html_safe if original_options[:html_safe]
|
39
|
+
value
|
40
|
+
end
|
41
|
+
|
42
|
+
def original_options
|
43
|
+
@original_options ||= options[:original_html] || {}
|
44
|
+
end
|
45
|
+
|
46
|
+
def input_options
|
47
|
+
@input_options ||= (options[:input_html] || {}).tap do |hash|
|
48
|
+
hash[:class] ||= ''
|
49
|
+
hash[:class] += ' form-control'
|
50
|
+
end
|
51
|
+
end
|
27
52
|
end
|
28
53
|
end
|
29
54
|
end
|
data/lib/para/i18n/model.rb
CHANGED
@@ -4,11 +4,11 @@ module Para
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
-
class_attribute :
|
7
|
+
class_attribute :translated_attribute_names
|
8
8
|
end
|
9
9
|
|
10
10
|
def read_translated_attribute(field, locale = ::I18n.locale)
|
11
|
-
return
|
11
|
+
return read_plain_or_store_attribute(field) if locale == ::I18n.default_locale
|
12
12
|
|
13
13
|
if model_translations[locale.to_s]
|
14
14
|
if (translation = model_translations[locale.to_s][field.to_s])
|
@@ -23,7 +23,7 @@ module Para
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def write_translated_attribute field, value, locale = ::I18n.locale
|
26
|
-
return
|
26
|
+
return write_plain_or_store_attribute(field, value) if locale == ::I18n.default_locale
|
27
27
|
|
28
28
|
model_translations[locale.to_s] ||= {}
|
29
29
|
model_translations[locale.to_s][field.to_s] = value
|
@@ -40,12 +40,46 @@ module Para
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def translation_for(locale)
|
43
|
-
model_translations[locale] || {}
|
43
|
+
model_translations[locale.to_s] || {}
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def read_plain_or_store_attribute(field)
|
49
|
+
if plain_column?(field)
|
50
|
+
read_attribute(field)
|
51
|
+
elsif (store_name = find_stored_column(field))
|
52
|
+
read_store_attribute(store_name, field)
|
53
|
+
else
|
54
|
+
raise ActiveRecord::UnknownAttributeError.new(self, field)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def write_plain_or_store_attribute(field, value)
|
59
|
+
if plain_column?(field)
|
60
|
+
write_attribute(field, value)
|
61
|
+
elsif (store_name = find_stored_column(field))
|
62
|
+
write_store_attribute(store_name, field, value)
|
63
|
+
else
|
64
|
+
raise ActiveRecord::UnknownAttributeError.new(self, field)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def plain_column?(field)
|
69
|
+
self.class.columns_hash.key?(field.to_s)
|
70
|
+
end
|
71
|
+
|
72
|
+
def find_stored_column(field)
|
73
|
+
store = self.class.stored_attributes.find do |name, attributes|
|
74
|
+
attributes.include?(field.to_sym)
|
75
|
+
end
|
76
|
+
|
77
|
+
store.first if store
|
44
78
|
end
|
45
79
|
|
46
80
|
module ClassMethods
|
47
81
|
def translates(*fields)
|
48
|
-
self.
|
82
|
+
self.translated_attribute_names = fields.map(&:to_sym)
|
49
83
|
|
50
84
|
fields.each do |field|
|
51
85
|
define_method field do
|
@@ -58,8 +92,8 @@ module Para
|
|
58
92
|
end
|
59
93
|
end
|
60
94
|
|
61
|
-
def
|
62
|
-
|
95
|
+
def translates?
|
96
|
+
translated_attribute_names && translated_attribute_names.length > 0
|
63
97
|
end
|
64
98
|
end
|
65
99
|
end
|
@@ -10,7 +10,7 @@ module Para
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def translate_button(resource)
|
13
|
-
return unless resource.class.
|
13
|
+
return unless resource.class.translates?
|
14
14
|
|
15
15
|
path = component.relation_path(resource, :translation, action: :edit)
|
16
16
|
options = { class: 'btn btn-info' }
|
@@ -4,7 +4,8 @@ module Para
|
|
4
4
|
# TODO : Support images & co
|
5
5
|
def translated_model_fields_for(model)
|
6
6
|
model_field_mappings(model).fields.select do |field|
|
7
|
-
model.
|
7
|
+
model.translated_attribute_names &&
|
8
|
+
model.translated_attribute_names.include?(field.name.to_sym)
|
8
9
|
end
|
9
10
|
end
|
10
11
|
end
|
data/lib/para/i18n/version.rb
CHANGED
data/lib/para/i18n.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: para-i18n
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Valentin Ballestrino
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-09-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -71,7 +71,6 @@ files:
|
|
71
71
|
- app/controllers/para/admin/translations_controller.rb
|
72
72
|
- app/views/para/admin/resources/_translations_form.html.haml
|
73
73
|
- app/views/para/admin/translations/edit.html.haml
|
74
|
-
- app/views/para/inputs/_i18n.html.haml
|
75
74
|
- bin/console
|
76
75
|
- bin/setup
|
77
76
|
- config/locales/para-i18n.fr.yml
|