lit 0.0.4.3 → 0.1.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.
Files changed (46) hide show
  1. data/README.md +27 -35
  2. data/app/assets/javascripts/lit/localizations.js.coffee +8 -1
  3. data/app/assets/stylesheets/lit/application.css +4 -0
  4. data/app/controllers/lit/api/v1/base_controller.rb +19 -0
  5. data/app/controllers/lit/api/v1/locales_controller.rb +14 -0
  6. data/app/controllers/lit/api/v1/localization_keys_controller.rb +16 -0
  7. data/app/controllers/lit/api/v1/localizations_controller.rb +18 -0
  8. data/app/controllers/lit/application_controller.rb +1 -1
  9. data/app/controllers/lit/incomming_localizations_controller.rb +42 -0
  10. data/app/controllers/lit/localization_keys_controller.rb +2 -2
  11. data/app/controllers/lit/localizations_controller.rb +8 -2
  12. data/app/controllers/lit/sources_controller.rb +60 -0
  13. data/app/helpers/lit/localizations_helper.rb +1 -1
  14. data/app/helpers/lit/sources_helper.rb +4 -0
  15. data/app/models/lit/incomming_localization.rb +60 -0
  16. data/app/models/lit/locale.rb +3 -2
  17. data/app/models/lit/localization.rb +33 -3
  18. data/app/models/lit/localization_key.rb +2 -1
  19. data/app/models/lit/localization_version.rb +12 -0
  20. data/app/models/lit/source.rb +87 -0
  21. data/app/views/layouts/lit/_navigation.html.erb +3 -0
  22. data/app/views/lit/incomming_localizations/index.html.erb +47 -0
  23. data/app/views/lit/localization_keys/_localization_row.html.erb +11 -0
  24. data/app/views/lit/localization_keys/index.html.erb +12 -5
  25. data/app/views/lit/localizations/_form.html.erb +9 -1
  26. data/app/views/lit/localizations/_previous_versions_rows.html.erb +15 -0
  27. data/app/views/lit/localizations/previous_versions.js.erb +3 -0
  28. data/app/views/lit/localizations/update.js.erb +2 -2
  29. data/app/views/lit/sources/_form.html.erb +35 -0
  30. data/app/views/lit/sources/edit.html.erb +6 -0
  31. data/app/views/lit/sources/index.html.erb +36 -0
  32. data/app/views/lit/sources/new.html.erb +5 -0
  33. data/app/views/lit/sources/show.html.erb +18 -0
  34. data/config/routes.rb +32 -1
  35. data/db/migrate/20130921071304_create_lit_localization_versions.rb +11 -0
  36. data/db/migrate/20130923162141_create_lit_sources.rb +12 -0
  37. data/db/migrate/20130924151910_create_lit_incomming_localizations.rb +21 -0
  38. data/lib/generators/lit/install/templates/initializer.rb +34 -0
  39. data/lib/generators/lit/install_generator.rb +73 -0
  40. data/lib/lit.rb +2 -0
  41. data/lib/lit/adapters/hash_storage.rb +2 -2
  42. data/lib/lit/adapters/redis_storage.rb +25 -5
  43. data/lib/lit/cache.rb +30 -22
  44. data/lib/lit/i18n_backend.rb +9 -7
  45. data/lib/lit/version.rb +1 -1
  46. metadata +42 -2
@@ -0,0 +1,18 @@
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <strong>Indetifier:</strong>
4
+ <%= @source.identifier %>
5
+ <br/>
6
+ <strong>Url:</strong>
7
+ <%= @source.url %>
8
+ <br/>
9
+ <strong>API key:</strong>
10
+ <%= @source.api_key %>
11
+ <br/>
12
+ <strong>Last updated at:</strong>
13
+ <%= @source.last_updated_at.to_s(:db) unless @source.last_updated_at.nil? %>
14
+ <br/>
15
+
16
+
17
+ <%= link_to 'Edit', edit_source_path(@source) %> |
18
+ <%= link_to 'Back', sources_path %>
@@ -1,5 +1,18 @@
1
1
  Lit::Engine.routes.draw do
