lesli_babel 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +5 -0
  3. data/app/assets/config/lesli_babel_manifest.js +7 -0
  4. data/app/assets/images/lesli_babel/babel-logo.svg +157 -0
  5. data/app/assets/javascripts/lesli_babel/application.js +3288 -0
  6. data/app/assets/stylesheets/lesli_babel/application.scss +41 -0
  7. data/app/assets/stylesheets/lesli_babel/dashboards.scss +55 -0
  8. data/app/assets/stylesheets/lesli_babel/modules.scss +33 -0
  9. data/app/assets/stylesheets/lesli_babel/translations.scss +58 -0
  10. data/app/controllers/lesli_babel/application_controller.rb +37 -0
  11. data/app/controllers/lesli_babel/buckets_controller.rb +79 -0
  12. data/app/controllers/lesli_babel/clones_controller.rb +80 -0
  13. data/app/controllers/lesli_babel/dashboards_controller.rb +38 -0
  14. data/app/controllers/lesli_babel/modules_controller.rb +91 -0
  15. data/app/controllers/lesli_babel/relevants_controller.rb +38 -0
  16. data/app/controllers/lesli_babel/strings_controller.rb +142 -0
  17. data/app/controllers/lesli_babel/translations_controller.rb +134 -0
  18. data/app/jobs/lesli_babel/application_job.rb +7 -0
  19. data/app/mailers/lesli_babel/application_mailer.rb +6 -0
  20. data/app/models/lesli_babel/application_record.rb +36 -0
  21. data/app/models/lesli_babel/bucket.rb +6 -0
  22. data/app/models/lesli_babel/clone.rb +24 -0
  23. data/app/models/lesli_babel/dashboard.rb +35 -0
  24. data/app/models/lesli_babel/module.rb +35 -0
  25. data/app/models/lesli_babel/relevant.rb +21 -0
  26. data/app/models/lesli_babel/string/activity.rb +5 -0
  27. data/app/models/lesli_babel/string/discussion.rb +68 -0
  28. data/app/models/lesli_babel/string.rb +225 -0
  29. data/app/models/lesli_babel/translation.rb +5 -0
  30. data/app/services/lesli_babel/module_service.rb +18 -0
  31. data/app/services/lesli_babel/old/translations_android_service.rb +82 -0
  32. data/app/services/lesli_babel/old/translations_clone_service.rb +161 -0
  33. data/app/services/lesli_babel/old/translations_flutter_service.rb +102 -0
  34. data/app/services/lesli_babel/old/translations_ios_service.rb +119 -0
  35. data/app/services/lesli_babel/old/translations_js_service.rb +114 -0
  36. data/app/services/lesli_babel/old/translations_middleman_service.rb +77 -0
  37. data/app/services/lesli_babel/old/translations_rails_service.rb +119 -0
  38. data/app/services/lesli_babel/old/translations_service.rb +97 -0
  39. data/app/services/lesli_babel/old/translations_synchronization_service.rb +215 -0
  40. data/app/services/lesli_babel/string_service.rb +80 -0
  41. data/app/views/lesli_babel/buckets/_form.html.erb +17 -0
  42. data/app/views/lesli_babel/buckets/edit.html.erb +6 -0
  43. data/app/views/lesli_babel/buckets/index.html.erb +25 -0
  44. data/app/views/lesli_babel/buckets/new.html.erb +5 -0
  45. data/app/views/lesli_babel/buckets/show.html.erb +4 -0
  46. data/app/views/lesli_babel/clones/_form.html.erb +19 -0
  47. data/app/views/lesli_babel/clones/edit.html.erb +20 -0
  48. data/app/views/lesli_babel/clones/index.html.erb +20 -0
  49. data/app/views/lesli_babel/clones/new.html.erb +20 -0
  50. data/app/views/lesli_babel/clones/show.html.erb +20 -0
  51. data/app/views/lesli_babel/dashboards/show.html.erb +1 -0
  52. data/app/views/lesli_babel/dashboards/stats..html.erb +1 -0
  53. data/app/views/lesli_babel/modules/_form.html.erb +17 -0
  54. data/app/views/lesli_babel/modules/edit.html.erb +1 -0
  55. data/app/views/lesli_babel/modules/index.html.erb +1 -0
  56. data/app/views/lesli_babel/modules/new.html.erb +1 -0
  57. data/app/views/lesli_babel/modules/show.html.erb +1 -0
  58. data/app/views/lesli_babel/partials/_engine-navigation.html.erb +37 -0
  59. data/app/views/lesli_babel/partials/_engine-sidebar.html.erb +45 -0
  60. data/app/views/lesli_babel/relevants/edit.html.erb +20 -0
  61. data/app/views/lesli_babel/relevants/index.html.erb +21 -0
  62. data/app/views/lesli_babel/relevants/new.html.erb +20 -0
  63. data/app/views/lesli_babel/relevants/show.html.erb +20 -0
  64. data/app/views/lesli_babel/string/activities/_form.html.erb +17 -0
  65. data/app/views/lesli_babel/string/activities/edit.html.erb +6 -0
  66. data/app/views/lesli_babel/string/activities/index.html.erb +25 -0
  67. data/app/views/lesli_babel/string/activities/new.html.erb +5 -0
  68. data/app/views/lesli_babel/string/activities/show.html.erb +4 -0
  69. data/app/views/lesli_babel/string/discussions/_form.html.erb +17 -0
  70. data/app/views/lesli_babel/string/discussions/edit.html.erb +6 -0
  71. data/app/views/lesli_babel/string/discussions/index.html.erb +25 -0
  72. data/app/views/lesli_babel/string/discussions/new.html.erb +5 -0
  73. data/app/views/lesli_babel/string/discussions/show.html.erb +4 -0
  74. data/app/views/lesli_babel/strings/_form.html.erb +17 -0
  75. data/app/views/lesli_babel/strings/edit.html.erb +6 -0
  76. data/app/views/lesli_babel/strings/index.html.erb +25 -0
  77. data/app/views/lesli_babel/strings/new.html.erb +5 -0
  78. data/app/views/lesli_babel/strings/show.html.erb +4 -0
  79. data/app/views/lesli_babel/translations/_form.html.erb +17 -0
  80. data/app/views/lesli_babel/translations/edit.html.erb +6 -0
  81. data/app/views/lesli_babel/translations/index.html.erb +1 -0
  82. data/app/views/lesli_babel/translations/new.html.erb +5 -0
  83. data/app/views/lesli_babel/translations/show.html.erb +1 -0
  84. data/config/routes.rb +63 -0
  85. data/db/migrate/v1.0/0901100110_create_lesli_babel_modules.rb +42 -0
  86. data/db/migrate/v1.0/0901110110_create_lesli_babel_buckets.rb +43 -0
  87. data/db/migrate/v1.0/0901120110_create_lesli_babel_strings.rb +80 -0
  88. data/lib/lesli_babel/engine.rb +54 -0
  89. data/lib/lesli_babel/version.rb +3 -0
  90. data/lib/lesli_babel.rb +6 -0
  91. data/lib/tasks/lesli_babel_tasks.rake +121 -0
  92. data/lib/vue/application.js +46 -0
  93. data/lib/vue/apps/dashboards/show.vue +85 -0
  94. data/lib/vue/apps/modules/show.vue +97 -0
  95. data/lib/vue/apps/relevants/index.vue +47 -0
  96. data/lib/vue/apps/translations/index.vue +64 -0
  97. data/lib/vue/components/actions.vue +29 -0
  98. data/lib/vue/components/form-label-editor.vue +439 -0
  99. data/lib/vue/components/form-string-new.vue +171 -0
  100. data/lib/vue/stores/module.js +49 -0
  101. data/lib/vue/stores/statistics.js +42 -0
  102. data/lib/vue/stores/strings.js +141 -0
  103. data/lib/vue/stores/translations.js +73 -0
  104. data/license +674 -0
  105. data/readme.md +19 -0
  106. metadata +149 -0
