moirai 0.2.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5cd2eae769961645bc1baa4295ed58bf261beb38a48e934c1d3d38dd083f033a
4
- data.tar.gz: fd3dddd2520c7f06987d814fec2986c5e02ac113748d39a1117315296cc0aaf3
3
+ metadata.gz: ecb41a395f21cd347b67e6e0233bd776a80493be4bf98d423077b7fd7cbe2005
4
+ data.tar.gz: 1335f5ca28ab8804459172894841f71cb8ac88740ce0b94d21096bc3a1713386
5
5
  SHA512:
6
- metadata.gz: 5ae7c1af2f697ea2f7fad123f4c2451e3fa9ba86ffb048ae0b6846c2002bc532e50f762ecf000e32d76f6631d62ebd9f211288b4dca081e61e9d1bbcb05fd6ef
7
- data.tar.gz: f113aa608adfe9b5fae4a073f2d23936bb30090b3fe9d544dfc7d9421663244a78e3350b7218f988fa9c413fe6aef6a6ab154dd79cb5d0160dd026205bdac30d
6
+ metadata.gz: 927bd40a31ce569fca7b6d6a68194106db7616bf3a733009dd84669a387450a4808bc650aeff8f7f1d6aefe630d859db0c0486972008189e183f957247fada80
7
+ data.tar.gz: c8a831cd233bf06ff6160acd096346afb3ab8b1209b3bda7a5a4c7ccbecffe263fadaffd4829508d5f13cb3f4201fdf3658ef46ddcb1ae14c16d46ca4c85c324
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.2.1
@@ -0,0 +1,18 @@
1
+ version: v1.0
2
+ name: main-deploy
3
+ agent:
4
+ machine:
5
+ type: e1-standard-2
6
+ os_image: ubuntu2004
7
+
8
+ blocks:
9
+ - name: main-deploy
10
+ task:
11
+ secrets:
12
+ - name: rubygems-deploy
13
+ jobs:
14
+ - name: main-deploy
15
+ commands:
16
+ - checkout --use-cache
17
+ - gem build moirai
18
+ - gem push moirai-*.gem
@@ -0,0 +1,50 @@
1
+ version: "v1.0"
2
+ name: moirai
3
+ agent:
4
+ machine:
5
+ type: e1-standard-2
6
+ os_image: ubuntu2004
7
+ auto_cancel:
8
+ running:
9
+ when: "true"
10
+
11
+ blocks:
12
+ - name: tests
13
+ execution_time_limit:
14
+ minutes: 10
15
+ task:
16
+ secrets:
17
+ - name: moirai
18
+ prologue:
19
+ commands:
20
+ - checkout --use-cache
21
+ - cache restore
22
+ - bundle config set path 'vendor/bundle'
23
+ - bundle install -j 4
24
+ - cache store
25
+ jobs:
26
+ - name: linter
27
+ commands:
28
+ - bundle exec standardrb
29
+ - name: tests sqlite
30
+ env_vars:
31
+ - name: TARGET_DB
32
+ value: sqlite
33
+ - name: RAILS_ENV
34
+ value: test
35
+ commands:
36
+ - bin/rails db:create db:schema:load
37
+ - bin/check
38
+ - name: tests postgres
39
+ env_vars:
40
+ - name: TARGET_DB
41
+ value: postgres
42
+ - name: RAILS_ENV
43
+ value: test
44
+ commands:
45
+ - sem-service start postgres 14 --username=semaphore
46
+ - bin/rails db:create db:schema:load
47
+ - bin/check
48
+ promotions:
49
+ - name: main
50
+ pipeline_file: main-deploy.yml
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
- ## Unreleased
1
+ ## 0.3.1
2
2
 
3
+ * Fixes a problem when running a rake command and no database exists yet using postgres. ([@coorasse][])
4
+
5
+ ## 0.3.0
6
+
7
+ * Added a method `I18n.translate_without_moirai` ([@oliveranthony17][])
8
+ * Simplified stimulus setup ([@coorasse][])
9
+ * Fixed some setup issues in test environments ([@oliveranthony17][])
10
+ * Show original translation when deleting the whole inline editing content. ([@CuddlyBunion341][])
11
+
12
+ * Support for html translations ([@CuddlyBunion341][])
13
+ =======
3
14
  ## 0.2.0
