solarsearch 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/.gitignore +23 -0
  2. data/.specification +294 -0
  3. data/LICENSE +20 -0
  4. data/README.rdoc +17 -0
  5. data/Rakefile +76 -0
  6. data/Solarsearch.gemspec +176 -0
  7. data/VERSION +1 -0
  8. data/app/controllers/article_controller.rb +30 -0
  9. data/app/controllers/article_statuses_controller.rb +12 -0
  10. data/app/controllers/infosources_controller.rb +143 -0
  11. data/app/controllers/search_keywords_controller.rb +99 -0
  12. data/app/controllers/user_sessions_controller.rb +48 -0
  13. data/app/controllers/users_controller.rb +62 -0
  14. data/app/helpers/article_helper.rb +25 -0
  15. data/app/helpers/article_statuses_helper.rb +2 -0
  16. data/app/helpers/infosources_helper.rb +2 -0
  17. data/app/helpers/layout_helper.rb +22 -0
  18. data/app/helpers/search_keywords_helper.rb +2 -0
  19. data/app/helpers/site_helper.rb +2 -0
  20. data/app/helpers/user_sessions_helper.rb +2 -0
  21. data/app/helpers/users_helper.rb +2 -0
  22. data/app/models/article.rb +74 -0
  23. data/app/models/article_status.rb +20 -0
  24. data/app/models/infosource.rb +83 -0
  25. data/app/models/role.rb +2 -0
  26. data/app/models/roles_users.rb +2 -0
  27. data/app/models/search_keyword.rb +14 -0
  28. data/app/models/user.rb +132 -0
  29. data/app/models/user_mailer.rb +12 -0
  30. data/app/models/user_session.rb +2 -0
  31. data/config/locales/hu.yml +111 -0
  32. data/config/locales/sk.yml +111 -0
  33. data/init.rb +1 -0
  34. data/install.rb +1 -0
  35. data/lib/solarsearch.rb +9 -0
  36. data/lib/solarsearch/locales.rb +3 -0
  37. data/lib/solarsearch/routing.rb +31 -0
  38. data/rails/init.rb +1 -0
  39. data/solarsearch.gemspec +178 -0
  40. data/tasks/solarsearch_tasks.rake +4 -0
  41. data/test/blueprints.rb +34 -0
  42. data/test/blueprints/articles.rb +37 -0
  43. data/test/blueprints/infosources.rb +53 -0
  44. data/test/blueprints/infosources_files/pretty.html +17 -0
  45. data/test/blueprints/infosources_files/ugly.html +399 -0
  46. data/test/blueprints/search_keywords.rb +13 -0
  47. data/test/blueprints/users.rb +17 -0
  48. data/test/content_scrapper.rb +13 -0
  49. data/test/database.yml +7 -0
  50. data/test/functional/article_controller_test.rb +40 -0
  51. data/test/functional/email_controller_test.rb +9 -0
  52. data/test/functional/infosources_controller_test.rb +65 -0
  53. data/test/functional/restricted_logged_exceptions_controller_test.rb +38 -0
  54. data/test/functional/search_keywords_controller_test.rb +108 -0
  55. data/test/functional/user_sessions_controller_test.rb +39 -0
  56. data/test/functional/users_controller_test.rb +109 -0
  57. data/test/schema.rb +92 -0
  58. data/test/test_helper.rb +48 -0
  59. data/test/unit/article_test.rb +56 -0
  60. data/test/unit/helpers/article_helper_test.rb +20 -0
  61. data/test/unit/helpers/email_helper_test.rb +4 -0
  62. data/test/unit/helpers/user_sessions_helper_test.rb +4 -0
  63. data/test/unit/helpers/users_helper_test.rb +4 -0
  64. data/test/unit/infosource_test.rb +132 -0
  65. data/test/unit/role_test.rb +6 -0
  66. data/test/unit/roles_users_test.rb +6 -0
  67. data/test/unit/user_mailer_test.rb +24 -0
  68. data/test/unit/user_test.rb +103 -0
  69. data/uninstall.rb +1 -0
  70. metadata +297 -0
