couch_i18n 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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,
|