releaf-i18n_database 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +24 -0
  3. data/app/assets/javascripts/releaf/controllers/releaf/i18n_database/translations.js +22 -0
  4. data/app/assets/stylesheets/releaf/controllers/releaf/i18n_database/translations.scss +95 -0
  5. data/app/builders/releaf/i18n_database/translations/builders_common.rb +13 -0
  6. data/app/builders/releaf/i18n_database/translations/edit_builder.rb +41 -0
  7. data/app/builders/releaf/i18n_database/translations/index_builder.rb +44 -0
  8. data/app/builders/releaf/i18n_database/translations/table_builder.rb +31 -0
  9. data/app/controllers/releaf/i18n_database/translations_controller.rb +171 -0
  10. data/app/lib/releaf/i18n_database/translations_importer.rb +72 -0
  11. data/app/lib/releaf/i18n_database/translations_utilities.rb +66 -0
  12. data/app/models/releaf/i18n_database/translation.rb +17 -0
  13. data/app/models/releaf/i18n_database/translation_data.rb +11 -0
  14. data/app/views/releaf/i18n_database/translations/_form_fields.haml +40 -0
  15. data/app/views/releaf/i18n_database/translations/export.xlsx.axlsx +24 -0
  16. data/lib/releaf-i18n_database.rb +5 -0
  17. data/lib/releaf/i18n_database/backend.rb +169 -0
  18. data/lib/releaf/i18n_database/builders_autoload.rb +10 -0
  19. data/lib/releaf/i18n_database/engine.rb +36 -0
  20. data/lib/releaf/i18n_database/humanize_missing_translations.rb +15 -0
  21. data/releaf-i18n_database.gemspec +21 -0
  22. data/spec/builders/translations/builder_common_spec.rb +39 -0
  23. data/spec/builders/translations/edit_builder_spec.rb +93 -0
  24. data/spec/builders/translations/index_builder_spec.rb +96 -0
  25. data/spec/builders/translations/table_builder_spec.rb +68 -0
  26. data/spec/controllers/i18n_backend/translations_controller_spec.rb +157 -0
  27. data/spec/features/translations_spec.rb +162 -0
  28. data/spec/fixtures/all_translations_exported.xlsx +0 -0
  29. data/spec/fixtures/time.formats.xlsx +0 -0
  30. data/spec/fixtures/translations_import.xlsx +0 -0
  31. data/spec/fixtures/unsupported_import_file.png +0 -0
  32. data/spec/lib/i18n_database/backend_spec.rb +337 -0
  33. data/spec/lib/i18n_database/humanize_missing_translations_spec.rb +18 -0
  34. data/spec/lib/i18n_database/translations_importer_spec.rb +17 -0
  35. data/spec/lib/i18n_database/translations_utilities_spec.rb +175 -0
  36. data/spec/models/i18n_database/translation_data_spec.rb +13 -0
  37. data/spec/models/i18n_database/translation_spec.rb +49 -0
  38. metadata +151 -0
