Revision 1298:4f746d8966dd .svn/pristine/0a

View differences:

.svn/pristine/0a/0a01ef88ba34bfc6a3c1cef8891538f7504e9b0c.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2013  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
module Redmine
19
  module I18n
20
    def self.included(base)
21
      base.extend Redmine::I18n
22
    end
23

  
24
    def l(*args)
25
      case args.size
26
      when 1
27
        ::I18n.t(*args)
28
      when 2
29
        if args.last.is_a?(Hash)
30
          ::I18n.t(*args)
31
        elsif args.last.is_a?(String)
32
          ::I18n.t(args.first, :value => args.last)
33
        else
34
          ::I18n.t(args.first, :count => args.last)
35
        end
36
      else
37
        raise "Translation string with multiple values: #{args.first}"
38
      end
39
    end
40

  
41
    def l_or_humanize(s, options={})
42
      k = "#{options[:prefix]}#{s}".to_sym
43
      ::I18n.t(k, :default => s.to_s.humanize)
44
    end
45

  
46
    def l_hours(hours)
47
      hours = hours.to_f
48
      l((hours < 2.0 ? :label_f_hour : :label_f_hour_plural), :value => ("%.2f" % hours.to_f))
49
    end
50

  
51
    def ll(lang, str, value=nil)
52
      ::I18n.t(str.to_s, :value => value, :locale => lang.to_s.gsub(%r{(.+)\-(.+)$}) { "#{$1}-#{$2.upcase}" })
53
    end
54

  
55
    def format_date(date)
56
      return nil unless date
57
      options = {}
58
      options[:format] = Setting.date_format unless Setting.date_format.blank?
59
      options[:locale] = User.current.language unless User.current.language.blank?
60
      ::I18n.l(date.to_date, options)
61
    end
62

  
63
    def format_time(time, include_date = true)
64
      return nil unless time
65
      options = {}
66
      options[:format] = (Setting.time_format.blank? ? :time : Setting.time_format)
67
      options[:locale] = User.current.language unless User.current.language.blank?
68
      time = time.to_time if time.is_a?(String)
69
      zone = User.current.time_zone
70
      local = zone ? time.in_time_zone(zone) : (time.utc? ? time.localtime : time)
71
      (include_date ? "#{format_date(local)} " : "") + ::I18n.l(local, options)
72
    end
73

  
74
    def day_name(day)
75
      ::I18n.t('date.day_names')[day % 7]
76
    end
77

  
78
    def day_letter(day)
79
      ::I18n.t('date.abbr_day_names')[day % 7].first
80
    end
81

  
82
    def month_name(month)
83
      ::I18n.t('date.month_names')[month]
84
    end
85

  
86
    def valid_languages
87
      ::I18n.available_locales
88
    end
89

  
90
    # Returns an array of languages names and code sorted by names, example:
91
    # [["Deutsch", "de"], ["English", "en"] ...]
92
    #
93
    # The result is cached to prevent from loading all translations files.
94
    def languages_options
95
      ActionController::Base.cache_store.fetch "i18n/languages_options" do
96
        valid_languages.map {|lang| [ll(lang.to_s, :general_lang_name), lang.to_s]}.sort {|x,y| x.first <=> y.first }
97
      end      
98
    end
99

  
100
    def find_language(lang)
101
      @@languages_lookup = valid_languages.inject({}) {|k, v| k[v.to_s.downcase] = v; k }
102
      @@languages_lookup[lang.to_s.downcase]
103
    end
104

  
105
    def set_language_if_valid(lang)
106
      if l = find_language(lang)
107
        ::I18n.locale = l
108
      end
109
    end
110

  
111
    def current_language
112
      ::I18n.locale
113
    end
114

  
115
    # Custom backend based on I18n::Backend::Simple with the following changes:
116
    # * lazy loading of translation files
117
    # * available_locales are determined by looking at translation file names
118
    class Backend
119
      (class << self; self; end).class_eval { public :include }
120

  
121
      module Implementation
122
        include ::I18n::Backend::Base
123

  
124
        # Stores translations for the given locale in memory.
125
        # This uses a deep merge for the translations hash, so existing
126
        # translations will be overwritten by new ones only at the deepest
127
        # level of the hash.
128
        def store_translations(locale, data, options = {})
