lesli_babel 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -29,6 +29,7 @@ module LesliBabel
29
29
 
30
30
  def format_module_name
31
31
 
32
+ return if self.code == "main_app"
32
33
  return if self.platform == "lesli_core"
33
34
  return if self.platform == "lesli_engine"
34
35
 
@@ -36,9 +37,7 @@ module LesliBabel
36
37
  .gsub(/[^0-9A-Za-z\s\-\_]/, '') # remove special characters from string
37
38
  .gsub(/-/, '') # replace dashes with underscore
38
39
  .gsub(/_/, '') # replace underscore with underscore
39
- .titlecase # Capitalizes all the words
40
40
  .gsub(/\s+/, '') # remove blank spaces
41
41
  end
42
-
43
42
  end
44
43
  end
@@ -5,17 +5,31 @@ module LesliBabel
5
5
 
6
6
  Lesli::System.engines.each do |engine, engine_info|
7
7
 
8
- L2.br(30)
9
- L2.info
10
-
11
8
  # get all rails engines to buil
12
9
  engine_id = Module
13
10
  .where("platform in ('lesli_core', 'lesli_engine')")
14
11
  .where(:code => engine_info[:code])
15
12
  .pluck(:id)
16
13
 
14
+ engine_id_lesli = Module
15
+ .where("platform in ('lesli_core', 'lesli_engine')")
16
+ .where(:code => "lesli")
17
+ .pluck(:id)
18
+
19
+ bucket_id_shared = Bucket
20
+ .where(:code => "shared")
21
+ .where(:module_id => engine_id_lesli)
22
+ .pluck(:id)
23
+
24
+ bucket_id_application = Bucket
25
+ .where(:code => "application")
26
+ .where(:module_id => engine_id_lesli)
27
+ .pluck(:id)
28
+
17
29
  # get strings filtered by module (only rails translations)
18
- strings = StringService.new(current_user, query).list #(engine_id)
30
+ strings = StringService.new(current_user, query).list(engine_id)
31
+ strings_shared = StringService.new(current_user, query).list(engine_id_lesli, bucket_id_shared)
32
+ strings_application = StringService.new(current_user, query).list(engine_id_lesli, bucket_id_application)
19
33
 
20
34
  strings = strings.select(
21
35
  :id,
@@ -52,6 +66,7 @@ module LesliBabel
52
66
  "config", "locales", "translations.#{lang}.yml"
53
67
  ).to_s
54
68
 
69
+ # Create a collection of strings for the current module
55
70
  strings.each do |string|
56
71
 
57
72
  bucket_code = string[:bucket_code]
@@ -71,6 +86,40 @@ module LesliBabel
71
86
 
72
87
  end
73
88
 
89
+ # Create a collection of strings for the shared labels of Lesli
90
+ strings_shared.each do |string|
91
+
92
+ unless translations[lang][:labels].has_key? "lesli"
93
+ translations[lang][:labels]["lesli"] = { }
94
+ end
95
+
96
+ unless translations[lang][:labels]["lesli"].has_key? "shared"
97
+ translations[lang][:labels]["lesli"]["shared"] = { }
98
+ end
99
+
100
+ # # send debug message for missing translations
101
+ string[lang] = ":" + string.path + ":" if string[lang].blank?
102
+
103
+ translations[lang][:labels]["lesli"]["shared"][string.label] = string[lang]
104
+ end
105
+
106
+ # Create a collection of strings for the application labels of Lesli
107
+ strings_application.each do |string|
108
+
109
+ unless translations[lang][:labels].has_key? "lesli"
110
+ translations[lang][:labels]["lesli"] = { }
111
+ end
112
+
113
+ unless translations[lang][:labels]["lesli"].has_key? "application"
114
+ translations[lang][:labels]["lesli"]["application"] = { }
115
+ end
116
+
117
+ # # send debug message for missing translations
118
+ string[lang] = ":" + string.path + ":" if string[lang].blank?
119
+
120
+ translations[lang][:labels]["lesli"]["application"][string.label] = string[lang]
121
+ end
122
+
74
123
  end
