phraseapp-in-context-editor-ruby 1.4.0 → 2.1.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 +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +18 -0
- data/.github/workflows/close_inactive_issues.yml +18 -0
- data/.github/workflows/release.yml +28 -0
- data/.github/workflows/test.yml +8 -9
- data/.gitignore +1 -1
- data/.tool-versions +1 -1
- data/CHANGELOG.md +9 -105
- data/CODEOWNERS +1 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +244 -0
- data/Guardfile +13 -13
- data/README.md +81 -51
- data/RELEASING.md +3 -0
- data/docs/CHANGELOG.md +116 -0
- data/examples/demo/.gitattributes +7 -0
- data/examples/demo/.gitignore +35 -0
- data/examples/demo/Gemfile +74 -0
- data/examples/demo/Gemfile.lock +268 -0
- data/examples/demo/README.md +5 -0
- data/examples/demo/Rakefile +6 -0
- data/examples/demo/app/assets/config/manifest.js +4 -0
- data/examples/demo/app/assets/images/.keep +0 -0
- data/examples/demo/app/assets/stylesheets/application.css +15 -0
- data/examples/demo/app/channels/application_cable/channel.rb +4 -0
- data/examples/demo/app/channels/application_cable/connection.rb +4 -0
- data/examples/demo/app/controllers/application_controller.rb +2 -0
- data/examples/demo/app/controllers/concerns/.keep +0 -0
- data/examples/demo/app/controllers/main_controller.rb +4 -0
- data/examples/demo/app/helpers/application_helper.rb +2 -0
- data/examples/demo/app/helpers/main_helper.rb +2 -0
- data/examples/demo/app/javascript/application.js +3 -0
- data/examples/demo/app/javascript/controllers/application.js +9 -0
- data/examples/demo/app/javascript/controllers/hello_controller.js +7 -0
- data/examples/demo/app/javascript/controllers/index.js +11 -0
- data/examples/demo/app/jobs/application_job.rb +7 -0
- data/examples/demo/app/mailers/application_mailer.rb +4 -0
- data/examples/demo/app/models/application_record.rb +3 -0
- data/examples/demo/app/models/concerns/.keep +0 -0
- data/examples/demo/app/views/layouts/application.html.erb +17 -0
- data/examples/demo/app/views/layouts/mailer.html.erb +13 -0
- data/examples/demo/app/views/layouts/mailer.text.erb +1 -0
- data/examples/demo/app/views/main/index.html.erb +8 -0
- data/examples/demo/bin/bundle +109 -0
- data/examples/demo/bin/importmap +4 -0
- data/examples/demo/bin/rails +4 -0
- data/examples/demo/bin/rake +4 -0
- data/examples/demo/bin/setup +33 -0
- data/examples/demo/config/application.rb +22 -0
- data/examples/demo/config/boot.rb +4 -0
- data/examples/demo/config/cable.yml +10 -0
- data/examples/demo/config/credentials.yml.enc +1 -0
- data/examples/demo/config/database.yml +25 -0
- data/examples/demo/config/environment.rb +5 -0
- data/examples/demo/config/environments/development.rb +70 -0
- data/examples/demo/config/environments/production.rb +93 -0
- data/examples/demo/config/environments/test.rb +60 -0
- data/examples/demo/config/importmap.rb +7 -0
- data/examples/demo/config/initializers/assets.rb +12 -0
- data/examples/demo/config/initializers/content_security_policy.rb +25 -0
- data/examples/demo/config/initializers/filter_parameter_logging.rb +8 -0
- data/examples/demo/config/initializers/inflections.rb +16 -0
- data/examples/demo/config/initializers/permissions_policy.rb +11 -0
- data/examples/demo/config/initializers/phraseapp_in_context_editor.rb +20 -0
- data/examples/demo/config/locales/en.yml +38 -0
- data/examples/demo/config/puma.rb +43 -0
- data/examples/demo/config/routes.rb +6 -0
- data/examples/demo/config/storage.yml +34 -0
- data/examples/demo/config.ru +6 -0
- data/examples/demo/db/seeds.rb +7 -0
- data/examples/demo/lib/assets/.keep +0 -0
- data/examples/demo/lib/tasks/.keep +0 -0
- data/examples/demo/log/.keep +0 -0
- data/examples/demo/public/404.html +67 -0
- data/examples/demo/public/422.html +67 -0
- data/examples/demo/public/500.html +66 -0
- data/examples/demo/public/apple-touch-icon-precomposed.png +0 -0
- data/examples/demo/public/apple-touch-icon.png +0 -0
- data/examples/demo/public/favicon.ico +0 -0
- data/examples/demo/public/robots.txt +1 -0
- data/examples/demo/storage/.keep +0 -0
- data/examples/demo/test/application_system_test_case.rb +5 -0
- data/examples/demo/test/channels/application_cable/connection_test.rb +11 -0
- data/examples/demo/test/controllers/.keep +0 -0
- data/examples/demo/test/controllers/main_controller_test.rb +8 -0
- data/examples/demo/test/fixtures/files/.keep +0 -0
- data/examples/demo/test/helpers/.keep +0 -0
- data/examples/demo/test/integration/.keep +0 -0
- data/examples/demo/test/mailers/.keep +0 -0
- data/examples/demo/test/models/.keep +0 -0
- data/examples/demo/test/system/.keep +0 -0
- data/examples/demo/test/test_helper.rb +13 -0
- data/examples/demo/tmp/.keep +0 -0
- data/examples/demo/tmp/pids/.keep +0 -0
- data/examples/demo/tmp/storage/.keep +0 -0
- data/examples/demo/vendor/.keep +0 -0
- data/examples/demo/vendor/javascript/.keep +0 -0
- data/lib/generators/phraseapp_in_context_editor/install_generator.rb +3 -9
- data/lib/generators/phraseapp_in_context_editor/templates/phraseapp_in_context_editor.rb +9 -17
- data/lib/phraseapp-in-context-editor-ruby/adapters/fast_gettext.rb +20 -20
- data/lib/phraseapp-in-context-editor-ruby/adapters/i18n.rb +10 -10
- data/lib/phraseapp-in-context-editor-ruby/backend_service.rb +12 -99
- data/lib/phraseapp-in-context-editor-ruby/config.rb +13 -49
- data/lib/phraseapp-in-context-editor-ruby/delegate/fast_gettext.rb +13 -15
- data/lib/phraseapp-in-context-editor-ruby/delegate/i18n_delegate.rb +4 -50
- data/lib/phraseapp-in-context-editor-ruby/delegate.rb +13 -14
- data/lib/phraseapp-in-context-editor-ruby/engine.rb +5 -6
- data/lib/phraseapp-in-context-editor-ruby/version.rb +1 -3
- data/lib/phraseapp-in-context-editor-ruby/view_helpers.rb +26 -19
- data/lib/phraseapp-in-context-editor-ruby.rb +17 -52
- data/package-lock.json +6576 -0
- data/package.json +13 -0
- data/phraseapp-in-context-editor-ruby.gemspec +19 -32
- data/release.config.js +10 -0
- metadata +113 -97
- data/lib/generators/phraseapp_in_context_editor/templates/README +0 -10
- data/lib/phraseapp-in-context-editor-ruby/api_collection.rb +0 -41
- data/lib/phraseapp-in-context-editor-ruby/api_wrapper.rb +0 -59
- data/lib/phraseapp-in-context-editor-ruby/cache.rb +0 -37
- data/lib/phraseapp-in-context-editor-ruby/displayable_key_identifier.rb +0 -46
- data/lib/phraseapp-in-context-editor-ruby/fallback_keys_fetcher.rb +0 -44
- data/lib/phraseapp-in-context-editor-ruby/hash_flattener.rb +0 -53
- data/lib/phraseapp-in-context-editor-ruby/key_names_cache.rb +0 -53
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>We're sorry, but something went wrong (500)</title>
|
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
+
<style>
|
|
7
|
+
.rails-default-error-page {
|
|
8
|
+
background-color: #EFEFEF;
|
|
9
|
+
color: #2E2F30;
|
|
10
|
+
text-align: center;
|
|
11
|
+
font-family: arial, sans-serif;
|
|
12
|
+
margin: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.rails-default-error-page div.dialog {
|
|
16
|
+
width: 95%;
|
|
17
|
+
max-width: 33em;
|
|
18
|
+
margin: 4em auto 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.rails-default-error-page div.dialog > div {
|
|
22
|
+
border: 1px solid #CCC;
|
|
23
|
+
border-right-color: #999;
|
|
24
|
+
border-left-color: #999;
|
|
25
|
+
border-bottom-color: #BBB;
|
|
26
|
+
border-top: #B00100 solid 4px;
|
|
27
|
+
border-top-left-radius: 9px;
|
|
28
|
+
border-top-right-radius: 9px;
|
|
29
|
+
background-color: white;
|
|
30
|
+
padding: 7px 12% 0;
|
|
31
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.rails-default-error-page h1 {
|
|
35
|
+
font-size: 100%;
|
|
36
|
+
color: #730E15;
|
|
37
|
+
line-height: 1.5em;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
.rails-default-error-page div.dialog > p {
|
|
41
|
+
margin: 0 0 1em;
|
|
42
|
+
padding: 1em;
|
|
43
|
+
background-color: #F7F7F7;
|
|
44
|
+
border: 1px solid #CCC;
|
|
45
|
+
border-right-color: #999;
|
|
46
|
+
border-left-color: #999;
|
|
47
|
+
border-bottom-color: #999;
|
|
48
|
+
border-bottom-left-radius: 4px;
|
|
49
|
+
border-bottom-right-radius: 4px;
|
|
50
|
+
border-top-color: #DADADA;
|
|
51
|
+
color: #666;
|
|
52
|
+
box-shadow: 0 3px 8px rgba(50, 50, 50, 0.17);
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
55
|
+
</head>
|
|
56
|
+
|
|
57
|
+
<body class="rails-default-error-page">
|
|
58
|
+
<!-- This file lives in public/500.html -->
|
|
59
|
+
<div class="dialog">
|
|
60
|
+
<div>
|
|
61
|
+
<h1>We're sorry, but something went wrong.</h1>
|
|
62
|
+
</div>
|
|
63
|
+
<p>If you are the application owner check the logs for more information.</p>
|
|
64
|
+
</div>
|
|
65
|
+
</body>
|
|
66
|
+
</html>
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# See https://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
ENV["RAILS_ENV"] ||= "test"
|
|
2
|
+
require_relative "../config/environment"
|
|
3
|
+
require "rails/test_help"
|
|
4
|
+
|
|
5
|
+
class ActiveSupport::TestCase
|
|
6
|
+
# Run tests in parallel with specified workers
|
|
7
|
+
parallelize(workers: :number_of_processors)
|
|
8
|
+
|
|
9
|
+
# Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
|
|
10
|
+
fixtures :all
|
|
11
|
+
|
|
12
|
+
# Add more helper methods to be used by all tests here...
|
|
13
|
+
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,21 +1,15 @@
|
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
|
2
|
-
|
|
3
1
|
module PhraseappInContextEditor
|
|
4
2
|
module Generators
|
|
5
3
|
class InstallGenerator < Rails::Generators::Base
|
|
6
4
|
source_root File.expand_path("../templates", __FILE__)
|
|
7
5
|
|
|
8
|
-
desc "Creates a
|
|
9
|
-
class_option :
|
|
10
|
-
class_option :project_id, type: :string, desc: "Your
|
|
6
|
+
desc "Creates a Phrase In-Context-Editor initializer for your application."
|
|
7
|
+
class_option :account_id, type: :string, desc: "Your Phrase account id", required: true
|
|
8
|
+
class_option :project_id, type: :string, desc: "Your Phrase project id", required: true
|
|
11
9
|
|
|
12
10
|
def copy_initializer
|
|
13
11
|
template "phraseapp_in_context_editor.rb", "config/initializers/phraseapp_in_context_editor.rb"
|
|
14
12
|
end
|
|
15
|
-
|
|
16
|
-
def show_readme
|
|
17
|
-
readme "README" if behavior == :invoke
|
|
18
|
-
end
|
|
19
13
|
end
|
|
20
14
|
end
|
|
21
15
|
end
|
|
@@ -2,26 +2,18 @@ PhraseApp::InContextEditor.configure do |config|
|
|
|
2
2
|
# Enable or disable the In-Context-Editor in general
|
|
3
3
|
config.enabled = true
|
|
4
4
|
|
|
5
|
-
#
|
|
6
|
-
# in
|
|
7
|
-
#
|
|
8
|
-
# page (https://phraseapp.com/projects)
|
|
5
|
+
# Configure with your project id and account id. You can find the
|
|
6
|
+
# project id in your project settings and account id in your account
|
|
7
|
+
# settings (https://app.phrase.com/)
|
|
9
8
|
config.project_id = "<%= options[:project_id] %>"
|
|
9
|
+
config.account_id = "<%= options[:account_id] %>"
|
|
10
|
+
config.datacenter = "eu"
|
|
10
11
|
|
|
11
|
-
#
|
|
12
|
-
# in Translation Center or via the Authorizations API
|
|
13
|
-
# (https://developers.phraseapp.com/api/#authorizations).
|
|
14
|
-
config.access_token = "<%= options[:access_token] %>"
|
|
15
|
-
|
|
16
|
-
# Configure an array of key names that should not be handled
|
|
17
|
-
# by the In-Context-Editor.
|
|
18
|
-
config.ignored_keys = ["number.*", "breadcrumb.*"]
|
|
19
|
-
|
|
20
|
-
# PhraseApp uses decorators to generate a unique identification key
|
|
12
|
+
# Phrase uses decorators to generate a unique identification key
|
|
21
13
|
# in context of your document. However, this might result in conflicts
|
|
22
14
|
# with other libraries (e.g. client-side template engines) that use a similar syntax.
|
|
23
15
|
# If you encounter this problem, you might want to change this decorator pattern.
|
|
24
|
-
# More information: https://help.
|
|
25
|
-
# config.prefix = "
|
|
26
|
-
# config.suffix = "__
|
|
16
|
+
# More information: https://help.phrase.com/hc/en-us/articles/5784095916188-In-Context-Editor-Strings-
|
|
17
|
+
# config.prefix = "[[__"
|
|
18
|
+
# config.suffix = "__]]"
|
|
27
19
|
end
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
|
|
1
|
+
require "phraseapp-in-context-editor-ruby/delegate/fast_gettext"
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
if defined? FastGettext::Translation
|
|
4
|
+
module FastGettext
|
|
5
|
+
module Translation
|
|
6
|
+
def __with_phraseapp(*args)
|
|
7
|
+
PhraseApp::InContextEditor::Delegate::FastGettext.new(:_, *args)
|
|
8
|
+
end
|
|
9
|
+
alias_method :__without_phraseapp, :_
|
|
10
|
+
alias_method :_, :__with_phraseapp
|
|
4
11
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
alias_method :__without_phraseapp, :_
|
|
11
|
-
alias_method :_, :__with_phraseapp
|
|
12
|
-
|
|
13
|
-
def n__with_phraseapp(*args)
|
|
14
|
-
PhraseApp::InContextEditor::Delegate::FastGettext.new(:n_, *args)
|
|
15
|
-
end
|
|
16
|
-
alias_method :n__without_phraseapp, :n_
|
|
17
|
-
alias_method :n_, :n__with_phraseapp
|
|
12
|
+
def n__with_phraseapp(*args)
|
|
13
|
+
PhraseApp::InContextEditor::Delegate::FastGettext.new(:n_, *args)
|
|
14
|
+
end
|
|
15
|
+
alias_method :n__without_phraseapp, :n_
|
|
16
|
+
alias_method :n_, :n__with_phraseapp
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
def s__with_phraseapp(*args)
|
|
19
|
+
PhraseApp::InContextEditor::Delegate::FastGettext.new(:s_, *args)
|
|
20
|
+
end
|
|
21
|
+
alias_method :s__without_phraseapp, :s_
|
|
22
|
+
alias_method :s_, :s__with_phraseapp
|
|
21
23
|
end
|
|
22
|
-
alias_method :s__without_phraseapp, :s_
|
|
23
|
-
alias_method :s_, :s__with_phraseapp
|
|
24
24
|
end
|
|
25
|
-
end
|
|
25
|
+
end
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
if defined?(I18n)
|
|
2
|
+
module I18n
|
|
3
|
+
class << self
|
|
4
|
+
def translate_with_phraseapp(*args)
|
|
5
|
+
PhraseApp::InContextEditor.backend.translate(*args)
|
|
6
|
+
end
|
|
7
|
+
alias_method :translate_without_phraseapp, :translate
|
|
8
|
+
alias_method :translate, :translate_with_phraseapp
|
|
9
|
+
alias_method :t, :translate
|
|
7
10
|
end
|
|
8
|
-
alias_method :translate_without_phraseapp, :translate
|
|
9
|
-
alias_method :translate, :translate_with_phraseapp
|
|
10
|
-
alias_method :t, :translate
|
|
11
11
|
end
|
|
12
|
-
end
|
|
12
|
+
end
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
require 'phraseapp-in-context-editor-ruby/api_collection'
|
|
3
|
-
require 'phraseapp-in-context-editor-ruby/delegate/i18n_delegate'
|
|
1
|
+
require_relative "delegate/i18n_delegate"
|
|
4
2
|
|
|
5
3
|
module PhraseApp
|
|
6
4
|
module InContextEditor
|
|
7
5
|
class BackendService
|
|
8
|
-
|
|
9
6
|
attr_accessor :blacklisted_keys
|
|
10
7
|
|
|
11
8
|
def initialize(args = {})
|
|
@@ -40,47 +37,20 @@ module PhraseApp
|
|
|
40
37
|
end
|
|
41
38
|
end
|
|
42
39
|
|
|
43
|
-
|
|
44
|
-
def to_be_translated_without_phraseapp?(args)
|
|
45
|
-
PhraseApp::InContextEditor.disabled? or has_been_given_blacklisted_key?(args) or has_been_given_ignored_key?(args) or has_been_forced_to_resolve_with_phraseapp?(args)
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
def has_been_given_blacklisted_key?(args)
|
|
49
|
-
key = given_key_from_args(args)
|
|
50
|
-
has_blacklist_entry_for_key?(key)
|
|
51
|
-
end
|
|
40
|
+
protected
|
|
52
41
|
|
|
53
|
-
def
|
|
54
|
-
|
|
55
|
-
key_is_ignored?(key)
|
|
42
|
+
def to_be_translated_without_phraseapp?(args)
|
|
43
|
+
PhraseApp::InContextEditor.disabled? || has_been_forced_to_resolve_with_phraseapp?(args)
|
|
56
44
|
end
|
|
57
45
|
|
|
58
46
|
def has_been_forced_to_resolve_with_phraseapp?(args)
|
|
59
|
-
(args.last.is_a?(Hash)
|
|
47
|
+
(args.last.is_a?(Hash) && args.last[:resolve] == false)
|
|
60
48
|
end
|
|
61
49
|
|
|
62
50
|
def given_key_from_args(args)
|
|
63
51
|
extract_normalized_key_from_args(args)
|
|
64
52
|
end
|
|
65
53
|
|
|
66
|
-
def has_blacklist_entry_for_key?(key)
|
|
67
|
-
blacklisted_keys.each do |blacklisted_key|
|
|
68
|
-
return true if present?(key.to_s[/\A#{blacklisted_key.gsub("*", ".*")}\Z/])
|
|
69
|
-
end
|
|
70
|
-
false
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def key_is_ignored?(key)
|
|
74
|
-
PhraseApp::InContextEditor.ignored_keys.each do |ignored_key|
|
|
75
|
-
return true if present?(key.to_s[/\A#{ignored_key.gsub("*", ".*")}\Z/])
|
|
76
|
-
end
|
|
77
|
-
false
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def blacklisted_keys
|
|
81
|
-
@blacklisted_keys ||= api_wrapper.blacklisted_keys
|
|
82
|
-
end
|
|
83
|
-
|
|
84
54
|
def phraseapp_delegate_for(args)
|
|
85
55
|
key = given_key_from_args(args)
|
|
86
56
|
return nil unless present?(key)
|
|
@@ -95,15 +65,14 @@ module PhraseApp
|
|
|
95
65
|
end
|
|
96
66
|
|
|
97
67
|
def transform_args(args)
|
|
98
|
-
duped_args = args.map { |item| (item.is_a?(Symbol)
|
|
99
|
-
transform_args_based_on_caller(duped_args)
|
|
68
|
+
duped_args = args.map { |item| (item.is_a?(Symbol) || item.nil?) ? item : item.dup }
|
|
100
69
|
end
|
|
101
70
|
|
|
102
71
|
def normalized_key(duped_args)
|
|
103
72
|
splitted_args = split_args(duped_args)
|
|
104
73
|
key = I18n::Backend::Flatten.normalize_flat_keys(*splitted_args)
|
|
105
74
|
key.gsub!("..", ".")
|
|
106
|
-
key.gsub!(/^\./,
|
|
75
|
+
key.gsub!(/^\./, "")
|
|
107
76
|
key
|
|
108
77
|
end
|
|
109
78
|
|
|
@@ -111,77 +80,21 @@ module PhraseApp
|
|
|
111
80
|
options = options_from_args(args)
|
|
112
81
|
key ||= args.shift
|
|
113
82
|
locale = options.delete(:locale) || I18n.locale
|
|
114
|
-
|
|
83
|
+
[locale, key, options[:scope], nil]
|
|
115
84
|
end
|
|
116
85
|
|
|
117
86
|
def options_from_args(args)
|
|
118
87
|
args.last.is_a?(Hash) ? args.pop : {}
|
|
119
88
|
end
|
|
120
89
|
|
|
121
|
-
def transform_args_based_on_caller(args)
|
|
122
|
-
translation_caller = identify_caller
|
|
123
|
-
|
|
124
|
-
if translation_caller and args.first =~ /^\./
|
|
125
|
-
options = options_from_args(args)
|
|
126
|
-
|
|
127
|
-
if not present?(options[:scope]) and present?(translation_caller)
|
|
128
|
-
options[:scope] = translation_caller
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
args.push(options)
|
|
132
|
-
parts = args.first.to_s.split(".").select { |e| not blank?(e) }
|
|
133
|
-
args[0] = parts[0] if parts.size == 1
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
args
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
def identify_caller
|
|
140
|
-
translation_caller = nil
|
|
141
|
-
send(:caller)[0..6].each do |intermediate_caller|
|
|
142
|
-
translation_caller = calling_template(intermediate_caller) unless translation_caller
|
|
143
|
-
end
|
|
144
|
-
|
|
145
|
-
if present?(translation_caller)
|
|
146
|
-
find_lookup_scope(translation_caller)
|
|
147
|
-
else
|
|
148
|
-
nil
|
|
149
|
-
end
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def calling_template(string)
|
|
153
|
-
string.match(/(views)(\/.+)(?>:[0-9]+:in)/)
|
|
154
|
-
end
|
|
155
|
-
|
|
156
90
|
def blank?(str)
|
|
157
|
-
raise "blank?(str) can only be given a String or nil" unless str.is_a?(String)
|
|
158
|
-
str.nil?
|
|
91
|
+
raise "blank?(str) can only be given a String or nil" unless str.is_a?(String) || str.nil?
|
|
92
|
+
str.nil? || str == ""
|
|
159
93
|
end
|
|
160
94
|
|
|
161
95
|
def present?(str)
|
|
162
|
-
raise "present?(str) can only be given a String or nil" unless str.is_a?(String)
|
|
163
|
-
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
def find_lookup_scope(caller)
|
|
167
|
-
split_path = caller[2][1..-1].split(".")[0].split("/")
|
|
168
|
-
|
|
169
|
-
template_or_partial = remove_underscore_form_partial(split_path[-1])
|
|
170
|
-
split_path[-1] = template_or_partial
|
|
171
|
-
|
|
172
|
-
split_path.map!(&:to_sym)
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def remove_underscore_form_partial(template_or_partial)
|
|
176
|
-
if template_or_partial.to_s[0,1] == "_"
|
|
177
|
-
template_or_partial.to_s[1..-1]
|
|
178
|
-
else
|
|
179
|
-
template_or_partial.to_s
|
|
180
|
-
end
|
|
181
|
-
end
|
|
182
|
-
|
|
183
|
-
def api_wrapper
|
|
184
|
-
@api_wrapper ||= PhraseApp::InContextEditor::ApiWrapper.new
|
|
96
|
+
raise "present?(str) can only be given a String or nil" unless str.is_a?(String) || str.nil?
|
|
97
|
+
!blank?(str)
|
|
185
98
|
end
|
|
186
99
|
end
|
|
187
100
|
end
|
|
@@ -1,62 +1,40 @@
|
|
|
1
|
-
# -*- encoding : utf-8 -*-
|
|
2
1
|
module PhraseApp
|
|
3
2
|
module InContextEditor
|
|
4
3
|
class Config
|
|
5
4
|
CONFIG_OPTIONS = {
|
|
5
|
+
account_id: nil,
|
|
6
6
|
project_id: nil,
|
|
7
|
-
|
|
7
|
+
datacenter: "eu",
|
|
8
8
|
enabled: false,
|
|
9
|
-
skip_ssl_verification: false,
|
|
10
9
|
backend: PhraseApp::InContextEditor::BackendService.new,
|
|
11
10
|
prefix: "{{__",
|
|
12
11
|
suffix: "__}}",
|
|
13
|
-
|
|
14
|
-
js_host: "phraseapp.com",
|
|
15
|
-
js_use_ssl: true,
|
|
16
|
-
js_path: "/assets/in-context-editor/2.0/app.js",
|
|
17
|
-
js_options: {},
|
|
18
|
-
cache_key_segments_initial: ["simple_form"],
|
|
19
|
-
cache_lifetime: 300,
|
|
20
|
-
ignored_keys: [],
|
|
12
|
+
origin: "in-context-editor-ruby"
|
|
21
13
|
}.freeze
|
|
22
14
|
|
|
23
|
-
CONFIG_OPTIONS_GLOBAL_ONLY = [
|
|
24
|
-
:access_token,
|
|
25
|
-
:skip_ssl_verification,
|
|
26
|
-
:api_host
|
|
27
|
-
].freeze
|
|
28
|
-
|
|
29
15
|
CONFIG_OPTIONS.each do |option, default_value|
|
|
30
|
-
class_eval "@@#{option} = CONFIG_OPTIONS[:#{option}]"
|
|
16
|
+
class_eval "@@#{option} = CONFIG_OPTIONS[:#{option}]", __FILE__, __LINE__
|
|
31
17
|
|
|
32
18
|
define_method("#{option}=") do |value|
|
|
33
|
-
instance_eval "@#{option} = value
|
|
34
|
-
end
|
|
19
|
+
instance_eval "@#{option} = value", __FILE__, __LINE__
|
|
20
|
+
end
|
|
35
21
|
|
|
36
|
-
define_method(
|
|
37
|
-
instance_eval "defined?(@#{option}) ? @#{option} : self.class.#{option}"
|
|
22
|
+
define_method(option.to_s) do
|
|
23
|
+
instance_eval "defined?(@#{option}) ? @#{option} : self.class.#{option}", __FILE__, __LINE__
|
|
38
24
|
end
|
|
39
25
|
|
|
40
26
|
define_singleton_method("#{option}=") do |value|
|
|
41
|
-
instance_eval "@@#{option} = value
|
|
27
|
+
instance_eval "@@#{option} = value", __FILE__, __LINE__
|
|
42
28
|
end
|
|
43
29
|
|
|
44
|
-
define_singleton_method(
|
|
45
|
-
instance_eval "@@#{option}"
|
|
30
|
+
define_singleton_method(option.to_s) do
|
|
31
|
+
instance_eval "@@#{option}", __FILE__, __LINE__
|
|
46
32
|
end
|
|
47
33
|
end
|
|
48
34
|
|
|
49
|
-
def
|
|
50
|
-
@@api_client ||= build_api_client
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
def api_client
|
|
54
|
-
self.class.api_client
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
def assign_values(config_options={})
|
|
35
|
+
def assign_values(config_options = {})
|
|
58
36
|
config_options.each do |config_option, value|
|
|
59
|
-
|
|
37
|
+
send("#{config_option}=", value)
|
|
60
38
|
end
|
|
61
39
|
end
|
|
62
40
|
|
|
@@ -65,20 +43,6 @@ module PhraseApp
|
|
|
65
43
|
send("#{option}=", default_value)
|
|
66
44
|
end
|
|
67
45
|
end
|
|
68
|
-
|
|
69
|
-
protected
|
|
70
|
-
def self.invalidate_api_client
|
|
71
|
-
@@api_client = nil
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
def self.build_api_client
|
|
75
|
-
credentials = PhraseApp::Auth::Credentials.new(
|
|
76
|
-
token: @@access_token,
|
|
77
|
-
host: @@api_host,
|
|
78
|
-
skip_ssl_verification: @@skip_ssl_verification
|
|
79
|
-
)
|
|
80
|
-
PhraseApp::Client.new(credentials)
|
|
81
|
-
end
|
|
82
46
|
end
|
|
83
47
|
end
|
|
84
48
|
end
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require 'phraseapp-in-context-editor-ruby/delegate'
|
|
1
|
+
require_relative "../delegate"
|
|
4
2
|
|
|
5
3
|
module PhraseApp
|
|
6
4
|
module InContextEditor
|
|
@@ -12,20 +10,20 @@ module PhraseApp
|
|
|
12
10
|
@display_key = params[:msgid]
|
|
13
11
|
end
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
private
|
|
14
|
+
|
|
16
15
|
def params_from_args(args)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
16
|
+
case @method
|
|
17
|
+
when :_
|
|
18
|
+
{msgid: args.first}
|
|
19
|
+
when :n_
|
|
20
|
+
{msgid: args.first, msgid_plural: args[1], count: args.last}
|
|
21
|
+
when :s_
|
|
22
|
+
{msgid: args.first}
|
|
23
|
+
else
|
|
24
|
+
self.class.log("Unsupported FastGettext method #{@method}")
|
|
25
|
+
{}
|
|
27
26
|
end
|
|
28
|
-
params
|
|
29
27
|
end
|
|
30
28
|
end
|
|
31
29
|
end
|
|
@@ -1,12 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
require 'phraseapp-in-context-editor-ruby/cache'
|
|
4
|
-
require 'phraseapp-in-context-editor-ruby/hash_flattener'
|
|
5
|
-
require 'phraseapp-in-context-editor-ruby/delegate'
|
|
6
|
-
require 'phraseapp-in-context-editor-ruby/api_wrapper'
|
|
7
|
-
require 'phraseapp-in-context-editor-ruby/displayable_key_identifier'
|
|
8
|
-
|
|
9
|
-
require 'set'
|
|
1
|
+
require_relative "../delegate"
|
|
10
2
|
|
|
11
3
|
module PhraseApp
|
|
12
4
|
module InContextEditor
|
|
@@ -14,11 +6,11 @@ module PhraseApp
|
|
|
14
6
|
class I18nDelegate < Base
|
|
15
7
|
attr_accessor :key, :display_key, :options, :api_client, :fallback_keys, :original_args
|
|
16
8
|
|
|
17
|
-
def initialize(key, options={}, original_args=nil)
|
|
9
|
+
def initialize(key, options = {}, original_args = nil)
|
|
18
10
|
@key = key
|
|
19
11
|
@options = options
|
|
20
12
|
@original_args = original_args
|
|
21
|
-
@display_key =
|
|
13
|
+
@display_key = @key
|
|
22
14
|
super(decorated_key_name)
|
|
23
15
|
end
|
|
24
16
|
|
|
@@ -27,7 +19,7 @@ module PhraseApp
|
|
|
27
19
|
if @key.respond_to?(args.first)
|
|
28
20
|
to_s.send(*args)
|
|
29
21
|
else
|
|
30
|
-
data =
|
|
22
|
+
data = [@key]
|
|
31
23
|
if data.respond_to?(args.first)
|
|
32
24
|
data.send(*args, &block)
|
|
33
25
|
else
|
|
@@ -37,44 +29,6 @@ module PhraseApp
|
|
|
37
29
|
end
|
|
38
30
|
end
|
|
39
31
|
end
|
|
40
|
-
|
|
41
|
-
private
|
|
42
|
-
|
|
43
|
-
def translation_or_subkeys
|
|
44
|
-
return nil if @key.nil? || @key.to_s == ""
|
|
45
|
-
|
|
46
|
-
keys = api_wrapper.keys_with_prefix(@key)
|
|
47
|
-
return nil unless keys.present?
|
|
48
|
-
|
|
49
|
-
if keys.size == 1
|
|
50
|
-
translation_content_for_key(keys.first)
|
|
51
|
-
else
|
|
52
|
-
translation_hash = keys.inject({}) do |hash, key|
|
|
53
|
-
hash[key.name] = translation_content_for_key(key)
|
|
54
|
-
hash
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
PhraseApp::InContextEditor::HashFlattener.expand_flat_hash(translation_hash, @key)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
def translation_content_for_key(key)
|
|
62
|
-
default_translations = api_wrapper.default_translation(key)
|
|
63
|
-
return unless default_translations.present?
|
|
64
|
-
|
|
65
|
-
if key.plural
|
|
66
|
-
default_translations.inject({}) do |hash, translation|
|
|
67
|
-
hash[translation.plural_suffix.to_sym] = translation.content
|
|
68
|
-
hash
|
|
69
|
-
end
|
|
70
|
-
else
|
|
71
|
-
default_translations.first.content
|
|
72
|
-
end
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def api_wrapper
|
|
76
|
-
@api_wrapper ||= InContextEditor::ApiWrapper.new
|
|
77
|
-
end
|
|
78
32
|
end
|
|
79
33
|
end
|
|
80
34
|
end
|