4
15
 
5
16
  * Support for strings coming from gems ([@coorasse][])
data/Gemfile CHANGED
@@ -12,6 +12,7 @@ gem "stimulus-rails"
12
12
  group :development, :test do
13
13
  gem "puma"
14
14
  gem "sqlite3"
15
+ gem "pg"
15
16
  gem "rake"
16
17
  gem "dotenv"
17
18
  gem "minitest"
data/README.md CHANGED
@@ -5,12 +5,13 @@
5
5
  ### Manage translation strings in real time
6
6
 
7
7
  - Let your non-developer team members finally manage translations (yes, even Karen from marketing...).
8
- - See those translations live in your app, so you can make sure “Submit” isn’t overlapping the button where “**Do not press this button EVER” should be.
9
- - Automatically create Pull Requests based on these changes, saving your developers from yet another “small tweakemail request.
8
+ - See those translations live in your app, so you can make sure “Submit” isn’t overlapping the button where “**Do not
9
+ press this button EVERshould be.
10
+ - Automatically create Pull Requests based on these changes, saving your developers from yet another “small tweak” email
11
+ request.
10
12
 
11
13
  > Let the world be translated, one typo at a time.
12
14
 
13
-
14
15
  ## Installation
15
16
 
16
17
  Add this line to your application's Gemfile:
@@ -20,11 +21,13 @@ gem "moirai"
20
21
  ```
21
22
 
22
23
  And then execute:
24
+
23
25
  ```bash
24
26
  bundle
25
27
  ```
26
28
 
27
- Next, you need to run the generator which will create the necessary files including the database migration, as well as inserting the engine in the `routes.rb` file:
29
+ Next, you need to run the generator which will create the necessary files including the database migration,
30
+ as well as inserting the engine in the `routes.rb` file, and importing the necessary javascript files:
28
31
 
29
32
  ```bash
30
33
  bin/rails g moirai:install
@@ -40,40 +43,51 @@ bin/rails db:migrate
40
43
 
41
44
  ### How to change translations
42
45
 
43
- If you mounted Moirai under "/moirai", head there and you will find a list of all the files containing texts that can be translated.
44
- Open a file, change the value of translations, and press ENTER to update the translation and see it immediately changed on the application.
46
+ If you mounted Moirai under "/moirai", head there and you will find a list of all the files containing texts that can be
47
+ translated.
48
+ Open a file, change the value of translations, and press ENTER to update the translation and see it immediately changed
49
+ on the application.
45
50
 
46
51
  ### Inline editing
47
52
 
48
53
  By default, inline editing is disabled. To enable it, set the `moirai=true` query parameter in the URL.
49
54
 
50
- If you want to only allow specific users to perform inline editing, you can override the `moirai_edit_enabled?` method in your application helper.
55
+ If you want to only allow specific users to perform inline editing, you can override the `moirai_edit_enabled?` method
56
+ in your application helper.
51
57
 
52
58
  ```ruby
59
+
53
60
  module ApplicationHelper
54
61
  def moirai_edit_enabled?
55
- params[:moirai] == "true" || current_user&.admin?
62
+ params[:moirai] == "true" && current_user&.admin?
56
63
  end
57
64
  end
58
65
  ```
59
66
 
60
67
  You also need to have the moirai_translations_controller.js Stimulus Controller initialized.
61
68
 
62
- If you use importmaps:
69
+ #### Importmap
63
70
 
64
- Pin the controller in `config/importmap.rb`
71
+ The command `bin/rails g moirai:install` should have already pinned the necessary controller for you in importmap.rb, so
72
+ no further steps are needed.
65
73
 
66
- ```ruby
67
- pin "controllers/moirai_translation_controller", to: "moirai_translation_controller.js"
68
- ```
74
+ #### jsbulding
69
75
 
70
- If you’re unsure about all the possible configuration options, you can simply copy and paste the stimulus controller into your app as a fallback.
76
+ The command `bin/rails g moirai:install` should have already copied the necessary controller for you in
77
+ `app/javascripts/controllers`, so no further steps are needed.
78
+
79
+ #### More?
80
+
81
+ If you’re unsure about all the possible configuration options, you can simply copy and paste the stimulus controller
82
+ into your app as a fallback.
71
83
 
