Commit d7fee6b905378a4d92b4c9da99b180003920b470
Committed by
Antonio Terceiro
1 parent
f5703d91
Exists in
master
and in
22 other branches
Adding articles translation support
(ActionItem894)
Showing
32 changed files
with
736 additions
and
5 deletions
Show diff stats
app/controllers/my_profile/cms_controller.rb
| ... | ... | @@ -89,6 +89,7 @@ class CmsController < MyProfileController |
| 89 | 89 | @article = profile.articles.find(params[:id]) |
| 90 | 90 | @parent_id = params[:parent_id] |
| 91 | 91 | @type = params[:type] || @article.class.to_s |
| 92 | + translations if @article.translatable? | |
| 92 | 93 | continue = params[:continue] |
| 93 | 94 | |
| 94 | 95 | refuse_blocks |
| ... | ... | @@ -138,6 +139,8 @@ class CmsController < MyProfileController |
| 138 | 139 | @parent_id = parent.id |
| 139 | 140 | end |
| 140 | 141 | |
| 142 | + translations if @article.translatable? | |
| 143 | + | |
| 141 | 144 | @article.profile = profile |
| 142 | 145 | @article.last_changed_by = user |
| 143 | 146 | |
| ... | ... | @@ -367,5 +370,11 @@ class CmsController < MyProfileController |
| 367 | 370 | def per_page |
| 368 | 371 | 10 |
| 369 | 372 | end |
| 373 | + | |
| 374 | + def translations | |
| 375 | + @locales = Noosfero.locales.invert.reject { |name, lang| !@article.possible_translations.include?(lang) } | |
| 376 | + @selected_locale = @article.language || FastGettext.locale | |
| 377 | + end | |
| 378 | + | |
| 370 | 379 | end |
| 371 | 380 | ... | ... |
app/controllers/public/content_viewer_controller.rb
| ... | ... | @@ -51,6 +51,8 @@ class ContentViewerController < ApplicationController |
| 51 | 51 | return |
| 52 | 52 | end |
| 53 | 53 | |
| 54 | + redirect_to_translation | |
| 55 | + | |
| 54 | 56 | # At this point the page will be showed |
| 55 | 57 | @page.hit |
| 56 | 58 | |
| ... | ... | @@ -85,7 +87,11 @@ class ContentViewerController < ApplicationController |
| 85 | 87 | @page.posts |
| 86 | 88 | end |
| 87 | 89 | |
| 90 | + posts = posts.native_translations if @page.blog? && @page.display_posts_in_current_language? | |
| 91 | + | |
| 88 | 92 | @posts = posts.paginate({ :page => params[:npage], :per_page => @page.posts_per_page }.merge(Article.display_filter(user, profile))) |
| 93 | + | |
| 94 | + @posts.map!{ |p| p.get_translation_to(FastGettext.locale) } if @page.blog? && @page.display_posts_in_current_language? | |
| 89 | 95 | end |
| 90 | 96 | |
| 91 | 97 | if @page.folder? && @page.gallery? |
| ... | ... | @@ -125,4 +131,24 @@ class ContentViewerController < ApplicationController |
| 125 | 131 | def per_page |
| 126 | 132 | 12 |
| 127 | 133 | end |
| 134 | + | |
| 135 | + def redirect_to_translation | |
| 136 | + locale = FastGettext.locale | |
| 137 | + if !@page.language.nil? && @page.language != locale | |
| 138 | + translations = [@page.native_translation] + @page.native_translation.translations | |
| 139 | + urls = translations.map{ |t| URI.parse(url_for(t.url)).path } | |
| 140 | + urls << URI.parse(url_for(profile.admin_url.merge({ :controller => 'cms', :action => 'edit', :id => @page.id }))).path | |
| 141 | + urls << URI.parse(url_for(profile.admin_url.merge(:controller => 'cms', :action => 'new'))).path | |
| 142 | + referer = URI.parse(url_for(request.referer)).path unless request.referer.blank? | |
| 143 | + unless urls.include?(referer) | |
| 144 | + translations.each do |translation| | |
| 145 | + if translation.language == locale | |
| 146 | + @page = translation | |
| 147 | + redirect_to :profile => @page.profile.identifier, :page => @page.explode_path | |
| 148 | + end | |
| 149 | + end | |
| 150 | + end | |
| 151 | + end | |
| 152 | + end | |
| 153 | + | |
| 128 | 154 | end | ... | ... |
app/helpers/application_helper.rb
app/helpers/content_viewer_helper.rb
| ... | ... | @@ -35,4 +35,16 @@ module ContentViewerHelper |
| 35 | 35 | text && (text.first(40) + (text.size > 40 ? '…' : '')) |
| 36 | 36 | end |
| 37 | 37 | |
| 38 | + def article_translations(article) | |
| 39 | + unless article.native_translation.translations.empty? | |
| 40 | + links = (article.native_translation.translations + [article.native_translation]).map do |translation| | |
| 41 | + { Noosfero.locales[translation.language] => { :href => url_for(translation.url) } } | |
| 42 | + end | |
| 43 | + content_tag(:div, link_to(_('Translations'), '#', | |
| 44 | + :onclick => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false", | |
| 45 | + :class => 'article-translations-menu simplemenu-trigger up'), | |
| 46 | + :class => 'article-translations') | |
| 47 | + end | |
| 48 | + end | |
| 49 | + | |
| 38 | 50 | end | ... | ... |
app/models/article.rb
| ... | ... | @@ -28,6 +28,10 @@ class Article < ActiveRecord::Base |
| 28 | 28 | |
| 29 | 29 | belongs_to :reference_article, :class_name => "Article", :foreign_key => 'reference_article_id' |
| 30 | 30 | |
| 31 | + has_many :translations, :class_name => 'Article', :foreign_key => :translation_of_id | |
| 32 | + belongs_to :translation_of, :class_name => 'Article', :foreign_key => :translation_of_id | |
| 33 | + before_destroy :rotate_translations | |
| 34 | + | |
| 31 | 35 | before_create do |article| |
| 32 | 36 | article.published_at = article.created_at if article.published_at.nil? |
| 33 | 37 | if article.reference_article && !article.parent |
| ... | ... | @@ -53,6 +57,10 @@ class Article < ActiveRecord::Base |
| 53 | 57 | URL_FORMAT = /\A(http|https):\/\/[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?\Z/ix |
| 54 | 58 | |
| 55 | 59 | validates_format_of :external_link, :with => URL_FORMAT, :if => lambda { |article| !article.external_link.blank? } |
| 60 | + validate :known_language | |
| 61 | + validate :used_translation | |
| 62 | + validate :native_translation_must_have_language | |
| 63 | + validate :translation_must_have_language | |
| 56 | 64 | |
| 57 | 65 | def is_trackable? |
| 58 | 66 | self.published? && self.notifiable? && self.advertise? |
| ... | ... | @@ -251,6 +259,65 @@ class Article < ActiveRecord::Base |
| 251 | 259 | false |
| 252 | 260 | end |
| 253 | 261 | |
| 262 | + named_scope :native_translations, :conditions => { :translation_of_id => nil } | |
| 263 | + | |
| 264 | + def translatable? | |
| 265 | + false | |
| 266 | + end | |
| 267 | + | |
| 268 | + def native_translation | |
| 269 | + self.translation_of.nil? ? self : self.translation_of | |
| 270 | + end | |
| 271 | + | |
| 272 | + def possible_translations | |
| 273 | + possibilities = Noosfero.locales.keys - self.native_translation.translations(:select => :language).map(&:language) - [self.native_translation.language] | |
| 274 | + possibilities << self.language unless self.language_changed? | |
| 275 | + possibilities | |
| 276 | + end | |
| 277 | + | |
| 278 | + def known_language | |
| 279 | + unless self.language.blank? | |
| 280 | + errors.add(:language, N_('Language not supported by Noosfero')) unless Noosfero.locales.key?(self.language) | |
| 281 | + end | |
| 282 | + end | |
| 283 | + | |
| 284 | + def used_translation | |
| 285 | + unless self.language.blank? or self.translation_of.nil? | |
| 286 | + errors.add(:language, N_('Language is already used')) unless self.possible_translations.include?(self.language) | |
| 287 | + end | |
| 288 | + end | |
| 289 | + | |
| 290 | + def translation_must_have_language | |
| 291 | + unless self.translation_of.nil? | |
| 292 | + errors.add(:language, N_('Language must be choosen')) if self.language.blank? | |
| 293 | + end | |
| 294 | + end | |
| 295 | + | |
| 296 | + def native_translation_must_have_language | |
| 297 | + unless self.translation_of.nil? | |
| 298 | + errors.add_to_base(N_('A language must be choosen for the native article')) if self.translation_of.language.blank? | |
| 299 | + end | |
| 300 | + end | |
| 301 | + | |
| 302 | + def rotate_translations | |
| 303 | + unless self.translations.empty? | |
| 304 | + rotate = self.translations | |
| 305 | + root = rotate.shift | |
| 306 | + root.update_attribute(:translation_of_id, nil) | |
| 307 | + root.translations = rotate | |
| 308 | + end | |
| 309 | + end | |
| 310 | + | |
| 311 | + def get_translation_to(locale) | |
| 312 | + if self.language.nil? || self.language == locale | |
| 313 | + self | |
| 314 | + elsif self.native_translation.language == locale | |
| 315 | + self.native_translation | |
| 316 | + else | |
| 317 | + self.native_translation.translations.first(:conditions => { :language => locale }) || self | |
| 318 | + end | |
| 319 | + end | |
| 320 | + | |
| 254 | 321 | def published? |
| 255 | 322 | if self.published |
| 256 | 323 | if self.parent && !self.parent.published? | ... | ... |
app/models/blog.rb
| ... | ... | @@ -57,4 +57,8 @@ class Blog < Folder |
| 57 | 57 | settings_items :visualization_format, :type => :string, :default => 'full' |
| 58 | 58 | validates_inclusion_of :visualization_format, :in => [ 'full', 'short' ], :if => :visualization_format |
| 59 | 59 | |
| 60 | + settings_items :display_posts_in_current_language, :type => :boolean, :default => true | |
| 61 | + | |
| 62 | + alias :display_posts_in_current_language? :display_posts_in_current_language | |
| 63 | + | |
| 60 | 64 | end | ... | ... |
app/models/blog_archives_block.rb
| ... | ... | @@ -24,7 +24,7 @@ class BlogArchivesBlock < Block |
| 24 | 24 | owner_blog = self.blog |
| 25 | 25 | return nil unless owner_blog |
| 26 | 26 | results = '' |
| 27 | - owner_blog.posts.group_by {|i| i.published_at.year }.sort_by { |year,count| -year }.each do |year, results_by_year| | |
| 27 | + owner_blog.posts.native_translations.group_by {|i| i.published_at.year }.sort_by { |year,count| -year }.each do |year, results_by_year| | |
| 28 | 28 | results << content_tag('li', content_tag('strong', "#{year} (#{results_by_year.size})")) |
| 29 | 29 | results << "<ul class='#{year}-archive'>" |
| 30 | 30 | results_by_year.group_by{|i| [ ('%02d' % i.published_at.month()), gettext(MONTHS[i.published_at.month() - 1])]}.sort.reverse.each do |month, results_by_month| | ... | ... |
app/models/environment.rb
| ... | ... | @@ -108,7 +108,7 @@ class Environment < ActiveRecord::Base |
| 108 | 108 | 'admin_must_approve_new_communities' => _("Admin must approve creation of communities"), |
| 109 | 109 | 'enterprises_are_disabled_when_created' => __('Enterprises are disabled when created'), |
| 110 | 110 | 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'), |
| 111 | - 'xmpp_chat' => _('XMPP/Jabber based chat'), | |
| 111 | + 'xmpp_chat' => _('XMPP/Jabber based chat') | |
| 112 | 112 | } |
| 113 | 113 | end |
| 114 | 114 | ... | ... |
app/models/event.rb
app/models/rss_feed.rb
| ... | ... | @@ -62,7 +62,8 @@ class RssFeed < Article |
| 62 | 62 | include ActionController::UrlWriter |
| 63 | 63 | def fetch_articles |
| 64 | 64 | if parent && parent.has_posts? |
| 65 | - return parent.posts.find(:all, :conditions => ['published = ?', true], :limit => self.limit, :order => 'id desc') | |
| 65 | + language = self.language.blank? ? {} : { :language => self.language } | |
| 66 | + return parent.posts.find(:all, :conditions => { :published => true }.merge(language), :limit => self.limit, :order => 'id desc') | |
| 66 | 67 | end |
| 67 | 68 | |
| 68 | 69 | articles = | ... | ... |
app/models/textile_article.rb
app/models/tiny_mce_article.rb
app/views/cms/_blog.rhtml
| ... | ... | @@ -56,8 +56,11 @@ |
| 56 | 56 | |
| 57 | 57 | <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, [5, 10, 20, 50, 100])) %> |
| 58 | 58 | |
| 59 | +<%= labelled_check_box(_('Display posts in current language, if available'), 'article[display_posts_in_current_language]', '1', @article.display_posts_in_current_language?) %> | |
| 60 | + | |
| 59 | 61 | <% f.fields_for 'feed', @article.feed do |feed| %> |
| 60 | 62 | <%= labelled_form_field(_('Limit of posts in RSS Feed'), feed.select(:limit, [5, 10, 20, 50])) %> |
| 63 | + <%= labelled_form_field(_('Include in RSS Feed only posts from language:'), feed.select(:language, { _('All') => nil }.merge(Noosfero.locales.invert))) %> | |
| 61 | 64 | <% end %> |
| 62 | 65 | |
| 63 | 66 | <% f.fields_for 'external_feed_builder', @article.external_feed do |efeed| %> | ... | ... |
app/views/cms/_event.rhtml
| ... | ... | @@ -5,6 +5,8 @@ |
| 5 | 5 | |
| 6 | 6 | <%= required f.text_field('name', :size => '64') %> |
| 7 | 7 | |
| 8 | +<%= render :partial => 'translatable' %> | |
| 9 | + | |
| 8 | 10 | <%= labelled_form_field(_('Start date'), pick_date(:article, :start_date)) %> |
| 9 | 11 | |
| 10 | 12 | <%= labelled_form_field(_('End date'), pick_date(:article, :end_date)) %> | ... | ... |
app/views/cms/_textile_article.rhtml
| ... | ... | @@ -4,6 +4,8 @@ |
| 4 | 4 | |
| 5 | 5 | <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64')) %> |
| 6 | 6 | |
| 7 | +<%= render :partial => 'translatable' %> | |
| 8 | + | |
| 7 | 9 | <br style="clear: both;"/> |
| 8 | 10 | <%= button :add, _("Lead"), '#', :id => "lead-button", :style => "margin-left: 0px;" %> |
| 9 | 11 | <em><%= _('Used when a short version of your text is needed.') %></em> | ... | ... |
app/views/cms/_tiny_mce_article.rhtml
| ... | ... | @@ -11,6 +11,8 @@ |
| 11 | 11 | <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64')) %> |
| 12 | 12 | <% end %> |
| 13 | 13 | |
| 14 | + <%= render :partial => 'translatable' %> | |
| 15 | + | |
| 14 | 16 | <br style="clear: both;"/> |
| 15 | 17 | <%= button :add, _("Lead"), '#', :id => "lead-button", :style => "margin-left: 0px;" %> |
| 16 | 18 | <em><%= _('Used when a short version of your text is needed.') %></em> | ... | ... |
| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | +<% if @article.translatable? %> | |
| 2 | + <div class="article-translation-field"> | |
| 3 | + <%= label :article, :language, _('Language') %> <br /> | |
| 4 | + <%= select :article, :language, @locales, { :selected => @selected_locale, :include_blank => true } %> | |
| 5 | + <%= hidden_field(:article, :translation_of_id) %> | |
| 6 | + </div> | |
| 7 | +<% end %> | ... | ... |
app/views/content_viewer/view_page.rhtml
| ... | ... | @@ -35,6 +35,11 @@ |
| 35 | 35 | <% end %> |
| 36 | 36 | <% if !(profile.kind_of?(Enterprise) && environment.enabled?('disable_cms')) %> |
| 37 | 37 | <% if !@page.gallery? %> |
| 38 | + <%= link_to _('Add translation'), | |
| 39 | + profile.admin_url.merge(:controller => 'cms', :action => 'new', | |
| 40 | + :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)), | |
| 41 | + :type => @page.type, :article => { :translation_of_id => @page.native_translation.id }), | |
| 42 | + :class => 'button with-text icon-locale' if @page.translatable? && !@page.native_translation.language.blank? %> | |
| 38 | 43 | <%= lightbox_button(:new, label_for_new_article(@page), profile.admin_url.merge(:controller => 'cms', :action => 'new', :parent_id => (@page.folder? ? @page : (@page.parent.nil? ? nil : @page.parent)))) %> |
| 39 | 44 | <% end %> |
| 40 | 45 | <% if (@page.folder? && !@page.has_posts?) || (@page.parent && @page.parent.folder? && !@page.parent.has_posts?) %> |
| ... | ... | @@ -50,6 +55,7 @@ |
| 50 | 55 | <%= link_to content_tag( 'span', _('Suggest an article') ), profile.admin_url.merge({ :controller => 'cms', :action => 'suggest_an_article'}), :class => 'button with-text icon-new' %> |
| 51 | 56 | <% end %> |
| 52 | 57 | <% end %> |
| 58 | + <%= article_translations(@page) %> | |
| 53 | 59 | <div id="article-header"> |
| 54 | 60 | <%= link_to(image_tag('icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %> |
| 55 | 61 | <%= article_title(@page, :no_link => true) %> | ... | ... |
db/migrate/20101205034144_add_language_and_translation_of_id_to_article.rb
0 → 100644
| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | +class AddLanguageAndTranslationOfIdToArticle < ActiveRecord::Migration | |
| 2 | + def self.up | |
| 3 | + add_column :articles, :translation_of_id, :interger | |
| 4 | + add_column :articles, :language, :string | |
| 5 | + | |
| 6 | + add_column :article_versions, :translation_of_id, :interger | |
| 7 | + add_column :article_versions, :language, :string | |
| 8 | + | |
| 9 | + add_index :articles, :translation_of_id | |
| 10 | + | |
| 11 | + select_all("select id, setting from articles where type = 'Blog'").each do |blog| | |
| 12 | + settings = YAML.load(blog['setting']) | |
| 13 | + settings[:display_posts_in_current_language] = true | |
| 14 | + assignments = ActiveRecord::Base.sanitize_sql_for_assignment(:setting => settings.to_yaml) | |
| 15 | + update("update articles set %s where id = %d" % [assignments, blog['id']]) | |
| 16 | + end | |
| 17 | + | |
| 18 | + end | |
| 19 | + | |
| 20 | + def self.down | |
| 21 | + remove_index :articles, :translation_of_id | |
| 22 | + | |
| 23 | + remove_column :article_versions, :translation_of_id | |
| 24 | + remove_column :article_versions, :language | |
| 25 | + | |
| 26 | + remove_column :articles, :language | |
| 27 | + remove_column :articles, :translation_of_id | |
| 28 | + end | |
| 29 | +end | ... | ... |
features/edit_article.feature
| ... | ... | @@ -133,3 +133,32 @@ Feature: edit article |
| 133 | 133 | Then I should be on "My new article" edit page |
| 134 | 134 | And the "Title" field should contain "My new article" |
| 135 | 135 | And the "Text" field should contain "text for the new article" |
| 136 | + | |
| 137 | + Scenario: add a translation to an article | |
| 138 | + Given I am on Joao Silva's sitemap | |
| 139 | + And I follow "Save the whales" | |
| 140 | + Then I should not see "Add translation" | |
| 141 | + And I follow "Edit" | |
| 142 | + And I select "English" from "Language" | |
| 143 | + Then I press "Save" | |
| 144 | + And I follow "Add translation" | |
| 145 | + And I fill in "Title" with "Mi neuvo artículo" | |
| 146 | + And I select "Español" from "Language" | |
| 147 | + When I press "Save" | |
| 148 | + Then I should be on /joaosilva/save-the-whales | |
| 149 | + And I should see "Translations" | |
| 150 | + | |
| 151 | + Scenario: not add a translation without a language | |
| 152 | + Given the following articles | |
| 153 | + | owner | name | language | | |
| 154 | + | joaosilva | Article in English | en | | |
| 155 | + And I am on Joao Silva's sitemap | |
| 156 | + And I follow "Article in English" | |
| 157 | + And I follow "Add translation" | |
| 158 | + And I fill in "Title" with "Article in Portuguese" | |
| 159 | + When I press "Save" | |
| 160 | + Then I should see "Language must be choosen" | |
| 161 | + And I select "Português" from "Language" | |
| 162 | + When I press "Save" | |
| 163 | + Then I should not see "Language must be choosen" | |
| 164 | + And I should be on /joaosilva/article-in-english | ... | ... |
public/designs/icons/tango/style.css
| ... | ... | @@ -75,3 +75,4 @@ |
| 75 | 75 | .icon-reply { background-image: url(Tango/16x16/actions/mail-reply-sender.png) } |
| 76 | 76 | .icon-newforum { background-image: url(Tango/16x16/apps/system-users.png) } |
| 77 | 77 | .icon-newgallery { background-image: url(Tango/16x16/mimetypes/image-x-generic.png) } |
| 78 | +.icon-locale { background-image: url(Tango/16x16/apps/preferences-desktop-locale.png) } | |
| 78 | 79 | \ No newline at end of file | ... | ... |
public/stylesheets/application.css
| ... | ... | @@ -5232,6 +5232,49 @@ h1#agenda-title { |
| 5232 | 5232 | margin-top: 10px; |
| 5233 | 5233 | } |
| 5234 | 5234 | |
| 5235 | + | |
| 5236 | +.article-translations-menu { | |
| 5237 | + float: right; | |
| 5238 | + bottom: -15px; | |
| 5239 | +} | |
| 5240 | + | |
| 5241 | +.opera .article-translations-menu { | |
| 5242 | + bottom: -8px; | |
| 5243 | +} | |
| 5244 | + | |
| 5245 | +.webkit .article-translations-menu { | |
| 5246 | + bottom: -10px; | |
| 5247 | +} | |
| 5248 | + | |
| 5249 | +.article-translations-menu { | |
| 5250 | + text-decoration: none !important; | |
| 5251 | + height: 0; | |
| 5252 | +} | |
| 5253 | + | |
| 5254 | +.article-translations .menu-submenu-header, | |
| 5255 | +.article-translations .menu-submenu-content, | |
| 5256 | +.article-translations .menu-submenu-footer { | |
| 5257 | + background: none; | |
| 5258 | +} | |
| 5259 | + | |
| 5260 | +.article-translations .menu-submenu { | |
| 5261 | + bottom: auto; | |
| 5262 | + top: 60px; | |
| 5263 | + right: 0; | |
| 5264 | + border: 1px solid; | |
| 5265 | + background: #fff; | |
| 5266 | +} | |
| 5267 | + | |
| 5268 | +.msie7 .article-translations .menu-submenu, | |
| 5269 | +.webkit .article-translations .menu-submenu, | |
| 5270 | +.opera .article-translations .menu-submenu { | |
| 5271 | + top: 30px; | |
| 5272 | +} | |
| 5273 | + | |
| 5274 | +.article-translations .menu-submenu-list { | |
| 5275 | + list-style: none; | |
| 5276 | +} | |
| 5277 | + | |
| 5235 | 5278 | /* Forum */ |
| 5236 | 5279 | |
| 5237 | 5280 | .forum-posts .pagination { | ... | ... |
test/functional/application_controller_test.rb
| ... | ... | @@ -419,4 +419,26 @@ class ApplicationControllerTest < Test::Unit::TestCase |
| 419 | 419 | assert_tag :tag => 'meta', :attributes => { :name => 'description', :content => assigns(:environment).name } |
| 420 | 420 | end |
| 421 | 421 | |
| 422 | + should 'set html lang as the article language if an article is present and has a language' do | |
| 423 | + a = fast_create(Article, :name => 'test article', :language => 'fr') | |
| 424 | + @controller.instance_variable_set('@page', a) | |
| 425 | + FastGettext.stubs(:locale).returns('es') | |
| 426 | + get :index | |
| 427 | + assert_tag :html, :attributes => { :lang => 'fr' } | |
| 428 | + end | |
| 429 | + | |
| 430 | + should 'set html lang as locale if no page present' do | |
| 431 | + FastGettext.stubs(:locale).returns('es') | |
| 432 | + get :index | |
| 433 | + assert_tag :html, :attributes => { :lang => 'es' } | |
| 434 | + end | |
| 435 | + | |
| 436 | + should 'set html lang as locale if page has no language' do | |
| 437 | + a = fast_create(Article, :name => 'test article', :language => nil) | |
| 438 | + @controller.instance_variable_set('@page', a) | |
| 439 | + FastGettext.stubs(:locale).returns('es') | |
| 440 | + get :index | |
| 441 | + assert_tag :html, :attributes => { :lang => 'es' } | |
| 442 | + end | |
| 443 | + | |
| 422 | 444 | end | ... | ... |
test/functional/cms_controller_test.rb
| ... | ... | @@ -1440,4 +1440,63 @@ class CmsControllerTest < Test::Unit::TestCase |
| 1440 | 1440 | assert_response :success |
| 1441 | 1441 | end |
| 1442 | 1442 | |
| 1443 | + should 'article language should be selected' do | |
| 1444 | + textile = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'textile', :language => 'ru') | |
| 1445 | + get :edit, :profile => @profile.identifier, :id => textile.id | |
| 1446 | + assert_tag :option, :attributes => { :selected => 'selected', :value => 'ru' }, :parent => { | |
| 1447 | + :tag => 'select', :attributes => { :id => 'article_language'} } | |
| 1448 | + end | |
| 1449 | + | |
| 1450 | + should 'list possible languages and include blank option' do | |
| 1451 | + get :new, :profile => @profile.identifier, :type => 'TextileArticle' | |
| 1452 | + assert_equal Noosfero.locales.invert, assigns(:locales) | |
| 1453 | + assert_tag :option, :attributes => { :value => '' }, :parent => { | |
| 1454 | + :tag => 'select', :attributes => { :id => 'article_language'} } | |
| 1455 | + end | |
| 1456 | + | |
| 1457 | + should 'add translation to an article' do | |
| 1458 | + textile = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'textile', :language => 'ru') | |
| 1459 | + assert_difference Article, :count do | |
| 1460 | + post :new, :profile => @profile.identifier, :type => 'TextileArticle', :article => { :name => 'english translation', :translation_of_id => textile.id, :language => 'en' } | |
| 1461 | + end | |
| 1462 | + end | |
| 1463 | + | |
| 1464 | + should 'not display language selection if article is not translatable' do | |
| 1465 | + blog = fast_create(Blog, :name => 'blog', :profile_id => @profile.id) | |
| 1466 | + get :edit, :profile => @profile.identifier, :id => blog.id | |
| 1467 | + assert_no_tag :select, :attributes => { :id => 'article_language'} | |
| 1468 | + end | |
| 1469 | + | |
| 1470 | + should 'display display posts in current language input checked on edit blog' do | |
| 1471 | + get :new, :profile => profile.identifier, :type => 'Blog' | |
| 1472 | + assert_tag :tag => 'input', :attributes => { :type => 'checkbox', :name => 'article[display_posts_in_current_language]', :checked => 'checked' } | |
| 1473 | + end | |
| 1474 | + | |
| 1475 | + should 'update to false blog display posts in current language setting' do | |
| 1476 | + profile.articles << Blog.new(:name => 'Blog for test', :profile => profile, :display_posts_in_current_language => true) | |
| 1477 | + post :edit, :profile => profile.identifier, :id => profile.blog.id, :article => { :display_posts_in_current_language => false } | |
| 1478 | + profile.blog.reload | |
| 1479 | + assert !profile.blog.display_posts_in_current_language? | |
| 1480 | + end | |
| 1481 | + | |
| 1482 | + should 'update to true blog display posts in current language setting' do | |
| 1483 | + profile.articles << Blog.new(:name => 'Blog for test', :profile => profile, :display_posts_in_current_language => false) | |
| 1484 | + post :edit, :profile => profile.identifier, :id => profile.blog.id, :article => { :display_posts_in_current_language => true } | |
| 1485 | + profile.blog.reload | |
| 1486 | + assert profile.blog.display_posts_in_current_language? | |
| 1487 | + end | |
| 1488 | + | |
| 1489 | + should 'be checked display posts in current language checkbox' do | |
| 1490 | + profile.articles << Blog.new(:name => 'Blog for test', :profile => profile, :display_posts_in_current_language => true) | |
| 1491 | + get :edit, :profile => profile.identifier, :id => profile.blog.id | |
| 1492 | + assert_tag :tag => 'input', :attributes => { :type => 'checkbox', :name => 'article[display_posts_in_current_language]', :checked => 'checked' } | |
| 1493 | + end | |
| 1494 | + | |
| 1495 | + should 'be unchecked display posts in current language checkbox' do | |
| 1496 | + profile.articles << Blog.new(:name => 'Blog for test', :profile => profile, :display_posts_in_current_language => false) | |
| 1497 | + get :edit, :profile => profile.identifier, :id => profile.blog.id | |
| 1498 | + assert_tag :tag => 'input', :attributes => { :type => 'checkbox', :name => 'article[display_posts_in_current_language]' } | |
| 1499 | + assert_no_tag :tag => 'input', :attributes => { :type => 'checkbox', :name => 'article[display_posts_in_current_language]', :checked => 'checked' } | |
| 1500 | + end | |
| 1501 | + | |
| 1443 | 1502 | end | ... | ... |
test/functional/content_viewer_controller_test.rb
| ... | ... | @@ -1095,4 +1095,147 @@ class ContentViewerControllerTest < Test::Unit::TestCase |
| 1095 | 1095 | assert_tag :tag => 'div', :attributes => { :class => /main-block/ }, :descendant => { :tag => 'a', :attributes => { :href => "/myprofile/testinguser/cms/edit/#{forum.id}" }, :content => 'Configure forum' } |
| 1096 | 1096 | end |
| 1097 | 1097 | |
| 1098 | + should 'display add translation link if article is translatable' do | |
| 1099 | + login_as @profile.identifier | |
| 1100 | + textile = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'textile', :language => 'en') | |
| 1101 | + get :view_page, :profile => @profile.identifier, :page => textile.explode_path | |
| 1102 | + assert_tag :a, :attributes => { :href => "/myprofile/#{profile.identifier}/cms/new?article%5Btranslation_of_id%5D=#{textile.id}&type=#{TextileArticle}" } | |
| 1103 | + end | |
| 1104 | + | |
| 1105 | + should 'not display add translation link if article is not translatable' do | |
| 1106 | + login_as @profile.identifier | |
| 1107 | + blog = fast_create(Blog, :profile_id => @profile.id, :path => 'blog') | |
| 1108 | + get :view_page, :profile => @profile.identifier, :page => blog.explode_path | |
| 1109 | + assert_no_tag :a, :attributes => { :content => 'Add translation', :class => /icon-locale/ } | |
| 1110 | + end | |
| 1111 | + | |
| 1112 | + should 'not display add translation link if article hasnt a language defined' do | |
| 1113 | + login_as @profile.identifier | |
| 1114 | + textile = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'textile') | |
| 1115 | + get :view_page, :profile => @profile.identifier, :page => textile.explode_path | |
| 1116 | + assert_no_tag :a, :attributes => { :content => 'Add translation', :class => /icon-locale/ } | |
| 1117 | + end | |
| 1118 | + | |
| 1119 | + should 'diplay translations link if article has translations' do | |
| 1120 | + login_as @profile.identifier | |
| 1121 | + textile = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'textile', :language => 'en') | |
| 1122 | + translation = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'translation', :language => 'es', :translation_of_id => textile) | |
| 1123 | + get :view_page, :profile => @profile.identifier, :page => textile.explode_path | |
| 1124 | + assert_tag :a, :attributes => { :class => /article-translations-menu/, :onclick => /toggleSubmenu/ } | |
| 1125 | + end | |
| 1126 | + | |
| 1127 | + should 'be redirected to translation if article is a root' do | |
| 1128 | + @request.env['HTTP_REFERER'] = 'http://some.path' | |
| 1129 | + FastGettext.stubs(:locale).returns('es') | |
| 1130 | + en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en') | |
| 1131 | + es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :translation_of_id => en_article) | |
| 1132 | + get :view_page, :profile => @profile.identifier, :page => en_article.explode_path | |
| 1133 | + assert_redirected_to :profile => @profile.identifier, :page => es_article.explode_path | |
| 1134 | + assert_equal es_article, assigns(:page) | |
| 1135 | + end | |
| 1136 | + | |
| 1137 | + should 'be redirected to translation' do | |
| 1138 | + @request.env['HTTP_REFERER'] = 'http://some.path' | |
| 1139 | + FastGettext.stubs(:locale).returns('en') | |
| 1140 | + en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en') | |
| 1141 | + es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :translation_of_id => en_article) | |
| 1142 | + get :view_page, :profile => @profile.identifier, :page => es_article.explode_path | |
| 1143 | + assert_redirected_to :profile => @profile.identifier, :page => en_article.explode_path | |
| 1144 | + assert_equal en_article, assigns(:page) | |
| 1145 | + end | |
| 1146 | + | |
| 1147 | + should 'not be redirected if already in translation' do | |
| 1148 | + en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en') | |
| 1149 | + es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :translation_of_id => en_article) | |
| 1150 | + @request.env['HTTP_REFERER'] = "http://localhost:3000/#{@profile.identifier}/#{es_article.path}" | |
| 1151 | + FastGettext.stubs(:locale).returns('es') | |
| 1152 | + get :view_page, :profile => @profile.identifier, :page => es_article.explode_path | |
| 1153 | + assert_response :success | |
| 1154 | + assert_equal es_article, assigns(:page) | |
| 1155 | + end | |
| 1156 | + | |
| 1157 | + should 'not be redirected if article does not have a language' do | |
| 1158 | + FastGettext.stubs(:locale).returns('es') | |
| 1159 | + article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'article') | |
| 1160 | + get :view_page, :profile => @profile.identifier, :page => article.explode_path | |
| 1161 | + assert_response :success | |
| 1162 | + assert_equal article, assigns(:page) | |
| 1163 | + end | |
| 1164 | + | |
| 1165 | + should 'not be redirected if http_referer is a translation' do | |
| 1166 | + en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en') | |
| 1167 | + es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :translation_of_id => en_article) | |
| 1168 | + @request.env['HTTP_REFERER'] = "http://localhost:3000/#{@profile.identifier}/#{es_article.path}" | |
| 1169 | + FastGettext.stubs(:locale).returns('es') | |
| 1170 | + get :view_page, :profile => @profile.identifier, :page => en_article.explode_path | |
| 1171 | + assert_response :success | |
| 1172 | + assert_equal en_article, assigns(:page) | |
| 1173 | + end | |
| 1174 | + | |
| 1175 | + should 'be redirected if http_referer is nil' do | |
| 1176 | + en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en') | |
| 1177 | + es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :translation_of_id => en_article) | |
| 1178 | + @request.env['HTTP_REFERER'] = nil | |
| 1179 | + FastGettext.stubs(:locale).returns('es') | |
| 1180 | + get :view_page, :profile => @profile.identifier, :page => en_article.explode_path | |
| 1181 | + assert_redirected_to :profile => @profile.identifier, :page => es_article.explode_path | |
| 1182 | + assert_equal es_article, assigns(:page) | |
| 1183 | + end | |
| 1184 | + | |
| 1185 | + should 'not be redirected to transition if came from edit' do | |
| 1186 | + en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en') | |
| 1187 | + es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :translation_of_id => en_article) | |
| 1188 | + FastGettext.stubs(:locale).returns('es') | |
| 1189 | + @request.env['HTTP_REFERER'] = "http://localhost/myprofile/#{@profile.identifier}/cms/edit/#{en_article.id}" | |
| 1190 | + get :view_page, :profile => @profile.identifier, :page => es_article.explode_path | |
| 1191 | + assert_response :success | |
| 1192 | + assert_equal es_article, assigns(:page) | |
| 1193 | + end | |
| 1194 | + | |
| 1195 | + should 'not be redirected to transition if came from new' do | |
| 1196 | + en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en') | |
| 1197 | + es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :translation_of_id => en_article) | |
| 1198 | + FastGettext.stubs(:locale).returns('es') | |
| 1199 | + @request.env['HTTP_REFERER'] = "http://localhost/myprofile/#{@profile.identifier}/cms/new" | |
| 1200 | + get :view_page, :profile => @profile.identifier, :page => es_article.explode_path | |
| 1201 | + assert_response :success | |
| 1202 | + assert_equal es_article, assigns(:page) | |
| 1203 | + end | |
| 1204 | + | |
| 1205 | + should 'replace article for his translation at blog listing if blog option is enabled' do | |
| 1206 | + FastGettext.stubs(:locale).returns('es') | |
| 1207 | + blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog') | |
| 1208 | + blog.stubs(:display_posts_in_current_language).returns(true) | |
| 1209 | + en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en') | |
| 1210 | + es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :translation_of_id => en_article) | |
| 1211 | + blog.posts = [en_article, es_article] | |
| 1212 | + | |
| 1213 | + get :view_page, :profile => @profile.identifier, :page => blog.explode_path | |
| 1214 | + assert_tag :div, :attributes => { :id => "post-#{es_article.id}" } | |
| 1215 | + assert_no_tag :div, :attributes => { :id => "post-#{en_article.id}" } | |
| 1216 | + end | |
| 1217 | + | |
| 1218 | + should 'list all posts at blog listing if blog option is disabled' do | |
| 1219 | + FastGettext.stubs(:locale).returns('es') | |
| 1220 | + blog = Blog.create!(:name => 'A blog test', :profile => profile, :display_posts_in_current_language => false) | |
| 1221 | + blog.posts << es_post = TextileArticle.create!(:name => 'Spanish Post', :profile => profile, :parent => blog, :language => 'es') | |
| 1222 | + blog.posts << en_post = TextileArticle.create!(:name => 'English Post', :profile => profile, :parent => blog, :language => 'en', :translation_of_id => es_post.id) | |
| 1223 | + get :view_page, :profile => profile.identifier, :page => [blog.path] | |
| 1224 | + assert_equal 2, assigns(:posts).size | |
| 1225 | + assert_tag :div, :attributes => { :id => "post-#{es_post.id}" } | |
| 1226 | + assert_tag :div, :attributes => { :id => "post-#{en_post.id}" } | |
| 1227 | + end | |
| 1228 | + | |
| 1229 | + should 'display only native translations at blog listing if blog option is enabled' do | |
| 1230 | + FastGettext.stubs(:locale).returns('es') | |
| 1231 | + blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog') | |
| 1232 | + blog.stubs(:display_posts_in_current_language).returns(true) | |
| 1233 | + en_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'en_article', :language => 'en') | |
| 1234 | + es_article = fast_create(TextileArticle, :profile_id => @profile.id, :path => 'es_article', :language => 'es', :translation_of_id => en_article) | |
| 1235 | + blog.posts = [en_article, es_article] | |
| 1236 | + | |
| 1237 | + get :view_page, :profile => @profile.identifier, :page => blog.explode_path | |
| 1238 | + assert_equal [es_article], assigns(:posts) | |
| 1239 | + end | |
| 1240 | + | |
| 1098 | 1241 | end | ... | ... |
test/unit/article_test.rb
| ... | ... | @@ -1229,4 +1229,174 @@ class ArticleTest < Test::Unit::TestCase |
| 1229 | 1229 | assert_equal [g], p.articles.galleries |
| 1230 | 1230 | end |
| 1231 | 1231 | |
| 1232 | + should 'has many translations' do | |
| 1233 | + a = build(Article) | |
| 1234 | + assert_raises(ActiveRecord::AssociationTypeMismatch) { a.translations << 1 } | |
| 1235 | + assert_nothing_raised { a.translations << build(Article) } | |
| 1236 | + end | |
| 1237 | + | |
| 1238 | + should 'belongs to translation of' do | |
| 1239 | + a = build(Article) | |
| 1240 | + assert_raises(ActiveRecord::AssociationTypeMismatch) { a.translation_of = 1 } | |
| 1241 | + assert_nothing_raised { a.translation_of = build(Article) } | |
| 1242 | + end | |
| 1243 | + | |
| 1244 | + should 'has language' do | |
| 1245 | + a = build(Article) | |
| 1246 | + assert_nothing_raised { a.language = 'en' } | |
| 1247 | + end | |
| 1248 | + | |
| 1249 | + should 'validade inclusion of language' do | |
| 1250 | + a = build(Article) | |
| 1251 | + a.language = '12' | |
| 1252 | + a.valid? | |
| 1253 | + assert a.errors.invalid?(:language) | |
| 1254 | + a.language = 'en' | |
| 1255 | + a.valid? | |
| 1256 | + assert !a.errors.invalid?(:language) | |
| 1257 | + end | |
| 1258 | + | |
| 1259 | + should 'language can be blank' do | |
| 1260 | + a = build(Article) | |
| 1261 | + a.valid? | |
| 1262 | + assert !a.errors.invalid?(:language) | |
| 1263 | + a.language = '' | |
| 1264 | + a.valid? | |
| 1265 | + assert !a.errors.invalid?(:language) | |
| 1266 | + end | |
| 1267 | + | |
| 1268 | + should 'article is not translatable' do | |
| 1269 | + a = build(Article) | |
| 1270 | + assert !a.translatable? | |
| 1271 | + end | |
| 1272 | + | |
| 1273 | + should 'get native translation' do | |
| 1274 | + native_article = fast_create(Article) | |
| 1275 | + article_translation = fast_create(Article) | |
| 1276 | + native_article.translations << article_translation | |
| 1277 | + assert_equal native_article, native_article.native_translation | |
| 1278 | + assert_equal native_article, article_translation.native_translation | |
| 1279 | + end | |
| 1280 | + | |
| 1281 | + should 'list possible translations' do | |
| 1282 | + native_article = fast_create(Article, :language => 'pt') | |
| 1283 | + article_translation = fast_create(Article, :language => 'en', :translation_of_id => native_article.id) | |
| 1284 | + possible_translations = native_article.possible_translations | |
| 1285 | + assert !possible_translations.include?('en') | |
| 1286 | + assert possible_translations.include?('pt') | |
| 1287 | + end | |
| 1288 | + | |
| 1289 | + should 'verify if translation is already in use' do | |
| 1290 | + native_article = fast_create(Article, :language => 'pt') | |
| 1291 | + article_translation = fast_create(Article, :language => 'en', :translation_of_id => native_article.id) | |
| 1292 | + a = build(Article) | |
| 1293 | + a.language = 'en' | |
| 1294 | + a.translation_of = native_article | |
| 1295 | + a.valid? | |
| 1296 | + assert a.errors.invalid?(:language) | |
| 1297 | + a.language = 'es' | |
| 1298 | + a.valid? | |
| 1299 | + assert !a.errors.invalid?(:language) | |
| 1300 | + end | |
| 1301 | + | |
| 1302 | + should 'verify if native translation is already in use' do | |
| 1303 | + native_article = fast_create(Article, :language => 'pt') | |
| 1304 | + a = build(Article) | |
| 1305 | + a.language = 'pt' | |
| 1306 | + a.translation_of = native_article | |
| 1307 | + a.valid? | |
| 1308 | + assert a.errors.invalid?(:language) | |
| 1309 | + a.language = 'es' | |
| 1310 | + a.valid? | |
| 1311 | + assert !a.errors.invalid?(:language) | |
| 1312 | + end | |
| 1313 | + | |
| 1314 | + should 'translation have a language' do | |
| 1315 | + native_article = fast_create(Article, :language => 'pt') | |
| 1316 | + a = build(Article) | |
| 1317 | + a.translation_of = native_article | |
| 1318 | + a.valid? | |
| 1319 | + assert a.errors.invalid?(:language) | |
| 1320 | + a.language = 'en' | |
| 1321 | + a.valid? | |
| 1322 | + assert !a.errors.invalid?(:language) | |
| 1323 | + end | |
| 1324 | + | |
| 1325 | + should 'native translation have a language' do | |
| 1326 | + native_article = fast_create(Article) | |
| 1327 | + a = build(Article) | |
| 1328 | + a.language = 'en' | |
| 1329 | + a.translation_of = native_article | |
| 1330 | + a.valid? | |
| 1331 | + n = a.errors.count | |
| 1332 | + native_article.language = 'pt' | |
| 1333 | + native_article.save | |
| 1334 | + a.valid? | |
| 1335 | + assert_equal n - 1, a.errors.count | |
| 1336 | + end | |
| 1337 | + | |
| 1338 | + should 'rotate translations when root article is destroyed' do | |
| 1339 | + native_article = fast_create(Article, :language => 'pt', :profile_id => @profile.id) | |
| 1340 | + translation1 = fast_create(Article, :language => 'en', :translation_of_id => native_article.id, :profile_id => @profile.id) | |
| 1341 | + translation2 = fast_create(Article, :language => 'es', :translation_of_id => native_article.id, :profile_id => @profile.id) | |
| 1342 | + native_article.destroy | |
| 1343 | + assert translation1.translation_of.nil? | |
| 1344 | + assert translation1.translations.include?(translation2) | |
| 1345 | + end | |
| 1346 | + | |
| 1347 | + should 'rotate one translation when root article is destroyed' do | |
| 1348 | + native_article = fast_create(Article, :language => 'pt', :profile_id => @profile.id) | |
| 1349 | + translation = fast_create(Article, :language => 'en', :translation_of_id => native_article.id, :profile_id => @profile.id) | |
| 1350 | + native_article.destroy | |
| 1351 | + assert translation.translation_of.nil? | |
| 1352 | + assert translation.translations.empty? | |
| 1353 | + end | |
| 1354 | + | |
| 1355 | + should 'get self if article does not a language' do | |
| 1356 | + article = fast_create(Article, :profile_id => @profile.id) | |
| 1357 | + assert_equal article, article.get_translation_to('en') | |
| 1358 | + end | |
| 1359 | + | |
| 1360 | + should 'get self if article is the translation' do | |
| 1361 | + article = fast_create(Article, :language => 'pt', :profile_id => @profile.id) | |
| 1362 | + assert_equal article, article.get_translation_to('pt') | |
| 1363 | + end | |
| 1364 | + | |
| 1365 | + should 'get the native translation if it is the translation' do | |
| 1366 | + native_article = fast_create(Article, :language => 'pt', :profile_id => @profile.id) | |
| 1367 | + translation = fast_create(Article, :language => 'en', :translation_of_id => native_article.id, :profile_id => @profile.id) | |
| 1368 | + assert_equal native_article, translation.get_translation_to('pt') | |
| 1369 | + end | |
| 1370 | + | |
| 1371 | + should 'get the translation if article has translation' do | |
| 1372 | + native_article = fast_create(Article, :language => 'pt', :profile_id => @profile.id) | |
| 1373 | + translation = fast_create(Article, :language => 'en', :translation_of_id => native_article.id, :profile_id => @profile.id) | |
| 1374 | + assert_equal translation, native_article.get_translation_to('en') | |
| 1375 | + end | |
| 1376 | + | |
| 1377 | + should 'get self if article does not has a translation' do | |
| 1378 | + native_article = fast_create(Article, :language => 'pt', :profile_id => @profile.id) | |
| 1379 | + assert_equal native_article, native_article.get_translation_to('en') | |
| 1380 | + end | |
| 1381 | + | |
| 1382 | + should 'get only non translated articles' do | |
| 1383 | + p = fast_create(Profile) | |
| 1384 | + native = fast_create(Article, :language => 'pt', :profile_id => p.id) | |
| 1385 | + translation = fast_create(Article, :language => 'en', :translation_of_id => native.id, :profile_id => p.id) | |
| 1386 | + assert_equal [native], p.articles.native_translations | |
| 1387 | + end | |
| 1388 | + | |
| 1389 | + should 'not list own language as a possible translation if language has changed' do | |
| 1390 | + a = build(Article, :language => 'pt') | |
| 1391 | + assert !a.possible_translations.include?('pt') | |
| 1392 | + a = fast_create(Article, :language => 'pt') | |
| 1393 | + a.language = 'en' | |
| 1394 | + assert !a.possible_translations.include?('en') | |
| 1395 | + end | |
| 1396 | + | |
| 1397 | + should 'list own language as a possible translation if language has not changed' do | |
| 1398 | + a = fast_create(Article, :language => 'pt') | |
| 1399 | + assert a.possible_translations.include?('pt') | |
| 1400 | + end | |
| 1401 | + | |
| 1232 | 1402 | end | ... | ... |
test/unit/blog_archives_block_test.rb
| ... | ... | @@ -102,4 +102,36 @@ class BlogArchivesBlockTest < ActiveSupport::TestCase |
| 102 | 102 | assert_no_match(/blog-two/m, block.content) |
| 103 | 103 | end |
| 104 | 104 | |
| 105 | + should 'list amount native posts by year' do | |
| 106 | + date = DateTime.parse('2008-01-01') | |
| 107 | + blog = profile.blog | |
| 108 | + 2.times do |i| | |
| 109 | + post = fast_create(TextileArticle, :name => "post #{i} test", :profile_id => profile.id, | |
| 110 | + :parent_id => blog.id, :language => 'en') | |
| 111 | + post.update_attribute(:published_at, date) | |
| 112 | + translation = fast_create(TextileArticle, :name => "post #{i} test", :profile_id => profile.id, | |
| 113 | + :parent_id => blog.id, :language => 'en', :translation_of_id => post.id) | |
| 114 | + translation.update_attribute(:published_at, date) | |
| 115 | + end | |
| 116 | + block = BlogArchivesBlock.new | |
| 117 | + block.stubs(:owner).returns(profile) | |
| 118 | + assert_tag_in_string block.content, :tag => 'li', :content => '2008 (2)' | |
| 119 | + end | |
| 120 | + | |
| 121 | + should 'list amount native posts by month' do | |
| 122 | + date = DateTime.parse('2008-01-01') | |
| 123 | + blog = profile.blog | |
| 124 | + 2.times do |i| | |
| 125 | + post = fast_create(TextileArticle, :name => "post #{i} test", :profile_id => profile.id, | |
| 126 | + :parent_id => blog.id, :language => 'en') | |
| 127 | + post.update_attribute(:published_at, date) | |
| 128 | + translation = fast_create(TextileArticle, :name => "post #{i} test", :profile_id => profile.id, | |
| 129 | + :parent_id => blog.id, :language => 'en', :translation_of_id => post.id) | |
| 130 | + translation.update_attribute(:published_at, date) | |
| 131 | + end | |
| 132 | + block = BlogArchivesBlock.new | |
| 133 | + block.stubs(:owner).returns(profile) | |
| 134 | + assert_tag_in_string block.content, :tag => 'a', :content => 'January (2)', :attributes => {:href => /^http:\/\/.*\/flatline\/blog-one\?month=01&year=2008$/ } | |
| 135 | + end | |
| 136 | + | |
| 105 | 137 | end | ... | ... |
test/unit/blog_test.rb
| ... | ... | @@ -175,4 +175,20 @@ class BlogTest < ActiveSupport::TestCase |
| 175 | 175 | assert Blog.new.has_posts? |
| 176 | 176 | end |
| 177 | 177 | |
| 178 | + should 'display posts in current language by default' do | |
| 179 | + blog = Blog.new | |
| 180 | + assert blog.display_posts_in_current_language | |
| 181 | + assert blog.display_posts_in_current_language? | |
| 182 | + end | |
| 183 | + | |
| 184 | + should 'update display posts in current language setting' do | |
| 185 | + p = create_user('testuser').person | |
| 186 | + p.articles << Blog.new(:profile => p, :name => 'Blog test') | |
| 187 | + blog = p.blog | |
| 188 | + blog.display_posts_in_current_language = false | |
| 189 | + assert blog.save! && blog.reload | |
| 190 | + assert !blog.reload.display_posts_in_current_language | |
| 191 | + assert !blog.reload.display_posts_in_current_language? | |
| 192 | + end | |
| 193 | + | |
| 178 | 194 | end | ... | ... |
test/unit/event_test.rb
| ... | ... | @@ -265,4 +265,10 @@ class EventTest < ActiveSupport::TestCase |
| 265 | 265 | assert_match /<!-- .* --> <h1> Wellformed html code <\/h1>/, event.description |
| 266 | 266 | assert_match /<!-- .* --> <h1> Wellformed html code <\/h1>/, event.address |
| 267 | 267 | end |
| 268 | + | |
| 269 | + should 'be translatable' do | |
| 270 | + e = Event.new | |
| 271 | + assert e.translatable? | |
| 272 | + end | |
| 273 | + | |
| 268 | 274 | end | ... | ... |
test/unit/rss_feed_test.rb
| ... | ... | @@ -240,4 +240,24 @@ class RssFeedTest < Test::Unit::TestCase |
| 240 | 240 | assert_not_nil RssFeed.new.to_html |
| 241 | 241 | end |
| 242 | 242 | |
| 243 | + should 'include posts from all languages' do | |
| 244 | + profile = create_user('testuser').person | |
| 245 | + blog = Blog.create!(:name => 'blog-test', :profile => profile, :language => nil) | |
| 246 | + blog.posts << en_post = fast_create(TextArticle, :name => "English", :profile_id => profile.id, :parent_id => blog.id, :published => true, :language => 'en') | |
| 247 | + blog.posts << es_post = fast_create(TextArticle, :name => "Spanish", :profile_id => profile.id, :parent_id => blog.id, :published => true, :language => 'es') | |
| 248 | + | |
| 249 | + assert blog.feed.fetch_articles.include?(en_post) | |
| 250 | + assert blog.feed.fetch_articles.include?(es_post) | |
| 251 | + end | |
| 252 | + | |
| 253 | + should 'include only posts from some language' do | |
| 254 | + profile = create_user('testuser').person | |
| 255 | + blog = Blog.create!(:name => 'blog-test', :profile => profile) | |
| 256 | + blog.feed.update_attributes! :language => 'es' | |
| 257 | + blog.posts << en_post = fast_create(TextArticle, :name => "English", :profile_id => profile.id, :parent_id => blog.id, :published => true, :language => 'en') | |
| 258 | + blog.posts << es_post = fast_create(TextArticle, :name => "Spanish", :profile_id => profile.id, :parent_id => blog.id, :published => true, :language => 'es') | |
| 259 | + | |
| 260 | + assert_equal [es_post], blog.feed.fetch_articles | |
| 261 | + end | |
| 262 | + | |
| 243 | 263 | end | ... | ... |
test/unit/textile_article_test.rb
test/unit/tiny_mce_article_test.rb