kakimasu 1.0.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 +7 -0
- data/.coveralls.yml +1 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.rubocop.yml +31 -0
- data/.travis.yml +8 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +135 -0
- data/Rakefile +6 -0
- data/app/controllers/kakimasu/home_controller.rb +18 -0
- data/app/controllers/kakimasu/keys_controller.rb +89 -0
- data/app/controllers/kakimasu/translations_controller.rb +37 -0
- data/app/helpers/counting_helper.rb +11 -0
- data/app/helpers/formatting_helper.rb +6 -0
- data/app/helpers/grouping_helper.rb +11 -0
- data/app/helpers/pagination_helper.rb +15 -0
- data/app/helpers/search_key_helper.rb +66 -0
- data/app/helpers/search_translations_helper.rb +101 -0
- data/app/models/translation.rb +2 -0
- data/app/policies/translation_policy.rb +9 -0
- data/app/views/kakimasu/home/index.html.erb +35 -0
- data/app/views/kakimasu/keys/create.js.erb +1 -0
- data/app/views/kakimasu/keys/index.html.erb +183 -0
- data/app/views/kakimasu/shared/_navbar.html.erb +15 -0
- data/app/views/kakimasu/translations/create.js.erb +1 -0
- data/app/views/kakimasu/translations/index.html.erb +168 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/config/initializers/i18n.rb +58 -0
- data/config/initializers/i18n_backend.rb +5 -0
- data/config/locales/en.yml +34 -0
- data/config/routes.rb +10 -0
- data/kakimasu.gemspec +49 -0
- data/lib/generators/kakimasu/backup_generator.rb +101 -0
- data/lib/generators/kakimasu/policy_generator.rb +18 -0
- data/lib/generators/kakimasu/restore_backup_generator.rb +89 -0
- data/lib/generators/kakimasu/views_generator.rb +22 -0
- data/lib/kakimasu.rb +11 -0
- data/lib/kakimasu/engine.rb +3 -0
- data/lib/kakimasu/version.rb +3 -0
- data/vendor/assets/javascripts/components/activation_button.coffee +10 -0
- data/vendor/assets/javascripts/components/modal.coffee +48 -0
- data/vendor/assets/javascripts/components/translate.coffee +93 -0
- data/vendor/assets/javascripts/components/translation_key_table.coffee +5 -0
- data/vendor/assets/javascripts/components/translation_navigation.coffee +13 -0
- data/vendor/assets/javascripts/components/translation_panel_table.coffee +5 -0
- data/vendor/assets/javascripts/components/translation_percent_chart.coffee +39 -0
- data/vendor/assets/javascripts/components/translation_popover.coffee +90 -0
- data/vendor/assets/javascripts/jquery/jquery.circliful.min.js +1 -0
- data/vendor/assets/javascripts/kakimasu.coffee +18 -0
- data/vendor/assets/stylesheets/circliful.scss +38 -0
- data/vendor/assets/stylesheets/components/_homepage.scss +17 -0
- data/vendor/assets/stylesheets/components/_key_management.scss +53 -0
- data/vendor/assets/stylesheets/components/_navbar.scss +52 -0
- data/vendor/assets/stylesheets/components/_translate_modal.scss +36 -0
- data/vendor/assets/stylesheets/components/_translation_panel.scss +31 -0
- data/vendor/assets/stylesheets/components/_translation_popover.scss +31 -0
- data/vendor/assets/stylesheets/font-awesome/HELP-US-OUT.txt +7 -0
- data/vendor/assets/stylesheets/font-awesome/css/font-awesome.css +2337 -0
- data/vendor/assets/stylesheets/font-awesome/css/font-awesome.min.css +4 -0
- data/vendor/assets/stylesheets/font-awesome/fonts/FontAwesome.otf +0 -0
- data/vendor/assets/stylesheets/font-awesome/fonts/fontawesome-webfont.eot +0 -0
- data/vendor/assets/stylesheets/font-awesome/fonts/fontawesome-webfont.svg +2671 -0
- data/vendor/assets/stylesheets/font-awesome/fonts/fontawesome-webfont.ttf +0 -0
- data/vendor/assets/stylesheets/font-awesome/fonts/fontawesome-webfont.woff +0 -0
- data/vendor/assets/stylesheets/font-awesome/fonts/fontawesome-webfont.woff2 +0 -0
- data/vendor/assets/stylesheets/font-awesome/less/animated.less +34 -0
- data/vendor/assets/stylesheets/font-awesome/less/bordered-pulled.less +25 -0
- data/vendor/assets/stylesheets/font-awesome/less/core.less +12 -0
- data/vendor/assets/stylesheets/font-awesome/less/fixed-width.less +6 -0
- data/vendor/assets/stylesheets/font-awesome/less/font-awesome.less +18 -0
- data/vendor/assets/stylesheets/font-awesome/less/icons.less +789 -0
- data/vendor/assets/stylesheets/font-awesome/less/larger.less +13 -0
- data/vendor/assets/stylesheets/font-awesome/less/list.less +19 -0
- data/vendor/assets/stylesheets/font-awesome/less/mixins.less +60 -0
- data/vendor/assets/stylesheets/font-awesome/less/path.less +15 -0
- data/vendor/assets/stylesheets/font-awesome/less/rotated-flipped.less +20 -0
- data/vendor/assets/stylesheets/font-awesome/less/screen-reader.less +5 -0
- data/vendor/assets/stylesheets/font-awesome/less/stacked.less +20 -0
- data/vendor/assets/stylesheets/font-awesome/less/variables.less +800 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_animated.scss +34 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_bordered-pulled.scss +25 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_core.scss +12 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_fixed-width.scss +6 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_icons.scss +789 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_larger.scss +13 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_list.scss +19 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_mixins.scss +60 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_path.scss +15 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_rotated-flipped.scss +20 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_screen-reader.scss +5 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_stacked.scss +20 -0
- data/vendor/assets/stylesheets/font-awesome/scss/_variables.scss +800 -0
- data/vendor/assets/stylesheets/font-awesome/scss/font-awesome.scss +18 -0
- data/vendor/assets/stylesheets/kakimasu.scss +35 -0
- metadata +364 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module CountingHelper
|
|
2
|
+
# Counts how much keys there is in key array
|
|
3
|
+
def countKeys(array)
|
|
4
|
+
array.flatten.count - array.count
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# Gets translation percentage
|
|
8
|
+
def translationPercentage(all_keys, missing_translations)
|
|
9
|
+
((1 - ( missing_translations.to_f / all_keys )) * 100).round(2)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module GroupingHelper
|
|
2
|
+
# Groups all translations by language in array
|
|
3
|
+
def group_by_language(array)
|
|
4
|
+
array.group_by { |el| el.partition('.').first }
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
# Gets all paths from keys array
|
|
8
|
+
def get_translation_key_paths(array)
|
|
9
|
+
array.map { |el| el.last }
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Sets translation key for lazy lookup or unsets it.
|
|
2
|
+
module SearchKeyHelper
|
|
3
|
+
def lazy_lookup_key(key, path)
|
|
4
|
+
path = 'app/views/' + path
|
|
5
|
+
file = File.read(path)
|
|
6
|
+
|
|
7
|
+
matches = Array.new #All places where this key is used in given file
|
|
8
|
+
locations = Array.new #Indexes which determines where to make changes
|
|
9
|
+
file_length_differential = 0 #File length difference because substitutions will change file size.
|
|
10
|
+
|
|
11
|
+
# Finds all places where given translation key is used
|
|
12
|
+
file.scan(/[=|\s][t][\s]*[(]?[\s]*['|:]#{key}/) do |c|
|
|
13
|
+
matches.push [c, $~.offset(0)[0]]
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
matches.each do |array|
|
|
17
|
+
if array.first.match /[=|\s][t][\s]*[(]?[\s]*[:]\w*/ # if translation written with : not '' then its special case
|
|
18
|
+
# Key with ':key' is sustituted with "'.key'"
|
|
19
|
+
index = array.first.index(/:#{key}/)
|
|
20
|
+
file.slice!(array.last + index + file_length_differential, (":#{key}").length)
|
|
21
|
+
file.insert(array.last + index + file_length_differential, "'.#{key}'")
|
|
22
|
+
file_length_differential += ("'.#{key}'").length - (":#{key}").length
|
|
23
|
+
elsif key[0] != '.'
|
|
24
|
+
index = array.first.index(key)
|
|
25
|
+
locations.push array.last + index + file_length_differential
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
# Insert '.' just before key for lazy lookup
|
|
30
|
+
locations.each_with_index do |location, index|
|
|
31
|
+
file.insert(location + index, '.')
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
File.write(path, file)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def remove_lazy_lookup(key, path)
|
|
38
|
+
path = 'app/views/' + path
|
|
39
|
+
file = File.read(path)
|
|
40
|
+
|
|
41
|
+
# Get rid of prefix of has lazy lookup prefix
|
|
42
|
+
if key.include? '.'
|
|
43
|
+
key = key.split('.').last
|
|
44
|
+
key.prepend '.'
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
matches = Array.new # All places where given key is used in file
|
|
48
|
+
locations = Array.new #Indexes which determintes where to make changes
|
|
49
|
+
|
|
50
|
+
key.slice! 0 if key[0] == '.'
|
|
51
|
+
file.scan(/[=|\s][t][\s]*[(]?[\s]*['][.]#{key}/) do |c|
|
|
52
|
+
matches.push [c, $~.offset(0)[0]]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
matches.each do |array|
|
|
56
|
+
index = array.first.index('.' + key)
|
|
57
|
+
locations.push array.last + index
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
locations.each_with_index do |location, index|
|
|
61
|
+
file.slice!(location - index) # Removes '.' from match
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
File.write(path, file)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
module SearchTranslationsHelper
|
|
2
|
+
# Method to get prefix for lazy lookup
|
|
3
|
+
def prefix(path)
|
|
4
|
+
prefix = path.split('/')
|
|
5
|
+
prefix[-1] = prefix.last.split('.').first
|
|
6
|
+
prefix = prefix.join('.')
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# Method returns if key has missing translation in one of locales
|
|
10
|
+
def missing_translations?(key)
|
|
11
|
+
missing_translation = false
|
|
12
|
+
I18n.available_locales.each do |locale|
|
|
13
|
+
if !I18n.exists?(key, locale)
|
|
14
|
+
missing_translation = true # If in one of locales key has no translation, method returns true
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
missing_translation
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Method searches used translations keys in a file
|
|
21
|
+
def find_keys(file, path)
|
|
22
|
+
array = file.scan(/[=|\s][t][\s]*[(]?[\s]*['|:]([.]*\w*)/).uniq
|
|
23
|
+
keys = Array.new
|
|
24
|
+
|
|
25
|
+
# If key has '.' in front of it, it should be completed as lazy lookup key.
|
|
26
|
+
array.each_with_index do |key, index|
|
|
27
|
+
if key.first[0] == '.'
|
|
28
|
+
array[index] = key.first.insert(0, prefix(path))
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
array
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Method returns array of keys with missing translations from given array
|
|
35
|
+
def find_missing_translations_keys(array)
|
|
36
|
+
missing_translations_keys = []
|
|
37
|
+
|
|
38
|
+
array.each do |key|
|
|
39
|
+
missing_translations_keys.push key if missing_translations?(key)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
missing_translations_keys
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Method searches used active record human attribute name keys in given file
|
|
46
|
+
def find_attribute_keys(file)
|
|
47
|
+
array = file.scan(/(\w*).human_attribute_name[(][:](\w*)/).uniq
|
|
48
|
+
keys = []
|
|
49
|
+
# Keys are transformed into correct active record attribute keys form
|
|
50
|
+
array.each do |arr|
|
|
51
|
+
arr = 'activerecord.' + 'attributes.' + arr.first.downcase + '.' + arr.last
|
|
52
|
+
keys.push arr
|
|
53
|
+
end
|
|
54
|
+
keys
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Method searches used Model name keys in given file
|
|
58
|
+
def find_model_name_keys(file)
|
|
59
|
+
array = file.scan(/(\w*).model_name.human/).uniq
|
|
60
|
+
keys = []
|
|
61
|
+
# Keys are transformed into correct active record model name keys form
|
|
62
|
+
array.each do |arr|
|
|
63
|
+
arr = 'activerecord.models.' + arr.first.downcase
|
|
64
|
+
keys.push arr
|
|
65
|
+
end
|
|
66
|
+
keys
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Method returns array with requested translation keys
|
|
70
|
+
def search_for_translations(category)
|
|
71
|
+
keys = []
|
|
72
|
+
|
|
73
|
+
Dir.glob("app/views/**/*").each do |path|
|
|
74
|
+
if File.file?(path)
|
|
75
|
+
file = File.read(path)
|
|
76
|
+
case category
|
|
77
|
+
when 'active_record_attribute_translations'
|
|
78
|
+
keys.push find_attribute_keys(file)
|
|
79
|
+
when 'active_record_model_translations'
|
|
80
|
+
keys.push find_model_name_keys(file)
|
|
81
|
+
when 'all_translation_keys'
|
|
82
|
+
path.slice! "app/views/"
|
|
83
|
+
keys.push find_keys(file, path).push path
|
|
84
|
+
when 'missing_translations'
|
|
85
|
+
path.slice! "app/views/"
|
|
86
|
+
# push in array only those keys which have missing translations
|
|
87
|
+
keys.push find_missing_translations_keys(find_keys(file, path)).push path
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
case category
|
|
93
|
+
when 'active_record_attribute_translations'
|
|
94
|
+
keys.flatten.uniq
|
|
95
|
+
when 'active_record_model_translations'
|
|
96
|
+
keys.flatten.uniq
|
|
97
|
+
else
|
|
98
|
+
keys
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<%= render 'kakimasu/shared/navbar' %>
|
|
2
|
+
|
|
3
|
+
<div class="container">
|
|
4
|
+
<div class="row">
|
|
5
|
+
<div class="col-md-4">
|
|
6
|
+
<h1 class="kakimasu-greetings"> Hello, user! </h1>
|
|
7
|
+
|
|
8
|
+
<% if params[:show_translation_key] == 'true' %>
|
|
9
|
+
<%= link_to t('deactivate_translation_mode'), { show_translation_key: false }, class: 'btn btn-primary' %>
|
|
10
|
+
<% else %>
|
|
11
|
+
<%= link_to t('activate_translation_mode'), { show_translation_key: true }, id: 'activate_translation_mode_button', class: 'btn btn-primary' %>
|
|
12
|
+
<% end %>
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
<div class="col-md-8" data-component="TranslationPercentChart">
|
|
16
|
+
<div class="translation-diagram">
|
|
17
|
+
<div id="translation-percentage-circle"></div>
|
|
18
|
+
<table>
|
|
19
|
+
<tr>
|
|
20
|
+
<th><%= t('total_translation_keys') %>:</th>
|
|
21
|
+
<td><%= @all_keys_count %></td>
|
|
22
|
+
</tr>
|
|
23
|
+
<tr>
|
|
24
|
+
<th><%= t('total_keys_with_missing_translation') %>:</th>
|
|
25
|
+
<td><%= @missing_translation_keys_count %></td>
|
|
26
|
+
</tr>
|
|
27
|
+
<tr class="translation-percentage" data-value="<%= @percentage %>">
|
|
28
|
+
<th><%= t('translation_percentage') %>:</th>
|
|
29
|
+
<td><%= @percentage %> %</td>
|
|
30
|
+
</tr>
|
|
31
|
+
</table>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
window.location.reload()
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
<%= render 'kakimasu/shared/navbar' %>
|
|
2
|
+
|
|
3
|
+
<div data-component="TranslationModal">
|
|
4
|
+
<h1 class="margin-left-15"><%= t('translation_keys') %></h1>
|
|
5
|
+
<!-- Category list -->
|
|
6
|
+
<div>
|
|
7
|
+
<div class="col-md-3 translation-key-categories">
|
|
8
|
+
<h3><%=t('categories')%></h3>
|
|
9
|
+
<ul class="list-group">
|
|
10
|
+
<% @categories.each do |category| %>
|
|
11
|
+
<% if @category == category %>
|
|
12
|
+
<li class="list-group-item active"><%= link_to t(category), keys_category: category %></li>
|
|
13
|
+
<% else %>
|
|
14
|
+
<li class="list-group-item"><%= link_to t(category), keys_category: category %></li>
|
|
15
|
+
<% end %>
|
|
16
|
+
<% end %>
|
|
17
|
+
</ul>
|
|
18
|
+
</div>
|
|
19
|
+
|
|
20
|
+
<div class="col-md-9 translation-key-table">
|
|
21
|
+
<h3><%=t(@category)%></h3>
|
|
22
|
+
<!-- Translation keys table -->
|
|
23
|
+
<%-# Check if there are keys to show in tables -%>
|
|
24
|
+
<% if @category == 'missing_translations' && @keys.count == 0 %>
|
|
25
|
+
<h3><%= t('no_keys_with_missing_translations') %></h3>
|
|
26
|
+
<% elsif @category == 'all_translation_keys' && @keys.count == 0 %>
|
|
27
|
+
<h3><%= t('no_translation_keys_found') %></h3>
|
|
28
|
+
<% else %>
|
|
29
|
+
<table class="table" data-component="TranslationKeyTable">
|
|
30
|
+
<thead>
|
|
31
|
+
<tr>
|
|
32
|
+
<th><%= t('key') %></th>
|
|
33
|
+
<% I18n.available_locales.each do |locale| %>
|
|
34
|
+
<th><%= locale.upcase %></th>
|
|
35
|
+
<% end %>
|
|
36
|
+
<% if @category == 'missing_translations' || @category == 'all_translation_keys' %>
|
|
37
|
+
<th><%= t('path') %></th>
|
|
38
|
+
<% end %>
|
|
39
|
+
<th></th>
|
|
40
|
+
</tr>
|
|
41
|
+
</thead>
|
|
42
|
+
|
|
43
|
+
<tbody>
|
|
44
|
+
<%-# Iteration counter for pagination realisation -%>
|
|
45
|
+
<% key_nr = 0 %>
|
|
46
|
+
<% if @category == 'missing_translations' || @category == 'all_translation_keys' %>
|
|
47
|
+
<% @keys.each do |array| %>
|
|
48
|
+
<% path = array.pop %>
|
|
49
|
+
<% array = array.flatten %>
|
|
50
|
+
<% array.each do |key| %>
|
|
51
|
+
<%-# Checks if this key is in this page-%>
|
|
52
|
+
<% if get_page_size * (params[:page].to_i - 1) <= key_nr && key_nr < get_page_size * params[:page].to_i %>
|
|
53
|
+
<tr>
|
|
54
|
+
<td><%= key %></td>
|
|
55
|
+
<% translations = [] %>
|
|
56
|
+
<% I18n.available_locales.each do |locale| %>
|
|
57
|
+
<% if !I18n.exists?(key, locale) %>
|
|
58
|
+
<td class="missing_translation_cell"><%= key %></td>
|
|
59
|
+
<% else %>
|
|
60
|
+
<td><%= t(key, locale: locale) %></td>
|
|
61
|
+
<% end %>
|
|
62
|
+
<% translations.push t(key, locale: locale) %>
|
|
63
|
+
<% end %>
|
|
64
|
+
<td><i><%= path %></i></td>
|
|
65
|
+
<td class="text-center">
|
|
66
|
+
<%= content_tag 'button', class: 'translate-key-button', data: {toggle: 'modal', target: '#translateModal', key: "#{key}", translations: translations, locales: I18n.available_locales, path: path, unique:
|
|
67
|
+
(key.include? '.') } do %>
|
|
68
|
+
<i class="fa fa-pencil" aria-hidden="true"></i>
|
|
69
|
+
<% end %>
|
|
70
|
+
</td>
|
|
71
|
+
</tr>
|
|
72
|
+
<% end %>
|
|
73
|
+
<% key_nr += 1 %>
|
|
74
|
+
<% end %>
|
|
75
|
+
<% end %>
|
|
76
|
+
|
|
77
|
+
<% else %>
|
|
78
|
+
<% @keys.each do |key| %>
|
|
79
|
+
<% if get_page_size * (params[:page].to_i - 1) <= key_nr && key_nr < get_page_size * params[:page].to_i %>
|
|
80
|
+
<tr>
|
|
81
|
+
<td><%= key %></td>
|
|
82
|
+
<% translations = [] %>
|
|
83
|
+
<% I18n.available_locales.each do |locale| %>
|
|
84
|
+
<td><%= t(key, locale: locale) %></td>
|
|
85
|
+
<% translations.push t(key, locale: locale) %>
|
|
86
|
+
<% end %>
|
|
87
|
+
<td class="text-center">
|
|
88
|
+
<%= content_tag 'button', class: 'translate-key-button', data: {toggle: 'modal', target: '#translateModal', key: "#{key}", translations: translations, locales: I18n.available_locales} do %>
|
|
89
|
+
<i class="fa fa-pencil" aria-hidden="true"></i>
|
|
90
|
+
<% end %>
|
|
91
|
+
</td>
|
|
92
|
+
</tr>
|
|
93
|
+
<% end %>
|
|
94
|
+
<% key_nr += 1 %>
|
|
95
|
+
<% end %>
|
|
96
|
+
<% end %>
|
|
97
|
+
</tbody>
|
|
98
|
+
</table>
|
|
99
|
+
<% end %>
|
|
100
|
+
|
|
101
|
+
<!-- Pagination -->
|
|
102
|
+
<div class="text-center">
|
|
103
|
+
<% if total_pages(@keys.flatten) > 1 %>
|
|
104
|
+
<ul class="pagination">
|
|
105
|
+
<li>
|
|
106
|
+
<% if params[:page].to_i > 1 %>
|
|
107
|
+
<%= link_to '«'.html_safe, page: params[:page].to_i - 1, keys_category: @category %>
|
|
108
|
+
<% end %>
|
|
109
|
+
</li>
|
|
110
|
+
<% for i in 1..total_pages(@keys.flatten) %>
|
|
111
|
+
<% if params[:page].to_i == i %>
|
|
112
|
+
<li class="active"><%= link_to i, page: i, keys_category: @category %></li>
|
|
113
|
+
<% else %>
|
|
114
|
+
<li><%= link_to i, page: i, keys_category: @category %></li>
|
|
115
|
+
<% end %>
|
|
116
|
+
<% end %>
|
|
117
|
+
<li>
|
|
118
|
+
<% unless params[:page].to_i == total_pages(@keys.flatten) %>
|
|
119
|
+
<%= link_to '»'.html_safe, page: params[:page].to_i + 1, keys_category: @category %>
|
|
120
|
+
<% end %>
|
|
121
|
+
</li>
|
|
122
|
+
</ul>
|
|
123
|
+
<% end %>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
</div>
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<!-- Modal -->
|
|
130
|
+
<div class="modal fade" id="translateModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
|
|
131
|
+
<div class="modal-dialog" role="document">
|
|
132
|
+
<div class="modal-content">
|
|
133
|
+
<div class="modal-header">
|
|
134
|
+
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
|
135
|
+
<p class="text-left translation-key"></p>
|
|
136
|
+
<p class="text-left translation-key-path"></p>
|
|
137
|
+
</div>
|
|
138
|
+
<div class="modal-body">
|
|
139
|
+
<%= form_tag kakimasu_keys_path(keys_category: @category), id: 'translation-modal-form', remote: true do %>
|
|
140
|
+
<p>
|
|
141
|
+
<%= hidden_field_tag :key %>
|
|
142
|
+
</p>
|
|
143
|
+
<p>
|
|
144
|
+
<%= hidden_field_tag :path %>
|
|
145
|
+
</p>
|
|
146
|
+
<% I18n.available_locales.each_with_index do |locale, index| %>
|
|
147
|
+
<div class="form-group">
|
|
148
|
+
<div class="row">
|
|
149
|
+
<div class="col-xs-1">
|
|
150
|
+
<%= label_tag locale %>
|
|
151
|
+
</div>
|
|
152
|
+
<div class="col-xs-7 translation-input">
|
|
153
|
+
<%= text_area_tag locale, nil, class: "form-control" %>
|
|
154
|
+
</div>
|
|
155
|
+
<div class="col-xs-4">
|
|
156
|
+
<div class="suggested-translation-link">
|
|
157
|
+
<a href='<%="#modal-translation-#{index}"%>' data-toggle="collapse"><%=t('suggested_translations')%></a>
|
|
158
|
+
<div id='<%="modal-translation-#{index}"%>' class="collapse suggested-translation">
|
|
159
|
+
<p></p>
|
|
160
|
+
</div>
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
<% end %>
|
|
166
|
+
<% if @category == 'missing_translations' || @category == 'all_translation_keys' %>
|
|
167
|
+
<div class="row">
|
|
168
|
+
<div class="col-xs-4 col-xs-offset-1">
|
|
169
|
+
<div id='lazy-lookup-checkbox'></div>
|
|
170
|
+
</div>
|
|
171
|
+
</div>
|
|
172
|
+
<% end %>
|
|
173
|
+
<p class="text-right">
|
|
174
|
+
<%= button_tag(class: "btn btn-primary") do%>
|
|
175
|
+
<% t('save') %>
|
|
176
|
+
<% end %>
|
|
177
|
+
</p>
|
|
178
|
+
<% end %>
|
|
179
|
+
</div>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|