rosette 0.2.0 → 0.3.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dffb250e67fdc3f3935d85dbbe875fa56b8843629b138cb4444f7e5f2166cb6b
4
- data.tar.gz: d2dcf4ab94c13916db15b7739661b86fcf06ad1f8fa16e73fffbd8f1d51793b5
3
+ metadata.gz: 7d06214ac63c9666ca0fd74730175cc9eb308dbd16bd83e3fca8e9336d7123dc
4
+ data.tar.gz: d7521ae037801fa8c83d74dd2a22f6aa11f3269f90e60fc117746429b238564b
5
5
  SHA512:
6
- metadata.gz: f559af7434bb4ccff09fa5eb0ba4532559fe424621846ea910bf050facce940b61b3e0edf1e09f37e2862b8f2e0083482d25e46b3412d8769aeba41c90a2f2d9
7
- data.tar.gz: 99f57b0c1edf0b156d76aec004fe200430940f4318229ca2d34d0b1b2d3cc57124bacffab894252bf7f3ff58a5eb5edd8b452067fad0d7f2b0dfa4101196bda4
6
+ metadata.gz: 2118244884e6269ae5b3ef2146037ca7086fe32bad51f4bc4be5ab9ba3a12c262cb9244ef48d564537f3223185b3f4f563787b1b14bbc4439a078e2a0dff6267
7
+ data.tar.gz: 62c3f6715880adb58917f3a69544673b4110c8b47f0f1e7192e4858919104e2679925f86bba89370410c049379f56de7c72818fe67f6752789617651c85828fe
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "bundler/setup"
2
4
 
3
5
  APP_RAKEFILE = File.expand_path("spec/example_app/Rakefile", __dir__)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rosette
2
4
  class ApplicationController < ActionController::Base
3
5
  end
@@ -2,12 +2,13 @@
2
2
 
3
3
  module Rosette
4
4
  class TranslationsController < ApplicationController
5
+
5
6
  def create
6
7
  available_locales.each { |locale, translation| Manager.create(locale, key, translation) }
7
8
 
8
9
  Manager.normalize!
9
10
 
10
- redirect_to redirect_path, notice: 'Translation(s) added'
11
+ redirect_to redirect_path, notice: "Translation(s) added"
11
12
  rescue StandardError => e
12
13
  @error_message = e.message
13
14
  render_rosette_new(key, redirect_path)
@@ -15,20 +16,21 @@ module Rosette
15
16
 
16
17
  private
17
18
 
18
- def translations_params
19
- params.require(:translations).permit(:key, :redirect_path, available_locales: {})
20
- end
19
+ def translations_params
20
+ params.require(:translations).permit(:key, :redirect_path, available_locales: {})
21
+ end
21
22
 
22
- def available_locales
23
- translations_params[:available_locales]
24
- end
23
+ def available_locales
24
+ translations_params[:available_locales]
25
+ end
25
26
 
26
- def key
27
- translations_params[:key]
28
- end
27
+ def key
28
+ translations_params[:key]
29
+ end
30
+
31
+ def redirect_path
32
+ URI.parse(translations_params[:redirect_path]).to_s
33
+ end
29
34
 
30
- def redirect_path
31
- URI.parse(translations_params[:redirect_path]).to_s
32
- end
33
35
  end
34
36
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rosette
2
4
  module ApplicationHelper
3
5
  end
@@ -1,5 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rosette
2
4
  class ApplicationRecord < ActiveRecord::Base
5
+
3
6
  self.abstract_class = true
7
+
4
8
  end
5
9
  end
@@ -12,7 +12,7 @@
12
12
  <%= f.hidden_field :redirect_path, value: redirect_path %>
13
13
 
14
14
  <%= f.fields_for :available_locales do |a| %>
15
- <% Rails.configuration.i18n.available_locales.each do |locale| %>
15
+ <% Rosette.available_locales.each do |locale| %>
16
16
  <%= a.label locale, "#{locale.capitalize} translation:" %>
17
17
  <%= a.text_field locale, required: false, label: false, class: 'input-text' %>
18
18
  <% end %>
data/bin/rails ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # This command will automatically be run when you run "rails" with Rails gems
5
+ # installed from the root of your application.
6
+
7
+ ENGINE_ROOT = File.expand_path("..", __dir__)
8
+ ENGINE_PATH = File.expand_path("../lib/rosette/engine", __dir__)
9
+ APP_PATH = File.expand_path("../spec/example_app/config/application", __dir__)
10
+
11
+ # Set up gems listed in the Gemfile.
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
13
+ require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
14
+
15
+ require "rails"
16
+
17
+ require "action_controller/railtie"
18
+ require "action_view/railtie"
19
+ require "active_model/railtie"
20
+ require "active_record/railtie"
21
+ require "rails/engine/commands"
data/bin/rosette ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ begin
5
+ require File.join(Dir.pwd, "config/environment")
6
+ rescue LoadError
7
+ puts <<~ERR
8
+
9
+ Could not load your Rails app
10
+ =============================
11
+ Rosette assumes you have a config/environment.rb file it can load. If this is the case, please
12
+ make sure you are using Rosette CLI from the root of your Rails application. Do not hesitate to
13
+ raise an issue if you need further assistance.
14
+
15
+ ERR
16
+ exit 1
17
+ end
18
+
19
+ require "rosette"
20
+
21
+ Rosette::CLI.run
data/config/routes.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Rosette::Engine.routes.draw do
2
4
  resources :translations, only: [:create]