75
124
 
76
125
  translations.each do |lang, translations|
@@ -85,7 +134,7 @@ module LesliBabel
85
134
 
86
135
  translation_file.close
87
136
 
88
- L2.msg "file added: #{ translations[:file] }"
137
+ #L2.msg "file added: #{ translations[:file] }"
89
138
  end
90
139
  end
91
140
  end
@@ -34,10 +34,10 @@ Building a better future, one line of code at a time.
34
34
 
35
35
 
36
36
  <p class="menu-label">Modules</p>
37
- <% LesliBabel::Module.all.order(:platform, :code).each do |engine| %>
37
+ <% LesliBabel::Module.all.order(:code).each do |engine| %>
38
38
  <%= navigation_item(
39
39
  lesli_babel.modules_path + "/" + engine.id.to_s,
40
40
  engine.code.titleize,
41
- "ri-folder-settings-line"
41
+ "ri-folder-line"
42
42
  ); %>
43
43
  <% end %>
@@ -1,5 +1,20 @@
1
1
  ---
2
2
  :en:
3
- lesli_babel:
3
+ lesli:
4
4
  shared:
5
+ view_discussions: Discussions
6
+ button_add_new: Add new
7
+ button_reload: Reload
8
+ view_files: Files
9
+ view_quick_actions: Quick actions
10
+ button_list: List
5
11
  button_save: Save
12
+ button_delete: Delete
13
+ button_edit: Edit
14
+ view_status_active: Active
15
+ view_status_inactive: Inactive
16
+ button_settings: Settings
17
+ button_show: Show
18
+ application:
19
+ navigation_logout: Logout
20
+ navigation_my_profile: My profile
@@ -1,5 +1,20 @@
1
1
  ---
2
2
  :es:
3
- lesli_babel:
3
+ lesli:
4
4
  shared:
5
+ view_discussions: Discusiones
6
+ button_add_new: Agregar nuevo
7
+ button_reload: Recargar
8
+ view_files: Archivos
9
+ view_quick_actions: Acciones rapidas
10
+ button_list: Lista
5
11
  button_save: Guardar
12
+ button_delete: Eliminar
13
+ button_edit: Editar
14
+ view_status_active: Activo
15
+ view_status_inactive: Inactivo
16
+ button_settings: Configuración
17
+ button_show: Ver
18
+ application:
19
+ navigation_logout: Cerrar sesión
20
+ navigation_my_profile: Mi perfil
@@ -43,6 +43,8 @@ module LesliBabel
43
43
  config.i18n.default_locale = Lesli.config.locales.keys.first || :en
44
44
  config.i18n.available_locales = Lesli.config.locales.keys || [:en]
45
45
 
46
+ config.i18n.load_path += Dir["#{Lesli::Engine.root.to_s}/config/locales/*.yml"]
47
+
46
48
  # register engine migrations path
47
49
  unless app.root.to_s.match root.to_s
48
50
  config.paths["db/migrate"].expanded.each do |expanded_path|
@@ -1,4 +1,4 @@
1
1
  module LesliBabel
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  BUILD = "1697000148"
4
4
  end
@@ -47,20 +47,35 @@ namespace :lesli_babel do
47
47
  desc "Create standard structure for translations according to the objects in the app"
48
48
  task build: [:environment] do
49
49
 
50
- engines = Lesli::SystemController.index(matrix: false)
50
+ engines = Lesli::SystemController.index(matrix: true)
51
51
 
52
- engines.each do |t|
52
+ engines.each do |engine, routes|
53
53
 
54
54
  platform = "lesli_engine"
