Skip to content

Commit 85ca6e3

Browse files
authored
Merge pull request #14 from ishikawa999/develop
Merge develop branch v0.01.0
2 parents f4993cc + f64a76b commit 85ca6e3

23 files changed

+439
-137
lines changed

.circleci/config.yml

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
version: 2.1
2+
3+
orbs:
4+
redmine: agileware-jp/[email protected]
5+
6+
workflows:
7+
version: 2
8+
test:
9+
jobs:
10+
- redmine/download:
11+
name: redmine40-download
12+
redmine_version: '4.0.4'
13+
- redmine/download:
14+
name: redmine34-download
15+
redmine_version: '3.4.11'
16+
- redmine/download:
17+
name: redmine33-download
18+
redmine_version: '3.3.9'
19+
- redmine/download:
20+
name: redmine32-download
21+
redmine_version: '3.2.9'
22+
- redmine/test:
23+
name: redmine40
24+
before-setup: [redmine/generate_database_yml-pg]
25+
executor: redmine/ruby-26-pg
26+
requires: [redmine40-download]
27+
- redmine/test:
28+
name: redmine34
29+
before-setup: [redmine/generate_database_yml-pg]
30+
executor: redmine/ruby-24-pg
31+
requires: [redmine34-download]
32+
- redmine/test:
33+
name: redmine33
34+
before-setup: [redmine/generate_database_yml-pg]
35+
executor: redmine/ruby-23-pg
36+
requires: [redmine33-download]
37+
- redmine/test:
38+
name: redmine32
39+
before-setup: [redmine/generate_database_yml-pg]
40+
executor: redmine/ruby-22-pg
41+
requires: [redmine32-download]

35_change_load_order_locales.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# frozen_string_literal: true
2+
3+
p = Redmine::Plugin.find(:redmine_message_customize)
4+
custom_locales = Dir.glob(File.join(p.directory, 'config', 'locales', 'custom_messages', '*.rb'))
5+
Rails.application.config.i18n.load_path = (Rails.application.config.i18n.load_path - custom_locales + custom_locales)

Gemfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
if dependencies.detect { |d| d.name == 'rails' && d.requirement.to_s.include?('4.2.') }
2+
gem 'rails_kwargs_testing', group: :test
3+
end

README.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,17 @@
33
This is a plugin for Redmine.
44
This plugin changes the translation of the wording on the screen defined in "config/locales/*.yml" in the admin view.
55

6+
## Install
7+
8+
```
9+
$ cd /your/path/redmine
10+
$ git clone https://github.com/ishikawa999/redmine_message_customize.git plugins/redmine_message_customize
11+
$ cp plugins/redmine_message_customize/35_change_load_order_locales.rb config/initializers/35_change_load_order_locales.rb
12+
$ # redmine restart
13+
```
14+
15+
:warning: In order to customize messages of other plugins, it is necessary to copy redmine_message_customize/35_change_load_order_locales.rb into redmine/config/initializers.
16+
617
## Usage
718

819
* 1: Open setting page
@@ -15,17 +26,13 @@ Administration > Message customize
1526
* 2-2: YAML mode tab
1627
<kbd><img src="https://github.com/ishikawa999/redmine_message_customize/blob/images/yaml_mode.png" /></kbd>
1728

18-
## Install
19-
20-
```
21-
$ cd /your/path/redmine/plugins
22-
$ git clone https://github.com/ishikawa999/redmine_message_customize.git
23-
$ # redmine restart
24-
```
25-
2629
## Run test
2730

2831
```
2932
$ cd /your/path/redmine
30-
$ bundle exec rake test TEST=plugins/redmine_message_customize/test RAILS_ENV=test
33+
$ bundle exec rake redmine:plugins:test NAME=redmine_message_customize RAILS_ENV=test
3134
```
35+
36+
## CircleCI test
37+
38+
https://circleci.com/gh/ishikawa999/redmine_message_customize