@@ -0,0 +1,2 @@
1
+ module SearchKeywordsHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ module SiteHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ module UserSessionsHelper
2
+ end
@@ -0,0 +1,2 @@
1
+ module UsersHelper
2
+ end
@@ -0,0 +1,74 @@
1
+
2
+ require 'sunspot'
3
+ require 'sunspot/rails'
4
+
5
+ class Article < ActiveRecord::Base
6
+
7
+ cattr_reader :per_page
8
+ @@per_page = 10
9
+
10
+ before_validation :remove_illegal_characters
11
+
12
+ belongs_to :infosource
13
+ has_many :article_statuses
14
+
15
+ has_many :was_sent_to,
16
+ :through => :article_statuses,
17
+ :source => :user,
18
+ :conditions => "status = '#{ArticleStatus::STATUS_SENT}'",
19
+ :order => :created_at
20
+
21
+ has_many :viewed_by,
22
+ :through => :article_statuses,
23
+ :source => :user,
24
+ :conditions => "status ='#{ArticleStatus::STATUS_VIEWED}'",
25
+ :order => :created_at
26
+
27
+ searchable do
28
+ string :author
29
+ text :title
30
+ text :summary
31
+ text :body
32
+ string :url
33
+ time :published_at
34
+ dynamic_boolean :status do
35
+ article_statuses.inject({}) do |user_statuses_hash, article_status|
36
+ user_status_symbol = Article.give_user_status_symbol(article_status.user, article_status.status)
37
+ user_statuses_hash.merge(user_status_symbol => true)
38
+ end
39
+ end
40
+ end
41
+
42
+ validates_format_of :url, :with => URI::regexp(%w(http https)), :allow_nil => true
43
+ validates_uniqueness_of :guid, :allow_nil => true
44
+
45
+ def self.give_user_status_symbol(user, status)
46
+ "user#{user.object_id}_status#{status}".to_sym
47
+ end
48
+
49
+ def size
50
+ title.size + summary.size + body.size + url.size
51
+ end
52
+
53
+ def set_user_status(user, status)
54
+ article_status = ArticleStatus.find_by_user_id_and_article_id_and_status(user, self, status)
55
+ if article_status.nil?
56
+ article_status = ArticleStatus.new
57
+ article_status.user = user
58
+ article_status.article = self
59
+ article_status.status = status
60
+ article_status.save!
61
+ end
62
+ self.touch
63
+ end
64
+
65
+ def remove_illegal_characters
66
+ ugly_characters = "\x00-\x1F" #"\x00-\x08\x0B\x0C\x0E-\x1F"
67
+ exchange_character = ' '
68
+ author.tr!(ugly_characters, exchange_character) unless author.nil?
69
+ title.tr!(ugly_characters, exchange_character) unless title.nil?
70
+ summary.tr!(ugly_characters, exchange_character) unless summary.nil?
71
+ body.tr!(ugly_characters, exchange_character) unless body.nil?
72
+ url.tr!(ugly_characters, '') unless url.nil?
73
+ end
74
+ end
@@ -0,0 +1,20 @@
1
+ class ArticleStatus < ActiveRecord::Base
2
+
3
+ cattr_reader :per_page
4
+ @@per_page = 50
5
+
6
+ STATUS_SENT = 1
7
+ STATUS_VIEWED = 2
8
+
9
+ WORD_FOR_STATUS = { STATUS_SENT => I18n.t(:article_status_sent_word),
10
+ STATUS_VIEWED => I18n.t(:article_status_viewed_word) }
11
+
12
+ attr_accessible :article_id, :user_id, :status
13
+ belongs_to :article
14
+ belongs_to :user
15
+ validates_presence_of :user_id, :message => I18n.t(:user_not_set_validation_error)
16
+ validates_presence_of :article_id, :message => I18n.t(:article_not_set_validation_error)
17
+ validates_presence_of :status, :message => I18n.t(:status_not_set_validation_error)
18
+ validates_uniqueness_of :status, :scope => [:user_id, :article_id],
19
+ :message => I18n.t(:status_user_article_not_unique_validation_error)
20
+ end
@@ -0,0 +1,83 @@
1
+
2
+ require 'content_scrapper'
3
+ require 'content_scrapper/feedzirra'
4
+
5
+ class Infosource < ActiveRecord::Base
6
+
7
+ include InfosourcesHelper
8
+
9
+ MIN_SOURCENAME_SIZE = 3
10
+ MAX_SOURCENAME_SIZE = 40
11
+ RANGE_SOURCENAMESIZE = (3..40)
12
+
13
+ has_many :articles, :order => "published_at DESC"
14
+
15
+ validates_uniqueness_of :sourcename
16
+ validates_length_of :sourcename, :within => RANGE_SOURCENAMESIZE
17
+ validates_format_of :sourcefeed, :with => Regexp.new(URI::regexp(%w(http https)).to_s + '|^$'),
18
+ :allow_nil => true
19
+
20
+ def fetch_source
21
+ if has_sourcefeed?
22
+ begin
23
+ #TODO simulate Feedzirra collapse in tests
24
+ feed = Feedzirra::Feed.fetch_and_parse(self.sourcefeed)
25
+ rescue Exception
26
+ Rails.logger.error("Error occured during fetching infosource #{self.sourcename} (#{self.sourcefeed}): #{$!}")
27
+ end
28
+ if feed != 0
29
+ entries_count = add_entries(feed.entries)
30
+ Rails.logger.info "Infosource #{self.sourcename}'s fetched from feed #{self.sourcefeed}, #{entries_count} entries added."
31
+ else
32
+ entries_count = nil
33
+ Rails.logger.error "Infosource #{self.sourcename} count not be fetched. An error occured."
34
+ end
35
+ else
36
+ entries_count = nil
37
+ Rails.logger.info "Infosource #{self.sourcename} has not feed set, nothing fetched."
38
+ end
39
+ entries_count
40
+ end
41
+
42
+ #TODO updating feed using the Feedzirra, the feeds should be mapped to the articles model
43
+ def self.fetch_all_sources
44
+ Rails.logger.info "Starting to fetch feeds for #{Infosource.count} infosources."
45
+ begin
46
+ total_fetches = 0
47
+ Infosource.all.each do |infosource|
48
+ total_fetches += infosource.fetch_source || 0
49
+ end
50
+ rescue Exception
51
+ #TODO test for failed fetching
52
+ Rails.logger.error("Error occured during fetching all infosources: #{$!}")
53
+ ensure
54
+ Sunspot.commit_if_dirty
55
+ Rails.logger.info "#{total_fetches} articles were fetched. Harvesting finished."
56
+ end
57
+ total_fetches
58
+ end
59
+
60
+ private
61
+
62
+ def add_entries(entries)
63
+ new_entries = 0
64
+ entries.each do |entry|
65
+ unless Article.exists?(:guid => entry.id) then
66
+ article = Article.create!(:title => entry.title,
67
+ :summary => entry.summary,
68
+ :body => entry.scrap_content,
69
+ :url => entry.url,
70
+ :published_at => entry.published,
71
+ :guid => entry.id,
72
+ :infosource => self)
73
+ new_entries += 1
74
+ end
75
+ end
76
+ new_entries
77
+ end
78
+
79
+ def has_sourcefeed?
80
+ self.sourcefeed && !self.sourcefeed.empty?
81
+ end
82
+
83
+ end
@@ -0,0 +1,2 @@
1
+ class Role < ActiveRecord::Base
2
+ end
@@ -0,0 +1,2 @@
1
+ class RolesUsers < ActiveRecord::Base
2
+ end
@@ -0,0 +1,14 @@
1
+
2
+ class SearchKeyword < ActiveRecord::Base
3
+
4
+ belongs_to :user
5
+
6
+ attr_accessible :query
7
+
8
+ MIN_QUERY_LENGTH = 3
9
+ MAX_QUERY_LENGTH = 120
10
+ RANGE_QUERY_LENGTH = (MIN_QUERY_LENGTH..MAX_QUERY_LENGTH)
11
+
12
+ validates_length_of :query, :within => RANGE_QUERY_LENGTH
13
+ end
14
+
@@ -0,0 +1,132 @@
1
+ class User < ActiveRecord::Base
2
+
3
+ cattr_reader :per_page
4
+ @@per_page = 20
5
+
6
+ before_validation :strip_and_and_put_to_lowercase
7
+
8
+ has_many :search_keywords
9
+ has_many :article_statuses
10
+
11
+ has_many :sent_articles,
12
+ :through => :article_statuses,
13
+ :source => :article,
14
+ :conditions => "status = '#{ArticleStatus::STATUS_SENT}'",
15
+ :order => :created_at
16
+
17
+ has_many :viewed_articles,
18
+ :through => :article_statuses,
19
+ :source => :article,
20
+ :conditions => "status ='#{ArticleStatus::STATUS_VIEWED}'",
21
+ :order => :created_at
22
+
23
+ USERNAME_MIN_LENGTH = 4
24
+ USERNAME_MAX_LENGTH = 20
25
+ PASSWORD_MIN_LENGTH = 4
26
+ PASSWORD_MAX_LENGTH = 40
27
+ EMAIL_MAX_LENGTH = 50
28
+ USERNAME_RANGE = USERNAME_MIN_LENGTH..USERNAME_MAX_LENGTH
29
+ PASSWORD_RANGE = PASSWORD_MIN_LENGTH..PASSWORD_MAX_LENGTH
30
+ MAX_NUMBER_OF_ARTICLES_PER_NEWSUPDATE = 10
31
+ MAX_SIZE_OF_A_MAIL_IN_CHARACTERS = 10000
32
+ NEWSUPDATE_RECENT_NUMBER_OF_DAYS = 120
33
+
34
+ =begin
35
+ validates_uniqueness_of :username, :email
36
+ validates_confirmation_of :password
37
+ validates_length_of :username, :within => USERNAME_RANGE
38
+ validates_length_of :password, :within => PASSWORD_RANGE
39
+ validates_length_of :email, :maximum => EMAIL_MAX_LENGTH
40
+
41
+ validates_format_of :username,
42
+ :with => /^[a-z_][a-z0-9_]*$/,
43
+ :message => I18n.t(:given_username_is_not_correct_validation_error)
44
+ validates_format_of :email,
45
+ :with => /^[A-Z0-9._%-]+@([A-Z0-9-]+\.)+[A-Z]{2,4}$/i,
46
+ :message => I18n.t(:given_email_is_not_correct_validation_error)
47
+ =end
48
+
49
+ acts_as_authentic
50
+ acts_as_authorization_subject
51
+
52
+ #FIXME: is not unittested
53
+ def post_recent_news
54
+ recent_articles = collect_recent_articles do |article|
55
+ article.size <= User::MAX_SIZE_OF_A_MAIL_IN_CHARACTERS
56
+ end
57
+ recent_articles.each do |article|
58
+ UserMailer.deliver_newsupdate(self, article)
59
+ article.set_user_status(self, ArticleStatus::STATUS_SENT)
60
+ logger.info <<-EOF
61
+ Email notification about article #{article.title} was sent to #{self.username},
62
+ address #{self.email}
63
+ EOF
64
+ end
65
+ end
66
+
67
+ def self.post_recent_news_for_every_user
68
+ logger.info 'Starting to send the recent news for every user through email.'
69
+ User.all.each do |user|
70
+ user.post_recent_news
71
+ end
72
+ logger.info 'Sending recent news for every user finished.'
73
+ end
74
+
75
+ def collect_recent_articles(&article_condition)
76
+ Sunspot.commit_if_dirty
77
+ =begin
78
+ searchquery = search_keywords.map do |search_keyword|
79
+ "(#{search_keyword.query})"
80
+ end.join(' OR ')
81
+ search = Sunspot.search(Article) do
82
+ keywords searchquery
83
+ with(:published_at).greater_than Time.now - NEWSUPDATE_RECENT_NUMBER_OF_DAYS.day
84
+ dynamic :status do
85
+ without Article.give_user_status_symbol(self, ArticleStatus::STATUS_VIEWED), true
86
+ without Article.give_user_status_symbol(self, ArticleStatus::STATUS_SENT), true
87
+ end
88
+ order_by(:published_at, :desc)
89
+ paginate(:page => 1, :per_page => MAX_NUMBER_OF_ARTICLES_PER_NEWSUPDATE)
90
+ end
91
+ search.results
92
+ =end
93
+ set_all_articles = Set.new
94
+ search_keywords.each do |search_keyword|
95
+ article_update = recent_articles_for_search_keyword(search_keyword)
96
+ set_all_articles += article_update
97
+ end
98
+ arr_all_articles = set_all_articles.to_a
99
+ arr_all_articles = arr_all_articles.find_all { |article| article_condition.call(article) } if article_condition
100
+ arr_all_articles.sort! { |article1, article2| article2.published_at <=> article1.published_at }
101
+ arr_all_articles = arr_all_articles[0, MAX_NUMBER_OF_ARTICLES_PER_NEWSUPDATE]
102
+ arr_all_articles
103
+ end
104
+
105
+ def recent_articles_for_search_keyword(search_keyword)
106
+ searchquery = search_keyword.query
107
+ search = Sunspot.search(Article) do
108
+ keywords searchquery
109
+ with(:published_at).greater_than Time.now - NEWSUPDATE_RECENT_NUMBER_OF_DAYS.day
110
+ dynamic :status do
111
+ without Article.give_user_status_symbol(self, ArticleStatus::STATUS_VIEWED), true
112
+ without Article.give_user_status_symbol(self, ArticleStatus::STATUS_SENT), true
113
+ end
114
+ order_by(:published_at, :desc)
115
+ paginate(:page => 1, :per_page => MAX_NUMBER_OF_ARTICLES_PER_NEWSUPDATE)
116
+ end
117
+ search.results
118
+ end
119
+
120
+ def can_be_modified_by(user)
121
+ !user.nil? and (user==self or user.has_role?(:admin))
122
+ end
123
+
124
+ private
125
+
126
+ def strip_and_and_put_to_lowercase
127
+ self.email.strip!
128
+ self.email.downcase!
129
+ end
130
+
131
+ end
132
+
@@ -0,0 +1,12 @@
1
+
2
+ class UserMailer < ActionMailer::Base
3
+
4
+ #TODO the from email has to me moved to a configuration file
5
+ def newsupdate(user, article)
6
+ recipients user.email
7
+ from 'fificium@gmail.com'
8
+ subject I18n.t(:usermailer_newsupdate_subject)
9
+ content_type 'text/html'
10
+ @article = article
11
+ end
12
+ end
@@ -0,0 +1,2 @@
1
+ class UserSession < Authlogic::Session::Base
2
+ end
@@ -0,0 +1,111 @@
1
+ hu:
2
+ #controllers
3
+ access_denied_flash: 'Hozzáférés elutasítva'
4
+ login_please_flash: 'Jelentkezzen be'
5
+
6
+ infosource_fetched_flash: 'Az információforrás megújítva. {{items_fetched}} cikk letöltve.'
7
+ nothing_was_fetched_flash: 'Nincs cikk letöltve.'
8
+ infosource_creation_success_flash: 'Az információforrás sikeresen kialakítva.'
9
+ infosource_update_success_flash: 'Az információforrás módosítása sikeres.'
10
+
11
+ news_were_posted_flash: 'A legújabb hírek feladva.'
12
+ no_news_were_posted_flash: 'Nincsenek új hírek.'
13
+ keyword_does_not_exist_flash: 'Nem létező kulcsszó.'
14
+ keyword_creation_success_flash: 'A kulcsszó sikeresen kialakítva.'
15
+ keyword_update_denied_flash: 'A kulcsszó módosítása elutasítva.'
16
+ keyword_update_success_flash: 'A kulcsszó sikeresen módosítva.'
17
+ keyword_destroy_success_flash: 'A kulcsszó sikeresen eltávolítva.'
18
+
19
+ login_successful_flash: 'Sikeres bejelentkezés.'
20
+ logout_successful_flash: 'Sikeres kijelentkezés.'
21
+
22
+ registration_successful_flash: 'Sikeres regisztráció.'
23
+ profil_change_success_flash: 'A profil sikeresen módosítva.'
24
+
25
+ #models
26
+ article_status_sent_word: 'Elküldve'
27
+ article_status_viewed_word: 'Megjelenítve'
28
+
29
+ given_username_is_not_correct_validation_error: 'csak kisbetűket, számjegyeket és aláhúzást tartalmazhat "_"'
30
+ given_email_is_not_correct_validation_error: 'Hibás e-mail cím'
31
+ user_not_set_validation_error: 'Nincs felhasználó.'
32
+ article_not_set_validation_error: 'Nincs cikk.'
33
+ status_not_set_validation_error: 'Nincs állapot.'
34
+ status_user_article_not_unique_validation_error: 'A cikk, állapot és felhasználó hármas esetében csak egyetlen bejegyzés lehetséges.'
35
+
36
+ #views
37
+ unknown_infosource: 'ismeretlen forrás'
38
+ did_not_find_any_results_for_query: 'Nincs találat a "{{query}}" lekérdezésre'
39
+ search_summary_articles_from: 'Cikkek {{articles_from}}-tól/-től'
40
+ search_summary_articles_to: 'cikkek {{articles_to}}-ba/-be'
41
+ search_summary_number_of_articles: 'a {{articles_total}} összesített számból.'
42
+ pagination_previous_label: 'Előző'
43
+ pagination_next_label: 'Következő'
44
+ search_articles_button_label: 'Keresd a következő cikkekben'
45
+ article_search_view_title: 'Keresés'
46
+
47
+ article_statuses_view_title: 'Események'
48
+ article_status_line: '{{article_status}} a következő napon {{status_update_date}}:'
49
+
50
+ infosources_edit_view_title: 'Az információforrás megváltozott'
51
+ infosources_sourcename_form_field_label: 'Címke'
52
+ infosources_url_form_field_label: 'URL a következő hírcsatornára'
53
+ infosources_list_view_title: 'Információforrások listája'
54
+ infosources_new_view_title: 'Új információforrás'
55
+ infosources_show_view_title: 'Jelenítsd meg az információforrás részleteit'
56
+ infosources_unknown_source_text: 'Ismeretlen forrás'
57
+
58
+ infosources_change_action_label: 'Módosítás'
59
+ infosources_destroy_action_label: 'Törlés'
60
+ infosources_view_action_label: 'Megjelenítés'
61
+ infosources_back_to_the_list_action_label: 'Vissza a listához'
62
+ infosources_new_action_label: 'Új információforrás'
63
+ infosources_create_action_label: 'Létrehozás'
64
+ infosources_fetch_action_label: 'A forrás felújítása'
65
+ infosources_test_scrapper_for_page_label: 'Az oldal tartalmának kivágása'
66
+ infosources_empty_web_page_content_text: 'Üres tartalom'
67
+
68
+ search_keywords_submit_action_label: 'Megerősítés'
69
+ search_keywords_change_view_title: 'A kulcsszó megváltozott'
70
+ search_keywords_index_view_title: 'Kulcsszavak'
71
+ search_keywords_show_view_title: 'Kulcsszó'
72
+ search_keywords_change_action_label: 'Módosítás'
73
+ search_keywords_destroy_action_label: 'Mégse'
74
+ search_keywords_back_to_the_list_action_label: 'Vissza a listához'
75
+ search_keywords_view_action_label: 'Megjelenítés'
76
+ search_keywords_new_search_keyword_text: 'Új kulcsszó:'
77
+ search_keywords_my_search_keywords: 'Az én kulcsszavaim (a keresés során használt lekérdezések listája):'
78
+ search_keywords_new_view_title: 'Új kulcsszó'
79
+ search_keywords_my_news_view_title: 'Saját üzeneteim'
80
+ search_keywords_send_to_email_action_label: 'Küldés e-mailben'
81
+ search_keywords_query_text: 'Kérdés:'
82
+
83
+ this_page_shows_news_not_older_than_xy_days_text: "Ezen az oldalon {{days}} napnál nem régebbi üzenetek jelennek meg."
84
+ for_a_keyword_only_xy_results_are_listed: 'Egy kulcsszóra legtöbb {{results}} üzenet kerül megjelenítésre.'
85
+ news_which_were_viewed_through_the_web_and_were_of_your_interest_are_not_listed: 'Azok az üzenetek, amelyekről e-mail értesítést küldtünk és amelyeket megjelenített, nem szerepelnek a listán.'
86
+
87
+ user_sessions_login_view_title: 'Bejelentkezve'
88
+ user_sessions_username_form_field_label: 'Login:'
89
+ user_sessions_password_form_field_label: 'Jelszó:'
90
+ user_sessions_login_action_label: "Bejelentkezés"
91
+
92
+ users_username_form_field_label: 'Felhasználónév'
93
+ users_email_form_field_label: 'E-mail'
94
+ users_password_from_field_label: 'Jelszó'
95
+ users_password_confirmation_label: 'Jelszó megerősítése'
96
+ users_submit_form_action_label: 'Megerősítés'
97
+ users_change_profile_view_title: 'Profil módosítása'
98
+ users_registration_view_title: 'Regisztráció'
99
+
100
+ root_page_action_label: 'Főoldal'
101
+ my_profile_action_label: 'Saját kontó'
102
+ agent_action_label: 'Ügynök'
103
+ my_news_action_label: 'Saját hírek'
104
+ users_action_label: 'Felhasználók'
105
+ inforsources_list_action_label: 'Információforrások'
106
+ errors_and_exceptions_action_label: 'Hibák és kivételek'
107
+ logout_user_action_label: 'Kijelentkezés ({{username}})'
108
+ registration_action_label: 'Regisztráció'
109
+ login_action_label: 'Bejelentkezés'
110
+
111
+ are_you_sure_confirmation: 'Biztosan ezt akarja?'