72
84
  ### Automatic PR creation with Octokit (**optional**)
73
85
 
74
- If you would like Moirai to automatically create a pull request on GitHub to keep translations synchronized with the codebase,
86
+ If you would like Moirai to automatically create a pull request on GitHub to keep translations synchronized with the
87
+ codebase,
75
88
  you need to set up [Octokit](https://github.com/octokit/octokit.rb).
76
- You will also need to create a **Personal Access Token** on GitHub, and configure the access in the appropriate **environment variables** (this is explained below).
89
+ You will also need to create a **Personal Access Token** on GitHub, and configure the access in the appropriate *
90
+ *environment variables** (this is explained below).
77
91
 
78
92
  #### 1. Add Octokit to Your Gemfile
79
93
 
@@ -87,22 +101,23 @@ Then run `bundle install`.
87
101
 
88
102
  #### 2. Create a Personal Access Token (PAT) on GitHub
89
103
 
90
- You will need a Personal Access Token (PAT) with the `Content - Write` permission to allow Octokit to create branches and pull requests.
104
+ You will need a Personal Access Token (PAT) with the `Content - Write` permission to allow Octokit to create branches
105
+ and pull requests.
91
106
 
92
- - Go to GitHub Token Settings.
93
- - Click Generate New Token.
94
- - Give your token a name (e.g., “Moirai”).
95
- - Under Scopes, select:
96
- - repo (for full control of private repositories, including writing content).
97
- - content (for read/write access to code, commit statuses, and pull requests).
98
- - Generate the token and copy it immediately as it will be shown only once.
107
+ - Go to GitHub Token Settings.
108
+ - Click Generate New Token.
109
+ - Give your token a name (e.g., “Moirai”).
110
+ - Under Scopes, select:
111
+ - repo (for full control of private repositories, including writing content).
112
+ - content (for read/write access to code, commit statuses, and pull requests).
113
+ - Generate the token and copy it immediately as it will be shown only once.
99
114
 
100
115
  #### 3. Set Up Environment Variables
101
116
 
102
117
  You need to configure the following environment variables in your application:
103
118
 
104
- - `MOIRAI_GITHUB_REPO_NAME`: The name of the repository where the pull request will be created.
105
- - `MOIRAI_GITHUB_ACCESS_TOKEN`: The Personal Access Token (PAT) you created earlier.
119
+ - `MOIRAI_GITHUB_REPO_NAME`: The name of the repository where the pull request will be created.
120
+ - `MOIRAI_GITHUB_ACCESS_TOKEN`: The Personal Access Token (PAT) you created earlier.
106
121
 
107
122
  For example, in your `.env` file:
108
123
 
@@ -111,7 +126,8 @@ MOIRAI_GITHUB_REPO_NAME=your-organization/your-repo
111
126
  MOIRAI_GITHUB_ACCESS_TOKEN=your-generated-token
112
127
  ```
113
128
 
114
- We also support Rails credentials. The environment variables need to be stored in a slightly different way to adhere to convention. For example:
129
+ We also support Rails credentials. The environment variables need to be stored in a slightly different way to adhere to
130
+ convention. For example:
115
131
 
116
132
  ```env
117
133
  moirai:
@@ -121,13 +137,14 @@ moirai:
121
137
 
122
138
  #### 4. Triggering the pull request creation
123
139
 
124
- Moirai will now be able to use this Personal Access Token to create a pull request on GitHub when a translation is updated.
140
+ Moirai will now be able to use this Personal Access Token to create a pull request on GitHub when a translation is
141
+ updated.
125
142
 
126
143
  To trigger this, you can press the `Create or update PR` button once you have made your changes.
127
144
 
128
145
  ### Authentication
129
146
 
130
- Moirai allows you to use basic HTTP authentication to protect the engine.
147
+ Moirai allows you to use basic HTTP authentication to protect the engine.
131
148
  To enable this, you need to set the following environment variables:
132
149
 
133
150
  ```env
@@ -137,11 +154,11 @@ MOIRAI_BASICAUTH_PASSWORD=moirai
137
154
 
138
155
  > ⚠️ Remember to protect Moirai. You don't want to give everyone the possibility to change strings in the application.
139
156
 
140
- If you have authenticated users, you can leverage the Rails Routes protection mechanism to protect the engine.
157
+ If you have authenticated users, you can leverage the Rails Routes protection mechanism to protect the engine.
141
158
  See the following example:
142
159
 
143
160
  ```ruby
144
- authenticated :user, lambda {|u| u.role == "admin"} do
161
+ authenticated :user, lambda { |u| u.role == "admin" } do
145
162
  mount Moirai::Engine => '/moirai', as: 'moirai'
146
163
  end
147
164
  ```
@@ -166,12 +183,12 @@ end
166
183
 
167
184
  4. Set your environment variables using the newly created `.env` file.
168
185
 
169
- You will need a repository to test against and a token. Generate a new Fine-GRained Personal access token and give the necessary permissions to your repository.
186
+ You will need a repository to test against and a token. Generate a new Fine-GRained Personal access token and give the
187
+ necessary permissions to your repository.
170
188
  See the image below as an example:
171
189
 
172
190
  ![](docs/github_settings.png)
173
191
 
174
-
175
192
  5. Run the tests:
176
193
  ```bash
177
194
  bin/check
@@ -191,6 +208,7 @@ See the image below as an example:
191
208
  * Support for fallbacks: it should detect when a fallback string is in use and prevent attempts to override its value.
192
209
 
193
210
  ## License
211
+
194
212
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
195
213
 
196
214
  ## Copyright
@@ -27,6 +27,15 @@ export default class MoiraiTranslationController extends Controller {
27
27
  value: event.target.innerText
28
28
  }
29
29
  })