app/controllers/custom_message_settings_controller.rb

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
11
class CustomMessageSettingsController < ApplicationController
22
layout 'admin'
33
before_action :require_admin, :set_custom_message_setting, :set_lang
4-
require_sudo_mode :edit, :update, :toggle_enabled
4+
require_sudo_mode :edit, :update, :toggle_enabled, :default_messages
55

66
def edit
77
end
88

9+
def default_messages
10+
@file_path = Rails.root.join('config', 'locales', "#{@lang}.yml")
11+
end
12+
913
def update
1014
languages = @setting.using_languages
1115

@@ -18,12 +22,16 @@ def update
1822
if @setting.errors.blank?
1923
flash[:notice] = l(:notice_successful_update)
2024
languages += @setting.using_languages
21-
CustomMessageSetting.reload_translations!(languages)
25+
MessageCustomize::Locale.reload!(languages)
2226

2327
redirect_to edit_custom_message_settings_path(tab: params[:tab], lang: @lang)
2428
else
2529
render :edit
2630
end
31+
32+
# Catch an exception that occurs when the value field capacity is exceeded (ActiveRecord::ValueTooLong)
33+
rescue ActiveRecord::StatementInvalid
34+
render_error l(:error_value_too_long)
2735
end
2836

2937
def toggle_enabled
@@ -37,6 +45,7 @@ def toggle_enabled
3745
end
3846

3947
private
48+
4049
def set_custom_message_setting
4150
@setting = CustomMessageSetting.find_or_default
4251
end
@@ -46,6 +55,6 @@ def setting_params
4655
end
4756

4857
def set_lang
49-
@lang = CustomMessageSetting.find_language(params[:lang].presence || User.current.language.presence || 'en')
58+
@lang = MessageCustomize::Locale.find_language(params[:lang].presence || User.current.language.presence || 'en')
5059
end
51-
end
60+
end

app/helpers/custom_message_settings_helper.rb

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
module CustomMessageSettingsHelper
22
def available_message_options(setting, lang)
33
options = [['', '']] +
4-
CustomMessageSetting.available_messages(lang).map{|k, v| ["#{k}: #{v}", k]}
4+
CustomMessageSetting.flatten_hash(MessageCustomize::Locale.available_messages(lang))
5+
.select{|_k, v| v.is_a?(String)}
6+
.map{|k, v| ["#{k}: #{v}", k]}
57

68
options_for_select(options, disabled: setting.custom_messages_to_flatten_hash(lang).keys)
79
end
810

911
def normal_mode_input_fields(setting, lang)
10-
return '' if setting.value[:custom_messages].is_a?(String) || setting.value[:custom_messages].blank?
12+
return '' if setting.custom_messages.is_a?(String) || setting.custom_messages.blank?
13+
1114
content = ActiveSupport::SafeBuffer.new
1215
custom_messages_hash = setting.custom_messages_to_flatten_hash(lang.to_s)
1316
custom_messages_hash.each do |k, v|
@@ -19,4 +22,12 @@ def normal_mode_input_fields(setting, lang)
1922
end
2023
content
2124
end
25+
26+
def open_default_messages_window_link(lang)
27+
link_to l(:label_default_messages),
28+
default_messages_custom_message_settings_path(lang: lang),
29+
class: 'icon icon-file text-plain',
30+
onclick: "window.open(this.href,'redmine_message_customize_plugin-default_messages', 'height=800, width=500');return false;",
31+
id: 'default-messages-link'
32+
end
2233
end
Lines changed: 50 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
class CustomMessageSetting < Setting
2-
validate :add_errors, :convertible_to_yaml,
2+
validate :convertible_to_yaml,
33
:custom_message_languages_are_available, :custom_message_keys_are_available
44

55
def self.find_or_default
@@ -11,30 +11,23 @@ def enabled?
1111
end
1212

1313
def custom_messages(lang=nil, check_enabled=false)
14-
messages = self.value[:custom_messages] || self.value['custom_messages']
15-
if lang.present?
16-
messages = messages[self.class.find_language(lang)]
17-
end
14+
return {} if check_enabled && !self.enabled?
1815