2
2
 
3
+
4
+ if Lit.api_enabled
5
+ namespace :api do
6
+ namespace :v1 do
7
+ get '/last_change' => 'localizations#last_change'
8
+ resources :locales, :only=>[:index]
9
+ resources :localization_keys, :only=>[:index]
10
+ resources :localizations, :only=>[:index] do
11
+ get 'last_change', :on=>:collection
12
+ end
13
+ end
14
+ end
15
+ end
3
16
  resources :locales, :only=>[:index, :destroy] do
4
17
  put :hide, :on=>:member
5
18
  end
@@ -10,7 +23,25 @@ Lit::Engine.routes.draw do
10
23
  collection do
11
24
  get :starred
12
25
  end
13
- resources :localizations
26
+ resources :localizations, :only=>[:edit, :update] do
27
+ member do
28
+ get :previous_versions
29
+ end
30
+ end
31
+ end
32
+ resources :sources do
33
+ member do
34
+ get :synchronize
35
+ end
36
+ resources :incomming_localizations, :only=>[:index, :destroy] do
37
+ member do
38
+ get :accept
39
+ end
40
+ collection do
41
+ get :accept_all
42
+ post :reject_all
43
+ end
44
+ end
14
45
  end
15
46
 
16
47
  root :to=>"dashboard#index"