3
5
  end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tty-prompt"
4
+
5
+ module Rosette
6
+ class CLI
7
+
8
+ class << self
9
+
10
+ attr_reader :prompt, :command
11
+
12
+ delegate :select, :ask, to: :@prompt
13
+
14
+ def run
15
+ ask_for_command
16
+
17
+ return help if command == "help"
18
+
19
+ ask_for_key
20
+ send command
21
+ end
22
+
23
+ private
24
+
25
+ def ask_for_command
26
+ @prompt = TTY::Prompt.new
27
+ @command = select("What do you want to achieve?") do |menu|
28
+ menu.choice("Read a translation", "read")
29
+ menu.choice("Add a translation", "add")
30
+ menu.choice("Remove a translation", "remove")
31
+ menu.choice("Display help", "help")
32
+ end
33
+ end
34
+
35
+ def ask_for_key
36
+ @key = ask "Please provide the key to translation:"
37
+ normalize_key!
38
+ end
39
+
40
+ def normalize_key!
41
+ Rosette.available_locales.each do |locale|
42
+ @key = @key.delete_prefix("#{locale}.")
43
+ end
44
+ end
45
+
46
+ # COMMANDS
47
+
48
+ def read
49
+ Rosette.available_locales.each do |locale|
50
+ translation = Manager.read(locale, @key)
51
+ puts "Translation for #{locale} is: #{translation}"
52
+ end
53
+ end
54
+
55
+ def add
56
+ Rosette.available_locales.each do |locale|
57
+ translation = ask "Please enter #{locale} translation:"
58
+ Manager.create(locale, @key, translation)
59
+ end
60
+ end
61
+
62
+ def remove
63
+ Rosette.available_locales.each do |locale|
64
+ Manager.delete(locale, @key)
65
+ end
66
+ end
67
+
68
+ def help
69
+ puts <<~HELP
70
+
71
+ For each command you must provide a key pointing to the translation.
72
+ It can begin with or without the locale. These are all valid keys:
73
+
74
+ fr.activemodel.errors.blank
75
+ en.activemodel.errors.blank
76
+ activemodel.errors.blank
77
+
78
+ HELP
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
@@ -2,20 +2,22 @@
2
2
 
3
3
  module Rosette
4
4
  module Controller
5
+
5
6
  extend ActiveSupport::Concern
6
7
 
7
8
  included { rescue_from I18n::MissingTranslationData, with: :add_missing_translation_data }
8
9
 
9
10
  private
10
11
 
11
- def add_missing_translation_data(exception)
12
- key = exception.message.sub(/translation missing:.+?\./, '')
12
+ def add_missing_translation_data(exception)
13
+ key = exception.message.sub(/translation missing:.+?\./, "")
14
+
15
+ render_rosette_new(key, request.fullpath)
16
+ end
13
17
 
14
- render_rosette_new(key, request.fullpath)
15
- end
18
+ def render_rosette_new(key, redirect_path)
19
+ render "rosette/new", layout: "rosette/application", locals: { key: key, redirect_path: redirect_path }
20
+ end
16
21
 
17
- def render_rosette_new(key, redirect_path)
18
- render 'rosette/new', layout: 'rosette/application', locals: { key: key, redirect_path: redirect_path }
19
- end
20
22
  end
21
23
  end
@@ -2,16 +2,18 @@
2
2
 
3
3
  module Rosette
4
4
  class Engine < ::Rails::Engine
5
+
5
6
  isolate_namespace Rosette
6
7
 
7
8
  config.after_initialize do |app|
8
9
  app.routes.prepend do
9
- mount Rosette::Engine, at: '/rosette'
10
+ mount Rosette::Engine, at: "/rosette"
10
11
  end
11
12
  end
12
13
 
13
14
  ActiveSupport.on_load(:action_controller_base) do
14
15
  include Rosette::Controller
15
16
  end
17
+
16
18
  end
17
19
  end
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Manager
4
- %w[create read delete].each do |verb|
4
+
5
+ ["create", "read", "delete"].each do |verb|
5
6
  class_eval <<-METHOD, __FILE__, __LINE__ + 1
6
7
  def self.#{verb}(*args)
7
8
  new(*args).send('#{verb}')
@@ -11,59 +12,64 @@ class Manager
11
12
 
12
13
  private
13
14
 
14
- def initialize(locale, key, translation = nil)
15
- @file_path = Rails.root.join("config/locales/#{locale}.yml")
16
- @keys = normalize "#{locale}.#{key}"
17
- @translation = translation
18
- end
15
+ def initialize(locale, key, translation = nil)
16
+ @file_path = Rails.root.join("config/locales/#{locale}.yml")
17
+ @keys = normalize "#{locale}.#{key}"
18
+ @translation = translation
19
+ end
19
20
 