30
+ })
31
+ .then(response => response.json())
32
+ .then(data => {
33
+ if (data?.fallback_translation) {
34
+ event.target.innerText = data.fallback_translation
35
+ }
36
+ })
37
+ .catch(error => {
38
+ console.error('Error:', error);
30
39
  });
31
40
  }
32
41
  }
@@ -12,4 +12,6 @@
12
12
  *
13
13
  *= require_tree .
14
14
  *= require_self
15
+ *= require translation_files
16
+
15
17
  */
@@ -0,0 +1,22 @@
1
+ td {
2
+ height: 100px;
3
+ width: 200px;
4
+ vertical-align: top;
5
+ }
6
+
7
+ form {
8
+ height: 100%;
9
+ display: flex;
10
+ align-items: stretch;
11
+ }
12
+
13
+ textarea.translation-textarea {
14
+ width: 100%;
15
+ height: auto;
16
+ resize: vertical;
17
+ min-height: 3em;
18
+ overflow: hidden;
19
+ margin-bottom: 0;
20
+ }
21
+
22
+ /*# TODO: this isn't coming through */
@@ -39,8 +39,17 @@ module Moirai
39
39
  def handle_update(translation)
40
40
  if translation_params[:value].blank? || translation_same_as_current?
41
41
  translation.destroy
42
- flash.notice = "Translation #{translation.key} was successfully deleted."
43
- redirect_to_translation_file(translation.file_path)
42
+ respond_to do |format|
43
+ format.json do
44
+ render json: {
45
+ fallback_translation: get_fallback_translation
46
+ }
47
+ end
48
+ format.html do
49
+ flash.notice = "Translation #{translation.key} was successfully deleted."
50
+ redirect_to_translation_file(translation.file_path)
51
+ end
52
+ end
44
53
  return
45
54
  end
46
55
 
@@ -60,6 +69,10 @@ module Moirai
60
69
  return
61
70
  end
62
71
 
72
+ if translation_params[:value].blank? && request.format.json?
73
+ return render json: {fallback_translation: get_fallback_translation}
74
+ end
75
+
63
76
  translation = Translation.new(translation_params)
64
77
 
65
78
  if translation.save
@@ -74,6 +87,7 @@ module Moirai
74
87
  def success_response(translation)
75
88
  respond_to do |format|
76
89
  format.json do
90
+ flash.discard
77
91
  render json: {}
78
92
  end
79
93
  format.all do
@@ -114,5 +128,14 @@ module Moirai
114
128
 
115
129
  translation_params[:value] == @file_handler.parse_file(file_paths.first)[translation_params[:key]]
116
130
  end