129
          locale = locale.to_sym
130
          translations[locale] ||= {}
131
          data = data.deep_symbolize_keys
132
          translations[locale].deep_merge!(data)
133
        end
134

  
135
        # Get available locales from the translations filenames
136
        def available_locales
137
          @available_locales ||= ::I18n.load_path.map {|path| File.basename(path, '.*')}.uniq.sort.map(&:to_sym)
138
        end
139

  
140
        # Clean up translations
141
        def reload!
142
          @translations = nil
143
          @available_locales = nil
144
          super
145
        end
146

  
147
        protected
148

  
149
        def init_translations(locale)
150
          locale = locale.to_s
151
          paths = ::I18n.load_path.select {|path| File.basename(path, '.*') == locale}
152
          load_translations(paths)
153
          translations[locale] ||= {}
154
        end
155

  
156
        def translations
157
          @translations ||= {}
158
        end
159

  
160
        # Looks up a translation from the translations hash. Returns nil if
161
        # eiher key is nil, or locale, scope or key do not exist as a key in the
162
        # nested translations hash. Splits keys or scopes containing dots
163
        # into multiple keys, i.e. <tt>currency.format</tt> is regarded the same as
164
        # <tt>%w(currency format)</tt>.
165
        def lookup(locale, key, scope = [], options = {})
166
          init_translations(locale) unless translations.key?(locale)
167
          keys = ::I18n.normalize_keys(locale, key, scope, options[:separator])
168

  
169
          keys.inject(translations) do |result, _key|
170
            _key = _key.to_sym
171
            return nil unless result.is_a?(Hash) && result.has_key?(_key)
172
            result = result[_key]
173
            result = resolve(locale, _key, result, options.merge(:scope => nil)) if result.is_a?(Symbol)
174
            result
175
          end
176
        end
177
      end
178

  
179
      include Implementation
180
      # Adds fallback to default locale for untranslated strings
181
      include ::I18n::Backend::Fallbacks
182
    end
183
  end
184
end
.svn/pristine/0a/0a371b310545389947180083feb53371bb868f67.svn-base
1
module CodeRay
2
module Encoders
3
  
4
  map \
5
    :loc             => :lines_of_code,
6
    :plain           => :text,
7
    :plaintext       => :text,
8
    :remove_comments => :comment_filter,
9
    :stats           => :statistic,
10
    :term            => :terminal,
11
    :tty             => :terminal,
12
    :yml             => :yaml
13
  
14
  # No default because Tokens#nonsense should raise NoMethodError.
15
  
16
end
17
end
.svn/pristine/0a/0a62a3ae28a4f2df93a63c650d603c29ff087559.svn-base
1
<% form_tag({:action => 'edit', :tab => 'mail_handler'}) do %>
2

  
3
<div class="box tabular settings">
4
  <p>
5
    <%= setting_text_area :mail_handler_body_delimiters, :rows => 5 %>
6
    <br /><em><%= l(:text_line_separated) %></em>
7
  </p>
8
</div>
9

  
10
<div class="box tabular settings">
11
<p><%= setting_check_box :mail_handler_api_enabled,
12
         :onclick => "if (this.checked) { Form.Element.enable('settings_mail_handler_api_key'); } else { Form.Element.disable('settings_mail_handler_api_key'); }"%></p>
13

  
14
<p><%= setting_text_field :mail_handler_api_key, :size => 30,
15
                                                 :id => 'settings_mail_handler_api_key',
16
                                                 :disabled => !Setting.mail_handler_api_enabled? %>
17
  <%= link_to_function l(:label_generate_key), "if ($('settings_mail_handler_api_key').disabled == false) { $('settings_mail_handler_api_key').value = randomKey(20) }" %>
18
</p>
19
</div>
20

  
21
<%= submit_tag l(:button_save) %>
22

  
23
<% end %>
.svn/pristine/0a/0a884b128ca03268f26234e1c96b240bce5a6e1b.svn-base
1
# Redmine - project management software
2
# Copyright (C) 2006-2011  Jean-Philippe Lang
3
#
4
# This program is free software; you can redistribute it and/or
5
# modify it under the terms of the GNU General Public License
6
# as published by the Free Software Foundation; either version 2
7
# of the License, or (at your option) any later version.
8
#
9
# This program is distributed in the hope that it will be useful,
10
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
# GNU General Public License for more details.
13
#
14
# You should have received a copy of the GNU General Public License
15
# along with this program; if not, write to the Free Software
16
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17

  
18
require File.expand_path('../../test_helper', __FILE__)
19

  
20
class EnumerationsControllerTest < ActionController::TestCase
21
  fixtures :enumerations, :issues, :users
22

  
23
  def setup
24
    @request.session[:user_id] = 1 # admin
25
  end
26

  
27
  def test_index
28
    get :index
29
    assert_response :success
30
    assert_template 'index'
31
  end
32

  
33
  def test_new
34
    get :new, :type => 'IssuePriority'
35
    assert_response :success
36
    assert_template 'new'
37
    assert_kind_of IssuePriority, assigns(:enumeration)
38
  end
39

  
40
  def test_create
41
    assert_difference 'IssuePriority.count' do
42
      post :create, :enumeration => {:type => 'IssuePriority', :name => 'Lowest'}
43
    end
44
    assert_redirected_to '/enumerations?type=IssuePriority'
45
    e = IssuePriority.first(:order => 'id DESC')
46
    assert_equal 'Lowest', e.name
47
  end
48

  
49
  def test_create_with_failure
50
    assert_no_difference 'IssuePriority.count' do
51
      post :create, :enumeration => {:type => 'IssuePriority', :name => ''}
52
    end
53
    assert_response :success
54
    assert_template 'new'
55
  end
56

  
57
  def test_edit
58
    get :edit, :id => 6
59
    assert_response :success
60
    assert_template 'edit'
61
  end
62

  
63
  def test_update
64
    assert_no_difference 'IssuePriority.count' do
65
      post :update, :id => 6, :enumeration => {:type => 'IssuePriority', :name => 'New name'}
66
    end
67
    assert_redirected_to '/enumerations?type=IssuePriority'
68
    e = IssuePriority.find(6)
69
    assert_equal 'New name', e.name
70
  end
71

  
72
  def test_update_with_failure
73
    assert_no_difference 'IssuePriority.count' do
74
      post :update, :id => 6, :enumeration => {:type => 'IssuePriority', :name => ''}
75
    end
76
    assert_response :success
77
    assert_template 'edit'
78
  end
79

  
80
  def test_destroy_enumeration_not_in_use
81
    post :destroy, :id => 7
82
    assert_redirected_to :controller => 'enumerations', :action => 'index'
83
    assert_nil Enumeration.find_by_id(7)
84
  end
85

  
86
  def test_destroy_enumeration_in_use
87
    post :destroy, :id => 4
88
    assert_response :success
89
    assert_template 'destroy'
90
    assert_not_nil Enumeration.find_by_id(4)
91
  end
92

  
93
  def test_destroy_enumeration_in_use_with_reassignment
94
    issue = Issue.find(:first, :conditions => {:priority_id => 4})
95
    post :destroy, :id => 4, :reassign_to_id => 6
96
    assert_redirected_to :controller => 'enumerations', :action => 'index'
97
    assert_nil Enumeration.find_by_id(4)
98
    # check that the issue was reassign
99
    assert_equal 6, issue.reload.priority_id
100
  end
101
end
.svn/pristine/0a/0ab85a80b71d453bc34359193f9b3a077fde14bb.svn-base
1
module ActiveRecord
2
  module Acts #:nodoc:
3
    module List #:nodoc:
4
      def self.included(base)
5
        base.extend(ClassMethods)
6
      end
7

  
8
      # This +acts_as+ extension provides the capabilities for sorting and reordering a number of objects in a list.
9
      # The class that has this specified needs to have a +position+ column defined as an integer on
10
      # the mapped database table.
11
      #
12
      # Todo list example:
13
      #
14
      #   class TodoList < ActiveRecord::Base
15
      #     has_many :todo_items, :order => "position"
16
      #   end
17
      #
18
      #   class TodoItem < ActiveRecord::Base
19
      #     belongs_to :todo_list
20
      #     acts_as_list :scope => :todo_list
21
      #   end
22
      #
23
      #   todo_list.first.move_to_bottom
24
      #   todo_list.last.move_higher
25
      module ClassMethods
26
        # Configuration options are:
27
        #
28
        # * +column+ - specifies the column name to use for keeping the position integer (default: +position+)
29
        # * +scope+ - restricts what is to be considered a list. Given a symbol, it'll attach <tt>_id</tt> 
30
        #   (if it hasn't already been added) and use that as the foreign key restriction. It's also possible 
31
        #   to give it an entire string that is interpolated if you need a tighter scope than just a foreign key.
32
        #   Example: <tt>acts_as_list :scope => 'todo_list_id = #{todo_list_id} AND completed = 0'</tt>
33
        def acts_as_list(options = {})
34
          configuration = { :column => "position", :scope => "1 = 1" }
35
          configuration.update(options) if options.is_a?(Hash)
36

  
37
          configuration[:scope] = "#{configuration[:scope]}_id".intern if configuration[:scope].is_a?(Symbol) && configuration[:scope].to_s !~ /_id$/
38

  
39
          if configuration[:scope].is_a?(Symbol)
40
            scope_condition_method = %(
41
              def scope_condition
42
                if #{configuration[:scope].to_s}.nil?
43
                  "#{configuration[:scope].to_s} IS NULL"
44
                else
45
                  "#{configuration[:scope].to_s} = \#{#{configuration[:scope].to_s}}"
46
                end
47
              end
48
            )
49
          else
50
            scope_condition_method = "def scope_condition() \"#{configuration[:scope]}\" end"
51
          end
52

  
53
          class_eval <<-EOV
54
            include ActiveRecord::Acts::List::InstanceMethods
55

  
56
            def acts_as_list_class
57
              ::#{self.name}
58
            end
59

  
60
            def position_column
61
              '#{configuration[:column]}'
62
            end
63

  
64
            #{scope_condition_method}
65

  
66
            before_destroy :remove_from_list
67
            before_create  :add_to_list_bottom
68
          EOV
69
        end
70
      end
71

  
72
      # All the methods available to a record that has had <tt>acts_as_list</tt> specified. Each method works
73
      # by assuming the object to be the item in the list, so <tt>chapter.move_lower</tt> would move that chapter
74
      # lower in the list of all chapters. Likewise, <tt>chapter.first?</tt> would return +true+ if that chapter is
75
      # the first in the list of all chapters.
76
      module InstanceMethods
77
        # Insert the item at the given position (defaults to the top position of 1).
78
        def insert_at(position = 1)
79
          insert_at_position(position)
80
        end
81

  
82
        # Swap positions with the next lower item, if one exists.
83
        def move_lower
84
          return unless lower_item
85

  
86
          acts_as_list_class.transaction do
87
            lower_item.decrement_position
88
            increment_position
89
          end
90
        end
91

  
92
        # Swap positions with the next higher item, if one exists.
93
        def move_higher
94
          return unless higher_item
95

  
96
          acts_as_list_class.transaction do
97
            higher_item.increment_position
98
            decrement_position
99
          end
100
        end
101

  
102
        # Move to the bottom of the list. If the item is already in the list, the items below it have their
103
        # position adjusted accordingly.
104
        def move_to_bottom
105
          return unless in_list?
106
          acts_as_list_class.transaction do
107
            decrement_positions_on_lower_items
108
            assume_bottom_position
109
          end
110
        end
111

  
112
        # Move to the top of the list. If the item is already in the list, the items above it have their
113
        # position adjusted accordingly.
114
        def move_to_top
115
          return unless in_list?
116
          acts_as_list_class.transaction do
117
            increment_positions_on_higher_items
118
            assume_top_position
119
          end
120
        end
121
        
122
        # Move to the given position
123
        def move_to=(pos)
124
          case pos.to_s
125
          when 'highest'
126
            move_to_top
127
          when 'higher'
128
            move_higher
129
          when 'lower'
130
            move_lower
131
          when 'lowest'
132
            move_to_bottom
133
          end
134
          reset_positions_in_list
135
        end
136

  
137
        def reset_positions_in_list
138
          acts_as_list_class.where(scope_condition).reorder("#{position_column} ASC, id ASC").each_with_index do |item, i|
139
            unless item.send(position_column) == (i + 1)
140
              acts_as_list_class.update_all({position_column => (i + 1)}, {:id => item.id})
141
            end
142
          end
143
        end
144

  
145
        # Removes the item from the list.
146
        def remove_from_list