@@ -0,0 +1,11 @@
1
+ class CreateLitLocalizationVersions < ActiveRecord::Migration
2
+ def change
3
+ create_table :lit_localization_versions do |t|
4
+ t.text :translated_value
5
+ t.references :localization
6
+
7
+ t.timestamps
8
+ end
9
+ add_index :lit_localization_versions, :localization_id
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ class CreateLitSources < ActiveRecord::Migration
2
+ def change
3
+ create_table :lit_sources do |t|
4
+ t.string :identifier
5
+ t.string :url
6
+ t.string :api_key
7
+ t.datetime :last_updated_at
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,21 @@
1
+ class CreateLitIncommingLocalizations < ActiveRecord::Migration
2
+ def change
3
+ create_table :lit_incomming_localizations do |t|
4
+ t.text :translated_value
5
+ t.references :locale
6
+ t.references :localization_key
7
+ t.references :localization
8
+ t.string :locale_str
9
+ t.string :localization_key_str
10
+ t.references :source
11
+ t.integer :incomming_id
12
+
13
+ t.timestamps
14
+ end
15
+ add_index :lit_incomming_localizations, :locale_id
16
+ add_index :lit_incomming_localizations, :localization_key_id
17
+ add_index :lit_incomming_localizations, :localization_id
18
+ add_index :lit_incomming_localizations, :source_id
19
+ add_index :lit_incomming_localizations, :incomming_id
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+
2
+ # Which authentication function to use (ie. :authenticate_user!)? When set to
3
+ # `nil` will let everyone in.
4
+ Lit.authentication_function = <%= @authentication_function || 'nil' %>
5
+
6
+ # Either 'redis' or 'hash'. Hash is the fastest, but will fail in multiprocess
7
+ # environment
8
+ Lit.key_value_engine = "<%= @key_value_engine %>"
9
+
10
+ # Pass extra options to key_value_neinge, ie. prefix for redis (only one
11
+ # supported at the moment)
12
+ # Lit.storage_options = { :prefix=>"my_project" }
13
+
14
+ # Translations without default will be humanized (default string will be added)
15
+ # ie. scope.page_header will become "Page header"
16
+ # If `false` then will serve nil instead (but translation will be wrapped in
17
+ # <span title="translation missing string"></span>
18
+ Lit.humanize_key = false
19
+
20
+ # Decide if missing translations will fallback to first found translated value
21
+ # (same key, different language)
22
+ Lit.fallback = true
23
+
24
+ # API enabled? API allows third party browsing your translations, as well as
25
+ # synchronizing them between environments
26
+ Lit.api_enabled = false
27
+
28
+ # API key is required to authorize third party, if API is enabled
29
+ Lit.api_key = "<%= @api_key %>"
30
+
31
+ # Initialize lit
32
+ Lit.init
33
+
34
+
@@ -0,0 +1,73 @@
1
+ require 'rails/generators'
2
+ module Lit
3
+ module Generators
4
+ class InstallGenerator < ::Rails::Generators::Base
5
+ class_option "key-value-engine", :type => :string
6
+ class_option "authentication-function", :type => :string
7
+ class_option "no-migrate", :type => :boolean
8
+
9
+ source_root File.expand_path("../install/templates", __FILE__)
10
+
11
+ desc "Automates Lit installation"
12
+
13
+ def copy_migrations
14
+ puts "Copying Lit migrations..."
15
+ Dir.chdir(::Rails.root) do
16
+ `rake lit:install:migrations`
17
+ end
18
+ end
19
+
20
+ def set_authentication_function
21
+ @authentication_function = options["authentication-function"].presence ||
22
+ ask("What's the authentication function, ie. :authenticate_user! :").presence ||
23
+ nil
24
+ end
25
+
26
+ def set_key_value_engine
27
+ @key_value_engine = options["key-value-engine"].presence ||
28
+ ask("What's the key value engine? ([hash] OR redis):").presence ||
29
+ :hash
30
+ end
31
+
32
+ def add_redis_dependency
33
+ if @key_value_engine == 'redis'
34
+ puts "Adding redis dependency"
35
+ gem 'redis'
36
+ Bundler.with_clean_env do
37
+ run "bundle install"
38
+ end
39
+ end
40
+ end
41
+
42
+ def generate_api_key
43
+ @api_key = SecureRandom.base64 32
44
+ end
45
+
46
+ def add_lit_initializer
47
+ path = "#{::Rails.root}/config/initializers/lit.rb"
48
+ if File.exists?(path)
49
+ puts "Skipping config/initializers/lit.rb creation, file already exists!"
50
+ else
51
+ puts "Adding lit initializer (config/initializers/lit.rb)..."
52
+ template "initializer.rb", path
53
+ end
54
+ end
55
+
56
+ def run_migrations
57
+ unless options["no-migrate"]
58
+ puts "Running rake db:migrate"
59
+ `rake db:migrate`
60
+ end
61
+ end
62
+
63
+ def clear_cache
64
+ Lit.init.cache.reset
65
+ end
66
+
67
+ def mount_engine
68
+ puts "Mounting Lit::Engine at \"/lit\" in config/routes.rb..."
69
+ route "mount Lit::Engine => '/lit'"
70
+ end
71
+ end
72
+ end
73
+ end
data/lib/lit.rb CHANGED
@@ -7,6 +7,8 @@ module Lit
7
7
  mattr_accessor :storage_options
8
8
  mattr_accessor :humanize_key
9
9
  mattr_accessor :fallback
10
+ mattr_accessor :api_enabled
11
+ mattr_accessor :api_key
10
12
  class << self
11
13
  attr_accessor :loader
12
14
  end
@@ -1,8 +1,8 @@
1
1
  module Lit
2
2
  class HashStorage < Hash
3
3
  def incr(key)
4
- self.[key] ||= 0
5
- self.[key] += 1
4
+ self[key] ||= 0
5
+ self[key] += 1
6
6
  end
7
7
  end
8
8
  end
@@ -11,15 +11,29 @@ module Lit
11
11
  end
12
12
 
13
13
  def [](key)
14
- Lit.redis.get(_prefixed_key(key))
14
+ if Lit.redis.exists(_prefixed_key_for_array(key))
15
+ Lit.redis.lrange(_prefixed_key(key), 0, -1)
16
+ else
17
+ Lit.redis.get(_prefixed_key(key))
18
+ end
15
19
  end
16
20
 
17
21
  def []=(k, v)