19-
if messages.blank? || (check_enabled && !self.enabled?)
20-
{}
21-
else
22-
messages
23-
end
16+
messages = raw_custom_messages
17+
messages = messages[lang.to_s] if lang.present?
18+
messages || {}
2419
end
2520

2621
def custom_messages_to_flatten_hash(lang=nil)
2722
self.class.flatten_hash(custom_messages(lang))
2823
end
2924

3025
def custom_messages_to_yaml
31-
messages = self.custom_messages
32-
if messages.blank?
33-
''
34-
elsif messages.is_a?(Hash)
35-
YAML.dump(messages)
26+
messages = custom_messages
27+
if messages.is_a?(Hash)
28+
messages.present? ? YAML.dump(messages) : ''
3629
else
37-
messages
30+
raw_custom_messages
3831
end
3932
end
4033

@@ -49,27 +42,20 @@ def update_with_custom_messages(custom_messages, lang)
4942
original_custom_messages
5043
end
5144

52-
self.value = {custom_messages: (messages.present? ? messages : {})}
45+
self.custom_messages = messages
5346
self.save
5447
end
5548

5649
def update_with_custom_messages_yaml(yaml)
57-
begin
58-
messages = YAML.load(yaml)
59-
@errs = {base: l(:error_invalid_yaml_format) } if !messages.is_a?(Hash) && messages.present?
60-
self.value = {custom_messages: (messages.present? ? messages : {})}
61-
rescue => e
62-
@errs = {base: e.message}
63-
self.value = {custom_messages: yaml}
64-
end
50+
self.custom_messages = yaml
6551
self.save
6652
end
6753

6854
def toggle_enabled!
69-
self.value = self.value.deep_merge({enabled: (!self.enabled?).to_s})
55+
self.value = self.value.merge({enabled: (!self.enabled?).to_s})
7056

7157
if result = self.save
72-
self.class.reload_translations!(self.using_languages)
58+
MessageCustomize::Locale.reload!(self.using_languages)
7359
end
7460
result
7561
end
@@ -83,21 +69,13 @@ def using_languages
8369
end
8470
end
8571

86-
def self.available_messages(lang)
87-
messages = I18n.backend.send(:translations)[self.find_language(lang).to_s.to_sym]
88-
if messages.nil?
89-
CustomMessageSetting.reload_translations!([lang])
90-
messages = I18n.backend.send(:translations)[lang.to_s.to_sym] || {}
91-
end
92-
self.flatten_hash(messages)
93-
end
94-
9572
# { date: { formats: { defaults: '%m/%d/%Y'}}} to {'date.formats.defaults' => '%m/%d/%Y'}
9673
def self.flatten_hash(hash=nil)
97-
hash = self.to_hash unless hash
74+
return hash unless hash.is_a?(Hash)
75+
9876
hash.each_with_object({}) do |(key, value), content|
9977
next self.flatten_hash(value).each do |k, v|
100-
content["#{key}.#{k}".intern] = v
78+
content[:"#{key}.#{k}"] = v
10179
end if value.is_a? Hash
10280
content[key] = value
10381
end
@@ -108,7 +86,6 @@ def self.nested_hash(hash=nil)
10886
new_hash = {}
10987
hash.each do |key, value|
11088
h = value
111-
h = YAML.load(value) if value.first == '[' && value.last == ']'
11289
key.to_s.split('.').reverse_each do |k|
11390
h = {k => h}
11491
end
@@ -117,62 +94,60 @@ def self.nested_hash(hash=nil)
11794
new_hash
11895
end
11996

120-
def self.reload_translations!(languages)
121-
paths = I18n.load_path.select {|path| self.find_language(languages).include?(File.basename(path, '.*').to_s)}
122-
I18n.backend.load_translations(paths)
123-
end
97+
private
12498