@@ -0,0 +1,18 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::I18nDatabase::HumanizeMissingTranslations do
4
+ describe ".call" do
5
+ context "when exception is I18n::MissingTranslation" do
6
+ it "humanizes missing translations" do
7
+ expect(I18n.t("some.missing translation")).to eq("Missing translation")
8
+ end
9
+ end
10
+
11
+ context "when exception is not I18n::MissingTranslation" do
12
+ it "does not intercept it" do
13
+ allow(I18n::Backend::Transliterator).to receive(:get).and_raise(I18n::ArgumentError)
14
+ expect{I18n.transliterate("error?")}.to raise_error(I18n::ArgumentError)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,17 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::I18nDatabase::TranslationsImporter do
4
+ describe "#initialize" do
5
+ context "when unsupported extension given" do
6
+ it "raises Releaf::TranslationsImporter::UnsupportedFileFormatError" do
7
+ expect{described_class.new("xx", "xx")}.to raise_error(described_class::UnsupportedFileFormatError)
8
+ end
9
+ end
10
+
11
+ context "when error raised from Roo" do
12
+ it "raises it" do
13
+ expect{described_class.new("xx", "xls")}.to raise_error(IOError)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,175 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::I18nDatabase::TranslationsUtilities do
4
+ def postgresql?
5
+ ActiveRecord::Base.connection.adapter_name == 'PostgreSQL'
6
+ end
7
+
8
+ describe ".search" do
9
+ before do
10
+ allow(described_class).to receive(:filter_by_text).with("aaa", "xxxx").and_return("bbb")
11
+ allow(described_class).to receive(:filter_only_blank_translations).with("bbb").and_return("ccc")
12
+ allow(described_class).to receive(:filter_only_blank_translations).with("ddd").and_return("eee")
13
+ end
14
+
15
+ context "when search string is present" do
16
+ it "applies search filter to given collection" do
17
+ expect(described_class.search("aaa", "xxxx", true)).to eq("ccc")
18
+ end
19
+ end
20
+
21
+ context "when search string is empty" do
22
+ it "does not apply search filter to given collection" do
23
+ expect(described_class.search("ddd", "", true)).to eq("eee")
24
+ end
25
+ end
26
+
27
+ context "when `only blank` option is true" do
28
+ it "applies `only blank` filter to given collection" do
29
+ expect(described_class.search("aaa", "xxxx", true)).to eq("ccc")
30
+ end
31
+ end
32
+
33
+ context "when `only blank` option is other than true" do
34
+ it "does not apply `only blank` filter to given collection" do
35
+ expect(described_class.search("aaa", "xxxx", false)).to eq("bbb")
36
+ end
37
+ end
38
+ end
39
+
40
+ describe ".filter_only_blank_translations" do
41
+ it "returns given collection applied with empty translation data search" do
42
+ collection = Releaf::I18nDatabase::Translation.where("id > 1")
43
+ allow(described_class).to receive(:search_columns).and_return([
44
+ Releaf::I18nDatabase::Translation.arel_table[:key],
45
+ Releaf::I18nDatabase::Translation.arel_table.alias("lv_data")[:localization],
46
+ ])
47
+ if postgresql?
48
+ result = "WHERE (id > 1) AND ((\"releaf_translations\".\"key\" = '' OR \"releaf_translations\".\"key\" IS NULL)"
49
+ result += " OR (\"lv_data\".\"localization\" = '' OR \"lv_data\".\"localization\" IS NULL))"
50
+ else
51
+ result = "WHERE (id > 1) AND ((`releaf_translations`.`key` = '' OR `releaf_translations`.`key` IS NULL)"
52
+ result += " OR (`lv_data`.`localization` = '' OR `lv_data`.`localization` IS NULL))"
53
+ end
54
+ expect(described_class.filter_only_blank_translations(collection).to_sql).to end_with(result)
55
+ end
56
+ end
57
+
58
+ describe ".filter_by_text" do
59
+ it "returns collection with grouped column searches" do
60
+ collection = Releaf::I18nDatabase::Translation.where("id > 1")
61
+ allow(described_class).to receive(:column_searches).with("redx").and_return([
62
+ "id = 8 AND id = 2",
63
+ "id = 9 AND id = 19",
64
+ ])
65
+ result = "WHERE (id > 1) AND ((id = 8 AND id = 2) OR (id = 9 AND id = 19))"
66
+ expect(described_class.filter_by_text(collection, "redx").to_sql).to end_with(result)
67
+ end
68
+ end
69
+
70
+ describe ".column_searches" do
71
+ it "return array with column based searches" do
72
+ allow(described_class).to receive(:search_columns).and_return([
73
+ Releaf::I18nDatabase::Translation.arel_table[:key],
74
+ Releaf::I18nDatabase::Translation.arel_table.alias("lv_data")[:localization],
75
+ ])
76
+ allow(described_class).to receive(:escape_search_string).with("red").twice.and_return("escaped_red")
77
+ allow(described_class).to receive(:escape_search_string).with("car").twice.and_return("escaped_car")
78
+ if postgresql?
79
+ result = ["\"releaf_translations\".\"key\" ILIKE '%escaped_red%' AND \"releaf_translations\".\"key\" ILIKE '%escaped_car%'",
80
+ "\"lv_data\".\"localization\" ILIKE '%escaped_red%' AND \"lv_data\".\"localization\" ILIKE '%escaped_car%'"]
81
+ else
82
+ result = ["`releaf_translations`.`key` LIKE '%escaped_red%' AND `releaf_translations`.`key` LIKE '%escaped_car%'",
83
+ "`lv_data`.`localization` LIKE '%escaped_red%' AND `lv_data`.`localization` LIKE '%escaped_car%'"]
84
+ end
85
+ expect(described_class.column_searches(" red car ")).to eq(result)
86
+ end
87
+ end
88
+
89
+ describe ".search_columns" do
90
+ it "returns array with translation key arel attribute and locale tables localization attributes" do
91
+ allow(described_class).to receive(:locale_tables).and_return(
92
+ de: Releaf::I18nDatabase::TranslationData.arel_table.alias("de_data"),
93
+ lv: Releaf::I18nDatabase::TranslationData.arel_table.alias("lv_data"),
94
+ en: Releaf::I18nDatabase::TranslationData.arel_table.alias("en_data")
95
+ )
96
+
97
+ result = [
98
+ Releaf::I18nDatabase::Translation.arel_table[:key],
99
+ Releaf::I18nDatabase::TranslationData.arel_table.alias("de_data")[:localization],
100
+ Releaf::I18nDatabase::TranslationData.arel_table.alias("lv_data")[:localization],
101
+ Releaf::I18nDatabase::TranslationData.arel_table.alias("en_data")[:localization]
102
+ ]
103
+ expect(described_class.search_columns).to eq(result)
104
+ end
105
+ end
106
+
107
+ describe ".escape_search_string" do
108
+ it "returns escaped search string with escaped `%` and `_` chars" do
109
+ expect(described_class.escape_search_string("k % _ x")).to eq("k \\% \\_ x")
110
+ end
111
+ end
112
+
113
+ describe ".locale_tables" do
114
+ it "returns array with arel aliased locale tables" do
115
+ allow(Releaf.application.config).to receive(:all_locales).and_return([:de, :en])
116
+ result = {
117
+ de: Releaf::I18nDatabase::TranslationData.arel_table.alias("de_data"),
118
+ en: Releaf::I18nDatabase::TranslationData.arel_table.alias("en_data")
119
+ }
120
+ expect(described_class.locale_tables).to eq(result)
121
+ end
122
+ end
123
+
124
+ describe ".include_localizations" do
125
+ it "returns given collection with included joins and overrided selects" do
126
+ allow(described_class).to receive(:localization_include_joins).and_return(["a", "b"])
127
+ allow(described_class).to receive(:localization_include_selects).and_return("x")
128
+ if postgresql?
129
+ result = "SELECT x FROM \"releaf_translations\" a b"
130
+ else
131
+ result = "SELECT x FROM `releaf_translations` a b"
132
+ end
133
+ expect(described_class.include_localizations(Releaf::I18nDatabase::Translation).to_sql).to eq(result)
134
+ end
135
+ end
136
+
137
+ describe ".localization_include_joins" do
138
+ it "returns array with locales translation table joins" do
139
+ allow(described_class).to receive(:locale_tables).and_return(
140
+ de: Releaf::I18nDatabase::TranslationData.arel_table.alias("de_data"),
141
+ lv: Releaf::I18nDatabase::TranslationData.arel_table.alias("lv_data"),
142
+ en: Releaf::I18nDatabase::TranslationData.arel_table.alias("en_data")
143
+ )
144
+ result = ["LEFT JOIN releaf_translation_data AS de_data ON de_data.translation_id = releaf_translations.id AND de_data.lang = 'de'",
145
+ "LEFT JOIN releaf_translation_data AS lv_data ON lv_data.translation_id = releaf_translations.id AND lv_data.lang = 'lv'",
146
+ "LEFT JOIN releaf_translation_data AS en_data ON en_data.translation_id = releaf_translations.id AND en_data.lang = 'en'"]
147
+ expect(described_class.localization_include_joins).to eq(result)
148
+ end
149
+ end
150
+
151
+ describe ".localization_include_selects" do
152
+ it "returns all base table columns and each locale translated values and ids" do
153
+ allow(described_class).to receive(:localization_include_locales_columns).and_return([
154
+ "de_data.localization AS de_localization",
155
+ "de_data.id AS de_localization_id"
156
+ ])
157
+ result = "releaf_translations.*, de_data.localization AS de_localization, de_data.id AS de_localization_id"
158
+ expect(described_class.localization_include_selects).to eq(result)
159
+ end
160
+ end
161
+
162
+ describe ".localization_include_locales_columns" do
163
+ it "returns locales translated values columns and ids" do
164
+ allow(described_class).to receive(:locale_tables).and_return(
165
+ de: Releaf::I18nDatabase::TranslationData.arel_table.alias("de_data"),
166
+ lv: Releaf::I18nDatabase::TranslationData.arel_table.alias("lv_data"),
167
+ en: Releaf::I18nDatabase::TranslationData.arel_table.alias("en_data")
168
+ )
169
+ result = ["de_data.localization AS de_localization", "de_data.id AS de_localization_id",
170
+ "lv_data.localization AS lv_localization", "lv_data.id AS lv_localization_id",
171
+ "en_data.localization AS en_localization", "en_data.id AS en_localization_id"]
172
+ expect(described_class.localization_include_locales_columns).to eq(result)
173
+ end
174
+ end
175
+ end
@@ -0,0 +1,13 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::I18nDatabase::TranslationData do
4
+
5
+ it { is_expected.to validate_presence_of(:translation) }
6
+ it { is_expected.to validate_presence_of(:lang) }
7
+ it { is_expected.to validate_length_of(:lang).is_at_most(5) }
8
+ it {
9
+ FactoryGirl.create(:translation_data)
10
+ is_expected.to validate_uniqueness_of(:translation_id).scoped_to([:lang])
11
+ }
12
+ it { is_expected.to belong_to(:translation) }
13
+ end
@@ -0,0 +1,49 @@
1
+ require "rails_helper"
2
+
3
+ describe Releaf::I18nDatabase::Translation do
4
+
5
+ it { is_expected.to validate_presence_of(:key) }
6
+ it { is_expected.to validate_length_of(:key).is_at_most(255) }
7
+ it do
8
+ FactoryGirl.create(:translation)
9
+ is_expected.to validate_uniqueness_of(:key)
10
+ end
11
+ it { is_expected.to have_many(:translation_data).dependent(:destroy) }
12
+ it { is_expected.to accept_nested_attributes_for(:translation_data).allow_destroy(true) }
13
+
14
+
15
+ before do
16
+ allow(Releaf.application.config).to receive(:available_locales) { ["de", "en"] }
17
+ allow(Releaf.application.config).to receive(:available_admin_locales) { ["lv"] }
18
+
19
+ @translation = FactoryGirl.create(:translation, :key => 'test.apple')
20
+ FactoryGirl.create(:translation_data, :localization => 'apple', :translation => @translation, :lang => "en")
21
+ FactoryGirl.create(:translation_data, :localization => 'apfel', :translation => @translation, :lang => "de")
22
+
23
+ I18n.backend.reload_cache
24
+ end
25
+
26
+ describe "translation" do
27
+ it "has relation to translation data" do
28
+ expect(@translation.translation_data.size).to eq(2)
29
+ end
30
+
31
+ it "destroys translation data when destroying translation itself" do
32
+ expect{ @translation.destroy }.to change{ Releaf::I18nDatabase::TranslationData.all.count }.from(2).to(0)
33
+ end
34
+ end
35
+
36
+ describe "#locale_value" do
37
+ it "returns translated value for given locale" do
38
+ expect(@translation.locale_value("en")).to eq("apple")
39
+ expect(@translation.locale_value("de")).to eq("apfel")
40
+ expect(@translation.locale_value("lt")).to eq(nil)
41
+ end
42
+
43
+ it "caches translated values with first call" do
44
+ expect(@translation.locale_value("en")).to eq("apple")
45
+ Releaf::I18nDatabase::TranslationData.destroy_all
46
+ expect(@translation.locale_value("de")).to eq("apfel")
47
+ end
48
+ end
49
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: releaf-i18n_database
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ platform: ruby
6
+ authors:
7
+ - CubeSystems
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: releaf-core
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 0.2.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 0.2.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: twitter_cldr
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: axlsx_rails
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.3.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.3.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: roo
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: i18n database backend for releaf
70
+ email: info@cubesystems.lv
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - LICENSE
76
+ - app/assets/javascripts/releaf/controllers/releaf/i18n_database/translations.js
77
+ - app/assets/stylesheets/releaf/controllers/releaf/i18n_database/translations.scss
78
+ - app/builders/releaf/i18n_database/translations/builders_common.rb
79
+ - app/builders/releaf/i18n_database/translations/edit_builder.rb
80
+ - app/builders/releaf/i18n_database/translations/index_builder.rb
81
+ - app/builders/releaf/i18n_database/translations/table_builder.rb
82
+ - app/controllers/releaf/i18n_database/translations_controller.rb
83
+ - app/lib/releaf/i18n_database/translations_importer.rb
84
+ - app/lib/releaf/i18n_database/translations_utilities.rb
85
+ - app/models/releaf/i18n_database/translation.rb
86
+ - app/models/releaf/i18n_database/translation_data.rb
87
+ - app/views/releaf/i18n_database/translations/_form_fields.haml
88
+ - app/views/releaf/i18n_database/translations/export.xlsx.axlsx
89
+ - lib/releaf-i18n_database.rb
90
+ - lib/releaf/i18n_database/backend.rb
91
+ - lib/releaf/i18n_database/builders_autoload.rb
92
+ - lib/releaf/i18n_database/engine.rb
93
+ - lib/releaf/i18n_database/humanize_missing_translations.rb
94
+ - releaf-i18n_database.gemspec
95
+ - spec/builders/translations/builder_common_spec.rb
96
+ - spec/builders/translations/edit_builder_spec.rb
97
+ - spec/builders/translations/index_builder_spec.rb
98
+ - spec/builders/translations/table_builder_spec.rb
99
+ - spec/controllers/i18n_backend/translations_controller_spec.rb
100
+ - spec/features/translations_spec.rb
101
+ - spec/fixtures/all_translations_exported.xlsx
102
+ - spec/fixtures/time.formats.xlsx
103
+ - spec/fixtures/translations_import.xlsx
104
+ - spec/fixtures/unsupported_import_file.png
105
+ - spec/lib/i18n_database/backend_spec.rb
106
+ - spec/lib/i18n_database/humanize_missing_translations_spec.rb
107
+ - spec/lib/i18n_database/translations_importer_spec.rb
108
+ - spec/lib/i18n_database/translations_utilities_spec.rb
109
+ - spec/models/i18n_database/translation_data_spec.rb
110
+ - spec/models/i18n_database/translation_spec.rb
111
+ homepage: https://github.com/cubesystems/releaf
112
+ licenses: []
113
+ metadata: {}
114
+ post_install_message:
115
+ rdoc_options: []
116
+ require_paths:
117
+ - lib
118
+ required_ruby_version: !ruby/object:Gem::Requirement
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ required_rubygems_version: !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - - ">="
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ requirements: []
129
+ rubyforge_project:
130
+ rubygems_version: 2.4.8
131
+ signing_key:
132
+ specification_version: 4
133
+ summary: i18n database gem for releaf
134
+ test_files:
135
+ - spec/builders/translations/builder_common_spec.rb
136
+ - spec/builders/translations/edit_builder_spec.rb
137
+ - spec/builders/translations/index_builder_spec.rb
138
+ - spec/builders/translations/table_builder_spec.rb
139
+ - spec/controllers/i18n_backend/translations_controller_spec.rb
140
+ - spec/features/translations_spec.rb
141
+ - spec/fixtures/all_translations_exported.xlsx
142
+ - spec/fixtures/time.formats.xlsx
143
+ - spec/fixtures/translations_import.xlsx
144
+ - spec/fixtures/unsupported_import_file.png
145
+ - spec/lib/i18n_database/backend_spec.rb
146
+ - spec/lib/i18n_database/humanize_missing_translations_spec.rb
147
+ - spec/lib/i18n_database/translations_importer_spec.rb
148
+ - spec/lib/i18n_database/translations_utilities_spec.rb
149
+ - spec/models/i18n_database/translation_data_spec.rb
150
+ - spec/models/i18n_database/translation_spec.rb
151
+ has_rdoc: