kete_translatable_content 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/.document +5 -0
  2. data/.gitignore +23 -0
  3. data/LICENSE +295 -0
  4. data/README.rdoc +80 -0
  5. data/README.rdoc.orig +72 -0
  6. data/Rakefile +53 -0
  7. data/VERSION +1 -0
  8. data/app/views/active_scaffold_overrides/_show.html.erb +8 -0
  9. data/app/views/active_scaffold_overrides/_update_form.html.erb +8 -0
  10. data/app/views/active_scaffold_overrides/list.html.erb +5 -0
  11. data/app/views/baskets/_additional_footer_content_fields.html.erb +33 -0
  12. data/app/views/baskets/_rss_feed.html.erb +42 -0
  13. data/app/views/baskets/_side_bar_html.html.erb +19 -0
  14. data/app/views/configure/section.rhtml +36 -0
  15. data/app/views/layouts/translations.html.erb +1 -0
  16. data/app/views/topics/_content_wrapper_start.rhtml +26 -0
  17. data/app/views/translations/_form.html.erb +54 -0
  18. data/app/views/translations/_translatable_value.html.erb +36 -0
  19. data/app/views/translations/_translation_field_input.html.erb +61 -0
  20. data/app/views/translations/show.html.erb +12 -0
  21. data/app/views/translations/versioned_edit.html.erb +9 -0
  22. data/config/locales/en.yml +51 -0
  23. data/config/routes.rb +11 -0
  24. data/config/translatables.yml +65 -0
  25. data/generators/kete_translatable_content_migration/USAGE +2 -0
  26. data/generators/kete_translatable_content_migration/kete_translatable_content_migration_generator.rb +7 -0
  27. data/generators/kete_translatable_content_migration/templates/migration.rb +82 -0
  28. data/generators/kete_translatable_content_tests/USAGE +2 -0
  29. data/generators/kete_translatable_content_tests/kete_translatable_content_tests_generator.rb +38 -0
  30. data/generators/kete_translatable_content_tests/templates/configure_kete_content_translation_controller_and_routes_test.rb +48 -0
  31. data/generators/kete_translatable_content_tests/templates/configure_kete_content_translation_test.rb +47 -0
  32. data/generators/kete_translatable_content_tests/templates/kete_translatable_content_helper_test.rb +19 -0
  33. data/generators/kete_translatable_content_tests/templates/kete_translatable_content_migration_test.rb +45 -0
  34. data/generators/kete_translatable_content_tests/templates/kete_translatable_content_oai_dc_helpers_test.rb +66 -0
  35. data/generators/kete_translatable_content_tests/templates/kete_translatable_content_translations_test.rb +23 -0
  36. data/generators/kete_translatable_content_tests/templates/kete_translations_test.rb +57 -0
  37. data/generators/kete_translatable_content_tests/templates/mongo_factories.rb +6 -0
  38. data/generators/kete_translatable_content_tests/templates/mongo_test_helper.rb +37 -0
  39. data/generators/kete_translatable_content_tests/templates/mongo_translatable_test.rb +262 -0
  40. data/lib/kete_translatable_content.rb +54 -0
  41. data/lib/kete_translatable_content/extensions/controllers/application_controller.rb +202 -0
  42. data/lib/kete_translatable_content/extensions/controllers/audio_controller.rb +7 -0
  43. data/lib/kete_translatable_content/extensions/controllers/baskets_controller.rb +3 -0
  44. data/lib/kete_translatable_content/extensions/controllers/documents_controller.rb +7 -0
  45. data/lib/kete_translatable_content/extensions/controllers/images_controller.rb +7 -0
  46. data/lib/kete_translatable_content/extensions/controllers/topics_controller.rb +7 -0
  47. data/lib/kete_translatable_content/extensions/controllers/translations_controller.rb +209 -0
  48. data/lib/kete_translatable_content/extensions/controllers/video_controller.rb +7 -0
  49. data/lib/kete_translatable_content/extensions/controllers/web_links_controller.rb +7 -0
  50. data/lib/kete_translatable_content/extensions/extended_content_translation.rb +54 -0
  51. data/lib/kete_translatable_content/extensions/helpers/application_helper.rb +156 -0
  52. data/lib/kete_translatable_content/extensions/helpers/extended_fields_helper.rb +17 -0
  53. data/lib/kete_translatable_content/extensions/helpers/search_helper.rb +5 -0
  54. data/lib/kete_translatable_content/extensions/helpers/translations_helper.rb +72 -0
  55. data/lib/kete_translatable_content/extensions/models/audio_recording.rb +12 -0
  56. data/lib/kete_translatable_content/extensions/models/basket.rb +34 -0
  57. data/lib/kete_translatable_content/extensions/models/comment.rb +12 -0
  58. data/lib/kete_translatable_content/extensions/models/document.rb +12 -0
  59. data/lib/kete_translatable_content/extensions/models/still_image.rb +12 -0
  60. data/lib/kete_translatable_content/extensions/models/system_setting.rb +13 -0
  61. data/lib/kete_translatable_content/extensions/models/tag.rb +37 -0
  62. data/lib/kete_translatable_content/extensions/models/topic.rb +12 -0
  63. data/lib/kete_translatable_content/extensions/models/user.rb +36 -0
  64. data/lib/kete_translatable_content/extensions/models/video.rb +12 -0
  65. data/lib/kete_translatable_content/extensions/models/web_link.rb +12 -0
  66. data/lib/kete_translatable_content/extensions/oai_dc_helpers_overrides.rb +99 -0
  67. data/lib/kete_translatable_content/extensions/tagging_controller_overrides.rb +21 -0
  68. data/lib/kete_translatable_content/extensions/tagging_overrides.rb +27 -0
  69. data/lib/kete_translatable_content/extensions/tinymce_controller_valid_action_override.rb +16 -0
  70. data/lib/kete_translatable_content/extensions/translation_from_version.rb +105 -0
  71. data/lib/kete_translatable_content/kete.rb +25 -0
  72. data/lib/kete_translatable_content/overwrites/oai_dc_helpers_test.rb +6 -0
  73. data/rails/init.rb +110 -0
  74. metadata +156 -0
@@ -0,0 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), '../tinymce_controller_valid_action_override')
2
+ require File.join(File.dirname(__FILE__), '../tagging_controller_overrides')
3
+
4
+ AudioController.class_eval do
5
+ include TinymceControllerValidActionOverride
6
+ include TaggingControllerOverrides
7
+ end
@@ -0,0 +1,3 @@
1
+ BasketsController.class_eval do
2
+ uses_tiny_mce :options => Kete.translatable_tiny_mce_options, :only => %w{ edit appearance }
3
+ end
@@ -0,0 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), '../tinymce_controller_valid_action_override')
2
+ require File.join(File.dirname(__FILE__), '../tagging_controller_overrides')
3
+
4
+ DocumentsController.class_eval do
5
+ include TinymceControllerValidActionOverride
6
+ include TaggingControllerOverrides
7
+ end
@@ -0,0 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), '../tinymce_controller_valid_action_override')
2
+ require File.join(File.dirname(__FILE__), '../tagging_controller_overrides')
3
+
4
+ ImagesController.class_eval do
5
+ include TinymceControllerValidActionOverride
6
+ include TaggingControllerOverrides
7
+ end
@@ -0,0 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), '../tinymce_controller_valid_action_override')
2
+ require File.join(File.dirname(__FILE__), '../tagging_controller_overrides')
3
+
4
+ TopicsController.class_eval do
5
+ include TinymceControllerValidActionOverride
6
+ include TaggingControllerOverrides
7
+ end
@@ -0,0 +1,209 @@
1
+ TranslationsController.class_eval do
2
+ uses_tiny_mce :options => Kete.translatable_tiny_mce_options, :only => %w{ new edit }
3
+
4
+ include WorkerControllerHelpers
5
+
6
+ before_filter :params_version_to_latest_if_necessary, :only => :new
7
+
8
+ after_filter :expire_locale_cache, :only => [:create, :update]
9
+ after_filter :update_zoom_record_if_applicable, :only => [:create, :update]
10
+
11
+ def edit
12
+ @translation = @translated.translation_for(params[:id]) || @translatable_class::Translation.find(params[:id])
13
+ if @translated.respond_to?("version")
14
+ @translation = @translated.translate(:locale => (params[:to_locale] || I18n.locale.to_s)) unless @translation.version.to_i == @translated.version.to_i
15
+ end
16
+
17
+ render :template => "translations/versioned_edit"
18
+ end
19
+
20
+ # POST /translations
21
+ # POST /translations.xml
22
+ def create
23
+ translation_params = params[:translation] || params[@translatable_params_name + '_translation']
24
+ params[:version] ||= params[@translatable_key][:version] if params[@translatable_key]
25
+ translation_params[:version] = params[:version].to_i if params[:version]
26
+ @translation = @translatable.translate(translation_params)
27
+
28
+ respond_to do |format|
29
+ if @translation.save
30
+ flash[:notice] = t('translations.controllers.created')
31
+ # we redirect to translated object in the new translated version
32
+ # assumes controller name is tableized version of class
33
+ format.html { redirect_to url_for_translated(:locale => I18n.locale) }
34
+ # TODO: adjust :location accordingly for being a nested route
35
+ format.xml { render :xml => @translation, :status => :created, :location => @translation }
36
+ else
37
+ format.html { render :action => "new" }
38
+ format.xml { render :xml => @translation.errors, :status => :unprocessable_entity }
39
+ end
40
+ end
41
+ end
42
+
43
+ # PUT /translations/1
44
+ # PUT /translations/1.xml
45
+ def update
46
+ respond_to do |format|
47
+ translation_params = params[:translation] || params[@translatable_params_name + '_translation']
48
+ params[:version] ||= params[@translatable_key][:version] if params[@translatable_key]
49
+ translation_params[:version] = params[:version].to_i if params[:version]
50
+ if @translation.update_attributes(translation_params)
51
+ flash[:notice] = t('translations.controllers.updated')
52
+ format.html { redirect_to url_for_translated(:locale => I18n.locale) }
53
+ format.xml { head :ok }
54
+ else
55
+ format.html { render :action => "edit" }
56
+ format.xml { render :xml => @translation.errors, :status => :unprocessable_entity }
57
+ end
58
+ end
59
+ end
60
+
61
+ private
62
+
63
+ def get_translation
64
+ @translation = @translated.translation_for(params[:id]) || @translatable_class::Translation.find(params[:id])
65
+ if @translated.respond_to?("version")
66
+ @translation = @translated.translate(:locale => (params[:to_locale] || I18n.locale.to_s)) unless @translation.version.to_i == @translated.version.to_i
67
+ end
68
+ end
69
+
70
+ %w{translatable translated}.each do |term|
71
+ define_method("get_" + term) do
72
+ params[:version] ||= params[@translatable_key][:version] if params[@translatable_key]
73
+
74
+ value = @translatable_class.find(params[@translatable_key])
75
+
76
+ value.revert_to(params[:version].to_i) if params[:version]
77
+
78
+ # handle case of editing translation from another locale than original
79
+ # unfortunately requires reloading of object
80
+ if value.locale != value.original_locale &&
81
+ params[:controller] == 'translations' &&
82
+ params[:action] == 'edit'
83
+
84
+ starting_locale = I18n.locale
85
+ I18n.locale = value.original_locale
86
+
87
+ if params[:version]
88
+ value.revert_to(params[:version].to_i)
89
+ else
90
+ value.reload
91
+ end
92
+
93
+ I18n.locale = starting_locale
94
+ end
95
+
96
+ instance_variable_set("@" + term, value)
97
+ end
98
+ end
99
+
100
+ #Expire the cache of documents related to this record works on
101
+ #a wider scale if the record is relevant to the global UI.
102
+ def expire_locale_cache
103
+ #Kete items to be cleared individually
104
+ @translatable = @translation.respond_to?("translatable") ? @translation.translatable : @translation
105
+ if ITEM_CLASSES.include?(@translatable_class.to_s)
106
+ expire_show_caches_for(@translatable)
107
+
108
+ #Clear out the available for_list which may be updated
109
+ clear_header_fragments_for(@translated)
110
+ @translatable.translations.each do |translation|
111
+ clear_header_fragments_for(translation.translatable)
112
+ end
113
+
114
+ return true
115
+ elsif @translatable.is_a?(Tag)
116
+ # we need to expire the tag part
117
+ # for everything with that tag
118
+ @translatable.taggings.each do |tagging|
119
+ item = tagging.taggable
120
+
121
+ # sort of redundent, but achieves what we want
122
+ item.locale = @translatable.locale
123
+
124
+ controller = zoom_class_controller(item.class.name)
125
+ part = 'secondary_content_tags_[privacy]'
126
+ resulting_part = cache_name_for(part, 'public')
127
+ expire_fragment_for_all_versions_and_locale(item, { :controller => controller, :action => 'show', :id => item, :part => resulting_part })
128
+ resulting_part = cache_name_for(part, 'private')
129
+ expire_fragment_for_all_versions_and_locale(item, { :controller => controller, :action => 'show', :id => item, :part => resulting_part })
130
+ end
131
+ elsif @translatable.is_a?(Feed)
132
+ @translatable.clear_caches
133
+ else
134
+ expire_all_locale_caches
135
+ end
136
+ end
137
+
138
+ def clear_header_fragments_for(item)
139
+ item_class = item.class.name
140
+ controller = zoom_class_controller(item_class)
141
+ @privacy_type ||= (item.private? ? "private" : "public")
142
+ return unless ITEM_CLASSES.include?(item_class)
143
+ part = 'details_first_[privacy]'
144
+ resulting_part = cache_name_for(part, @privacy_type)
145
+ expire_fragment_for_all_versions_and_locale(item, { :controller => controller, :action => 'show', :id => item, :part => resulting_part })
146
+ end
147
+
148
+ def expire_fragment_for_all_versions_and_locale(item, name = {})
149
+ #blank title or url_for comes up with something it shouldn't
150
+ name[:id].title = "" if name[:id].title
151
+
152
+ name = name.merge(:id => item.id)
153
+
154
+ file_path = "#{RAILS_ROOT}/tmp/cache/#{fragment_cache_key(name).gsub(/(\?|:)/, '.')}.cache"
155
+ file_path.sub!("\/#{@translatable.locale}\/", "\/#{item.locale}\/")
156
+ File.delete(file_path) if File.exists?(file_path)
157
+ end
158
+
159
+ def expire_all_locale_caches
160
+ # this is the big hammer for translation clearing # it does the entire locale's cache if a translation changes
161
+ # only use on UI element related models
162
+ # Kete items (i.e. user generated content) should be done on an item by item basis
163
+ expire_locale = @translatable.locale
164
+ method_name = "clear_locale_cache"
165
+ options = { :locale_to_clear => expire_locale }
166
+
167
+ worker_type = :generic_muted_worker
168
+ worker_key = worker_key_for("generic_muted_worker_#{method_name}_#{expire_locale}")
169
+
170
+ # only allow a single cache clearing to happen at once
171
+ MiddleMan.new_worker( :worker => worker_type,
172
+ :worker_key => worker_key )
173
+
174
+ MiddleMan.worker(worker_type, worker_key).async_do_work( :arg => { :method_name => method_name, :options => options } )
175
+ true
176
+ end
177
+
178
+ # filter that will trigger zoom record rebuild for translatable
179
+ # if translatable.class is in ITEM_CLASSES
180
+ def update_zoom_record_if_applicable
181
+ @translatable = @translation.respond_to?("translatable") ? @translation.translatable : @translation
182
+ if ITEM_CLASSES.include?(@translatable.class.name)
183
+ rebuild_zoom_for_translatable
184
+ end
185
+ end
186
+
187
+ def rebuild_zoom_for_translatable
188
+ method_name = "rebuild_zoom_record_for"
189
+ options = { :item => @translatable }
190
+
191
+ worker_type = :generic_muted_worker
192
+ worker_key = worker_key_for("generic_muted_worker_#{method_name}_#{@translatable_class.to_s}_#{@translatable.id}")
193
+
194
+ # only allow a single cache clearing to happen at once
195
+ MiddleMan.new_worker( :worker => worker_type,
196
+ :worker_key => worker_key )
197
+
198
+ MiddleMan.worker(worker_type, worker_key).async_do_work( :arg => { :method_name => method_name, :options => options } )
199
+ true
200
+ end
201
+
202
+ # default to latest version, unless it is passed in
203
+ # private versions should pass version
204
+ def params_version_to_latest_if_necessary
205
+ if params[:version].blank? && @translatable.respond_to?(:version)
206
+ params[:version] = @translatable.version
207
+ end
208
+ end
209
+ end
@@ -0,0 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), '../tinymce_controller_valid_action_override')
2
+ require File.join(File.dirname(__FILE__), '../tagging_controller_overrides')
3
+
4
+ VideoController.class_eval do
5
+ include TinymceControllerValidActionOverride
6
+ include TaggingControllerOverrides
7
+ end
@@ -0,0 +1,7 @@
1
+ require File.join(File.dirname(__FILE__), '../tinymce_controller_valid_action_override')
2
+ require File.join(File.dirname(__FILE__), '../tagging_controller_overrides')
3
+
4
+ WebLinksController.class_eval do
5
+ include TinymceControllerValidActionOverride
6
+ include TaggingControllerOverrides
7
+ end
@@ -0,0 +1,54 @@
1
+ # for ZOOM_CLASSES, extended_content is translatable_attribute
2
+ # however, in mongodb we store indivdual values for the extended fields
3
+ # and then we swap in actual translatable extended field values via individual
4
+ # extended field setter methods (method missing methods)
5
+ # the advantage is that we only have to tell mongo_translatable that extended_content
6
+ # is translatable at the time of system startup
7
+ # and we can go on declaring new extended fields dynamically
8
+ module ExtendedContentTranslation
9
+ unless included_modules.include? ExtendedContentTranslation
10
+ def self.included(base)
11
+
12
+ #Send define method because scopes are not playing nicely together
13
+ base.send(:define_method, :translatable_attributes) do
14
+ return @translatable_attributes if @translatable_attributes.present?
15
+
16
+ # klass is ::Version classes parent namespace wise
17
+ klass = self.class
18
+
19
+ type = klass == Topic ? topic_type : ContentType.find_by_class_name(klass.name)
20
+
21
+ if type
22
+ # fields = type.mapped_fields.select { |f| ['text', 'textarea', 'choice', 'autocomplete'].include?(f.ftype) }
23
+ fields = type.mapped_fields.select { |f| ['text', 'textarea',].include?(f.ftype) }
24
+
25
+ type_translatable_attributes = fields.collect do |f|
26
+ unless f.multiple
27
+ f.label_for_params.to_sym
28
+ else
29
+ [f.label_for_params.to_sym, Array]
30
+ end
31
+ end
32
+
33
+ klass::Translation.update_keys_if_necessary_with(type_translatable_attributes)
34
+
35
+ update_translation_for_methods_if_necessary_with(type_translatable_attributes)
36
+
37
+ type_translatable_attribute_keys_only = type_translatable_attributes.collect do |a|
38
+ if a.is_a?(Array)
39
+ a[0]
40
+ else
41
+ a
42
+ end
43
+ end
44
+
45
+ @translatable_attributes = self.class.translatable_attributes + type_translatable_attribute_keys_only
46
+ else
47
+ @translatable_attributes = self.class.translatable_attributes
48
+ end
49
+ @translatable_attributes
50
+ end
51
+ end
52
+ end
53
+ end
54
+
@@ -0,0 +1,156 @@
1
+ ApplicationHelper.module_eval do
2
+ # lighboxes only used when user is logged in
3
+ def lightbox?
4
+ logged_in?
5
+ end
6
+
7
+ def tags_for(item)
8
+ html_string = String.new
9
+
10
+ return html_string if item.tags.blank?
11
+
12
+ html_string = "<p>#{t('application_helper.tags_for.tags')} "
13
+ item_tags = item.tags
14
+
15
+ item_tags.each_with_index do |tag,index|
16
+ html_string += link_to_tagged(tag, item.class.name)
17
+
18
+ # since tags-list is cached,
19
+ # we have to assume the user is logged out, use false for lightbox
20
+
21
+ # all we need to know is whether this tag is in the I18n.locale
22
+ # if not, provide translate link
23
+ unless tag.locale == I18n.locale
24
+ html_string += '<sup class="badge">' +
25
+ translate_link(tag,
26
+ :lightbox => false,
27
+ :action => 'new') +
28
+ '</sup>'
29
+ end
30
+
31
+ html_string += ", " unless item_tags.size == (index + 1)
32
+ end
33
+ html_string += "</p>"
34
+
35
+ html_string
36
+ end
37
+
38
+ def display_label_for(field_or_choice)
39
+ field_or_choice.label_translation_for(I18n.locale) || field_or_choice.label
40
+ end
41
+
42
+ def combined_tranlation_links
43
+ version = (current_translatable_record.respond_to?(:version) && current_translatable_record.version)
44
+ html = ''
45
+ html += '<div class="content-wrapper-submenu" id="translations">' + I18n.t('translations.available_in')
46
+ html += '<ul class="horizontal-list">'
47
+
48
+ available_locale_links = raw_available_in_locales_links(current_translatable_record, :params => {:version => version })
49
+
50
+ available_locales = available_locale_links.collect { |link| link[:locale].to_s }
51
+
52
+ available_locale_links.each_with_index do |link, i|
53
+ html += "<li#{' class="first"' if i == 0 }>"
54
+ html += link[:link]
55
+
56
+ unless link[:locale] == current_translatable_record.original_locale
57
+ record_translation_for_locale = current_translatable_record.translation_for(link[:locale])
58
+
59
+ if record_translation_for_locale &&
60
+ current_translatable_record.version.to_i > record_translation_for_locale.version.to_i
61
+ html += '<sup class="badge">' + I18n.t('translations.old') + '</sup>'
62
+ # drop locale from available_locales, so we get the translate link
63
+ available_locales.delete(link[:locale].to_s)
64
+ end
65
+ end
66
+
67
+ html += '</li>'
68
+ end
69
+
70
+ translate_link_version = nil
71
+
72
+ if version &&
73
+ current_translatable_record.respond_to?(:private?) &&
74
+ current_translatable_record.private?
75
+
76
+ translate_link_version = version
77
+ end
78
+
79
+ if current_translatable_record.original_locale != I18n.locale &&
80
+ !available_locales.include?(I18n.locale.to_s)
81
+ html += '<li id="translate">' + translate_link(current_translatable_record,
82
+ :lightbox => lightbox?,
83
+ :action => 'new',
84
+ :params => {:version => translate_link_version}) + '</li>'
85
+ elsif current_translatable_record.original_locale == I18n.locale && available_locales.size == 1
86
+ other_locales = TranslationsHelper::available_locales.keys - [current_translatable_record.original_locale]
87
+
88
+ html += '<li id="translate">' + translate_link(current_translatable_record,
89
+ :lightbox => lightbox?,
90
+ :action => 'new',
91
+ :params => {:version => translate_link_version,
92
+ :to_locale => other_locales.first}) + '</li>'
93
+ end
94
+
95
+ translations_params = Hash.new
96
+ params.each do |k,v|
97
+ translations_params[k] = v unless %w(action controller id).include?(k.to_s)
98
+ end
99
+
100
+ manage_links = manage_translations_links_for(current_translatable_record,
101
+ available_locales - [current_translatable_record.original_locale],
102
+ { :params => translations_params })
103
+
104
+
105
+ if manage_links.present? && logged_in?
106
+ # drop the 'delete' link unless a moderator or above
107
+ # a little brittle, as it relies on knowledge that ( edit | delete ) html
108
+ # as returned by helper method has | when (edit | delete) rather than manage
109
+ unless @at_least_a_moderator && manage_links.include?('|')
110
+
111
+ # only moderators and above can have access to 'delete'
112
+ manage_links = ' ' + manage_links.split('|')[0]
113
+ end
114
+
115
+ html += '<li id="manage-translations">(' + manage_links + ')</li>'
116
+ end
117
+
118
+ html += '</ul>
119
+ </div>'
120
+
121
+ translatable_lightbox_js_and_css
122
+
123
+ html
124
+ end
125
+
126
+ def add_ons_item_form_beginning(form=nil)
127
+ return unless form
128
+ locale_dropdown(form, :default => I18n.locale)
129
+ end
130
+
131
+ # redefining, because under certain circumstances
132
+ # user should get a confirm dialog before going to edit page
133
+ def link_to_edit_for(item)
134
+ t_key = t("topics.actions_menu.edit")
135
+
136
+
137
+ args = ["<span class=\"edit-link\">#{t_key}</span>",
138
+ { :action => :edit,
139
+ :id => item,
140
+ :private => params[:private]}]
141
+
142
+ additional_options = { :tabindex => '1' }
143
+
144
+ # translation for this locale exists,
145
+ # but it isn't the original locale
146
+ if item.original_locale != I18n.locale &&
147
+ item.available_in_these_locales.include?(I18n.locale)
148
+
149
+ additional_options[:confirm] = t('translations.are_you_sure_for_item_edit')
150
+ end
151
+
152
+ args << additional_options
153
+
154
+ link_to(*args)
155
+ end
156
+ end