125-
def self.find_language(language=nil)
126-
if language.is_a?(Array)
127-
language.select{|l| I18n.available_locales.include?(l.to_s.to_sym)}.map(&:to_s).compact
128-
elsif language.present? && I18n.available_locales.include?(language.to_s.to_sym)
129-
language.to_s
130-
else
131-
nil
132-
end
99+
def raw_custom_messages
100+
self.value[:custom_messages] || self.value['custom_messages']
133101
end
134102

135-
private
103+
def custom_messages=(messages)
104+
messages = YAML.load("#{messages}") unless messages.is_a?(Hash)
105+
self.value = self.value.merge({custom_messages: messages.presence || {}})
106+
rescue Psych::SyntaxError => e
107+
self.value = self.value.merge({custom_messages: messages})
108+
end
136109

137110
def custom_message_keys_are_available
138-
return false if !value[:custom_messages].is_a?(Hash) || errors.present?
111+
return if errors.present?
112+
113+
en_translation_hash = self.class.flatten_hash(MessageCustomize::Locale.available_messages('en'))
114+
custom_message_keys =
115+
custom_messages.values.each_with_object([]){|val, ar|
116+
ar.concat(self.class.flatten_hash(val).keys)
117+
}.uniq
118+
119+
unused_keys = custom_message_keys.reject{|k| en_translation_hash.keys.include?(:"#{k}")}
120+
unusable_type_of_keys = (custom_message_keys - unused_keys).reject{|k| en_translation_hash[:"#{k}"].is_a?(String)}
139121

140-
custom_messages_hash = {}
141-
custom_messages.values.compact.each do |val|
142-
custom_messages_hash = self.class.flatten_hash(custom_messages_hash.merge(val)) if val.is_a?(Hash)
122+
if unused_keys.present?
123+
errors.add(:base, "#{l(:error_unused_keys)} keys: [#{unused_keys.join(', ')}]")
143124
end
144-
available_keys = self.class.flatten_hash(self.class.available_messages('en')).keys
145-
unavailable_keys = custom_messages_hash.keys.reject{|k| available_keys.include?(k.to_sym)}
146-
if unavailable_keys.present?
147-
self.errors.add(:base, l(:error_unavailable_keys) + " keys: [#{unavailable_keys.join(', ')}]")
148-
false
125+
if unusable_type_of_keys.present?
126+
errors.add(:base, "#{l(:error_unusable_type_of_keys)} keys: [#{unusable_type_of_keys.join(', ')}]")
149127
end
150128
end
151129

152130
def custom_message_languages_are_available
153-
return false if !value[:custom_messages].is_a?(Hash) || errors.present?
131+
return if errors.present?
154132

155133
unavailable_languages =
156134
custom_messages.keys.compact.reject do |language|
157-
I18n.available_locales.include?(language.to_sym)
135+
MessageCustomize::Locale.available_locales.include?(language.to_sym)
158136
end
159137
if unavailable_languages.present?
160-
self.errors.add(:base, l(:error_unavailable_languages) + " [#{unavailable_languages.join(', ')}]")
161-
false
138+
errors.add(:base, l(:error_unavailable_languages) + " [#{unavailable_languages.join(', ')}]")
162139
end
163140
end
164141

165142
def convertible_to_yaml
166-
YAML.dump(self.value[:custom_messages])
167-
end
168-
169-
def add_errors
170-
if @errs.present?
171-
@errs.each do |key, value|
172-
self.errors.add(key, value)
143+
raw_messages = raw_custom_messages
144+
if raw_messages.present? && !raw_messages.is_a?(Hash)
145+
begin
146+
YAML.load("#{raw_messages}")
147+
errors.add(:base, l(:error_invalid_yaml_format))
148+
rescue Psych::SyntaxError => e
149+
errors.add(:base, "#{l(:error_invalid_yaml_format)} #{e.message}")
173150
end
174-
@errs = nil
175-
false
176151
end
177152
end
178-
end
153+
end

0 commit comments

Comments
 (0)