18
- Lit.redis.set(_prefixed_key(k).to_s, v.to_s)
22
+ if v.is_a?(Array)
23
+ delete(k)
24
+ Lit.redis.set(_prefixed_key_for_array(k), "1")
25
+ v.each do |ve|
26
+ Lit.redis.rpush(_prefixed_key(k), ve.to_s)
27
+ end
28
+ else
29
+ Lit.redis.del(_prefixed_key_for_array(k))
30
+ Lit.redis.set(_prefixed_key(k), v) unless v.nil?
31
+ end
19
32
  end
20
33
 
21
34
  def delete(k)
22
- Lit.redis.del k
35
+ Lit.redis.del(_prefixed_key_for_array(k))
36
+ Lit.redis.del(_prefixed_key(k))
23
37
  end
24
38
 
25
39
  def clear
@@ -45,12 +59,18 @@ module Lit
45
59
  end
46
60
 
47
61
  private
48
- def _prefixed_key(key="")
62
+ def _prefix
49
63
  prefix = "lit:"
50
64
  if Lit.storage_options.is_a?(Hash)
51
65
  prefix += "#{Lit.storage_options[:prefix]}:" if Lit.storage_options.has_key?(:prefix)
52
66
  end
53
- prefix+key
67
+ prefix
68
+ end
69
+ def _prefixed_key(key="")
70
+ _prefix+key.to_s
71
+ end
72
+ def _prefixed_key_for_array(key="")
73
+ _prefix+"array_flags:"+key.to_s
54
74
  end
55
75
  end
56
76
  end
@@ -9,13 +9,23 @@ module Lit
9
9
 
10
10
  def [](key)
11
11
  update_hits_count(key)
12
- @localizations[key]
12
+ ret = @localizations[key]
13
+ ret
13
14
  end
14
15
 
15
16
  def []=(key, value)
16
17
  update_locale(key, value)
17
18
  end
18
19
 
20
+ def init_key_with_value(key, value)
21
+ update_locale(key, value, true)
22
+ end
23
+
24
+ def has_key?(key)
25
+ # @TODO: change into correct has_key? call
26
+ @localizations.has_key?(key)
27
+ end
28
+
19
29
  def sync
20
30
  @localizations.clear
21
31
  end
@@ -24,16 +34,15 @@ module Lit
24
34
  @localizations.keys
25
35
  end
26
36
 
27
- def update_locale(key, value)
37
+ def update_locale(key, value, force_array=false)
28
38
  key = key.to_s
29
39
  locale_key, key_without_locale = split_key(key)
30
40
  locale = find_locale(locale_key)
31
- localization = find_localization(locale, key_without_locale, value)
41
+ localization = find_localization(locale, key_without_locale, value, force_array, true)
32
42
  @localizations[key] = localization.get_value if localization
33
43
  end
34
44
 
35
45
  def load_all_translations(oninit=false)
36
- Lit.init.logger.info "loading all translations"
37
46
  doinit = false
38
47
  first = Localization.order('id ASC').first
39
48
  last = Localization.order('id DESC').first
@@ -51,7 +60,6 @@ module Lit
51
60
 
52
61
  def refresh_key(key)
53
62
  key = key.to_s
54
- Lit.init.logger.info "refreshing key: #{key}"
55
63
  locale_key, key_without_locale = split_key(key)
56
64
  locale = find_locale(locale_key)
57
65
  localization = find_localization(locale, key_without_locale)
@@ -60,7 +68,6 @@ module Lit
60
68
 
61
69
  def delete_key(key)
62
70
  key = key.to_s
63
- Lit.init.logger.info "deleting key: #{key}"
64
71
  @localizations.delete(key)
65
72
  key_without_locale = split_key(key).last
66
73
  @localization_keys.delete(key_without_locale)
@@ -80,7 +87,6 @@ module Lit
80
87
  locale_key = locale_key.to_s
81
88
  @locale_cache ||= {}
82
89
  unless @locale_cache.has_key?(locale_key)
83
- #Lit.init.logger.info "looking for locale: #{locale_key}"
84
90
  locale = Lit::Locale.where(:locale=>locale_key).first_or_create!
85
91
  @locale_cache[locale_key] = locale
86
92
  end
@@ -131,19 +137,22 @@ module Lit
131
137
 
132
138
  private
133
139
 
