lesli_babel 1.1.1 → 1.1.2
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.
- checksums.yaml +4 -4
- data/Rakefile +3 -1
- data/app/assets/stylesheets/lesli_babel/application.tailwind.css +2 -0
- data/app/models/lesli_babel/bucket.rb +1 -1
- data/app/models/lesli_babel/module.rb +1 -1
- data/app/views/lesli_babel/dashboards/show.html.erb +13 -11
- data/app/views/lesli_babel/labels/_form.html.erb +3 -3
- data/app/views/lesli_babel/labels/index.html.erb +8 -6
- data/app/views/lesli_babel/partials/_sidebar.html.erb +6 -4
- data/lib/lesli_babel/version.rb +2 -2
- data/readme.md +143 -49
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8164c242dfa1ccc58035909df600d0275e0be6727b489373c3bc3330025c349c
|
|
4
|
+
data.tar.gz: b1f4a8d43873994e7e2cc5cd773bd4029befaa781cd9bfdb75e2dd81173e03cb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 473c046acfb89d09bb13b5798d88a6c8a0190b61b45c0fe5d2260f372e8e3a41163e53b7951352edde10ce6bb0e244aaa53fbb889f931b014ddddb2afd494458
|
|
7
|
+
data.tar.gz: 056bab6d9d69bec84892a7a85c34be10464b8e5e34bb792be6bf95bc39f62aa2dde78511f5ecd281b429c9934cac312f4552fe9ae4c81b94f91ed8ba31a025dd
|
data/Rakefile
CHANGED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */
|
|
2
|
+
@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000}}}@layer theme{:root,:host{--font-mono:ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;--color-sky-500:oklch(68.5% .169 237.323);--color-slate-100:oklch(96.8% .007 247.896);--color-slate-200:oklch(92.9% .013 255.508);--color-slate-400:oklch(70.4% .04 256.788);--color-slate-500:oklch(55.4% .046 257.417);--color-slate-600:oklch(44.6% .043 257.281);--color-slate-900:oklch(20.8% .042 265.755);--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75 / 1.125);--font-weight-medium:500;--font-weight-semibold:600;--tracking-wider:.05em;--radius-lg:.5rem;--radius-2xl:1rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer utilities{.my-6{margin-block:calc(var(--spacing) * 6)}.mt-1{margin-top:var(--spacing)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.flex{display:flex}.grid{display:grid}.inline-flex{display:inline-flex}.size-5{width:calc(var(--spacing) * 5);height:calc(var(--spacing) * 5)}.h-12{height:calc(var(--spacing) * 12)}.w-16{width:calc(var(--spacing) * 16)}.max-w-full{max-width:100%}.shrink-0{flex-shrink:0}.flex-col{flex-direction:column}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-center{justify-content:center}.gap-2{gap:calc(var(--spacing) * 2)}.gap-5{gap:calc(var(--spacing) * 5)}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-lg{border-radius:var(--radius-lg)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-slate-200{border-color:var(--color-slate-200)}.bg-white{background-color:var(--color-white)}.p-5{padding:calc(var(--spacing) * 5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-6{padding-block:calc(var(--spacing) * 6)}.pt-1{padding-top:var(--spacing)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-none{--tw-leading:1;line-height:1}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-wider{--tw-tracking:var(--tracking-wider);letter-spacing:var(--tracking-wider)}.break-all{word-break:break-all}.text-slate-400{color:var(--color-slate-400)}.text-slate-500{color:var(--color-slate-500)}.text-slate-600{color:var(--color-slate-600)}.text-slate-900{color:var(--color-slate-900)}.uppercase{text-transform:uppercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}@media (hover:hover){.group-hover\:text-slate-600:is(:where(.group):hover *){color:var(--color-slate-600)}.hover\:bg-slate-100:hover{background-color:var(--color-slate-100)}.hover\:text-slate-900:hover{color:var(--color-slate-900)}}.focus-visible\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.focus-visible\:ring-sky-500\/40:focus-visible{--tw-ring-color:#00a5ef66}@supports (color:color-mix(in lab, red, red)){.focus-visible\:ring-sky-500\/40:focus-visible{--tw-ring-color:color-mix(in oklab, var(--color-sky-500) 40%, transparent)}}.focus-visible\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}@media (min-width:40rem){.sm\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.sm\:gap-6{gap:calc(var(--spacing) * 6)}.sm\:p-6{padding:calc(var(--spacing) * 6)}.sm\:py-8{padding-block:calc(var(--spacing) * 8)}}@media (min-width:64rem){.lg\:grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}}@media (min-width:80rem){.xl\:grid-cols-4{grid-template-columns:repeat(4,minmax(0,1fr))}}}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
|
|
@@ -7,18 +7,20 @@
|
|
|
7
7
|
|
|
8
8
|
<%= render(LesliView::Components::Toolbar.new) %>
|
|
9
9
|
|
|
10
|
-
<section class="
|
|
11
|
-
<div class="
|
|
10
|
+
<section class="py-6 sm:py-8" aria-label="Translation status by locale">
|
|
11
|
+
<div class="grid gap-5 sm:grid-cols-2 sm:gap-6 lg:grid-cols-3 xl:grid-cols-4">
|
|
12
12
|
<% @stats[:total_strings_translations].each do |locale| %>
|
|
13
|
-
<
|
|
14
|
-
<
|
|
15
|
-
<
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
<article class="flex flex-col items-center rounded-2xl border border-slate-200 bg-white p-5 text-center shadow-sm sm:p-6">
|
|
14
|
+
<svg class="mb-3 h-12 w-16" aria-hidden="true">
|
|
15
|
+
<use xlink:href="#locale-<%= locale[:code] %>"></use>
|
|
16
|
+
</svg>
|
|
17
|
+
<h2 class="text-lg font-semibold text-slate-900">
|
|
18
|
+
<%= locale[:name] %>: <span class="tabular-nums"><%= locale[:total] %></span>
|
|
19
|
+
</h2>
|
|
20
|
+
<p class="mt-1 text-sm text-slate-500">
|
|
21
|
+
missing: <span class="tabular-nums"><%= @stats[:total_strings].to_i - locale[:total] %></span> translations
|
|
22
|
+
</p>
|
|
23
|
+
</article>
|
|
22
24
|
<% end %>
|
|
23
25
|
</div>
|
|
24
26
|
</section>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
<%= form_with(
|
|
3
3
|
id: "lesli-babel-labels-form",
|
|
4
|
-
model: @label,
|
|
4
|
+
model: @label,
|
|
5
5
|
builder: LesliView::Forms::BuilderHorizontal
|
|
6
6
|
) do |form| %>
|
|
7
7
|
|
|
@@ -21,13 +21,13 @@
|
|
|
21
21
|
<% I18n.available_locales.each do |locale| %>
|
|
22
22
|
<%= form.field_control(locale, label:language_name(locale)) %>
|
|
23
23
|
<% end %>
|
|
24
|
-
<hr>
|
|
24
|
+
<hr class="my-6 border-0 border-t border-slate-200">
|
|
25
25
|
<%= form.field_control(:context) %>
|
|
26
26
|
<%= form.field_control_select(:status, LesliBabel::Label.statuses) %>
|
|
27
27
|
<%= form.field_control(:path) unless @label[:path].blank? %>
|
|
28
28
|
<% end %>
|
|
29
29
|
|
|
30
|
-
<hr>
|
|
30
|
+
<hr class="my-6 border-0 border-t border-slate-200">
|
|
31
31
|
|
|
32
32
|
<%= form.field_control_button("Update", icon:"save") %>
|
|
33
33
|
|
|
@@ -25,8 +25,8 @@ columns = [{
|
|
|
25
25
|
|
|
26
26
|
<%= render LesliView::Elements::Table.new(columns: columns) do |table| %>
|
|
27
27
|
<% @labels[:records].each do |record| %>
|
|
28
|
-
<% table.with_row(
|
|
29
|
-
<% row.with_cell(
|
|
28
|
+
<% table.with_row(status: record.category) do |row| %>
|
|
29
|
+
<% row.with_cell(align: :center) do %>
|
|
30
30
|
<%= turbo_link_to(record["id"], label_path(record["id"])) %>
|
|
31
31
|
<% end %>
|
|
32
32
|
<% row.with_cell do %>
|
|
@@ -38,16 +38,18 @@ columns = [{
|
|
|
38
38
|
<% row.with_cell do %>
|
|
39
39
|
<div x-data="{ copied: false }">
|
|
40
40
|
<button
|
|
41
|
-
|
|
41
|
+
type="button"
|
|
42
|
+
class="group inline-flex max-w-full items-start gap-2 rounded-lg px-3 py-2 text-left text-sm font-medium text-slate-600 transition-colors hover:bg-slate-100 hover:text-slate-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-sky-500/40"
|
|
43
|
+
:aria-label="copied ? 'Path copied' : 'Copy path'"
|
|
42
44
|
@click="
|
|
43
45
|
navigator.clipboard.writeText($refs.path.innerText.trim());
|
|
44
46
|
copied = true;
|
|
45
47
|
setTimeout(() => copied = false, 2000)
|
|
46
48
|
">
|
|
47
|
-
<span class="
|
|
48
|
-
<span class="material-symbols" x-text="copied ? 'check' : 'content_copy'" x-transition></span>
|
|
49
|
+
<span class="inline-flex size-5 shrink-0 items-center justify-center text-slate-400 transition-colors group-hover:text-slate-600" aria-hidden="true">
|
|
50
|
+
<span class="material-symbols text-lg leading-none" x-text="copied ? 'check' : 'content_copy'" x-transition></span>
|
|
49
51
|
</span>
|
|
50
|
-
<span x-ref="path">
|
|
52
|
+
<span class="break-all font-mono text-xs leading-5" x-ref="path">
|
|
51
53
|
<%= record["path"] %>
|
|
52
54
|
</span>
|
|
53
55
|
</button>
|
|
@@ -33,11 +33,13 @@ Building a better future, one line of code at a time.
|
|
|
33
33
|
%>
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
<
|
|
36
|
+
<li class="px-4 pb-2 pt-1">
|
|
37
|
+
<h2 class="text-xs font-semibold uppercase tracking-wider text-slate-500">Modules</h2>
|
|
38
|
+
</li>
|
|
37
39
|
<% LesliBabel::Module.all.order(:code).each do |engine| %>
|
|
38
40
|
<%= navigation_item(
|
|
39
|
-
lesli_babel.modules_path + "/" + engine.id.to_s,
|
|
40
|
-
engine.code.titleize,
|
|
41
|
+
lesli_babel.modules_path + "/" + engine.id.to_s,
|
|
42
|
+
engine.code.titleize,
|
|
41
43
|
"ri-folder-line"
|
|
42
|
-
)
|
|
44
|
+
) %>
|
|
43
45
|
<% end %>
|
data/lib/lesli_babel/version.rb
CHANGED
data/readme.md
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<
|
|
3
|
-
|
|
2
|
+
<h1 align="center">
|
|
3
|
+
<img width="100" alt="LesliBabel" src="./app/assets/images/lesli_babel/babel-logo.svg" />
|
|
4
|
+
</h1>
|
|
5
|
+
<h3 align="center">Translation management for the Lesli Framework.</h3>
|
|
4
6
|
</div>
|
|
5
7
|
|
|
6
8
|
<br />
|
|
7
|
-
<hr/>
|
|
8
9
|
|
|
9
10
|
<div align="center">
|
|
10
|
-
<a target="_blank" href="https://github.com/LesliTech/LesliBabel/actions">
|
|
11
|
-
<img alt="
|
|
11
|
+
<a target="_blank" href="https://github.com/LesliTech/LesliBabel/actions/workflows/lesli-ci.yaml">
|
|
12
|
+
<img alt="LesliBabel test status" src="https://img.shields.io/github/actions/workflow/status/LesliTech/LesliBabel/lesli-ci.yaml?branch=master&style=for-the-badge&logo=github&label=tests">
|
|
12
13
|
</a>
|
|
13
14
|
<a target="_blank" href="https://rubygems.org/gems/lesli_babel">
|
|
14
15
|
<img alt="Gem Version" src="https://img.shields.io/gem/v/lesli_babel?style=for-the-badge&logo=ruby">
|
|
@@ -16,83 +17,179 @@
|
|
|
16
17
|
<a target="_blank" href="https://codecov.io/github/LesliTech/LesliBabel">
|
|
17
18
|
<img alt="Codecov" src="https://img.shields.io/codecov/c/github/LesliTech/LesliBabel?style=for-the-badge&logo=codecov">
|
|
18
19
|
</a>
|
|
20
|
+
<a target="_blank" href="https://sonarcloud.io/project/overview?id=LesliTech_LesliBabel">
|
|
21
|
+
<img alt="Sonar Quality Gate" src="https://img.shields.io/sonar/quality_gate/LesliTech_LesliBabel?server=https%3A%2F%2Fsonarcloud.io&style=for-the-badge&logo=sonarqubecloud&label=Quality">
|
|
22
|
+
</a>
|
|
19
23
|
</div>
|
|
20
24
|
|
|
21
|
-
<hr/>
|
|
22
25
|
<br />
|
|
23
26
|
|
|
24
27
|
<div align="center">
|
|
25
28
|
<img
|
|
26
29
|
style="width:100%;max-width:800px;border-radius:6px;"
|
|
27
|
-
alt="
|
|
30
|
+
alt="LesliBabel translation management"
|
|
31
|
+
src="./docs/images/screenshot.png" />
|
|
28
32
|
</div>
|
|
29
33
|
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
<br />
|
|
37
|
+
|
|
38
|
+
## Introduction
|
|
39
|
+
|
|
40
|
+
LesliBabel is the official translation management engine for the [Lesli Framework](https://github.com/LesliTech/Lesli).
|
|
41
|
+
|
|
42
|
+
It organizes application text and helps teams maintain, synchronize, and deploy translations across Lesli engines.
|
|
43
|
+
|
|
44
|
+
<br />
|
|
45
|
+
|
|
46
|
+
## Features
|
|
47
|
+
|
|
48
|
+
- Translation modules and buckets
|
|
49
|
+
- Centralized label management
|
|
50
|
+
- Language-specific translation values
|
|
51
|
+
- Synchronization of source labels
|
|
52
|
+
- Translation deployment across Lesli applications
|
|
53
|
+
|
|
30
54
|
<br />
|
|
31
|
-
|
|
55
|
+
|
|
56
|
+
## Try LesliBabel
|
|
57
|
+
|
|
58
|
+
- [Try the online demo](https://demo.lesli.dev/)
|
|
59
|
+
- [Run the Docker demo](https://github.com/LesliTech/lesli-docker-demo)
|
|
60
|
+
|
|
32
61
|
<br />
|
|
33
62
|
|
|
34
|
-
|
|
63
|
+
## Quick Start
|
|
64
|
+
|
|
65
|
+
### Requirements
|
|
66
|
+
|
|
67
|
+
- A Rails application with [Lesli](https://rubygems.org/gems/lesli)
|
|
68
|
+
- SQLite by default, or PostgreSQL when preferred by the host application
|
|
69
|
+
|
|
70
|
+
### Install LesliBabel
|
|
71
|
+
|
|
72
|
+
Add the engine to the host Rails application and prepare its database:
|
|
35
73
|
|
|
36
74
|
```shell
|
|
37
|
-
# Add LesliBabel engine gem
|
|
38
75
|
bundle add lesli_babel
|
|
76
|
+
bin/rails lesli:db:prepare
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Mount the engine
|
|
39
80
|
|
|
40
|
-
|
|
41
|
-
|
|
81
|
+
Applications using Lesli's standard router mount LesliBabel automatically at `/babel`:
|
|
82
|
+
|
|
83
|
+
```ruby
|
|
84
|
+
# config/routes.rb
|
|
85
|
+
Rails.application.routes.draw do
|
|
86
|
+
Lesli::Router.mount(self)
|
|
87
|
+
end
|
|
42
88
|
```
|
|
43
89
|
|
|
90
|
+
If the application does not use the standard Lesli router, mount the engine directly:
|
|
91
|
+
|
|
44
92
|
```ruby
|
|
45
|
-
#
|
|
93
|
+
# config/routes.rb
|
|
46
94
|
Rails.application.routes.draw do
|
|
47
95
|
mount LesliBabel::Engine => "/babel"
|
|
48
96
|
end
|
|
49
97
|
```
|
|
50
98
|
|
|
51
|
-
|
|
52
|
-
|
|
99
|
+
Start Rails and visit [http://127.0.0.1:3000/babel](http://127.0.0.1:3000/babel):
|
|
100
|
+
|
|
101
|
+
```shell
|
|
102
|
+
bin/rails server
|
|
103
|
+
```
|
|
104
|
+
|
|
53
105
|
<br />
|
|
54
106
|
|
|
55
|
-
|
|
107
|
+
## Development
|
|
108
|
+
|
|
109
|
+
Clone LesliBabel into the host application's `engines` directory:
|
|
56
110
|
|
|
57
111
|
```shell
|
|
58
|
-
|
|
59
|
-
|
|
112
|
+
cd RailsApp
|
|
113
|
+
mkdir -p engines
|
|
114
|
+
git clone https://github.com/LesliTech/LesliBabel.git engines/LesliBabel
|
|
115
|
+
```
|
|
60
116
|
|
|
61
|
-
|
|
62
|
-
gem "lesli", path: "engines/LesliBabel"
|
|
117
|
+
Reference the local engine from the host application's `Gemfile`:
|
|
63
118
|
|
|
64
|
-
|
|
119
|
+
```ruby
|
|
120
|
+
gem "lesli_babel", path: "engines/LesliBabel"
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Install dependencies, prepare the host database, and start Rails:
|
|
124
|
+
|
|
125
|
+
```shell
|
|
65
126
|
bundle install
|
|
127
|
+
bin/rails lesli:db:prepare
|
|
128
|
+
bin/rails server
|
|
129
|
+
```
|
|
66
130
|
|
|
67
|
-
|
|
68
|
-
rake lesli:db:setup
|
|
131
|
+
### Frontend
|
|
69
132
|
|
|
133
|
+
LesliBabel uses LesliView for shared interface components and Tailwind CSS for engine-specific presentation. Tailwind source files and generated Rails assets are kept separate:
|
|
134
|
+
|
|
135
|
+
```text
|
|
136
|
+
source/tailwind/application.tailwind.css
|
|
137
|
+
↓ build
|
|
138
|
+
app/assets/stylesheets/lesli_babel/application.tailwind.css
|
|
70
139
|
```
|
|
71
140
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
141
|
+
From a complete Lesli development workspace, compile the assets through the shared LesliAssets builder:
|
|
142
|
+
|
|
143
|
+
```shell
|
|
144
|
+
cd gems/LesliAssets
|
|
145
|
+
make build.tailwind
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
See the [frontend guide](./docs/about/frontend.md) for source registration, view conventions, responsive testing, and utility-collision guidance.
|
|
149
|
+
|
|
150
|
+
### Tests
|
|
151
|
+
|
|
152
|
+
From a complete Lesli development workspace, run the engine test suite from the LesliBabel directory:
|
|
153
|
+
|
|
154
|
+
```shell
|
|
155
|
+
cd engines/LesliBabel
|
|
156
|
+
RAILS_ENV=test bundle exec rake app:db:prepare
|
|
157
|
+
bundle exec rake app:test
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Run the eager-loaded CI equivalent before pushing changes:
|
|
161
|
+
|
|
162
|
+
```shell
|
|
163
|
+
CI=true bundle exec rake app:test
|
|
164
|
+
```
|
|
75
165
|
|
|
76
|
-
|
|
166
|
+
<br />
|
|
77
167
|
|
|
78
|
-
|
|
79
|
-
* [docker demo](https://github.com/LesliTech/lesli-docker-demo)
|
|
168
|
+
## Documentation
|
|
80
169
|
|
|
170
|
+
- [Installation guide](./docs/about/installation.md)
|
|
171
|
+
- [Translation workflow](./docs/about/translations.md)
|
|
172
|
+
- [Frontend development](./docs/about/frontend.md)
|
|
173
|
+
- [Database](./docs/about/database.md)
|
|
174
|
+
- [Tasks](./docs/about/tasks.md)
|
|
175
|
+
- [Lesli website](https://www.lesli.dev/)
|
|
176
|
+
- [Documentation](https://www.lesli.dev/engines/babel)
|
|
177
|
+
- [Release notes](https://github.com/LesliTech/LesliBabel/releases)
|
|
178
|
+
- [Issue tracker](https://github.com/LesliTech/LesliBabel/issues)
|
|
179
|
+
- [Source code](https://github.com/LesliTech/LesliBabel)
|
|
81
180
|
|
|
82
|
-
|
|
83
|
-
* [website](https://www.lesli.dev/)
|
|
84
|
-
* [documentation](https://www.lesli.dev/engines/babel)
|
|
181
|
+
<br />
|
|
85
182
|
|
|
183
|
+
## Community
|
|
86
184
|
|
|
87
|
-
|
|
185
|
+
- [X: @LesliTech](https://x.com/LesliTech)
|
|
186
|
+
- [hello@lesli.tech](mailto:hello@lesli.tech)
|
|
187
|
+
- [https://www.lesli.tech](https://www.lesli.tech)
|
|
88
188
|
|
|
89
|
-
|
|
90
|
-
* [Email: hello@lesli.tech](hello@lesli.tech)
|
|
91
|
-
* [Website: https://www.lesli.tech](https://www.lesli.tech)
|
|
189
|
+
<br />
|
|
92
190
|
|
|
191
|
+
## License
|
|
93
192
|
|
|
94
|
-
### License
|
|
95
|
-
-------
|
|
96
193
|
Copyright (c) 2026, Lesli Technologies, S. A.
|
|
97
194
|
|
|
98
195
|
This program is free software: you can redistribute it and/or modify
|
|
@@ -106,19 +203,16 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
106
203
|
GNU General Public License for more details.
|
|
107
204
|
|
|
108
205
|
You should have received a copy of the GNU General Public License
|
|
109
|
-
along with this program. If not, see
|
|
206
|
+
along with this program. If not, see [https://www.gnu.org/licenses/](https://www.gnu.org/licenses/).
|
|
110
207
|
|
|
111
|
-
|
|
112
|
-
<hr />
|
|
113
|
-
<br />
|
|
114
|
-
<br />
|
|
208
|
+
The complete license text is available in the [license file](./license).
|
|
115
209
|
|
|
116
|
-
|
|
117
|
-
<img width="200" alt="Lesli logo" src="https://cdn.lesli.tech/lesli/brand/app-logo.svg" />
|
|
118
|
-
<h3 align="center" class="mt-0">
|
|
119
|
-
The Open-Source SaaS Development Framework for Ruby on Rails.
|
|
120
|
-
</h3>
|
|
121
|
-
</div>
|
|
210
|
+
---
|
|
122
211
|
|
|
123
212
|
<br />
|
|
124
213
|
<br />
|
|
214
|
+
|
|
215
|
+
<div align="center">
|
|
216
|
+
<img width="80" alt="Lesli icon" src="https://cdn.lesli.tech/lesli/brand/app-icon.svg" />
|
|
217
|
+
<h3 align="center">The Open-Source SaaS Development Framework for Ruby on Rails.</h3>
|
|
218
|
+
</div>
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lesli_babel
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.1.
|
|
4
|
+
version: 1.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The Lesli Development Team
|
|
@@ -36,6 +36,7 @@ files:
|
|
|
36
36
|
- app/assets/images/lesli_babel/babel-logo.svg
|
|
37
37
|
- app/assets/javascripts/lesli_babel/application.js
|
|
38
38
|
- app/assets/stylesheets/lesli_babel/application.css
|
|
39
|
+
- app/assets/stylesheets/lesli_babel/application.tailwind.css
|
|
39
40
|
- app/controllers/lesli_babel/application_controller.rb
|
|
40
41
|
- app/controllers/lesli_babel/buckets_controller.rb
|
|
41
42
|
- app/controllers/lesli_babel/dashboards_controller.rb
|