@@ -0,0 +1,119 @@
1
+ module LesliBabel
2
+ class TranslationsRailsService
3
+
4
+ def self.build
5
+
6
+ engines_installed = Rails.application.config.lesli_settings["engines"].map do |engine|
7
+ engine[:name]
8
+ end
9
+
10
+ # get all rails engines to buil
11
+ engines = Module
12
+ .where("platform in ('rails_core', 'rails_builder', 'rails_engine', 'standard')")
13
+ .where("name in (?)", engines_installed.push("Core","LesliMails"))
14
+ .map do |engine|
15
+ engine[:id]
16
+ end
17
+
18
+ # get strings filtered by module (only rails translations)
19
+ strings = TranslationsService.strings(engines)
20
+
21
+ strings = strings.select(
22
+ :id,
23
+ :label,
24
+ :status,
25
+ :context,
26
+ :priority,
27
+ :need_help,
28
+ :need_translation,
29
+ Rails.application.config.lesli_settings["configuration"]["locales"],
30
+ "cloud_babel_modules.id as engine_id",
31
+ "cloud_babel_buckets.id as bucket_id",
32
+ "cloud_babel_buckets.name as bucket_name",
33
+ "cloud_babel_modules.name as engine_name",
34
+ "cloud_babel_modules.platform as platform",
35
+ "'' as path"
36
+ )
37
+
38
+ translations = {}
39
+
40
+ available_locales = Rails.application.config.lesli_settings["configuration"]["locales"]
41
+
42
+ # add key for every available language (required by i18n Rails gem)
43
+ available_locales.each do |lang|
44
+ translations[lang] = { }
45
+ end
46
+
47
+ strings.each do |string|
48
+ module_name = string[:engine_name].downcase.sub("cloud", "")
49
+ engine_code = string[:engine_name].underscore
50
+ engine_name = string[:engine_name]
51
+ bucket_name = string[:bucket_name]
52
+ platform = string[:platform]
53
+
54
+ available_locales.each do |lang|
55
+
56
+ # translations path for lesli core
57
+ file_path = Rails.root.join("config", "locales", bucket_name, "#{ bucket_name.gsub("/","_") }.#{ lang }.yml")
58
+
59
+ # translations path for translations for engines
60
+ if platform == "rails_builder" || platform == "rails_engine" || platform == "standard"
61
+ file_path = Rails.root.join("engines", engine_name, "config", "locales", bucket_name, "#{ bucket_name }.#{ lang }.yml")
62
+ file_path = Rails.root.join("config", "locales", engine_code, bucket_name, "#{ bucket_name.gsub("/","_") }.#{ lang }.yml")
63
+ end
64
+
65
+ file_id = file_path.to_s.to_sym
66
+
67
+ unless translations[lang].has_key? file_id
68
+ translations[lang][file_id] = { }
69
+ end
70
+
71
+ unless translations[lang][file_id].has_key? module_name
72
+ translations[lang][file_id][module_name] = { }
73
+ end
74
+
75
+ unless translations[lang][file_id][module_name].has_key? bucket_name
76
+ translations[lang][file_id][module_name][bucket_name] = { }
77
+ end
78
+
79
+ # send debug message for missing translations
80
+ string[lang] = ":" + string.path + ":" if string[lang].blank?
81
+
82
+ translations[lang][file_id][module_name][bucket_name][string.label] = string[lang]
83
+
84
+ end
85
+
86
+ end
87
+
88
+ translations.each do |file_by_language|
89
+
90
+ lang = file_by_language[0]
91
+ file_by_controller = file_by_language[1]
92
+
93
+ file_by_controller.each do |file|
94
+
95
+ file_path = file[0].to_s
96
+ translations = file[1]
97
+
98
+ # creates folder and subfolders
99
+ FileUtils.makedirs(File.dirname(file_path))
100
+
101
+ # creates translation file for every available language
102
+ translation_file = File.new(file_path, "w+")
103
+
104
+ translation_file.write({ "#{lang}": translations}.to_yaml)
105
+
106
+ translation_file.close
107
+
108
+ p "file added: #{ file_path }"
109
+
110
+ end
111
+
112
+ end
113
+
114
+ LC::Response.service true, translations
115
+
116
+ end
117
+
118
+ end
119
+ end
@@ -0,0 +1,97 @@
1
+ =begin
2
+
3
+ Lesli
4
+
5
+ Copyright (c) 2020, all rights reserved.
6
+
7
+ All the information provided by this platform is protected by international laws related to
8
+ industrial property, intellectual property, copyright and relative international laws.
9
+ All intellectual or industrial property rights of the code, texts, trade mark, design,
10
+ pictures and any other information belongs to the owner of this platform.
11
+
12
+ Without the written permission of the owner, any replication, modification,
13
+ transmission, publication is strictly forbidden.
14
+
15
+ For more information read the license file including with this software.
16
+
17
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
18
+ // ·
19
+
20
+ =end
21
+ module LesliBabel
22
+ class TranslationsService
23
+
24
+ def self.restart_server
25
+ return if Rails.env != "production"
26
+ system "bundle exec rake i18n:js:export RAILS_ENV=production"
27
+ FileUtils.touch Rails.root.join("tmp", "restart.txt")
28
+ end
29
+
30
+ def self.clean
31
+
32
+ # store full path to translation files for every language
33
+ files_to_delete = []
34
+
35
+ # remove javascript translation cache
36
+ files_to_delete.push(Rails.root.join("public", "javascripts", "translations.js"))
37
+
38
+ # get translation files for engines only
39
+ Lesli::engines.each do |engine|
40
+ files_to_delete.push(Rails.root.join("engines", engine["name"], "config", "locales"))
41
+ end
42
+
43
+ # include translation files for lesli core
44
+ files_to_delete.push(Rails.root.join("config", "locales"))
45
+
46
+ # include external app translations
47
+ files_to_delete.push(Rails.root.join("public", "tmp", "locales"))
48
+
49
+ # delete all the translation files found
50
+ files_to_delete.each do |file|
51
+ FileUtils.rm_rf(file)
52
+ end
53
+
54
+ LC::Response.service true, files_to_delete
55
+
56
+ end
57
+
58
+ def self.strings engines_id=nil, buckets_id=nil
59
+
60
+ # get strings with bucket and module information
61
+ strings = String
62
+ .joins("inner join cloud_babel_buckets on cloud_babel_buckets.id = cloud_babel_strings.cloud_babel_buckets_id and cloud_babel_buckets.deleted_at is NULL")
63
+ .joins("inner join cloud_babel_modules on cloud_babel_modules.id = cloud_babel_buckets.cloud_babel_modules_id and cloud_babel_modules.deleted_at is NULL")
64
+ .where("cloud_babel_modules.id in (?)", TranslationsService.installed_engines_id)
65
+
66
+ # filter by specific engines
67
+ if engines_id
68
+ strings = strings.where("cloud_babel_modules.id in (?)", engines_id)
69
+ end
70
+
71
+ # filter by specific engine buckets
72
+ if buckets_id
73
+ strings = strings.where("cloud_babel_buckets.id in (?)", buckets_id)
74
+ end
75
+
76
+ strings
77
+
78
+ end
79
+
80
+ def self.strings_for_apps engines_id=nil, buckets_id=nil
81
+
82
+ strings = strings(engines_id, buckets_id)
83
+ strings = strings.select(
84
+ :id,
85
+ :label,
86
+ "cloud_babel_modules.name as engine_name",
87
+ "cloud_babel_buckets.name as bucket_name",
88
+ "cloud_babel_modules.platform",
89
+ Rails.application.config.lesli_settings["configuration"]["locales"]
90
+ )
91
+
92
+ strings
93
+
94
+ end
95
+
96
+ end
97
+ end
@@ -0,0 +1,215 @@
1
+ =begin
2
+
3
+ Copyright (c) 2020, all rights reserved.
4
+
5
+ All the information provided by this platform is protected by international laws related to
6
+ industrial property, intellectual property, copyright and relative international laws.
7
+ All intellectual or industrial property rights of the code, texts, trade mark, design,
8
+ pictures and any other information belongs to the owner of this platform.
9
+
10
+ Without the written permission of the owner, any replication, modification,
11
+ transmission, publication is strictly forbidden.
12
+
13
+ For more information read the license file including with this software.
14
+
15
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
16
+ // ·
17
+
18
+ =end
19
+
20
+ module LesliBabel
21
+ class TranslationsSynchronizationService
22
+
23
+ # IMPORTANT: If you modify this file please check the CloneService that contains a modified
24
+ # copy of this synchronization code
25
+ def self.remote_sync double_way_sync=false
26
+
27
+ host = "http://localhost:8080"
28
+ host = "https://api.datenbanken.dev/v2"
29
+ instance_code = LC::System::Info.instance[:code].gsub("_","-")
30
+
31
+ # if special namespace is configured in the lesli.yml settings
32
+ # this is useful when we need install an instance and customize
33
+ # the translations for a client
34
+ #instance_code = Rails.application.config.lesli.dig(:configuration, :babel, :namespace)
35
+
36
+ api_endpoint = "#{host}/buckets/#{instance_code}-babel/documents"
37
+
38
+
39
+ # get last sync data
40
+ response = Faraday.get("#{api_endpoint}/last")
41
+ response = FastJsonparser.parse(response.body)
42
+ response = response[:documents][0]
43
+
44
+ # if first time sync
45
+ response = FastJsonparser.parse({ modules: [], buckets: [], strings: [] }.to_json) if response.blank?
46
+
47
+ # add new modules
48
+ response[:modules].each do |babel_module|
49
+ next if babel_module[:name].blank?
50
+
51
+ local_module = CloudBabel::Module
52
+ .create_with({
53
+ created_at: babel_module[:created_at],
54
+ platform: babel_module[:platform]
55
+ }).find_or_create_by({ name: babel_module[:name] })
56
+
57
+ platform = babel_module[:platform]
58
+ platform = "rails_engine" if babel_module[:name].start_with?("Cloud")
59
+ platform = "rails_core" if babel_module[:name] == "Core"
60
+ platform = "rails_builder" if ["MitwerkenCloud", "DeutscheLeibrenten", "LesliCloud"].include?(babel_module[:name])
61
+
62
+ local_module.platform = platform
63
+ local_module.updated_at = DateTime.now
64
+ local_module.save
65
+
66
+ end
67
+
68
+ # working with buckets
69
+ babel_reference_modules = {}
70
+
71
+ response[:buckets].each do |babel_bucket|
72
+
73
+ next if babel_bucket[:name].blank?
74
+
75
+ # reference to modules that buckets belongs to
76
+ # this reference as string is necessary because the id of the module can change
77
+ # between synchronizations, thats why we search for the id of the module every time
78
+ if babel_reference_modules[babel_bucket[:reference_module]].blank?
79
+ babel_reference_modules[babel_bucket[:reference_module]] =
80
+ CloudBabel::Module.find_by(name: babel_bucket[:reference_module])
81
+ end
82
+
83
+ # add new bucket
84
+ CloudBabel::Bucket
85
+ .create_with({
86
+ created_at: babel_bucket[:created_at],
87
+ module: babel_reference_modules[babel_bucket[:reference_module]]
88
+ }).find_or_create_by({
89
+ name: babel_bucket[:name],
90
+ reference_module: babel_bucket[:reference_module]
91
+ })
92
+
93
+ end
94
+
95
+ # · working with strings
96
+ babel_reference_buckets = {}
97
+
98
+ response[:strings].each do |remote_string|
99
+ # reference to modules that buckets belongs to
100
+ # this reference as string is necessary because the id of the module or bucket can change
101
+ # between synchronizations, thats why we search for the id of the module every time
102
+ if babel_reference_buckets[remote_string[:reference_bucket]].blank?
103
+ remote_string[:reference_bucket] ||= remote_string[:reference_module_bucket]
104
+ babel_reference_buckets[remote_string[:reference_bucket]] =
105
+ CloudBabel::Bucket.find_by(
106
+ name: remote_string[:reference_bucket].split("-")[1],
107
+ reference_module: remote_string[:reference_bucket].split("-")[0]
108
+ )
109
+ end
110
+
111
+ # Do not sync labes that do not have a valid module and bucket reference
112
+ next if babel_reference_buckets[remote_string[:reference_bucket]].blank?
113
+
114
+ remote_string_reference = "#{babel_reference_buckets[remote_string[:reference_bucket]].reference_module}-#{babel_reference_buckets[remote_string[:reference_bucket]].name}"
115
+
116
+ # add new string if it does not exist
117
+ local_string = CloudBabel::String.with_deleted.create_with({
118
+ bucket: babel_reference_buckets[remote_string[:reference_bucket]]
119
+ }).find_or_create_by({
120
+ label: remote_string[:label],
121
+ reference_module_bucket: remote_string_reference
122
+ })
123
+
124
+ # if status changed
125
+ if remote_string[:status] != local_string["status"]
126
+
127
+ remote_string[:last_update_status] = Time.now if remote_string[:last_update_status].blank?
128
+ local_string["last_update_status"] = Time.now if local_string["last_update_status"].blank?
129
+
130
+ # check if remote is newer than local
131
+ if (remote_string[:last_update_status] > local_string["last_update_status"])
132
+
133
+ # if so, update local translation with the incoming
134
+ local_string["status"] = remote_string[:status]
135
+ local_string["last_update_status"] = remote_string[:last_update_status]
136
+
137
+ end
138
+
139
+ end
140
+
141
+ # if context changed
142
+ if remote_string[:context] != local_string["context"]
143
+
144
+ remote_string[:last_update_context] = Time.now if remote_string[:last_update_context].blank?
145
+ local_string["last_update_context"] = Time.now if local_string["last_update_context"].blank?
146
+
147
+ # check if remote is newer than local
148
+ if (remote_string[:last_update_context] > local_string["last_update_context"])
149
+
150
+ # if so, update local translation with the incoming
151
+ local_string["context"] = remote_string[:context]
152
+ local_string["last_update_context"] = remote_string[:last_update_context]
153
+
154
+ end
155
+
156
+ end
157
+
158
+ # check if necessary to update any translation
159
+ # due babel can work as client and server at the same time, we have to synchronize labels for all supported languages
160
+ I18n.available_locales.each do |locale|
161
+
162
+ # parse the remote time for comparison, if no time use the current time
163
+ remote_time = Time.parse remote_string[:"last_update_#{locale}"] rescue Time.now.getutc
164
+
165
+ # parse the remote time for comparison, if no time use old time so we can update the string
166
+ local_time = Time.parse local_string["last_update_#{locale}"] rescue Time.parse("Jan 1900")
167
+
168
+ # if translation changed
169
+ if local_string[locale] != remote_string[:"#{locale}"]
170
+
171
+ # check if remote is newer than local
172
+ if (remote_time > local_time)
173
+
174
+ # if so, update local translation with the incoming
175
+ local_string[locale] = local_time
176
+ local_string["last_update_#{locale}"] = remote_time
177
+
178
+ end
179
+
180
+ end
181
+
182
+ end
183
+
184
+ local_string.save
185
+
186
+ end
187
+
188
+ return LC::Response.service(true) if double_way_sync == false
189
+
190
+ # · Collect modules, buckets and strings for syncronization
191
+
192
+ # get and parse modules
193
+ modules = CloudBabel::Module.all.map do |babel_module|
194
+ babel_module.as_json
195
+ end
196
+
197
+ # get and parse buckets
198
+ buckets = CloudBabel::Bucket.all.map do |babel_bucket|
199
+ babel_bucket.as_json
200
+ end
201
+
202
+ # get and parse strings including the deleted ones
203
+ strings = CloudBabel::String.with_deleted.all.map do |babel_string|
204
+ babel_string.as_json
205
+ end
206
+
207
+ # send latest translation to raven
208
+ response = Faraday.post(api_endpoint, ({ modules: modules, buckets: buckets, strings: strings }).to_json, "Content-Type" => "application/json")
209
+
210
+ LC::Response.service true
211
+
212
+ end
213
+
214
+ end
215
+ end
@@ -0,0 +1,80 @@
1
+ module LesliBabel
2
+ class StringService < Lesli::ApplicationLesliService
3
+
4
+ def list engines_id=nil, buckets_id=nil
5
+
6
+ # get strings with bucket and module information
7
+ strings = String
8
+ .joins("inner join lesli_babel_buckets on lesli_babel_buckets.id = lesli_babel_strings.bucket_id and lesli_babel_buckets.deleted_at is NULL")
9
+ .joins("inner join lesli_babel_modules on lesli_babel_modules.id = lesli_babel_buckets.module_id and lesli_babel_modules.deleted_at is NULL")
10
+ .where("lesli_babel_modules.id in (?)", ModuleService.new(current_user, query).list())
11
+
12
+ # filter by specific engines
13
+ if engines_id
14
+ strings = strings.where("lesli_babel_modules.id in (?)", engines_id)
15
+ end
16
+
17
+ # filter by specific engine buckets
18
+ if buckets_id
19
+ strings = strings.where("lesli_babel_buckets.id in (?)", buckets_id)
20
+ end
21
+
22
+ strings
23
+ end
24
+
25
+ def index params
26
+ strings = self.list.select(
27
+ :id,
28
+ :label,
29
+ :status,
30
+ :context,
31
+ Lesli.config.locales.keys,
32
+ "lesli_babel_modules.id as engine_id",
33
+ "lesli_babel_buckets.id as bucket_id",
34
+ "lesli_babel_buckets.name as bucket_name",
35
+ "lesli_babel_modules.name as engine_name",
36
+ "lesli_babel_modules.platform as platform",
37
+ "'' as path"
38
+ )
39
+
40
+ strings = strings
41
+ .page(query[:pagination][:page])
42
+ .per(query[:pagination][:perPage])
43
+ .order(:updated_at)
44
+ end
45
+
46
+ def stats
47
+
48
+ Rails.cache.fetch("babel/strings/stats", expires_in: 1.hour) do
49
+
50
+ # total translations registered in babel
51
+ total_strings = self.list.count
52
+
53
+ # total translations by language
54
+ total_strings_translations = []
55
+
56
+ #Rails.application.config.lesli.dig(:configuration, :locales_available).each do |locale|
57
+ Lesli.config.locales.each do |locale|
58
+ total_strings_translations.push({
59
+ code: locale[0],
60
+ name: locale[1],
61
+ total: self.list.where("#{locale[0]} is not null").where("#{locale[0]} != ''").count
62
+ })
63
+ end
64
+
65
+ # total translations that needs help
66
+ total_strings_waiting_for_help = self.list.where(:status => 1).count
67
+
68
+ # total translations that needs translation
69
+ total_strings_waiting_for_translation = self.list.where(:status => 2).count
70
+
71
+ {
72
+ total_strings: total_strings,
73
+ total_strings_translations: total_strings_translations,
74
+ total_strings_waiting_for_help: total_strings_waiting_for_help,
75
+ total_strings_waiting_for_translation: total_strings_waiting_for_translation
76
+ }
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,17 @@
1
+ <%= form_with(model: bucket, local: true) do |form| %>
2
+ <% if bucket.errors.any? %>
3
+ <div id="error_explanation">
4
+ <h2><%= pluralize(bucket.errors.count, "error") %> prohibited this bucket from being saved:</h2>
5
+
6
+ <ul>
7
+ <% bucket.errors.full_messages.each do |message| %>
8
+ <li><%= message %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div class="actions">
15
+ <%= form.submit %>
16
+ </div>
17
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <h1>Editing Bucket</h1>
2
+
3
+ <%= render 'form', bucket: @bucket %>
4
+
5
+ <%= link_to 'Show', @bucket %> |
6
+ <%= link_to 'Back', buckets_path %>
@@ -0,0 +1,25 @@
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <h1>Buckets</h1>
4
+
5
+ <table>
6
+ <thead>
7
+ <tr>
8
+ <th colspan="3"></th>
9
+ </tr>
10
+ </thead>
11
+
12
+ <tbody>
13
+ <% @buckets.each do |bucket| %>
14
+ <tr>
15
+ <td><%= link_to 'Show', bucket %></td>
16
+ <td><%= link_to 'Edit', edit_bucket_path(bucket) %></td>
17
+ <td><%= link_to 'Destroy', bucket, method: :delete, data: { confirm: 'Are you sure?' } %></td>
18
+ </tr>
19
+ <% end %>
20
+ </tbody>
21
+ </table>
22
+
23
+ <br>
24
+
25
+ <%= link_to 'New Bucket', new_bucket_path %>
@@ -0,0 +1,5 @@
1
+ <h1>New Bucket</h1>
2
+
3
+ <%= render 'form', bucket: @bucket %>
4
+
5
+ <%= link_to 'Back', buckets_path %>
@@ -0,0 +1,4 @@
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <%= link_to 'Edit', edit_bucket_path(@bucket) %> |
4
+ <%= link_to 'Back', buckets_path %>
@@ -0,0 +1,19 @@
1
+ <%
2
+ =begin
3
+ Copyright (c) 2021, all rights reserved.
4
+
5
+ All the information provided by this platform is protected by international laws related to
6
+ industrial property, intellectual property, copyright and relative international laws.
7
+ All intellectual or industrial property rights of the code, texts, trade mark, design,
8
+ pictures and any other information belongs to the owner of this platform.
9
+
10
+ Without the written permission of the owner, any replication, modification,
11
+ transmission, publication is strictly forbidden.
12
+
13
+ For more information read the license file including with this software.
14
+
15
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
16
+ // ·
17
+
18
+ =end
19
+ %>
@@ -0,0 +1,20 @@
1
+ <%
2
+ =begin
3
+ Copyright (c) 2021, all rights reserved.
4
+
5
+ All the information provided by this platform is protected by international laws related to
6
+ industrial property, intellectual property, copyright and relative international laws.
7
+ All intellectual or industrial property rights of the code, texts, trade mark, design,
8
+ pictures and any other information belongs to the owner of this platform.
9
+
10
+ Without the written permission of the owner, any replication, modification,
11
+ transmission, publication is strictly forbidden.
12
+
13
+ For more information read the license file including with this software.
14
+
15
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
16
+ // ·
17
+
18
+ =end
19
+ %>
20
+ <router-view></router-view>
@@ -0,0 +1,20 @@
1
+ <%
2
+ =begin
3
+ Copyright (c) 2021, all rights reserved.
4
+
5
+ All the information provided by this platform is protected by international laws related to
6
+ industrial property, intellectual property, copyright and relative international laws.
7
+ All intellectual or industrial property rights of the code, texts, trade mark, design,
8
+ pictures and any other information belongs to the owner of this platform.
9
+
10
+ Without the written permission of the owner, any replication, modification,
11
+ transmission, publication is strictly forbidden.
12
+
13
+ For more information read the license file including with this software.
14
+
15
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
16
+ // ·
17
+
18
+ =end
19
+ %>
20
+ <router-view></router-view>
@@ -0,0 +1,20 @@
1
+ <%
2
+ =begin
3
+ Copyright (c) 2021, all rights reserved.
4
+
5
+ All the information provided by this platform is protected by international laws related to
6
+ industrial property, intellectual property, copyright and relative international laws.
7
+ All intellectual or industrial property rights of the code, texts, trade mark, design,
8
+ pictures and any other information belongs to the owner of this platform.
9
+
10
+ Without the written permission of the owner, any replication, modification,
11
+ transmission, publication is strictly forbidden.
12
+
13
+ For more information read the license file including with this software.
14
+
15
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
16
+ // ·
17
+
18
+ =end
19
+ %>
20
+ <router-view></router-view>