couch_i18n 0.1.0 → 0.2.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.
- data/Rakefile +14 -3
- data/app/assets/stylesheets/couch_i18n/structure.css.scss +11 -1
- data/app/controllers/couch_i18n/translations_controller.rb +37 -14
- data/app/helpers/couch_i18n/application_helper.rb +8 -0
- data/app/models/couch_i18n/translation.rb +19 -6
- data/app/views/couch_i18n/translations/index.html.haml +15 -3
- data/config/locales/couch_i18n.en.yml +49 -0
- data/lib/couch_i18n/backend.rb +0 -3
- data/lib/couch_i18n/engine.rb +2 -1
- data/lib/couch_i18n/store.rb +1 -1
- data/lib/couch_i18n.rb +17 -4
- metadata +19 -8
data/Rakefile
CHANGED
@@ -5,7 +5,15 @@ rescue LoadError
|
|
5
5
|
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
6
|
end
|
7
7
|
|
8
|
-
|
8
|
+
begin
|
9
|
+
require 'rdoc/task'
|
10
|
+
rescue LoadError
|
11
|
+
require 'rdoc/rdoc'
|
12
|
+
require 'rake/rdoctask'
|
13
|
+
RDoc::Task = Rake::RDocTask
|
14
|
+
end
|
15
|
+
require 'rspec/core'
|
16
|
+
require 'rspec/core/rake_task'
|
9
17
|
|
10
18
|
Rake::RDocTask.new(:rdoc) do |rdoc|
|
11
19
|
rdoc.rdoc_dir = 'rdoc'
|
@@ -15,7 +23,10 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
15
23
|
rdoc.rdoc_files.include('lib/**/*.rb')
|
16
24
|
end
|
17
25
|
|
18
|
-
|
26
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
27
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
28
|
+
end
|
29
|
+
APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
|
19
30
|
load 'rails/tasks/engine.rake'
|
20
31
|
|
21
32
|
require 'rake/testtask'
|
@@ -28,4 +39,4 @@ Rake::TestTask.new(:test) do |t|
|
|
28
39
|
end
|
29
40
|
|
30
41
|
|
31
|
-
task :default => :
|
42
|
+
task :default => :spec
|
@@ -55,8 +55,13 @@ tr.even{
|
|
55
55
|
border-color: #444;
|
56
56
|
border-left-width: 0;
|
57
57
|
border-right-width: 0;
|
58
|
+
padding: 5px 0;
|
59
|
+
margin-top: 5px;
|
58
60
|
.offset-navigation-deeper, .offset-navigation-higher{
|
59
61
|
a{
|
62
|
+
float: left;
|
63
|
+
margin-right: 5px;
|
64
|
+
margin-top: 5px;
|
60
65
|
padding: 4px;
|
61
66
|
border: 1px solid #aaa;
|
62
67
|
&:hover {
|
@@ -64,6 +69,11 @@ tr.even{
|
|
64
69
|
border-color: black;
|
65
70
|
}
|
66
71
|
}
|
67
|
-
padding: 8px;
|
68
72
|
}
|
73
|
+
.offset-navigation-form{
|
74
|
+
margin-top: 5px;
|
75
|
+
}
|
76
|
+
}
|
77
|
+
.clearing{
|
78
|
+
clear: both;
|
69
79
|
}
|
@@ -2,21 +2,37 @@ module CouchI18n
|
|
2
2
|
class TranslationsController < CouchI18n::ApplicationController
|
3
3
|
def index
|
4
4
|
@available_higher_offsets = []
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
@
|
9
|
-
|
10
|
-
|
11
|
-
:offset => @levels[0..i].join('.')
|
12
|
-
}
|
13
|
-
end
|
14
|
-
@translations = CouchI18n::Translation.with_offset(params[:offset], :page => params[:page], :per_page => 30)
|
15
|
-
@available_deeper_offsets = CouchI18n::Translation.get_keys_by_level(@levels.size, :startkey => @levels, :endkey => @levels + [{}]).
|
16
|
-
map{|dl| {:name => dl, :offset => [params[:offset], dl].join('.')}}
|
5
|
+
@available_deeper_offsets = []
|
6
|
+
per_page = params[:per_page].presence.try(:to_i) || 30
|
7
|
+
if params[:partfinder].present?
|
8
|
+
@translations = CouchI18n::Translation.find_all_by_key_part(params[:offset], page: params[:page], per_page: per_page)
|
9
|
+
elsif params[:valuefinder].present?
|
10
|
+
@translations = CouchI18n::Translation.find_all_by_value(params[:offset], page: params[:page], per_page: per_page)
|
17
11
|
else
|
18
|
-
|
19
|
-
|
12
|
+
if params[:offset].present?
|
13
|
+
@levels = params[:offset].split('.')
|
14
|
+
# Add higher levels. Do not add the last level, since it is the current one => 0..-2
|
15
|
+
@levels[0..-2].each_with_index do |level_name, i|
|
16
|
+
@available_higher_offsets << {
|
17
|
+
:name => level_name,
|
18
|
+
:offset => @levels[0..i].join('.')
|
19
|
+
}
|
20
|
+
end
|
21
|
+
if untranslated?
|
22
|
+
@translations = CouchI18n::Translation.untranslated_with_offset(params[:offset], :page => params[:page], :per_page => per_page)
|
23
|
+
else
|
24
|
+
@translations = CouchI18n::Translation.with_offset(params[:offset], :page => params[:page], :per_page => per_page)
|
25
|
+
end
|
26
|
+
@available_deeper_offsets = CouchI18n::Translation.get_keys_by_level(@levels.size, :startkey => @levels, :endkey => @levels + [{}]).
|
27
|
+
map{|dl| {:name => dl, :offset => [params[:offset], dl].join('.')}}
|
28
|
+
else
|
29
|
+
if untranslated?
|
30
|
+
@translations = CouchI18n::Translation.untranslated(:page => params[:page], :per_page => per_page)
|
31
|
+
else
|
32
|
+
@translations = CouchI18n::Translation.all(:page => params[:page], :per_page => per_page)
|
33
|
+
end
|
34
|
+
@available_deeper_offsets = CouchI18n::Translation.get_keys_by_level(0).map{|dl| {:name => dl, :offset => dl}}
|
35
|
+
end
|
20
36
|
end
|
21
37
|
end
|
22
38
|
|
@@ -138,5 +154,12 @@ module CouchI18n
|
|
138
154
|
@translations.map(&:destroy)
|
139
155
|
redirect_to({:action => :index}, :notice => I18n.t('couch_i18n.translation.offset deleted', :count => @translations.size, :offset => params[:offset]))
|
140
156
|
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
def untranslated?
|
161
|
+
params[:untranslated].presence
|
162
|
+
end
|
163
|
+
helper_method :untranslated?
|
141
164
|
end
|
142
165
|
end
|
@@ -29,7 +29,7 @@ module CouchI18n
|
|
29
29
|
emit(parts[i], 1);
|
30
30
|
}
|
31
31
|
}
|
32
|
-
}
|
32
|
+
}|, reduce_function: '_count'
|
33
33
|
|
34
34
|
def self.get_keys_by_level(level = 0, options = {})
|
35
35
|
data = database.view(with_key_array(options.merge(:group_level => level.succ)))["rows"]
|
@@ -42,16 +42,29 @@ module CouchI18n
|
|
42
42
|
CouchI18n::Translation.find_all_by_key("#{offset}.".."#{offset}.ZZZZZZZZZ", options)
|
43
43
|
end
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
# Find all records having the term part in their key
|
46
|
+
# nl.action.one
|
47
|
+
# en.action.two
|
48
|
+
# en.activemodel.plural.models.user
|
49
|
+
# and using
|
50
|
+
# find_all_by_part('action')
|
51
|
+
# will return the first two since they have action as key part
|
52
|
+
def self.find_all_by_key_part(part, options = {})
|
53
|
+
total_entries = database.view(by_key_part(key: part, reduce: true))
|
54
|
+
with_pagination_options options.merge(total_entries: total_entries) do |options|
|
55
|
+
database.view(by_key_part(options.merge(key: part, reduce: false, include_docs: true)))
|
56
|
+
end
|
47
57
|
end
|
48
58
|
|
49
|
-
def self.untranslated(
|
50
|
-
database.view(untranslated_view(
|
59
|
+
def self.untranslated(options = {})
|
60
|
+
total_entries = database.view(untranslated_view(options.select{|k,v| [:key, :keys, :startkey, :endkey].include?(k)}.merge(reduce: true)))
|
61
|
+
with_pagination_options options.merge(total_entries: total_entries) do |options|
|
62
|
+
database.view(untranslated_view(options))
|
63
|
+
end
|
51
64
|
end
|
52
65
|
|
53
66
|
def self.untranslated_with_offset(offset, options = {})
|
54
|
-
CouchI18n::Translation.untranslated("#{offset}.".."#{offset}.ZZZZZZZZZ"
|
67
|
+
CouchI18n::Translation.untranslated(options.merge(key: "#{offset}.".."#{offset}.ZZZZZZZZZ"))
|
55
68
|
end
|
56
69
|
|
57
70
|
# Expire I18n when record is update
|
@@ -6,11 +6,13 @@
|
|
6
6
|
= link_to t('couch_i18n.action.destroy.offset_link'), couch_i18n.destroy_offset_translations_path(:offset => params[:offset]), :method => :delete, :confirm => (defined?(:are_you_sure) ? are_you_sure : t('couch_i18n.general.are_you_sure'))
|
7
7
|
.import-form
|
8
8
|
= form_tag({:action => :import}, :multipart => true) do
|
9
|
+
= label_tag :importfile, t('couch_i18n.import.label')
|
9
10
|
= file_field_tag :importfile
|
10
11
|
= submit_tag I18n.t('couch_i18n.import.button')
|
11
12
|
.export-form
|
12
13
|
= form_tag :action => :export do
|
13
14
|
= hidden_field_tag :offset, params[:offset]
|
15
|
+
= label_tag :exportformat, t('couch_i18n.export.label')
|
14
16
|
= select_tag :exportformat, options_for_select(%w[yml csv json], params[:exportformat])
|
15
17
|
= check_box_tag :untranslated
|
16
18
|
= label_tag :untranslated, t('couch_i18n.export.untranslated')
|
@@ -19,16 +21,22 @@
|
|
19
21
|
.offset-navigation-higher
|
20
22
|
- for offset in @available_higher_offsets
|
21
23
|
= link_to offset[:name], :offset => offset[:offset]
|
24
|
+
.clearing
|
22
25
|
.offset-navigation-form
|
23
26
|
= form_tag({}, :method => :get )do
|
24
27
|
- if params[:offset].present?
|
25
28
|
= link_to I18n.t('couch_i18n.general.go_to_zero_offset'), :offset => nil
|
26
29
|
= text_field_tag :offset, params[:offset], :size => 60
|
27
|
-
= "(#{@translations.
|
28
|
-
|
30
|
+
= "(#{@translations.total_count})"
|
31
|
+
%input{:type => :submit, :name => :commit, :value => I18n.t('couch_i18n.general.go_to_offset')}
|
32
|
+
%input{:type => :submit, :name => :partfinder, :value => I18n.t('couch_i18n.general.find_part')}
|
33
|
+
%input{:type => :submit, :name => :valuefinder, :value => I18n.t('couch_i18n.general.find_value')}
|
34
|
+
= check_box_tag :untranslated, 1, untranslated?
|
35
|
+
= label_tag :untranslated, I18n.t('couch_i18n.general.untranslated_label')
|
29
36
|
.offset-navigation-deeper
|
30
37
|
- for offset in @available_deeper_offsets
|
31
38
|
= link_to offset[:name], :offset => offset[:offset]
|
39
|
+
.clearing
|
32
40
|
- if @translations.any?
|
33
41
|
= paginate @translations, :right => 3, :left => 3
|
34
42
|
%table.index-table
|
@@ -42,7 +50,11 @@
|
|
42
50
|
%tbody
|
43
51
|
- @translations.each do |translation|
|
44
52
|
%tr{:class => cycle('odd', 'even')}
|
45
|
-
%td
|
53
|
+
%td
|
54
|
+
- if partfinder? || valuefinder?
|
55
|
+
= link_to translation.key.sub(/^\./, ''), couch_i18n.edit_translation_path(translation)
|
56
|
+
- else
|
57
|
+
= link_to translation.key[(params[:offset].try(:size) || 0)..-1].sub(/^\./, ''), couch_i18n.edit_translation_path(translation)
|
46
58
|
%td= link_to translation.value, couch_i18n.edit_translation_path(translation)
|
47
59
|
%td.boolean= boolean_show(translation.translated)
|
48
60
|
%td.action.edit= link_to link_to_edit_content(translation), couch_i18n.edit_translation_path(translation)
|
@@ -0,0 +1,49 @@
|
|
1
|
+
---
|
2
|
+
en:
|
3
|
+
couch_i18n:
|
4
|
+
action:
|
5
|
+
edit:
|
6
|
+
title: Edit translation
|
7
|
+
destroy:
|
8
|
+
label: Delete
|
9
|
+
offset_link: Delete all from offset
|
10
|
+
edit:
|
11
|
+
label: Edit
|
12
|
+
index:
|
13
|
+
label: Translations
|
14
|
+
title: Translations
|
15
|
+
new:
|
16
|
+
label: New
|
17
|
+
update:
|
18
|
+
button_text: Update
|
19
|
+
export:
|
20
|
+
execute: Execute
|
21
|
+
untranslated: Untranslated
|
22
|
+
label: Export
|
23
|
+
general:
|
24
|
+
are_you_sure: 'Are you sure?'
|
25
|
+
boolean_false: 'no'
|
26
|
+
boolean_true: 'yes'
|
27
|
+
go_to_offset: Go to offset
|
28
|
+
go_to_zero_offset: x
|
29
|
+
find_part: Find key part
|
30
|
+
find_value: Find value
|
31
|
+
none_found: No translations found
|
32
|
+
site_title: CouchI18n translations
|
33
|
+
untranslated_title: Untranslated
|
34
|
+
import:
|
35
|
+
button: Import
|
36
|
+
label: Import
|
37
|
+
activemodel:
|
38
|
+
models:
|
39
|
+
couch_i18n:
|
40
|
+
translation: Translation
|
41
|
+
plural:
|
42
|
+
couch_i18n:
|
43
|
+
translation: Translations
|
44
|
+
attributes:
|
45
|
+
couch_i18n:
|
46
|
+
translation:
|
47
|
+
key: Key
|
48
|
+
value: Value
|
49
|
+
translated: 'Translated?'
|
data/lib/couch_i18n/backend.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
require 'i18n/backend/base'
|
2
2
|
require 'active_support/json'
|
3
|
-
require 'active_support/ordered_hash' # active_support/json/encoding uses ActiveSupport::OrderedHash but does not require it
|
4
|
-
require "i18n/backend/cache"
|
5
3
|
module CouchI18n
|
6
4
|
class Backend
|
7
5
|
# This is a basic backend for key value stores. It receives on
|
@@ -52,7 +50,6 @@ module CouchI18n
|
|
52
50
|
attr_accessor :store
|
53
51
|
|
54
52
|
include I18n::Backend::Base, I18n::Backend::Flatten
|
55
|
-
include I18n::Backend::Cache
|
56
53
|
def initialize(store, subtrees=true)
|
57
54
|
@store, @subtrees = store, subtrees
|
58
55
|
end
|
data/lib/couch_i18n/engine.rb
CHANGED
data/lib/couch_i18n/store.rb
CHANGED
@@ -17,7 +17,7 @@ module CouchI18n
|
|
17
17
|
# alias for read
|
18
18
|
def [](key, options = {})
|
19
19
|
key = key.to_s.gsub('/', '.')
|
20
|
-
Rails.cache.fetch(key) do
|
20
|
+
Rails.cache.fetch("couch_i18n-#{key}") do
|
21
21
|
old_database_name = get_couchrest_name
|
22
22
|
begin
|
23
23
|
set_couchrest_name CouchPotato::Config.database_name # Set database to original configured name
|
data/lib/couch_i18n.rb
CHANGED
@@ -4,8 +4,11 @@ require 'couch_i18n/backend'
|
|
4
4
|
require 'couch_i18n/active_model_errors'
|
5
5
|
module CouchI18n
|
6
6
|
# This method imports yaml translations to the couchdb version. When run again new ones will
|
7
|
-
# be added. Translations already stored in the couchdb database are not overwritten
|
8
|
-
def self.import_from_yaml
|
7
|
+
# be added. Translations already stored in the couchdb database are not overwritten if true or ovveride_existing: true is given
|
8
|
+
def self.import_from_yaml(options = {})
|
9
|
+
options = {:override_existing => true} if options.is_a?(TrueClass)
|
10
|
+
options = {:override_existing => false} if options.is_a?(FalseClass)
|
11
|
+
options = {:override_existing => false}.merge!(options)
|
9
12
|
raise "I18.backend not a I18n::Backend::Chain" unless I18n.backend.is_a?(I18n::Backend::Chain)
|
10
13
|
#
|
11
14
|
yml_backend = I18n.backend.backends.last
|
@@ -13,8 +16,16 @@ module CouchI18n
|
|
13
16
|
raise "Last backend not a I18n::Backend::Simple" unless yml_backend.is_a?(I18n::Backend::Simple)
|
14
17
|
yml_backend.load_translations
|
15
18
|
flattened_hash = traverse_flatten_keys(yml_backend.send(:translations))
|
19
|
+
available_translations = CouchI18n::Translation.all
|
16
20
|
flattened_hash.each do |key, value|
|
17
|
-
|
21
|
+
available_translation = available_translations.find{|t| t.key == key}
|
22
|
+
if available_translation && options[:override_existing]
|
23
|
+
available_translation.value = value
|
24
|
+
available_translation.translated = true
|
25
|
+
available_translation.save
|
26
|
+
else
|
27
|
+
available_translation = CouchI18n::Translation.create :key => key, :value => value
|
28
|
+
end
|
18
29
|
end
|
19
30
|
end
|
20
31
|
|
@@ -58,9 +69,11 @@ module CouchI18n
|
|
58
69
|
# Add all translations to the cache to avoid one by one loading and caching
|
59
70
|
def self.cache_all
|
60
71
|
CouchI18n::Translation.all.each do |t|
|
61
|
-
Rails.cache.write(t.key, t.value)
|
72
|
+
Rails.cache.write("couch_i18n-#{t.key}", t.value)
|
62
73
|
end
|
63
74
|
end
|
64
75
|
end
|
76
|
+
|
65
77
|
# Now extend the I18n backend
|
66
78
|
I18n.backend = I18n::Backend::Chain.new(CouchI18n::Backend.new(CouchI18n::Store.new), I18n.backend) unless Rails.env == 'test'
|
79
|
+
I18n.load_path += Dir.glob(File.join(File.dirname(__FILE__), '..', 'config', 'locales', '*'))
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: couch_i18n
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,27 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activemodel
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: '
|
21
|
+
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: simply_stored
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,7 +37,12 @@ dependencies:
|
|
32
37
|
version: '0'
|
33
38
|
type: :runtime
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
36
46
|
description: couch_i18n is an in database storage for I18n translations, tested for
|
37
47
|
rails, with online management views
|
38
48
|
email: bterkuile@gmail.com
|
@@ -64,6 +74,7 @@ files:
|
|
64
74
|
- app/views/couch_i18n/translations/index.html.haml
|
65
75
|
- app/views/couch_i18n/translations/new.html.haml
|
66
76
|
- app/views/layouts/couch_i18n/application.html.haml
|
77
|
+
- config/locales/couch_i18n.en.yml
|
67
78
|
- config/routes.rb
|
68
79
|
- MIT-LICENSE
|
69
80
|
- Rakefile
|
@@ -88,7 +99,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
99
|
version: '0'
|
89
100
|
requirements: []
|
90
101
|
rubyforge_project: couch_i18n
|
91
|
-
rubygems_version: 1.8.
|
102
|
+
rubygems_version: 1.8.24
|
92
103
|
signing_key:
|
93
104
|
specification_version: 3
|
94
105
|
summary: couch_i18n is an in database storage for I18n translations, tested for rails,
|