131
+
132
+ def get_fallback_translation
133
+ file_paths = KeyFinder.new.file_paths_for(translation_params[:key], locale: translation_params[:locale])
134
+
135
+ return "" if file_paths.empty?
136
+ return "" unless file_paths.all? { |file_path| File.exist?(file_path) }
137
+
138
+ @file_handler.parse_file(file_paths.first)[translation_params[:key]]
139
+ end
117
140
  end
118
141
  end
@@ -8,6 +8,34 @@
8
8
  <%= stylesheet_link_tag "moirai/application", media: "all" %>
9
9
  <link rel="stylesheet" href="https://cdn.simplecss.org/simple.min.css">
10
10
  <link rel="icon" href="data:image/png;base64,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">
11
+
12
+ <style>
13
+ td {
14
+ height: 100px; /* Ensure the cell has a consistent height */
15
+ width: 200px; /* Set a reasonable width */
16
+ vertical-align: top;
17
+ }
18
+
19
+ form {
20
+ height: 100%;
21
+ display: flex;
22
+ align-items: stretch;
23
+ }
24
+
25
+ textarea {
26
+ flex: 1; /* Allow the textarea to expand */
27
+ width: 100%; /* Ensure it fills the width */
28
+ resize: none; /* Disable manual resizing */
29
+ box-sizing: border-box; /* Account for padding and borders */
30
+ border: 1px solid #ccc; /* Standard input border style */
31
+ border-radius: 4px; /* Match the design */
32
+ padding: 5px; /* Inner padding for text */
33
+ font-family: inherit; /* Use consistent font */
34
+ font-size: inherit; /* Match the font size */
35
+ overflow: hidden; /* Hide overflow before it resizes */
36
+ }
37
+ </style>
38
+
11
39
  </head>
12
40
  <body>
13
41
 
@@ -1,9 +1,9 @@
1
1
  <span
2
- contenteditable
2
+ contenteditable
3
3
  data-action="blur->moirai-translation#submit click->moirai-translation#click"
4
- style="border: 1px dashed #1d9f74; min-width: 30px; display: inline-block;"
4
+ style="outline: 1px solid #1d9f74; min-width: 30px; display: inline-block; <%= 'color: red;' if is_missing_translation %>"
5
5
  data-moirai-translation-key-value="<%= key %>"
6
6
  data-moirai-translation-locale-value="<%= locale %>"
7
7
  data-controller="moirai-translation">
8
- <%= value %>
8
+ <%= value.to_s.gsub("<", "&lt;").gsub(">", "&gt;").html_safe %>
9
9
  </span>
@@ -9,6 +9,7 @@
9
9
  <tr>
10
10
  <th>Key</th>
11
11
  <th>Value</th>
12
+ <th>Original Translation</th>
12
13
  </tr>
13
14
  </thead>
14
15
  <tbody>
@@ -24,13 +25,17 @@
24
25
  <% end %>
25
26
  </td>
26
27
  <td>
27
- <%= form_for translation&.presence || Moirai::Translation.new(key: key, locale: @locale, value: value), url: moirai_create_or_update_translation_path, method: :post do |f| %>
28
+ <%= form_for translation&.presence || Moirai::Translation.new(key: key, locale: @locale, value: value),
29
+ url: moirai_create_or_update_translation_path,
30
+ method: :post do |f| %>
28
31
  <%= f.hidden_field :key %>
29
32
  <%= f.hidden_field :locale %>
30
- <%= f.text_field :value %>
31
- <%= f.submit 'Update', style: 'display: none;' %>
33
+ <%= f.text_field :value, class: 'translation-textarea' %>
32
34
  <% end %>
33
35
  </td>
36
+ <td>
37
+ <%= I18n.translate_without_moirai(key, @locale) %>
38
+ </td>
34
39
  </tr>
35
40
  <% end %>
36
41
  </tbody>
@@ -10,9 +10,35 @@ module Moirai
10
10
  invoke "moirai:migration"
11
11
  end
12
12
 