55
- platform = "lesli_core" if t[:engine] == "lesli"
56
- platform = "rails_app" if t[:engine] == "app"
55
+ platform = "lesli_core" if engine == "lesli"
56
+ platform = "rails_app" if engine == "main_app"
57
57
 
58
- # add object to the translation workflow
59
- translation_module = LesliBabel::Module.find_or_create_by(code: t[:engine], platform: platform)
60
- translation_bucket = LesliBabel::Bucket.find_or_create_by(code: t[:route].sub(t[:engine]+"/", ""), module: translation_module, reference_module: translation_module.code)
61
- translation_bucket = LesliBabel::Bucket.find_or_create_by(code: "shared", module: translation_module, reference_module: translation_module.code)
62
58
 
63
- end
59
+ translation_module = LesliBabel::Module
60
+ .create_with(:platform => platform)
61
+ .find_or_create_by!(:code => engine)
62
+
63
+
64
+ routes.each do |controller, route|
65
+
66
+ LesliBabel::Bucket.find_or_create_by(
67
+ code: route[:route].sub("#{ engine }/", ""),
68
+ module: translation_module,
69
+ reference_module: translation_module.code
70
+ )
71
+
72
+ LesliBabel::Bucket.find_or_create_by(
73
+ code: "shared",
74
+ module: translation_module,
75
+ reference_module: translation_module.code
76
+ )
77
+ end
78
+ end
64
79
 
65
80
  L2.msg "CloudBabel: Module/Controllers scanned and registered"
66
81
 
@@ -77,8 +92,6 @@ namespace :lesli_babel do
77
92
  {
78
93
  "file"=>"engines/#{engine}/lib/vue/stores/translations.json",
79
94
  "patterns"=>[
80
- "*.#{engine_info[:code]}",
81
- "*.lesli.*",
82
95
  "!*.date",
83
96
  "!*.devise",
84
97
  "!*.faker",
@@ -91,7 +104,11 @@ namespace :lesli_babel do
91
104
  "!*.i18n",
92
105
  "!*.activerecord",
93
106
  "!*.errors",
94
- "!*.number.nth"
107
+ "!*.number.nth",
108
+ "*.lesli.shared.*",
109
+ "*.lesli.application.*",
110
+ "*.#{engine_info[:code]}.*",
111
+
95
112
  ]
96
113
  }
97
114
  ]
@@ -100,4 +117,63 @@ namespace :lesli_babel do
100
117
  pp I18nJS.call(config: config)
101
118
  end
102
119
  end
120
+
121
+
122
+ desc "Load local translations into LesliBabel"
123
+ task :load => :environment do |task, args|
124
+
125
+ # Get all the locally installed engines
126
+ engines = Lesli::System.engines
127
+
128
+
129
+ engines.each do |engine, engine_info|
130
+
131
+ # cache the engine code
132
+ engine_code = engine_info[:code]
133
+
134
+ # platform name
135
+ platform = "lesli_engine"
136
+ platform = "lesli_core" if engine_code == "lesli"
137
+
138
+
139
+ # create the babel module if it does not exists
140
+ translation_module = LesliBabel::Module
141
+ .create_with(:platform => platform)
142
+ .find_or_create_by!(:code => engine_code)
143
+
144
+
145
+ # Iterate over the available locales
146
+ I18n.available_locales.each do |locale|
147
+
148
+ # get the translations for an specific engine for an specific locale
149
+ translations = I18n.t(engine_code, locale: locale)
150
+
151
+ # check if the translations is an object
152
+ next unless translations.class == Hash
153
+ translations.each do |bucket, labels|
154
+
155
+ # create the bucket if it does not exist
156
+ translation_bucket = LesliBabel::Bucket.find_or_create_by(
157
+ code: bucket,
158
+ module: translation_module,
159
+ reference_module: translation_module.code
160
+ )
161
+
162
+ labels.each do |label, translation|
163
+
164
+ # create or get the label
165
+ label = LesliBabel::String.create_with(
166
+ reference_bucket: "#{translation_module.code}-#{translation_bucket.code}"
167
+ ).find_or_create_by(
168
+ label: label,
169
+ bucket_id: translation_bucket.id
170
+ )
171
+
172
+ # add the correct translation to the label
173
+ label.update(locale => translation)
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
103
179
  end