134
- def find_localization(locale, key_without_locale, value=nil)
140
+ def find_localization(locale, key_without_locale, value=nil, force_array=false, update_value=false)
135
141
  unless value.is_a?(Hash)
136
142
  localization_key = find_localization_key(key_without_locale)
137
143
  localization = Lit::Localization.where(:locale_id=>locale.id).
138
- where(:localization_key_id=>localization_key.id).first_or_create do |l|
144
+ where(:localization_key_id=>localization_key.id).first_or_initialize
145
+ if update_value || localization.new_record?
139
146
  if value.is_a?(Array)
140
- new_value = nil
141
- value_clone = value.dup
142
- while (v = value_clone.shift) && v.present?
143
- pv = parse_value(v, locale)
144
- new_value = pv unless pv.nil?
147
+ unless force_array
148
+ new_value = nil
149
+ value_clone = value.dup
150
+ while (v = value_clone.shift) && v.present?
151
+ pv = parse_value(v, locale)
152
+ new_value = pv unless pv.nil?
153
+ end
154
+ value = new_value
145
155
  end
146
- value = new_value
147
156
  else
148
157
  value = parse_value(value, locale) unless value.nil?
149
158
  end
@@ -157,14 +166,14 @@ module Lit
157
166
  end
158
167
  end
159
168
  end
160
- value = key_without_locale.split('.').last.humanize if value.nil? &&
169
+ value = key_without_locale.split('.').last.humanize if value.nil? &&
161
170
  Lit.humanize_key
162
171
  end
163
- l.default_value = value
172
+ localization.default_value = value
173
+ localization.save!
164
174
  end
165
- localization
175
+ return localization
166
176
  else
167
- Lit.init.logger.info "returning value for hash: #{key_without_locale}: #{value.to_s}"
168
177
  nil
169
178
  end
170
179
  end
@@ -211,14 +220,13 @@ module Lit
211
220
  end
212
221
 
213
222
  def find_or_create_localization_key(key_without_locale)
214
- #Lit.init.logger.info "creating key: #{key_without_locale} with id #{localization_key.id}"
215
- localization_key = Lit::LocalizationKey.where(:localization_key=>key_without_locale).first_or_create!
223
+ localization_key = Lit::LocalizationKey.where(:localization_key=>key_without_locale).first_or_create!
216
224
  @localization_keys[key_without_locale] = localization_key.id
217
225
  localization_key
218
226
  end
219
227
 
220
228
  def update_hits_count(key)
221
- if @hits_counter_working
229
+ if @hits_counter_working
222
230
  key_without_locale = split_key(key).last
223
231
  @hits_counter.incr('hits_counter.'+key)
224
232
  @hits_counter.incr('global_hits_counter.'+key_without_locale)
@@ -27,7 +27,6 @@ module Lit
27
27
  # @param [Hash] data nested key-value pairs to be added as blurbs
28
28
  def store_translations(locale, data, options = {})
29
29
  super
30
- #Lit.init.logger.info "store translation: #{locale}, data: #{data}, options: #{options}"
31
30
  store_item(locale, data)
32
31
  end
33
32
 
@@ -37,14 +36,17 @@ module Lit
37
36
  def lookup(locale, key, scope = [], options = {})
38
37
  parts = I18n.normalize_keys(locale, key, scope, options[:separator])
39
38
  key_with_locale = parts.join('.')
40
-
39
+
41
40
  ## check in cache or in simple backend
42
41
  content = @cache[key_with_locale] || super
43
-
44
- ## store value if not found
45
- if content.nil?
46
- @cache[key_with_locale] = options[:default]
47
- content = @cache[key_with_locale]
42
+ newly_created = false
43
+ unless @cache.has_key?(key_with_locale)
44
+ @cache.init_key_with_value(key_with_locale, content)
45
+ newly_created = true
46
+ end
47
+ if content.nil? || (newly_created && options[:default].present?)
48
+ @cache[key_with_locale] = options[:default]
49
+ content = @cache[key_with_locale]
48
50
  end
49
51
  ## return translated content
50
52
  content