13
+ def setup_javascript
14
+ if using_importmap?
15
+ say "Pin moirai"
16
+ string_to_be_added = "pin \"controllers/moirai_translation_controller\", to: \"moirai_translation_controller.js\""
17
+ say %(Appending: #{string_to_be_added})
18
+ append_to_file "config/importmap.rb", %(#{string_to_be_added}\n)
19
+ elsif using_js_bundling?
20
+ append_path = "app/javascript/controllers/moirai_translation_controller.js"
21
+ say "Copying Moirai Stimulus controller in #{append_path}"
22
+ copy_file "../../../../app/assets/javascripts/moirai_translation_controller.js", append_path
23
+ rails_command "stimulus:manifest:update"
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def using_js_bundling?
30
+ Rails.root.join("app/javascript/controllers").exist?
31
+ end
32
+
13
33
  def mount_engine
14
34
  route 'mount Moirai::Engine => "/moirai", as: "moirai"'
15
35
  end
36
+
37
+ private
38
+
39
+ def using_importmap?
40
+ Rails.root.join("config/importmap.rb").exist?
41
+ end
16
42
  end
17
43
  end
18
44
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module I18n
4
+ class << self
5
+ attr_accessor :original_backend
6
+ end
7
+
8
+ def self.translate_without_moirai(key, locale, **)
9
+ raise "Original backend is not set" unless original_backend
10
+
11
+ original_backend.translate(locale, key, **)
12
+ end
13
+ end
data/lib/moirai/engine.rb CHANGED
@@ -9,7 +9,20 @@ module Moirai
9
9
  end
10
10
 
11
11
  config.after_initialize do
12
- I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Moirai.new, I18n.backend)
12
+ I18n.original_backend = I18n.backend
13
+ table_created =
14
+ begin
15
+ (defined?(ActiveRecord::ConnectionAdapters::SQLite3Adapter) &&
16
+ ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters::SQLite3Adapter)) ||
17
+ ActiveRecord::Base.connection.table_exists?("moirai_translations")
18
+ rescue ActiveRecord::NoDatabaseError
19
+ false
20
+ end
21
+ if table_created
22
+ I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Moirai.new, I18n.backend)
23
+ else
24
+ Rails.logger.warn("moirai disabled: tables have not been generated yet.")
25
+ end
13
26
  end
14
27
 
15
28
  # TODO: how to do this without rewriting the entire method?
@@ -22,12 +35,18 @@ module Moirai
22
35
  def translate(key, **options)
23
36
  value = original_translate(key, **options)
24
37
 
38
+ is_missing_translation = value.include?('class="translation_missing"')
39
+ if value.is_a?(String) && is_missing_translation
40
+ value = extract_inner_content(value)
41
+ end
42
+
25
43
  if moirai_edit_enabled?
26
44
  @key_finder ||= Moirai::KeyFinder.new
27
45
 
28
46
  render(partial: "moirai/translation_files/form",
29
47
  locals: {key: scope_key_by_partial(key),
30
48
  locale: I18n.locale,
49
+ is_missing_translation: is_missing_translation,
31
50
  value: value})
32
51
  else
33
52
  value
@@ -39,6 +58,13 @@ module Moirai
39
58
  def moirai_edit_enabled?
40
59
  params[:moirai] == "true"
41
60
  end
61
+
62
+ private
63
+
64
+ def extract_inner_content(html)
65
+ match = html.match(/<[^>]+>([^<]*)<\/[^>]+>/)
66
+ match ? match[1] : nil
67
+ end
42
68
  end
43
69
  end
44
70
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Moirai
4
- VERSION = "0.1.0"
4
+ VERSION = "0.3.1"
5
5
  end
data/lib/moirai.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "moirai/version"
4
+ require "i18n/extensions/i18n"
5
+ require "i18n/backend/moirai"
4
6
  require "moirai/engine"
5
7
  require "moirai/pull_request_creator"
6
- require "i18n/backend/moirai"
7
8
 
8
9
  module Moirai
9
10
  # Your code goes here...
data/moirai.gemspec CHANGED
@@ -1,8 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "lib/moirai/version"
4
+
3
5
  Gem::Specification.new do |spec|
4
6
  spec.name = "moirai"
5
- spec.version = "0.2.0"
7
+ spec.version = Moirai::VERSION
6
8
  spec.authors = ["Alessandro Rodi", "Oliver Anthony", "Daniel Bengl"]
7
9
  spec.email = %w[alessandro.rodi@renuo.ch oliver.anthony@renuo.ch daniel.bengl@renuo.ch]
8
10
 
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: moirai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alessandro Rodi
8
8
  - Oliver Anthony