20
- def create
21
- new_translation = @keys.reverse.inject(@translation) { |v, k| { k => v } }
22
- updated_translations = deep_merge(stored_translations, new_translation)
23
- persist(updated_translations)
24
- end
21
+ def read
22
+ stored_translations.dig(*@keys)
23
+ end
25
24
 
26
- def read
27
- stored_translations.dig(*@keys)
28
- end
25
+ def create
26
+ new_translation = @keys.reverse.inject(@translation) { |v, k| { k => v } }
27
+ updated_translations = deep_merge(stored_translations, new_translation)
28
+ persist(updated_translations)
29
29
 
30
- def delete
31
- updated_translations = delete_translation(stored_translations, @keys)
32
- persist(updated_translations)
33
- end
30
+ Manager.normalize!
31
+ end
34
32
 
35
- def delete_translation(translations, keys)
36
- return translations.delete(keys.first) if keys.length == 1
33
+ def delete
34
+ updated_translations = delete_translation(stored_translations, @keys)
35
+ persist(updated_translations)
37
36
 
38
- head, *tail = keys
39
- delete_translation(translations[head], tail)
37
+ Manager.normalize!
38
+ end
40
39
 
41
- translations
42
- end
40
+ def delete_translation(translations, keys)
41
+ return translations.delete(keys.first) if keys.length == 1
43
42
 
44
- def persist(translations)
45
- File.write(@file_path, translations.deep_stringify_keys.to_yaml)
46
- end
43
+ head, *tail = keys
44
+ delete_translation(translations[head], tail)
47
45
 
48
- def stored_translations
49
- YAML.safe_load(File.read(@file_path), symbolize_names: true)
50
- end
46
+ translations
47
+ end
48
+
49
+ def persist(translations)
50
+ File.write(@file_path, translations.deep_stringify_keys.to_yaml)
51
+ end
51
52
 
52
- def deep_merge(hash, other_hash)
53
- hash.merge(other_hash) do |_key, this_val, other_val|
54
- if this_val.is_a?(Hash) && other_val.is_a?(Hash)
55
- deep_merge(this_val, other_val)
56
- else
57
- other_val
53
+ def stored_translations
54
+ YAML.safe_load(File.read(@file_path), symbolize_names: true)
55
+ end
56
+
57
+ def deep_merge(hash, other_hash)
58
+ hash.merge(other_hash) do |_key, this_val, other_val|
59
+ if this_val.is_a?(Hash) && other_val.is_a?(Hash)
60
+ deep_merge(this_val, other_val)
61
+ else
62
+ other_val
63
+ end
58
64
  end
59
65
  end
60
- end
61
66
 
62
- def normalize(key)
63
- key.split('.').map(&:to_sym)
64
- end
67
+ def normalize(key)
68
+ key.split(".").map(&:to_sym)
69
+ end
70
+
71
+ def self.normalize!
72
+ I18n::Tasks::CLI.start(["normalize"]) if Rosette.normalize
73
+ end
65
74
 
66
- def self.normalize!
67
- I18n::Tasks::CLI.start(['normalize']) if Rosette.normalize
68
- end
69
75
  end
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Rosette
2
- VERSION = "0.2.0"
4
+
5
+ VERSION = "0.3.1"
6
+
3
7
  end
data/lib/rosette.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "rosette/cli"
3
4
  require "rosette/controller"
4
5
  require "rosette/engine"
5
6
  require "rosette/manager"
@@ -9,5 +10,11 @@ require "i18n/tasks/cli"
9
10
  require "yaml"
10
11
 
11
12
  module Rosette
13
+
12
14
  mattr_accessor :normalize
15
+
16
+ def self.available_locales
17
+ Rails.configuration.i18n.available_locales.map(&:to_s)
18
+ end
19
+
13
20
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # desc "Explaining what the task does"
2
3
  # task :rosette do
3
4
  # # Task goes here
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rosette
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
  - Alexandre Platteeuw
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-04-17 00:00:00.000000000 Z
11
+ date: 2023-04-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n-tasks
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 7.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: tty-prompt
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.23.1
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.23.1
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec-rails
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -55,7 +69,8 @@ dependencies:
55
69
  description: Add missing translations from the interface of your application
56
70
  email:
57
71
  - alexplatteeuw@gmail.com
58
- executables: []
72
+ executables:
73
+ - rosette
59
74
  extensions: []
60
75
  extra_rdoc_files: []
61
76
  files:
@@ -70,8 +85,11 @@ files:
70
85
  - app/models/rosette/application_record.rb
71
86
  - app/views/layouts/rosette/application.html.erb
72
87
  - app/views/rosette/new.html.erb
88
+ - bin/rails
89
+ - bin/rosette
73
90
  - config/routes.rb
74
91
  - lib/rosette.rb
92
+ - lib/rosette/cli.rb
75
93
  - lib/rosette/controller.rb
76
94
  - lib/rosette/engine.rb
77
95
  - lib/rosette/manager.rb