147
          if in_list?
148
            decrement_positions_on_lower_items
149
            update_attribute position_column, nil
150
          end
151
        end
152

  
153
        # Increase the position of this item without adjusting the rest of the list.
154
        def increment_position
155
          return unless in_list?
156
          update_attribute position_column, self.send(position_column).to_i + 1
157
        end
158

  
159
        # Decrease the position of this item without adjusting the rest of the list.
160
        def decrement_position
161
          return unless in_list?
162
          update_attribute position_column, self.send(position_column).to_i - 1
163
        end
164

  
165
        # Return +true+ if this object is the first in the list.
166
        def first?
167
          return false unless in_list?
168
          self.send(position_column) == 1
169
        end
170

  
171
        # Return +true+ if this object is the last in the list.
172
        def last?
173
          return false unless in_list?
174
          self.send(position_column) == bottom_position_in_list
175
        end
176

  
177
        # Return the next higher item in the list.
178
        def higher_item
179
          return nil unless in_list?
180
          acts_as_list_class.where(
181
            "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i - 1).to_s}"
182
          ).first
183
        end
184

  
185
        # Return the next lower item in the list.
186
        def lower_item
187
          return nil unless in_list?
188
          acts_as_list_class.where(
189
            "#{scope_condition} AND #{position_column} = #{(send(position_column).to_i + 1).to_s}"
190
          ).first
191
        end
192

  
193
        # Test if this record is in a list
194
        def in_list?
195
          !send(position_column).nil?
196
        end
197

  
198
        private
199
          def add_to_list_top
200
            increment_positions_on_all_items
201
          end
202

  
203
          def add_to_list_bottom
204
            self[position_column] = bottom_position_in_list.to_i + 1
205
          end
206

  
207
          # Overwrite this method to define the scope of the list changes
208
          def scope_condition() "1" end
209

  
210
          # Returns the bottom position number in the list.
211
          #   bottom_position_in_list    # => 2
212
          def bottom_position_in_list(except = nil)
213
            item = bottom_item(except)
214
            item ? item.send(position_column) : 0
215
          end
216

  
217
          # Returns the bottom item
218
          def bottom_item(except = nil)
219
            conditions = scope_condition
220
            conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except
221
            acts_as_list_class.where(conditions).reorder("#{position_column} DESC").first
222
          end
223

  
224
          # Forces item to assume the bottom position in the list.
225
          def assume_bottom_position
226
            update_attribute(position_column, bottom_position_in_list(self).to_i + 1)
227
          end
228

  
229
          # Forces item to assume the top position in the list.
230
          def assume_top_position
231
            update_attribute(position_column, 1)
232
          end
233

  
234
          # This has the effect of moving all the higher items up one.
235
          def decrement_positions_on_higher_items(position)
236
            acts_as_list_class.update_all(
237
              "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} <= #{position}"
238
            )
239
          end
240

  
241
          # This has the effect of moving all the lower items up one.
242
          def decrement_positions_on_lower_items
243
            return unless in_list?
244
            acts_as_list_class.update_all(
245
              "#{position_column} = (#{position_column} - 1)", "#{scope_condition} AND #{position_column} > #{send(position_column).to_i}"
246
            )
247
          end
248

  
249
          # This has the effect of moving all the higher items down one.
250
          def increment_positions_on_higher_items
251
            return unless in_list?
252
            acts_as_list_class.update_all(
253
              "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} < #{send(position_column).to_i}"
254
            )
255
          end
256

  
257
          # This has the effect of moving all the lower items down one.
258
          def increment_positions_on_lower_items(position)
259
            acts_as_list_class.update_all(
260
              "#{position_column} = (#{position_column} + 1)", "#{scope_condition} AND #{position_column} >= #{position}"
261
           )
262
          end
263

  
264
          # Increments position (<tt>position_column</tt>) of all items in the list.
265
          def increment_positions_on_all_items
266
            acts_as_list_class.update_all(
267
              "#{position_column} = (#{position_column} + 1)",  "#{scope_condition}"
268
            )
269
          end
270

  
271
          def insert_at_position(position)
272
            remove_from_list
273
            increment_positions_on_lower_items(position)
274
            self.update_attribute(position_column, position)
275
          end
276
      end 
277
    end
278
  end
279
end

Also available in: Unified diff