9
9
  - Daniel Bengl
10
- autorequire:
10
+ autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2024-11-06 00:00:00.000000000 Z
13
+ date: 2024-11-26 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rails
@@ -38,8 +38,10 @@ extensions: []
38
38
  extra_rdoc_files: []
39
39
  files:
40
40
  - ".github/CODEOWNERS"
41
- - ".github/workflows/test.yml"
42
41
  - ".gitignore"
42
+ - ".ruby-version"
43
+ - ".semaphore/main-deploy.yml"
44
+ - ".semaphore/semaphore.yml"
43
45
  - Appraisals
44
46
  - CHANGELOG.md
45
47
  - Gemfile
@@ -49,6 +51,7 @@ files:
49
51
  - app/assets/images/moirai/.keep
50
52
  - app/assets/javascripts/moirai_translation_controller.js
51
53
  - app/assets/stylesheets/moirai/application.css
54
+ - app/assets/stylesheets/translation_files.css
52
55
  - app/controllers/concerns/.keep
53
56
  - app/controllers/moirai/application_controller.rb
54
57
  - app/controllers/moirai/translation_files_controller.rb
@@ -78,6 +81,7 @@ files:
78
81
  - lib/generators/moirai/templates/create_moirai_translations.rb.erb
79
82
  - lib/generators/moirai/templates/make_moirai_translations_file_path_not_required.rb.erb
80
83
  - lib/i18n/backend/moirai.rb
84
+ - lib/i18n/extensions/i18n.rb
81
85
  - lib/moirai.rb
82
86
  - lib/moirai/engine.rb
83
87
  - lib/moirai/pull_request_creator.rb
@@ -92,7 +96,7 @@ metadata:
92
96
  changelog_uri: https://github.com/renuo/moirai/CHANGELOG.md
93
97
  steep_types: sig
94
98
  rubygems_mfa_required: 'true'
95
- post_install_message:
99
+ post_install_message:
96
100
  rdoc_options: []
97
101
  require_paths:
98
102
  - lib
@@ -107,8 +111,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
111
  - !ruby/object:Gem::Version
108
112
  version: '0'
109
113
  requirements: []
110
- rubygems_version: 3.4.20
111
- signing_key:
114
+ rubygems_version: 3.4.7
115
+ signing_key:
112
116
  specification_version: 4
113
117
  summary: Manage translation strings in real time
114
118
  test_files: []
@@ -1,60 +0,0 @@
1
- name: Test & lint
2
- on: [push]
3
-
4
- env:
5
- RAILS_ENV: test
6
- PGHOST: localhost
7
- PGUSER: postgres
8
- MOIRAI_GITHUB_REPO_NAME: ${{ secrets.MOIRAI_GITHUB_REPO_NAME }}
9
- MOIRAI_GITHUB_ACCESS_TOKEN: ${{ secrets.MOIRAI_GITHUB_ACCESS_TOKEN }}
10
- jobs:
11
- tests:
12
- name: Test
13
-
14
- strategy:
15
- fail-fast: false
16
- matrix:
17
- os: [ubuntu-latest]
18
- ruby: [3.3]
19
-
20
- runs-on: ${{ matrix.os }}
21
-
22
- steps:
23
- - name: Checkout code
24
- uses: actions/checkout@v4
25
-
26
- - name: Set up Ruby
27
- uses: ruby/setup-ruby@v1
28
- with:
29
- ruby-version: ${{ matrix.ruby }}
30
- bundler-cache: true
31
-
32
- - name: Install dependencies
33
- run: bundle install --jobs 4 --retry 3
34
-
35
- - name: Run tests
36
- run: bundle exec rails test
37
-
38
- - name: Run system tests
39
- run: bundle exec rails test:system
40
-
41
-
42
- lint:
43
- name: Lint
44
- runs-on: ubuntu-latest
45
-
46
- steps:
47
- - name: Checkout code
48
- uses: actions/checkout@v2
49
-
50
- - name: Set up Ruby
51
- uses: ruby/setup-ruby@v1
52
- with:
53
- ruby-version: 3.3
54
- bundler-cache: true
55
-
56
- - name: Install dependencies
57
- run: bundle install --jobs 4 --retry 3
58
-
59
- - name: Run linters
60
- run: bin/fastcheck