@@ -30,8 +30,13 @@ Building a better future, one line of code at a time.
30
30
  */
31
31
 
32
32
 
33
- // ·
33
+ // · Import Lesli builders
34
34
  import application from "Lesli/application"
35
+ import translation from "Lesli/translation"
36
+
37
+
38
+ // · Import engine translations
39
+ import translations from "LesliBabel/stores/translations.json"
35
40
 
36
41
 
37
42
  // ·
@@ -41,6 +46,10 @@ import appTranslationsIndex from "LesliBabel/apps/translations/index.vue"
41
46
  import appModulesShow from "LesliBabel/apps/modules/show.vue"
42
47
 
43
48
 
49
+ // · Buil Lesli translations
50
+ translation(translations)
51
+
52
+
44
53
  // ·
45
54
  application("LesliBabel", [{
46
55
  path: "/",
@@ -82,7 +82,7 @@ watch(() => route.params.id, () => {
82
82
  <lesli-application-container>
83
83
  <lesli-header :title="storeModule.code">
84
84
  <component-actions></component-actions>
85
- <lesli-button solid icon="add" @click="storeStrings.showPanel = true">
85
+ <lesli-button main icon="add" @click="storeStrings.showPanel = true">
86
86
  add new string
87
87
  </lesli-button>
88
88
  </lesli-header>
@@ -37,13 +37,13 @@ import { ref, reactive, onMounted, watch, computed, onUnmounted } from "vue"
37
37
 
38
38
 
39
39
  // ·
40
- import { useStrings } from "LesliBabel/stores/strings"
40
+ import { useString } from "LesliBabel/stores/string"
41
41
  import { useModule } from "LesliBabel/stores/module"
42
42
 
43
43
 
44
44
  // · implement stores
45
45
  const storeModule = useModule()
46
- const storeString = useStrings()
46
+ const storeString = useString()
47
47
 
48
48
 
49
49
  // ·
@@ -55,12 +55,6 @@ const props = defineProps({
55
55
  })
56
56
 
57
57
 
58
- // ·
59
- onMounted(() => {
60
-
61
- })
62
-
63
-
64
58
  // ·
65
59
  const bucket = ref('')
66
60
  const prefix = ref('')
@@ -68,7 +62,7 @@ const string = ref('')
68
62
 
69
63
 
70
64
  // ·
71
- const prefixes = [{
65
+ const components = [{
72
66
  label: "column",
73
67
  value: "column"
74
68
  }, {
@@ -87,68 +81,45 @@ const prefixes = [{
87
81
  label: "chart",
88
82
  value: "chart"
89
83
  }, {
90
- label: "tab_title",
91
- value: "tab_title"
92
- }, {
93
- label: "table_action",
94
- value: "table_action"
84
+ label: "tab",
85
+ value: "tab"
95
86
  }, {
96
- label: "table_header",
97
- value: "table_header"
98
- }, {
99
- label: "title",
100
- value: "title"
87
+ label: "table",
88
+ value: "table"
101
89
  }, {
102
90
  label: "toolbar",
103
91
  value: "toolbar"
104
92
  }, {
105
93
  label: "view",
106
94
  value: "view"
107
- }, {
108
- label: "view_text",
109
- value: "view_text"
110
- }, {
111
- label: "view_placeholder",
112
- value: "view_placeholder"
113
95
  }]
114
96
 
115
-
116
- function postString() {
117
- storeString.post({
118
- bucket_id: bucket.value,
119
- context: '',
120
- label: prefix.value + "_" + string.value
121
- })
122
-
123
- string.value = ''
124
- }
125
-
126
97
  </script>
127
98
  <template>
128
- <lesli-form @submit="postString">
99
+ <lesli-form @submit="storeString.post()">
129
100
  <div class="card-content">
130
101
  <div class="field">
131
102
  <label class="label">Bucket</label>
132
103
  <div class="control">
133
104
  <lesli-select
134
- v-model="bucket"
105
+ v-model="storeString.string.bucket_id"
135
106
  :options="storeModule.buckets.map(b => { return { value: b.id, label: b.code }})">
136
107
  </lesli-select>
137
108
  </div>
138
109
  </div>
139
110
  <div class="field">
140
- <label class="label">Prefix</label>
111
+ <label class="label">Component</label>
141
112
  <div class="control">
142
113
  <lesli-select
143
- v-model="prefix"
144
- :options="prefixes">
114
+ v-model="storeString.component"
115
+ :options="components">
145
116
  </lesli-select>
146
117
  </div>
147
118
  </div>
148
119
  <div class="field">
149
120
  <label class="label">Label</label>
150
121
  <div class="control">
151
- <input required v-model="string" class="input" type="text" placeholder="Add label to translation workflow" />
122
+ <input required v-model="storeString.string.label" class="input" type="text" placeholder="Add label to translation workflow" />
152
123
  </div>
153
124
  </div>
154
125
  <div class="control">
@@ -0,0 +1,84 @@
1
+ /*
2
+ Copyright (c) 2022, all rights reserved.
3
+
4
+ All the information provided by this platform is protected by international laws related to
5
+ industrial property, intellectual property, copyright and relative international laws.
6
+ All intellectual or industrial property rights of the code, texts, trade mark, design,
7
+ pictures and any other information belongs to the owner of this platform.
8
+
9
+ Without the written permission of the owner, any replication, modification,
10
+ transmission, publication is strictly forbidden.
11
+
12
+ For more information read the license file including with this software.
13
+
14
+ // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
15
+ // ·
16
+ */
17
+
18
+
19
+ // ·
20
+ import { defineStore } from "pinia"
21
+
22
+
23
+ // ·
24
+ export const useString = defineStore("babel.string", {
25
+ state: () => {
26
+ return {
27
+ component: "",
28
+ string: {
29
+ bucket_id: null,
30
+ context: "",
31
+ label: ""
32
+ }
33
+ }
34
+ },
35
+ actions: {
36
+
37
+ updateString(string, locale=false) {
38
+ clearTimeout(this.timer)
39
+ this.timer = setTimeout(() => {
40
+ this.putString(string, locale)
41
+ }, 1500)
42
+ },
43
+
44
+ putString(string, locale=false) {
45
+
46
+ // we need to send only properties that we can update
47
+ let stringToUpdate = {
48
+ status: string.status,
49
+ context: string.context,
50
+ priority: string.priority,
51
+ need_help: string.need_help,
52
+ need_translation: string.need_translation
53
+ }
54
+
55
+ // if locale send then we update only the specific translation
56
+ if (locale) {
57
+ stringToUpdate[locale] = string[locale]
58
+ }
59
+
60
+ this.http.put(this.url.babel("strings/:id", string.id), {
61
+ string: stringToUpdate
62
+ }).then(result => {
63
+ this.msg.success("Translation updated successfully")
64
+ }).catch(error => {
65
+ console.log(error)
66
+ })
67
+ },
68
+
69
+ post() {
70
+ this.http.post(this.url.babel('strings'), {
71
+ string: {
72
+ bucket_id: this.string.bucket_id,
73
+ context: this.string.context,
74
+ label: this.component + "_" + this.string.label
75
+ }
76
+ }).then(result => {
77
+ this.msg.success("Label successfully added")
78
+ this.string.label = ""
79
+ }).finally(() => {
80
+
81
+ })
82
+ }
83
+ }
84
+ })
@@ -1,37 +1,47 @@
1
1
  {
2
2
  "en": {
3
3
  "lesli": {
4
- "shared": {
5
- "title_lesli": ":lesli.shared.title_lesli:"
4
+ "application": {
5
+ "navigation_logout": "Logout",
6
+ "navigation_my_profile": "My profile"
6
7
  },
7
- "users": {
8
- "title_users": "Users"
9
- }
10
- },
11
- "lesli_babel": {
12
8
  "shared": {
13
- "title_lesli": ":lesli.shared.title_lesli:"
14
- },
15
- "users": {
16
- "title_users": "Users"
9
+ "button_add_new": "Add new",
10
+ "button_delete": "Delete",
11
+ "button_edit": "Edit",
12
+ "button_list": "List",
13
+ "button_reload": "Reload",
14
+ "button_save": "Save",
15
+ "button_settings": "Settings",
16
+ "button_show": "Show",
17
+ "view_discussions": "Discussions",
18
+ "view_files": "Files",
19
+ "view_quick_actions": "Quick actions",
20
+ "view_status_active": "Active",
21
+ "view_status_inactive": "Inactive"
17
22
  }
18
23
  }
19
24
  },
20
25
  "es": {
21
26
  "lesli": {
22
- "shared": {
23
- "title_lesli": "Lesli en español "
27
+ "application": {
28
+ "navigation_logout": "Cerrar sesión",
29
+ "navigation_my_profile": "Mi perfil"
24
30
  },
25
- "users": {
26
- "title_users": "Usuarios"
27
- }
28
- },
29
- "lesli_babel": {
30
31
  "shared": {
31
- "title_lesli": "Lesli en español "
32
- },
33
- "users": {
34
- "title_users": "Usuarios"
32
+ "button_add_new": "Agregar nuevo",
33
+ "button_delete": "Eliminar",
34
+ "button_edit": "Editar",
35
+ "button_list": "Lista",
36
+ "button_reload": "Recargar",
37
+ "button_save": "Guardar",
38
+ "button_settings": "Configuración",
39
+ "button_show": "Ver",
40
+ "view_discussions": "Discusiones",
41
+ "view_files": "Archivos",
42
+ "view_quick_actions": "Acciones rapidas",
43
+ "view_status_active": "Activo",
44
+ "view_status_inactive": "Inactivo"
35
45
  }
36
46
  }
37
47
  }
data/readme.md CHANGED
@@ -1,16 +1,17 @@
1
1
  <p align="center">
2
2
  <img width="75" alt="LesliBabel logo" src="./app/assets/images/lesli_babel/babel-logo.svg" />
3
- <h3 align="center">Babel - Translation Management System for the Lesli Framework.</h3>
3
+ <h3 align="center">Translation Management System for the Lesli Framework.</h3>
4
4
  </p>
5
5
 
6
6
  <hr/>
7
7
  <p align="center">
8
8
  <a target="blank" href="https://rubygems.org/gems/lesli_babel">
9
- <img src="https://badge.fury.io/rb/lesli_babel.svg" alt="Gem Version" height="24">
9
+ <img height="22" alt="Gem Version" src="https://badge.fury.io/rb/lesli_babel.svg" />
10
10
  </a>
11
11
  </p>
12
12
  <hr/>
13
13
 
14
+
14
15
  ### Quick start
15
16
 
16
17
  ```shell
@@ -32,9 +33,9 @@ end
32
33
 
33
34
 
34
35
  ### Documentation
35
- * [Roadmap](./docs/roadmap.md)
36
- * [database](./docs/database.md)
37
- * [documentation](https://www.lesli.dev/documentation/)
36
+ * [Website](https://www.lesli.dev/babel/)
37
+ * [Database](./docs/database.md)
38
+ * [Documentation](https://www.lesli.dev/documentation/)
38
39
 
39
40
 
40
41
  ### Get in touch