Merge pull request #37 from Retrospring/locale

Translation support
This commit is contained in:
Georg G. 2015-06-08 22:26:03 +02:00
commit b24ee7fb0d
96 changed files with 1169 additions and 670 deletions

3
.gitignore vendored
View file

@ -23,6 +23,9 @@ coverage/
# damn vim backup files
*~
# dont push generated js translations to repository
/public/javascripts/i18n/
# every fucking time, dolphin
.directory
# lookin' at you, OS trash

View file

@ -2,6 +2,8 @@ source 'https://rubygems.org'
source 'https://rails-assets.org'
gem 'rails', '4.2.1'
gem 'rails-i18n'
gem 'i18n-js'
gem 'pg', group: :postgres
gem 'mysql2', group: :mysql
@ -25,6 +27,7 @@ gem 'will_paginate'
gem 'will_paginate-bootstrap'
gem 'http_accept_language'
gem 'devise'
gem 'devise-i18n'
gem 'devise-async'
gem 'bootstrap_form'
gem 'font-kit-rails'
@ -63,7 +66,8 @@ gem 'foreman'
gem 'redis'
group :development do
gem 'spring'
# require spring 1.3.5 since shit's on fire on my local instance with 1.3.4 (Gem::LoadError)
gem 'spring', '~> 1.3.5'
# ten thousand raises no more!
gem 'byebug'
gem 'web-console'

View file

@ -102,6 +102,7 @@ GEM
warden (~> 1.2.3)
devise-async (0.9.0)
devise (~> 3.2)
devise-i18n (0.12.0)
diff-lcs (1.2.5)
docile (1.1.5)
equalizer (0.0.11)
@ -221,6 +222,8 @@ GEM
http_accept_language (2.0.5)
http_parser.rb (0.6.0)
i18n (0.7.0)
i18n-js (3.0.0.rc10)
i18n (~> 0.6)
inflecto (0.0.2)
ipaddress (0.8.0)
jbuilder (2.2.13)
@ -318,6 +321,9 @@ GEM
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.0.2)
loofah (~> 2.0)
rails-i18n (4.0.4)
i18n (~> 0.6)
railties (~> 4.0)
rails_admin (0.6.7)
builder (~> 3.1)
coffee-rails (~> 4.0)
@ -400,7 +406,7 @@ GEM
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (>= 1.3, < 3)
spring (1.3.4)
spring (1.3.5)
sprockets (2.12.3)
hike (~> 1.2)
multi_json (~> 1.0)
@ -483,6 +489,7 @@ DEPENDENCIES
delayed_paperclip
devise
devise-async
devise-i18n
factory_girl_rails
faker
fog
@ -492,6 +499,7 @@ DEPENDENCIES
foreman
haml
http_accept_language
i18n-js
jbuilder (~> 2.2.4)
jquery-rails
jquery-turbolinks
@ -507,6 +515,7 @@ DEPENDENCIES
questiongenerator!
rails (= 4.2.1)
rails-assets-growl
rails-i18n
rails_admin
rake
redcarpet
@ -521,7 +530,7 @@ DEPENDENCIES
simplecov-json
simplecov-rcov
sinatra
spring
spring (~> 1.3.5)
sweetalert-rails
thin
tumblr_client

View file

@ -41,11 +41,11 @@ $(document).on "keyup", "input[name=ab-comment-new]", (evt) ->
$("span#ab-comment-count-#{aid}").html data.count
subs = $("a[data-action=ab-submarine][data-a-id=#{aid}]")[0]
subs.dataset.torpedo = "no"
subs.children[0].nextSibling.textContent = "Unsubscribe"
subs.children[0].nextSibling.textContent = translate('views.actions.unsubscribe')
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
input.removeAttr 'disabled'

View file

@ -3,12 +3,13 @@ $(document).on "click", "a[data-action=ab-comment-destroy]", (ev) ->
btn = $(this)
cid = btn[0].dataset.cId
swal
title: "Really delete?"
text: "You will not be able to recover this comment."
title: translate('frontend.destroy_comment.confirm.title')
text: translate('frontend.destroy_comment.confirm.text')
type: "warning"
showCancelButton: true
confirmButtonColor: "#DD6B55"
confirmButtonText: "Delete"
confirmButtonText: translate('views.actions.delete')
cancelButtonText: translate('views.actions.cancel')
closeOnConfirm: true
, ->
$.ajax
@ -22,5 +23,5 @@ $(document).on "click", "a[data-action=ab-comment-destroy]", (ev) ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
complete: (jqxhr, status) ->
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->

View file

@ -28,7 +28,7 @@ $(document).on "click", "button[name=ab-smile-comment]", ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
btn.button "reset"
if success

View file

@ -3,13 +3,13 @@ $(document).on "click", "a[data-action=ab-destroy]", (ev) ->
btn = $(this)
aid = btn[0].dataset.aId
swal
title: "Are you sure?"
text: "The question will be moved back to your inbox, but it won't delete any posts to social media."
title: translate('frontend.destroy_question.confirm.title')
text: translate('frontend.destroy_question.confirm.text')
type: "warning"
showCancelButton: true
confirmButtonColor: "#DD6B55"
confirmButtonText: "Yes"
cancelButtonText: "No"
confirmButtonText: translate('views.actions.y')
cancelButtonText: translate('views.actions.n')
closeOnConfirm: true
, ->
$.ajax
@ -23,5 +23,5 @@ $(document).on "click", "a[data-action=ab-destroy]", (ev) ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->

View file

@ -28,7 +28,7 @@ $(document).on "click", "button[name=ab-smile]", ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
btn.button "reset"
if success

View file

@ -1,4 +1,5 @@
# the laziest coding known to man
# TODO: so lazy, I don't know how to localize it properly
$(document).on "click", "a[data-action=ab-submarine]", (ev) ->
ev.preventDefault()
btn = $(this)
@ -6,9 +7,11 @@ $(document).on "click", "a[data-action=ab-submarine]", (ev) ->
torpedo = 0
if btn[0].dataset.torpedo == "yes"
torpedo = 1
endpoint = "subscribe"
if torpedo == 0
endpoint = "un" + endpoint
$.ajax
url: '/ajax/' + endpoint # TODO: find a way to use rake routes instead of hardcoding them here
type: 'POST'
@ -17,11 +20,9 @@ $(document).on "click", "a[data-action=ab-submarine]", (ev) ->
success: (data, status, jqxhr) ->
if data.success
btn[0].dataset.torpedo = ["yes", "no"][torpedo]
btn[0].children[0].nextSibling.textContent = ["Subscribe", "Unsubscribe"][torpedo]
showNotification "Successfully " + endpoint + "d.", true
btn[0].children[0].nextSibling.textContent = if torpedo then translate("views.actions.unsubscribe") else translate("views.actions.subscribe")
showNotification translate("frontend.subscription.#{endpoint}"), true
else
showNotification "Couldn't unsubscribe from the answer.", false
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate("frontend.subscription.fail.#{endpoint}"), false
error: showNotificationXHRError
complete: (jqxhr, status) ->

View file

@ -10,6 +10,9 @@
#= require jquery.guillotine
#= require jquery.particleground
#= require sweet-alert
#= require js.cookie
#= require i18n
#= require i18n/translations
# local requires to be seen by everyone:
#= require_tree ./answerbox
#= require_tree ./questionbox
@ -29,15 +32,26 @@
NProgress.configure
showSpinner: false
window.translate = (scope, options) ->
# for some reason I18n errors when calling it by assign proxy, so we got to wrap it
I18n.translate(scope, options)
window.showNotification = (text, success=true) ->
args =
title: if success then "Success!" else "Uh-oh..."
title: translate((if success then 'frontend.success.title' else 'frontend.error.title'))
message: text
if success
$.growl.notice args
else
$.growl.error args
I18n.defaultLocale = 'en';
I18n.locale = Cookies.get('hl') || 'en';
window.showNotificationXHRError = (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification translate('frontend.error.message'), false
$(document).on "click", "button#create-account", ->
Turbolinks.visit "/sign_up"

View file

@ -24,7 +24,7 @@
error: (jqxhr, status, error) ->
box[0].checked = false
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
box.removeAttr "disabled"
@ -54,7 +54,7 @@ $(document).on "keyup", "input#new-group-name", (evt) ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
btn.button "reset"
@ -65,12 +65,13 @@ $(document).on "keyup", "input#new-group-name", (evt) ->
group = btn[0].dataset.group
swal
title: "Really delete this group?"
text: "You will not be able to recover this group."
title: translate('frontend.group.title')
text: translate('frontend.group.text')
type: "warning"
showCancelButton: true
confirmButtonColor: "#DD6B55"
confirmButtonText: "Delete"
confirmButtonText: translate('views.actions.delete')
cancelButtonText: translate('views.actions.cancel')
closeOnConfirm: true
, ->
$.ajax
@ -85,5 +86,5 @@ $(document).on "keyup", "input#new-group-name", (evt) ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->

View file

@ -14,7 +14,7 @@
del_all_btn[0].dataset.ibCount = (Number del_all_btn[0].dataset.ibCount) + 1
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
btn.button "reset"
@ -23,12 +23,13 @@
btn = ($ this)
count = btn[0].dataset.ibCount
swal
title: "Really delete #{count} questions?"
text: "They will be gone forever."
title: translate('frontend.inbox.confirm_all.title', {count: count})
text: translate('frontend.inbox.confirm_all.text')
type: "warning"
showCancelButton: true
confirmButtonColor: "#DD6B55"
confirmButtonText: "Delete"
confirmButtonText: translate('views.actions.delete')
cancelButtonText: translate('views.actions.cancel')
closeOnConfirm: true
, ->
btn.button "loading"
@ -47,7 +48,7 @@
entries.fadeIn()
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
if succ
# and now: a (broken?) re-implementation of Bootstrap's button.js
@ -87,7 +88,7 @@ $(document).on "click", "button[name=ib-answer]", ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
btn.button "reset"
$("textarea[name=ib-answer][data-id=#{iid}]").removeAttr "readonly"
@ -96,12 +97,13 @@ $(document).on "click", "button[name=ib-answer]", ->
$(document).on "click", "button[name=ib-destroy]", ->
btn = $(this)
swal
title: "Really delete?"
text: "This question will be gone forever."
title: translate('frontend.inbox.confirm.title')
text: translate('frontend.inbox.confirm.text')
type: "warning"
showCancelButton: true
confirmButtonColor: "#DD6B55"
confirmButtonText: "Delete"
confirmButtonText: translate('views.actions.delete')
cancelButtonText: translate('views.actions.cancel')
closeOnConfirm: true
, ->
btn.button "loading"
@ -118,7 +120,7 @@ $(document).on "click", "button[name=ib-destroy]", ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
btn.button "reset"
$("textarea[name=ib-answer][data-id=#{iid}]").removeAttr "readonly"
@ -137,4 +139,4 @@ $(document).on "click", "button[name=ib-options]", ->
btn[0].dataset.state = 'shown'
when 'shown'
optionBox.slideUp()
btn[0].dataset.state = 'hidden'
btn[0].dataset.state = 'hidden'

View file

@ -56,7 +56,7 @@ load = ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
$(document).on "DOMContentLoaded", ->

View file

@ -42,7 +42,7 @@ $(document).on "keyup", "input[name=mod-comment-new]", (evt) ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
input.removeAttr 'disabled'
@ -71,12 +71,13 @@ $(document).on "click", "a[data-action=mod-comment-destroy]", (ev) ->
btn = $(this)
cid = btn[0].dataset.id
swal
title: "Really delete?"
text: "You will not be able to recover this comment."
title: translate('frontend.destroy_comment.confirm.title')
text: translate('frontend.destroy_comment.confirm.text')
type: "warning"
showCancelButton: true
confirmButtonColor: "#DD6B55"
confirmButtonText: "Delete"
confirmButtonText: translate('views.actions.delete')
cancelButtonText: translate('views.actions.cancel')
closeOnConfirm: true
, ->
$.ajax
@ -90,5 +91,5 @@ $(document).on "click", "a[data-action=mod-comment-destroy]", (ev) ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->

View file

@ -2,12 +2,13 @@ $(document).on "click", "button[name=mod-delete-report]", ->
btn = $(this)
id = btn[0].dataset.id
swal
title: "Really delete?"
text: "You will not be able to recover this report."
title: translate('frontend.destroy_report.confirm.title')
text: translate('frontend.destroy_report.confirm.text')
type: "warning"
showCancelButton: true
confirmButtonColor: "#DD6B55"
confirmButtonText: "Delete"
confirmButtonText: translate('views.actions.delete')
cancelButtonText: translate('views.actions.cancel')
closeOnConfirm: true
, ->
$.ajax
@ -21,5 +22,5 @@ $(document).on "click", "button[name=mod-delete-report]", ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
complete: (jqxhr, status) ->
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->

View file

@ -19,6 +19,6 @@
error: (jqxhr, status, error) ->
box[0].checked = false
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
box.removeAttr "disabled"

View file

@ -26,7 +26,7 @@
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
if success
switch action
@ -43,4 +43,4 @@
console.log("vote for #{upvote ? 'downvote' : 'upvote'}")
other_btn = $ "button[name=mod-vote][data-id=#{id}][data-vote-type=#{if upvote then 'downvote' else 'upvote'}]"
other_btn.removeAttr 'disabled', 'disabled'
other_btn[0].dataset.action = 'vote'
other_btn[0].dataset.action = 'vote'

View file

@ -31,7 +31,7 @@ $(document).on "click", "button#q-answer", ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
btn.button "reset"
$("textarea#q-answer").removeAttr "readonly"

View file

@ -24,7 +24,7 @@ $(document).on "click", "button[name=qb-all-ask]", ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
btn.button "reset"
$("textarea[name=qb-all-question]").removeAttr "readonly"

View file

@ -3,13 +3,13 @@ $(document).on "click", "a[data-action=ab-question-destroy]", (ev) ->
btn = $(this)
qid = btn[0].dataset.qId
swal
title: "Are you sure?"
text: "The question will be removed."
title: translate('frontend.delete_own.confirm.title')
text: translate('frontend.delete_own.confirm.text')
type: "warning"
showCancelButton: true
confirmButtonColor: "#DD6B55"
confirmButtonText: "Yes"
cancelButtonText: "No"
confirmButtonText: translate('views.actions.y')
cancelButtonText: translate('views.actions.n')
closeOnConfirm: true
, ->
$.ajax
@ -26,5 +26,5 @@ $(document).on "click", "a[data-action=ab-question-destroy]", (ev) ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->

View file

@ -23,7 +23,7 @@ $(document).on "click", "button[name=qb-ask]", ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
btn.button "reset"
$("textarea[name=qb-question]").removeAttr "readonly"
@ -38,4 +38,4 @@ $(document).on "click", "button#new-question", ->
# see GitHub issue #2
($ document).on "keydown", "textarea[name=qb-question]", (evt) ->
if evt.keyCode == 13 and evt.ctrlKey
($ "button[name=qb-ask]").trigger 'click'
($ "button[name=qb-ask]").trigger 'click'

View file

@ -1,13 +1,14 @@
window.reportDialog = (type, target, callback) ->
swal
title: "Really report this #{type}?"
text: "A moderator will review your report and decide what happens.\nIf you'd like, you can also specify a reason."
title: translate('frontend.report.confirm.title', {type: type})
text: translate('frontend.report.confirm.text')
type: "input"
showCancelButton: true
confirmButtonColor: "#DD6B55"
confirmButtonText: "Report"
confirmButtonText: translate('views.actions.report')
cancelButtonText: translate('views.actions.cancel')
closeOnConfirm: true
inputPlaceholder: "Specify a reason..."
inputPlaceholder: translate('frontend.report.confirm.input')
, (value) ->
if typeof value == "boolean" && value == false
return false
@ -23,6 +24,6 @@ window.reportDialog = (type, target, callback) ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
callback type, target, jqxhr, status

View file

@ -30,7 +30,7 @@ $(document).on "click", "button[name=user-action]", ->
showNotification data.message, data.success
error: (jqxhr, status, error) ->
console.log jqxhr, status, error
showNotification "An error occurred, a developer should check the console for details", false
showNotification translate('frontend.error.message'), false
complete: (jqxhr, status) ->
btn.button "reset"
if success
@ -38,11 +38,11 @@ $(document).on "click", "button[name=user-action]", ->
when 'follow'
btn[0].dataset.action = 'unfollow'
btn.attr 'class', 'btn btn-default btn-block profile--follow-btn'
btn.html 'Unfollow'
btn.html translate('views.actions.unfollow')
when 'unfollow'
btn[0].dataset.action = 'follow'
btn.attr 'class', 'btn btn-primary btn-block profile--follow-btn'
btn.html 'Follow'
btn.html translate('views.actions.follow')
# report user

View file

@ -1,7 +1,7 @@
class Ajax::AnswerController < ApplicationController
rescue_from(ActionController::ParameterMissing) do |titanic_param|
@status = :parameter_error
@message = "#{titanic_param.param.capitalize} is required"
@message = I18n.t('messages.parameter_error', parameter: titanic_param.param.capitalize)
@success = false
render partial: "ajax/shared/status"
end
@ -19,7 +19,7 @@ class Ajax::AnswerController < ApplicationController
unless current_user == inbox_entry.user
@status = :fail
@message = "question not in your inbox"
@message = I18n.t('messages.answer.create.fail')
@success = false
return
end
@ -28,7 +28,7 @@ class Ajax::AnswerController < ApplicationController
unless question.user.privacy_allow_stranger_answers
@status = :privacy_stronk
@message = "This user does not want other users to answer their question."
@message = I18n.t('messages.answer.create.privacy_stronk')
@success = false
return
end
@ -37,7 +37,7 @@ class Ajax::AnswerController < ApplicationController
# this should never trigger because empty params throw ParameterMissing
unless params[:answer].length > 0
@status = :peter_dinklage
@message = "Answer is too short"
@message = I18n.t('messages.answer.create.peter_dinklage')
@success = false
return
end
@ -52,7 +52,7 @@ class Ajax::AnswerController < ApplicationController
end
rescue
@status = :err
@message = "An error occurred"
@message = I18n.t('messages.error')
@success = false
return
end
@ -62,7 +62,7 @@ class Ajax::AnswerController < ApplicationController
@status = :okay
@message = "Successfully answered question."
@message = I18n.t('messages.answer.create.okay')
@success = true
unless inbox
@question = 1
@ -77,7 +77,7 @@ class Ajax::AnswerController < ApplicationController
unless (current_user == answer.user) or (privileged? answer.user)
@status = :nopriv
@message = "can't delete other people's answers"
@message = I18n.t('messages.answer.destroy.nopriv')
@success = false
return
end
@ -88,7 +88,7 @@ class Ajax::AnswerController < ApplicationController
answer.destroy
@status = :okay
@message = "Successfully deleted answer."
@message = I18n.t('messages.answer.destroy.okay')
@success = true
end
end

View file

@ -1,7 +1,7 @@
class Ajax::CommentController < ApplicationController
rescue_from(ActionController::ParameterMissing) do |param_miss_ex|
@status = :parameter_error
@message = "#{param_miss_ex.param.capitalize} is required"
@message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize)
@success = false
render partial: "ajax/shared/status"
end
@ -16,13 +16,13 @@ class Ajax::CommentController < ApplicationController
current_user.comment(answer, params[:comment])
rescue ActiveRecord::RecordInvalid
@status = :rec_inv
@message = "Your comment is too long."
@message = I18n.t('messages.comment.create.rec_inv')
@success = false
return
end
@status = :okay
@message = "Comment posted successfully."
@message = I18n.t('messages.comment.create.okay')
@success = true
@render = render_to_string(partial: 'shared/comments', locals: { a: answer })
@count = answer.comment_count
@ -37,7 +37,7 @@ class Ajax::CommentController < ApplicationController
unless (current_user == comment.user) or (current_user == comment.answer.user) or (privileged? comment.user)
@status = :nopriv
@message = "can't delete other people's comments"
@message = I18n.t('messages.comment.destroy.nopriv')
@success = false
return
end
@ -46,7 +46,7 @@ class Ajax::CommentController < ApplicationController
comment.destroy
@status = :okay
@message = "Successfully deleted comment."
@message = I18n.t('messages.comment.destroy.okay')
@success = true
end
end

View file

@ -1,7 +1,7 @@
class Ajax::FriendController < ApplicationController
rescue_from(ActionController::ParameterMissing) do |param_miss_ex|
@status = :parameter_error
@message = "#{param_miss_ex.param.capitalize} is required"
@message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize)
@success = false
render partial: "ajax/shared/status"
end
@ -15,13 +15,13 @@ class Ajax::FriendController < ApplicationController
current_user.follow target_user
rescue
@status = :fail
@message = "You are already following that user."
@message = I18n.t('messages.friend.create.fail')
@success = false
return
end
@status = :okay
@message = "Successfully followed user."
@message = I18n.t('messages.friend.create.okay')
@success = true
end
@ -34,13 +34,13 @@ class Ajax::FriendController < ApplicationController
current_user.unfollow target_user
rescue
@status = :fail
@message = "You are not following that user."
@message = I18n.t('messages.friend.destroy.fail')
@success = false
return
end
@status = :okay
@message = "Successfully unfollowed user."
@message = I18n.t('messages.friend.destroy.okay')
@success = true
end
end

View file

@ -1,7 +1,7 @@
class Ajax::GroupController < ApplicationController
rescue_from(ActionController::ParameterMissing) do |param_miss_ex|
@status = :parameter_error
@message = "#{param_miss_ex.param.capitalize} is required"
@message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize)
@success = false
render partial: "ajax/shared/status"
end
@ -12,7 +12,7 @@ class Ajax::GroupController < ApplicationController
unless user_signed_in?
@status = :noauth
@message = "requires authentication"
@message = I18n.t('messages.noauth')
return
end
@ -20,7 +20,7 @@ class Ajax::GroupController < ApplicationController
params.require :name
rescue ActionController::ParameterMissing
@status = :toolong
@message = "Please give that group a name."
@message = I18n.t('messages.group.create.noname')
return
end
params.require :user
@ -30,21 +30,21 @@ class Ajax::GroupController < ApplicationController
group = Group.create! user: current_user, display_name: params[:name]
rescue ActiveRecord::RecordInvalid
@status = :toolong
@message = "Group name too long (30 characters max.)"
@message = I18n.t('messages.group.create.toolong')
return
rescue ActiveRecord::RecordNotFound
@status = :notfound
@message = "Could not find user."
@message = I18n.t('messages.group.create.notfound')
return
rescue ActiveRecord::RecordNotUnique
@status = :exists
@message = "Group already exists."
@message = I18n.t('messages.group.create.exists')
return
end
@status = :okay
@success = true
@message = "Successfully created group."
@message = I18n.t('messages.group.create.okay')
@render = render_to_string(partial: 'user/modal_group_item', locals: { group: group, user: target_user })
end
@ -54,7 +54,7 @@ class Ajax::GroupController < ApplicationController
unless user_signed_in?
@status = :noauth
@message = "requires authentication"
@message = I18n.t('messages.noauth')
return
end
@ -64,13 +64,13 @@ class Ajax::GroupController < ApplicationController
Group.where(user: current_user, name: params[:group]).first.destroy!
rescue ActiveRecord::RecordNotFound
@status = :notfound
@message = "Could not find group."
@message = I18n.t('messages.group.destroy.notfound')
return
end
@status = :okay
@success = true
@message = "Successfully deleted group."
@message = I18n.t('messages.group.destroy.okay')
end
def membership
@ -79,7 +79,7 @@ class Ajax::GroupController < ApplicationController
unless user_signed_in?
@status = :noauth
@message = "requires authentication"
@message = I18n.t('messages.noauth')
return
end
@ -93,7 +93,7 @@ class Ajax::GroupController < ApplicationController
group = current_user.groups.find_by_name(params[:group])
rescue ActiveRecord::RecordNotFound
@status = :notfound
@message = "Group not found."
@message = I18n.t('messages.group.membership.notfound')
return
end
@ -102,11 +102,11 @@ class Ajax::GroupController < ApplicationController
if add
group.add_member target_user if group.members.find_by_user_id(target_user.id).nil?
@checked = true
@message = "Successfully added user to group."
@message = I18n.t('messages.group.membership.add')
else
group.remove_member target_user unless group.members.find_by_user_id(target_user.id).nil?
@checked = false
@message = "Successfully removed user from group."
@message = I18n.t('messages.group.membership.remove')
end
@status = :okay

View file

@ -1,7 +1,7 @@
class Ajax::InboxController < ApplicationController
rescue_from(ActionController::ParameterMissing) do |param_miss_ex|
@status = :parameter_error
@message = "#{param_miss_ex.param.capitalize} is required"
@message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize)
@success = false
render partial: "ajax/shared/status"
end
@ -9,7 +9,7 @@ class Ajax::InboxController < ApplicationController
def create
unless user_signed_in?
@status = :noauth
@message = "requires authentication"
@message = I18n.t('messages.noauth')
@success = false
return
end
@ -22,7 +22,7 @@ class Ajax::InboxController < ApplicationController
inbox = Inbox.create!(user: current_user, question_id: question.id, new: true)
@status = :okay
@message = "Successfully added new question."
@message = I18n.t('messages.inbox.create.okay')
@success = true
@render = render_to_string(partial: 'inbox/entry', locals: { i: inbox })
inbox.update(new: false)
@ -35,7 +35,7 @@ class Ajax::InboxController < ApplicationController
unless current_user == inbox.user
@status = :fail
@message = "question not in your inbox"
@message = I18n.t('messages.inbox.remove.fail')
@success = false
return
end
@ -44,13 +44,13 @@ class Ajax::InboxController < ApplicationController
inbox.remove
rescue
@status = :err
@message = "An error occurred"
@message = I18n.t('messages.error')
@success = false
return
end
@status = :okay
@message = "Successfully deleted question."
@message = I18n.t('messages.inbox.remove.okay')
@success = true
end
@ -59,13 +59,13 @@ class Ajax::InboxController < ApplicationController
Inbox.where(user: current_user).each { |i| i.remove }
rescue
@status = :err
@message = "An error occurred"
@message = I18n.t('messages.error')
@success = false
return
end
@status = :okay
@message = "Successfully deleted questions."
@message = I18n.t('messages.inbox.remove_all.okay')
@success = true
render 'ajax/inbox/remove'
end

View file

@ -1,7 +1,7 @@
class Ajax::ModerationController < ApplicationController
rescue_from(ActionController::ParameterMissing) do |param_miss_ex|
@status = :parameter_error
@message = "#{param_miss_ex.param.capitalize} is required"
@message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize)
@success = false
render partial: "ajax/shared/status"
end
@ -16,14 +16,14 @@ class Ajax::ModerationController < ApplicationController
current_user.report_vote(report, params[:upvote])
rescue
@status = :fail
@message = "You have already voted on this report."
@message = I18n.t('messages.moderation.vote.fail')
@success = false
return
end
@count = report.votes
@status = :okay
@message = "Successfully voted on report."
@message = I18n.t('messages.moderation.vote.okay')
@success = true
end
@ -36,14 +36,14 @@ class Ajax::ModerationController < ApplicationController
current_user.report_unvote report
rescue
@status = :fail
@message = "You have not voted on that report."
@message = I18n.t('messages.moderation.destroy_vote.fail')
@success = false
return
end
@count = report.votes
@status = :okay
@message = "Successfully removed vote from report."
@message = I18n.t('messages.moderation.destroy_vote.okay')
@success = true
end
@ -57,13 +57,13 @@ class Ajax::ModerationController < ApplicationController
report.save
rescue
@status = :fail
@message = "Something bad happened!"
@message = I18n.t('messages.moderation.destroy_report.fail')
@success = false
return
end
@status = :okay
@message = "WHERE DID IT GO??? OH NO!!!"
@message = I18n.t('messages.moderation.destroy_report.okay')
@success = true
end
@ -79,12 +79,12 @@ class Ajax::ModerationController < ApplicationController
current_user.report_comment(report, params[:comment])
rescue ActiveRecord::RecordInvalid
@status = :rec_inv
@message = "Your comment is too long."
@message = I18n.t('messages.moderation.create_comment.rec_inv')
return
end
@status = :okay
@message = "Comment posted successfully."
@message = I18n.t('messages.moderation.create_comment.okay')
@success = true
@render = render_to_string(partial: 'moderation/discussion', locals: { report: report })
@count = report.moderation_comments.all.count
@ -99,7 +99,7 @@ class Ajax::ModerationController < ApplicationController
unless current_user == comment.user
@status = :nopriv
@message = "can't delete other people's comments"
@message = I18n.t('messages.moderation.destroy_comment.nopriv')
@success = false
return
end
@ -107,13 +107,13 @@ class Ajax::ModerationController < ApplicationController
comment.destroy
@status = :okay
@message = "Successfully deleted comment."
@message = I18n.t('messages.moderation.destroy_comment.okay')
@success = true
end
def ban
@status = :err
@message = "Weird..."
@message = I18n.t('messages.moderation.ban.error')
@success = false
params.require :user
@ -129,21 +129,21 @@ class Ajax::ModerationController < ApplicationController
if not unban and target.admin?
@status = :nopriv
@message = "You cannot ban an administrator!"
@message = I18n.t('messages.moderation.ban.nopriv')
@success = false
return
end
if unban
target.unban
@message = "Unbanned user."
@message = I18n.t('messages.moderation.ban.unban')
@success = true
elsif perma
target.ban nil, reason
@message = "Permanently banned user."
@message = I18n.t('messages.moderation.ban.perma')
else
target.ban buntil, reason
@message = "Banned user until #{buntil.to_s}"
@message = I18n.t('messages.moderation.ban.temp', date: buntil.to_s)
end
target.save!
@ -163,12 +163,12 @@ class Ajax::ModerationController < ApplicationController
target_user = User.find_by_screen_name(params[:user])
@message = "nope!"
@message = I18n.t('messages.moderation.privilege.nope')
return unless %w(blogger supporter moderator admin contributor).include? params[:type].downcase
if %w(supporter moderator admin).include?(params[:type].downcase) and !current_user.admin?
@status = :nopriv
@message = "You'd better check YOUR privileges first!"
@message = I18n.t('messages.moderation.privilege.nopriv')
@success = false
return
end
@ -177,7 +177,7 @@ class Ajax::ModerationController < ApplicationController
target_user.send("#{params[:type]}=", status)
target_user.save!
@message = "Successfully checked this user's #{params[:type]} privilege."
@message = I18n.t('messages.moderation.privilege.checked', privilege: params[:type])
@status = :okay
@success = true

View file

@ -3,7 +3,7 @@ class Ajax::QuestionController < ApplicationController
rescue_from(ActionController::ParameterMissing) do |param_miss_ex|
@status = :parameter_error
@message = "#{param_miss_ex.param.capitalize} is required"
@message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize)
@success = false
render partial: "ajax/shared/status"
end
@ -14,14 +14,14 @@ class Ajax::QuestionController < ApplicationController
question = Question.find params[:question]
if question.nil?
@status = :not_found
@message = "Question does not exist"
@message = I18n.t('messages.question.destroy.not_found')
@success = false
return
end
if not (current_user.mod? or question.user == current_user)
@status = :not_authorized
@message = "You are not allowed to delete this question"
@message = I18n.t('messages.question.destroy.not_authorized')
@success = false
return
end
@ -29,7 +29,7 @@ class Ajax::QuestionController < ApplicationController
question.destroy!
@status = :okay
@message = "Successfully deleted question."
@message = I18n.t('messages.question.destroy.okay')
@success = true
end
@ -44,7 +44,7 @@ class Ajax::QuestionController < ApplicationController
user: current_user)
rescue ActiveRecord::RecordInvalid
@status = :rec_inv
@message = "Your question is too long."
@message = I18n.t('messages.question.create.rec_inv')
@success = false
return
end
@ -67,7 +67,7 @@ class Ajax::QuestionController < ApplicationController
end
rescue ActiveRecord::RecordNotFound
@status = :not_found
@message = "Group not found"
@message = I18n.t('messages.question.create.not_found')
@success = false
return
end
@ -77,17 +77,17 @@ class Ajax::QuestionController < ApplicationController
end
@status = :okay
@message = "Question asked successfully."
@message = I18n.t('messages.question.create.okay')
@success = true
end
def preview
params.require :md
@message = "Failed to render markdown."
@message = I18n.t('messages.question.preview.fail')
begin
@markdown = markdown params[:md]
@message = "Successfully rendered markdown."
@message = I18n.t('messages.question.preview.okay')
rescue
@status = :fail
@success = false

View file

@ -1,7 +1,7 @@
class Ajax::ReportController < ApplicationController
rescue_from(ActionController::ParameterMissing) do |param_miss_ex|
@status = :parameter_error
@message = "#{param_miss_ex.param.capitalize} is required"
@message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize)
@success = false
render partial: "ajax/shared/status"
end
@ -14,12 +14,12 @@ class Ajax::ReportController < ApplicationController
@success = false
if current_user.nil?
@message = "login required"
@message = I18n.t('messages.report.create.login')
return
end
unless %w(answer comment question user).include? params[:type]
@message = "unknown type"
@message = I18n.t('messages.report.create.unknown')
return
end
@ -30,14 +30,14 @@ class Ajax::ReportController < ApplicationController
end
if object.nil?
@message = "Could not find #{params[:type]}"
@message = I18n.t('messages.report.create.not_found', parameter: params[:type])
return
end
current_user.report object, params[:reason]
@status = :okay
@message = "#{params[:type].capitalize} reported. A moderator will decide what happens with the #{params[:type]}."
@message = I18n.t('messages.report.create.okay', parameter: params[:type])
@success = true
end
end

View file

@ -1,7 +1,7 @@
class Ajax::SmileController < ApplicationController
rescue_from(ActionController::ParameterMissing) do |param_miss_ex|
@status = :parameter_error
@message = "#{param_miss_ex.param.capitalize} is required"
@message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize)
@success = false
render partial: "ajax/shared/status"
end
@ -15,13 +15,13 @@ class Ajax::SmileController < ApplicationController
current_user.smile answer
rescue
@status = :fail
@message = "You have already smiled that answer."
@message = I18n.t('messages.smile.create.fail')
@success = false
return
end
@status = :okay
@message = "Successfully smiled answer."
@message = I18n.t('messages.smile.create.okay')
@success = true
end
@ -34,13 +34,13 @@ class Ajax::SmileController < ApplicationController
current_user.unsmile answer
rescue
@status = :fail
@message = "You have not smiled that answer."
@message = I18n.t('messages.smile.destroy.fail')
@success = false
return
end
@status = :okay
@message = "Successfully unsmiled answer."
@message = I18n.t('messages.smile.destroy.okay')
@success = true
end
@ -53,13 +53,13 @@ class Ajax::SmileController < ApplicationController
current_user.smile_comment comment
rescue
@status = :fail
@message = "You have already smiled that comment."
@message = I18n.t('messages.smile.create_comment.fail')
@success = false
return
end
@status = :okay
@message = "Successfully smiled comment."
@message = I18n.t('messages.smile.create_comment.okay')
@success = true
end
@ -72,13 +72,13 @@ class Ajax::SmileController < ApplicationController
current_user.unsmile_comment comment
rescue
@status = :fail
@message = "You have not smiled that comment."
@message = I18n.t('messages.smile.destroy_comment.fail')
@success = false
return
end
@status = :okay
@message = "Successfully unsmiled comment."
@message = I18n.t('messages.smile.destroy_comment.okay')
@success = true
end
end

View file

@ -2,7 +2,7 @@ class Ajax::SubscriptionController < ApplicationController
before_filter :authenticate_user!
rescue_from(ActionController::ParameterMissing) do |param_miss_ex|
@status = :parameter_error
@message = "#{param_miss_ex.param.capitalize} is required"
@message = I18n.t('messages.parameter_error', parameter: param_miss_ex.param.capitalize)
@success = false
render partial: "ajax/shared/status"
end
@ -10,7 +10,7 @@ class Ajax::SubscriptionController < ApplicationController
def subscribe
params.require :answer
@status = 418
@message = "418 I'm a torpedo"
@message = I18n.t('messages.subscription.torpedo')
state = Subscription.subscribe(current_user, Answer.find(params[:answer])).nil?
@success = state == false
end
@ -18,7 +18,7 @@ class Ajax::SubscriptionController < ApplicationController
def unsubscribe
params.require :answer
@status = 418
@message = "418 I'm a torpedo"
@message = I18n.t('messages.subscription.torpedo')
state = Subscription.unsubscribe(current_user, Answer.find(params[:answer])).nil?
@success = state == false
end

View file

@ -4,20 +4,44 @@ class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_filter :configure_permitted_parameters, if: :devise_controller?
before_filter :check_locale
before_filter :banned?
# check if user wants to read
def check_locale
return I18n.locale = 'en' if Rails.env.test?
if params[:hl].nil?
if current_user.present?
I18n.locale = current_user.locale
elsif not cookies[:hl].nil?
I18n.locale = cookies[:hl]
elsif not http_accept_language.user_preferred_languages.length > 0
I18n.locale = http_accept_language.compatible_language_from(I18n.available_locales) or "en"
end
else
I18n.locale = params[:hl]
if current_user.present?
current_user.locale = I18n.locale
current_user.save!
end
end
cookies[:hl] = I18n.locale #unless cookies[:allow_cookies].nil? # some EU cookie bullsh-
end
# check if user got hit by the banhammer of doom
def banned?
if current_user.present? && current_user.banned?
name = current_user.screen_name
# obligatory '2001: A Space Odyssey' reference
flash[:notice] = "I'm sorry, #{name}, I'm afraid I can't do that."
flash[:notice] = t('flash.ban.error', name: name)
unless current_user.ban_reason.nil?
flash[:notice] += "\nBan reason: #{current_user.ban_reason}"
flash[:notice] += "\n#{t('flash.ban.reason', reason: current_user.ban_reason)}"
end
if not current_user.permanently_banned?
# TODO format banned_until
flash[:notice] += "\nBanned until: #{current_user.banned_until}"
flash[:notice] += "\n#{t('flash.ban.until', time: current_user.banned_until)}"
end
sign_out current_user
redirect_to new_user_session_path

View file

@ -11,9 +11,9 @@ class ServicesController < ApplicationController
service = Service.initialize_from_omniauth( omniauth_hash )
if current_user.services << service
flash[:success] = 'Successfully added service'
flash[:success] = t('flash.service.create.success')
else
flash[:error] = 'Could not add service :('
flash[:error] = t('flash.service.create.error')
end
if origin
@ -25,14 +25,14 @@ class ServicesController < ApplicationController
def failure
Rails.logger.info "oauth error: #{params.inspect}"
flash[:error] = 'An error occurred'
flash[:error] = t('flash.service.failure')
redirect_to services_path
end
def destroy
@service = current_user.services.find(params[:id])
@service.destroy
flash[:success] = 'Successfully removed service'
flash[:success] = t('flash.service.destroy')
redirect_to services_path
end

View file

@ -27,12 +27,12 @@ class UserController < ApplicationController
user_attributes = params.require(:user).permit(:display_name, :profile_picture, :profile_header, :motivation_header, :website,
:location, :bio, :crop_x, :crop_y, :crop_w, :crop_h, :crop_h_x, :crop_h_y, :crop_h_w, :crop_h_h)
if current_user.update_attributes(user_attributes)
text = 'Your profile has been updated!'
text += ' It might take a few minutes until your new profile picture is shown everywhere.' if user_attributes[:profile_picture]
text += ' It might take a few minutes until your new profile header is shown everywhere.' if user_attributes[:profile_header]
text = t('flash.user.update.text')
text += t('flash.user.update.avatar') if user_attributes[:profile_picture]
text += t('flash.user.update.header') if user_attributes[:profile_header]
flash[:success] = text
else
flash[:error] = 'An error occurred. ;_;'
flash[:error] = t('flash.user.update.error')
end
redirect_to edit_user_profile_path
end
@ -48,9 +48,9 @@ class UserController < ApplicationController
:privacy_allow_stranger_answers,
:privacy_show_in_search)
if current_user.update_attributes(user_attributes)
flash[:success] = 'Your privacy settings have been updated!'
flash[:success] = t('flash.user.update_privacy.success')
else
flash[:error] = 'An error occurred. ;_;'
flash[:error] = t('flash.user.update_privacy.error')
end
redirect_to edit_user_privacy_path
end

View file

@ -39,6 +39,22 @@ module ApplicationHelper
content_tag(:a, body.html_safe, href: path, class: ("list-group-item #{'active ' if current_page? path}#{options[:class]}"))
end
def tooltip(body, tooltip_content, placement = "bottom")
content_tag(:span, body, {title: tooltip_content, "data-toggle" => "tooltip", "data-placement" => placement} )
end
def time_tooltip(subject, placement = "bottom")
t = tooltip time_ago_in_words(subject.created_at), localize(subject.created_at), placement
unless subject.user.nil? or (subject.respond_to?(:author_is_anonymous) and subject.author_is_anonymous)
t = content_tag(:a, t, {href: show_user_question_path(subject.user.screen_name, subject.id)})
end
t
end
def hidespan(body, hide)
content_tag(:span, body, class: "hidden-#{hide}")
end
##
#
def bootstrap_color c

View file

@ -1,18 +1,17 @@
- provide(:title, generate_title("Sign Up"))
.container
%h1 Sign up
%h1= t('views.sessions.new')
= bootstrap_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f|
= devise_error_messages!
= f.text_field :screen_name, autofocus: true, label: "User name"
= f.email_field :email, autofocus: false, label: "Email address"
= f.text_field :screen_name, autofocus: true, label: t('views.settings.account.username')
= f.email_field :email, autofocus: false, label: t('views.settings.account.email')
= f.password_field :password, autocomplete: "off", label: "Password"
= f.password_field :password_confirmation, autocomplete: "off", label: "Confirm password"
= f.password_field :password, autocomplete: "off", label: t('views.settings.account.password')
= f.password_field :password_confirmation, autocomplete: "off", label: t('views.settings.account.password_confirm')
%p
With signing up you accept our
%p= raw t('views.sessions.info', terms: link_to(t('views.general.terms'), terms_path))
= link_to "Terms of Service", terms_path
= f.submit "Sign up"

View file

@ -1,17 +1,17 @@
- provide(:title, generate_title("Sign In"))
.container
%h1 Sign in
%h1= t('views.sessions.create')
= render 'layouts/messages'
= bootstrap_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f|
= f.text_field :login, autofocus: true, label: "User name"
= f.password_field :password, autocomplete: "off", label: "Password"
= f.text_field :login, autofocus: true, label: t('views.settings.account.username')
= f.password_field :password, autocomplete: "off", label: t('views.settings.account.password')
- if devise_mapping.rememberable?
= f.check_box :remember_me
= f.submit "Sign in"
= f.submit t('views.sessions.create')
= render "devise/shared/links"
= render "shared/links"

View file

@ -15,12 +15,8 @@
%span.text-muted= "@#{u.screen_name}"
%p.answerbox--question-text
- if type == "new"
registered
= time_ago_in_words(u.created_at)
ago
= t('views.discover.userbox.new', time: time_ago_in_words(u.created_at))
- elsif type == "most"
answered
= pluralize(a, "question")
= t('views.discover.userbox.answers', questions: pluralize(a, t('views.general.question')))
- else
asked
= pluralize(q, "question")
= t('views.discover.userbox.answers', questions: pluralize(q, t('views.general.question')))

View file

@ -2,45 +2,36 @@
.jumbotron.j2-jumbo.text-center.particle-jumbotron
#particles
.particle-content
%h1 Discover
%p
The perfect place to find interesting content from the last week on
= succeed '!' do
= APP_CONFIG['site_name']
%h1= t 'views.discover.title'
%p= t('views.discover.subtitle', app_title: APP_CONFIG['site_name'])
.container
.row
.col-md-7.col-sm-6
%h2 Popular Content
%p Answers with most smiles and most answered questions
%h2= t 'views.discover.content.title'
%p= t 'views.discover.content.desc'
%div{role: "tabpanel"}
%ul.nav.nav-tabs{role: "tablist"}
%li.active{role: "presentation"}
%a{href: "#answers", role: "tab", aria: {controls: "answers"}, data: {toggle: "tab"}}
Most Liked
%a{href: "#answers", role: "tab", aria: {controls: "answers"}, data: {toggle: "tab"}}= t 'views.discover.content.tab.answers'
%li{role: "presentation"}
%a{href: "#questions", role: "tab", aria: {controls: "questions"}, data: {toggle: "tab"}}
Most Answers
%a{href: "#questions", role: "tab", aria: {controls: "questions"}, data: {toggle: "tab"}}= t 'views.discover.content.tab.questions'
%li{role: "presentation"}
%a{href: "#comments", role: "tab", aria: {controls: "comments"}, data: {toggle: "tab"}}
Most Controversial
%a{href: "#comments", role: "tab", aria: {controls: "comments"}, data: {toggle: "tab"}}= t 'views.discover.content.tab.comments'
.tab-content.discover
= render 'discover/tab_answers', answers: @popular_answers
= render 'discover/tab_questions', questions: @popular_questions
= render 'discover/tab_discussed', comments: @most_discussed
.col-md-5.col-sm-6
%h2 People
%p Newcomers and people who asked the most questions
%h2= t 'views.discover.people.title'
%p= t 'views.discover.people.desc'
%div{role: "tabpanel"}
%ul.nav.nav-tabs{role: "tablist"}
%li.active{role: "presentation"}
%a{href: "#new", role: "tab", aria: {controls: "new"}, data: {toggle: "tab"}}
New Users
%a{href: "#new", role: "tab", aria: {controls: "new"}, data: {toggle: "tab"}}= t 'views.discover.people.tab.new'
%li{role: "presentation"}
%a{href: "#asked", role: "tab", aria: {controls: "asked"}, data: {toggle: "tab"}}
Active Askers
%a{href: "#asked", role: "tab", aria: {controls: "asked"}, data: {toggle: "tab"}}= t 'views.discover.people.tab.questions'
%li{role: "presentation"}
%a{href: "#answered", role: "tab", aria: {controls: "answered"}, data: {toggle: "tab"}}
Most Answers
%a{href: "#answered", role: "tab", aria: {controls: "answered"}, data: {toggle: "tab"}}= t 'views.discover.people.tab.answers'
.tab-content.discover
= render 'discover/tab_new', new: @new_users
= render 'discover/tab_asked', asked: @users_with_most_questions

View file

@ -14,5 +14,5 @@
- if @timeline.next_page
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @timeline.current_page }}
Load more
= t 'views.actions.load'
.visible-xs= render 'shared/links'

View file

@ -6,39 +6,31 @@
%img.img-rounded.answerbox--img{src: gravatar_url(i.question.user)}
.media-body
%h6.text-muted.media-heading.answerbox--question-user
= user_screen_name i.question.user, i.question.author_is_anonymous
asked
%span{title: i.question.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words(i.question.created_at)
ago
= raw t('views.inbox.entry.asked', user: user_screen_name(i.question.user, i.question.author_is_anonymous), time: time_tooltip(i.question))
- unless i.question.author_is_anonymous
- if i.question.answer_count > 0
·
%a{href: show_user_question_path(i.question.user.screen_name, i.question.id)}
#{i.question.answer_count} response(s)
= pluralize(i.question.answer_count, t('views.inbox.entry.response'))
%p.answerbox--question-text= i.question.content
.panel-body
%textarea.form-control{name: 'ib-answer', placeholder: 'Write your answer here...', data: { id: i.id }}
%textarea.form-control{name: 'ib-answer', placeholder: t('views.placeholder.inbox'), data: { id: i.id }}
%br/
%button.btn.btn-success{name: 'ib-answer', data: { ib_id: i.id }}
Answer
= t 'views.actions.answer'
%button.btn.btn-danger{name: 'ib-destroy', data: { ib_id: i.id }}
Delete
= t 'views.actions.delete'
%button.btn.btn-default{name: 'ib-options', data: { ib_id: i.id, state: :hidden }}
%i.fa.fa-cog
%span.sr-only Options
%span.sr-only= t 'views.actions.options'
.panel-footer{id: "ib-options-#{i.id}", style: 'display: none'}
%h4 Sharing
%h4= t 'views.inbox.entry.sharing.title'
- if current_user.services.count > 0
.row
- current_user.services.each do |service|
.col-md-3.col-sm-4.col-xs-6
%label
%input{type: 'checkbox', name: 'ib-share', checked: :checked, data: { ib_id: i.id, service: service.provider }}
Post to
= service.provider.capitalize
= raw t('views.inbox.entry.sharing.post', service: service.provider.capitalize)
- else
%p
You have not connected any services yet. Visit your
= link_to "service settings", services_path
to connect one.
%p= raw t('views.inbox.entry.sharing.none', settings: link_to(t('views.inbox.entry.sharing.settings'), services_path))

View file

@ -1,20 +1,20 @@
.panel.panel-default.inbox--panel
.panel-heading
%h3.panel-title Out of questions?
%h3.panel-title= t 'views.inbox.sidebar.questions.title'
.panel-body
%button.btn.btn-block.btn-info{type: :button, id: 'ib-generate-question'} Get new question
%button.btn.btn-block.btn-info{type: :button, id: 'ib-generate-question'}= t 'views.inbox.sidebar.questions.button'
.panel.panel-default.inbox--panel
.panel-heading
%h3.panel-title Share
%h3.panel-title= t 'views.inbox.sidebar.share.title'
.panel-body
%a.btn.btn-block.btn-primary{target: '_blank', href: "https://twitter.com/intent/tweet?text=Ask%20me%20anything%21&url=#{show_user_profile_url(current_user.screen_name)}"}
%i.fa.fa-twitter
Share on Twitter
%i.fa.fa-fw.fa-twitter
= raw t('views.inbox.sidebar.share.button', service: "Twitter")
%a.btn.btn-block.btn-primary{target: '_blank', href: "http://www.tumblr.com/share/link?url=#{show_user_profile_url(current_user.screen_name)}&name=Ask%20me%20anything%21"}
%i.fa.fa-tumblr
Share on Tumblr
%i.fa.fa-fw.fa-tumblr
= raw t('views.inbox.sidebar.share.button', service: "Tumblr")
.panel.panel-default.warning--panel
.panel-heading
%h3.panel-title Actions
%h3.panel-title= t 'views.inbox.sidebar.actions.title'
.panel-body
%button.btn.btn-block.btn-danger{type: :button, id: 'ib-delete-all', disabled: (Inbox.where(user: current_user).empty? ? 'disabled' : nil), data: { ib_count: Inbox.where(user: current_user).count }} Delete all questions
%button.btn.btn-block.btn-danger{type: :button, id: 'ib-delete-all', disabled: (Inbox.where(user: current_user).empty? ? 'disabled' : nil), data: { ib_count: Inbox.where(user: current_user).count }}= t 'views.inbox.sidebar.actions.button'

View file

@ -10,13 +10,13 @@
= render 'inbox/entry', i: i
- if @inbox.empty?
Nothing to see here.
= t 'views.inbox.empty'
#pagination= will_paginate @inbox, renderer: BootstrapPagination::Rails, page_links: false
- if @inbox.next_page
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @inbox.current_page }}
Load more
= t 'views.actions.load'
.col-md-9.col-xs-12.col-sm-9.visible-xs
= render 'inbox/sidebar'

View file

@ -20,25 +20,25 @@
#j2-main-navbar-collapse.collapse.navbar-collapse
- if user_signed_in?
%ul.nav.navbar-nav
= nav_entry "Timeline", root_path
= nav_entry "Inbox", "/inbox", badge: inbox_count
= nav_entry "Discover", discover_path
= nav_entry t('views.navigation.timeline'), root_path
= nav_entry t('views.navigation.inbox'), "/inbox", badge: inbox_count
= nav_entry t('views.navigation.discover'), discover_path
%ul.nav.navbar-nav.navbar-right
- unless @user.nil?
- unless @user == current_user
%li.hidden-xs{"data-toggle" => "tooltip", "data-placement" => "bottom", title: "Manage group memberships"}
%li.hidden-xs{"data-toggle" => "tooltip", "data-placement" => "bottom", title: t('views.actions.group')}
%a{href: '#', data: { target: "#modal-group-memberships", toggle: :modal }}
%i.fa.fa-users.hidden-xs
%span.visible-xs Manage group memberships
%span.visible-xs= t('views.actions.group')
= render "layouts/notifications"
%li.hidden-xs{"data-toggle" => "tooltip", "data-placement" => "bottom", title: "Ask a question"}
%li.hidden-xs{"data-toggle" => "tooltip", "data-placement" => "bottom", title: t('views.actions.ask_question')}
.btn.btn-link.navbar-btn{name: "toggle-all-ask", "data-target" => "#modal-ask-followers", "data-toggle" => "modal", :type => "button"}
%i.fa.fa-pencil-square-o
= render "layouts/profile"
- else
%ul.nav.navbar-nav.navbar-right
= nav_entry "Sign in", new_user_session_path
= nav_entry "Sign up", new_user_registration_path
= nav_entry t('views.sessions.create'), new_user_session_path
= nav_entry t('views.sessions.new'), new_user_registration_path
- if user_signed_in?
= render 'shared/modal_ask_followers'

View file

@ -1,10 +1,10 @@
%noscript
.alert.alert-danger
Please activate JavaScript.
= t 'messages.noscript'
- flash.each do |key, value|
.alert.alert-dismissible{class: "alert-#{bootstrap_color key}", role: "alert"}
%button.close{type: "button", "data-dismiss" => "alert"}
%span{"aria-hidden" => "true"} &times;
%span.sr-only Close
= value
%span.sr-only= t 'views.actions.close'
= value

View file

@ -1,4 +1,4 @@
= nav_entry "Notifications", notifications_path, badge: notification_count, class: 'visible-xs'
= nav_entry t('views.navigation.notifications'), notifications_path, badge: notification_count, class: 'visible-xs'
- notifications = Notification.for(current_user).limit(4)
%li.dropdown.hidden-xs
%a.dropdown-toggle{href: "#", "data-toggle" => "dropdown"}
@ -23,11 +23,7 @@
%h6.media-heading.notification--dropdown-user
= user_screen_name notification.target.user
.notification--dropdown-text
answered
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.id), title: "#{notification.target.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
your question
= time_ago_in_words notification.target.created_at
ago
= raw t('views.notifications.answer.body', question: link_to(t('views.notifications.answer.question'), show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.id)), time: time_ago_in_words(notification.target.created_at))
- when "Relationship"
.pull-left
%img.img-rounded.notification--dropdown-img{src: gravatar_url(notification.target.source)}
@ -35,9 +31,7 @@
%h6.media-heading.notification--dropdown-user
= user_screen_name notification.target.source
.notification--dropdown-text
followed you
= time_ago_in_words notification.target.created_at
ago
= raw t('views.notifications.relationship.body', time: time_ago_in_words(notification.target.created_at))
- when "Smile"
.pull-left
%img.img-rounded.notification--dropdown-img{src: gravatar_url(notification.target.user)}
@ -45,11 +39,7 @@
%h6.media-heading.notification--dropdown-user
= user_screen_name notification.target.user
.notification--dropdown-text
smiled at
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id), title: "#{notification.target.answer.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
your answer
= time_ago_in_words notification.target.created_at
ago
= raw t('views.notifications.smile.body', content: link_to(t('views.notifications.smile.answer'), show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id)), time: time_ago_in_words(notification.target.created_at))
- when "CommentSmile"
.pull-left
%img.img-rounded.notification--dropdown-img{src: gravatar_url(notification.target.user)}
@ -57,11 +47,7 @@
%h6.media-heading.notification--dropdown-user
= user_screen_name notification.target.user
.notification--dropdown-text
smiled at
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.comment.answer.id), title: "#{notification.target.comment.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
your comment
= time_ago_in_words notification.target.created_at
ago
= raw t('views.notifications.smile.body', content: link_to(t('views.notifications.smile.comment'), show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id)), time: time_ago_in_words(notification.target.created_at))
- when "Comment"
.pull-left
%img.img-rounded.notification--dropdown-img{src: gravatar_url(notification.target.user)}
@ -69,15 +55,10 @@
%h6.media-heading.notification--dropdown-user
= user_screen_name notification.target.user
.notification--dropdown-text
commented on
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id), title: "#{notification.target.answer.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
- if notification.target.answer.user == current_user
your
- elsif notification.target.user == notification.target.answer.user
their
- else
= user_screen_name(notification.target.answer.user, false, false) + "'s"
answer
= time_ago_in_words notification.target.created_at
ago
%li= link_to "Show all notifications#{" and mark them as read" if notifications.pluck(:new).any?}", notifications_path
- if notification.target.answer.user == current_user
= raw t('views.notifications.comment.body', content: link_to(t('views.notifications.comment.your', user: user_screen_name(current_user, false, false)), show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id)), time: time_tooltip(notification.target))
- elsif notification.target.user == notification.target.answer.user
= raw t('views.notifications.comment.body', content: link_to(t('views.notifications.comment.their', user: user_screen_name(notification.target.answer.user, false, false)), show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id)), time: time_tooltip(notification.target))
- else
= raw t('views.notifications.comment.body', content: link_to(t('views.notifications.comment.user', user: user_screen_name(notification.target.user, false, false)), show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id)), time: time_tooltip(notification.target))
%li= link_to "#{t('views.notifications.show')}#{t('views.notifications.mark') if notifications.pluck(:new).any?}", notifications_path

View file

@ -9,28 +9,28 @@
%li
%a{href: show_user_profile_path(current_user.screen_name)}
%i.fa.fa-fw.fa-user
View profile
= t('views.navigation.show')
%li
%a{href: edit_user_registration_path}
%i.fa.fa-fw.fa-cog
Settings
= t('views.navigation.settings')
%li.divider
- if current_user.admin?
%li
%a{href: rails_admin_path}
%i.fa.fa-fw.fa-cogs
Kontrollzentrum
= t('views.navigation.admin')
%li
%a{href: sidekiq_web_path}
%i.fa.fa-fw.fa-bar-chart
Sidekiq
= t('views.navigation.sidekiq')
- if current_user.mod?
%li
%a{href: moderation_path}
%i.fa.fa-fw.fa-gavel
Moderation Panel
= t('views.navigation.moderation')
%li.divider
%li
%a{href: destroy_user_session_path, data: {method: :delete} }
%i.fa.fa-fw.fa-sign-out
Logout
= t 'views.sessions.destroy'

View file

@ -13,6 +13,7 @@
%link{rel: 'icon', href: '/icon-152.png', sizes: '152x152'}
%link{rel: 'icon', href: '/images/favicon/favicon-32.png', sizes: '32x32'}
%title= yield(:title)
= javascript_include_tag 'i18n', 'data-turbolinks-track' => true
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
= javascript_include_tag 'application', 'data-turbolinks-track' => true
- if user_signed_in?

View file

@ -1,5 +1,5 @@
- if report.moderation_comments.all.count == 0
There are no comments yet.
= t 'views.answerbox.no_comment'
- else
%ul.comments
- report.moderation_comments.order(:created_at).each do |comment|
@ -21,8 +21,8 @@
%li.text-danger
%a{href: '#', tabindex: -1, data: { action: 'mod-comment-destroy', id: comment.id }}
%i.fa.fa-trash-o
Delete
= t 'views.actions.delete'
%p.comments--content= comment.content
.form-group.has-feedback{name: 'mod-comment-new-group', data: { id: report.id }}
%input.form-control.comments--box{type: :text, placeholder: 'Comment...', name: 'mod-comment-new', data: { id: report.id }}
%input.form-control.comments--box{type: :text, placeholder: t('views.placeholder.comment'), name: 'mod-comment-new', data: { id: report.id }}
%span.text-muted.form-control-feedback.comments--count{id: "mod-comment-charcount-#{report.id}"} 160

View file

@ -6,11 +6,11 @@
%span.icon-bar
%span.icon-bar
%span.icon-bar
%a.navbar-brand{href: "/"} Moderation
%a.navbar-brand{href: moderation_path} Moderation
#j2-tl-navbar-collapse.collapse.navbar-collapse
%ul.nav.navbar-nav
= nav_entry "All reports", moderation_path
= nav_entry "Answers", moderation_path('answer')
= nav_entry "Comments", moderation_path('comment')
= nav_entry "Users", moderation_path('user')
= nav_entry "Questions", moderation_path('question')
= nav_entry t('views.moderation.tabs.all'), moderation_path
= nav_entry t('views.general.answer').pluralize(2) , moderation_path('answer')
= nav_entry t('views.general.comment').pluralize(2), moderation_path('comment')
= nav_entry t('views.general.user').pluralize(2) , moderation_path('user')
= nav_entry t('views.general.question').pluralize(2), moderation_path('question')

View file

@ -1,8 +1,8 @@
.col-md-3.col-sm-3.col-xs-12
.panel.panel-default.hidden-xs
%ul.nav.nav-pills.nav-stacked
= list_group_item "All reports", moderation_path
= list_group_item "Answers", moderation_path('answer')
= list_group_item "Comments", moderation_path('comment')
= list_group_item "Users", moderation_path('user')
= list_group_item "Questions", moderation_path('question')
= list_group_item t('views.moderation.tabs.all'), moderation_path
= list_group_item t('views.general.answer').pluralize(2), moderation_path('answer')
= list_group_item t('views.general.comment').pluralize(2), moderation_path('comment')
= list_group_item t('views.general.user').pluralize(2), moderation_path('user')
= list_group_item t('views.general.question').pluralize(2), moderation_path('question')

View file

@ -2,12 +2,7 @@
.panel.panel-default.moderationbox{data: { id: report.id }}
.panel-heading
%img.img-rounded.answerbox--img{src: gravatar_url(report.user)}
= user_screen_name report.user
reported a
= report.type.sub('Reports::', '')
%span{title: report.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words(report.created_at)
ago
= raw t('views.moderation.moderationbox.reported', user: user_screen_name(report.user), content: report.type.sub('Reports::', ''), time: time_tooltip(report))
.panel-body
%p
- if report.type == 'Reports::User'
@ -15,8 +10,7 @@
- else
= report.target.content
%p
%b
Reason:
%b= t 'views.moderation.moderationbox.reason'
%br
- (report.reason || "No reason provided.").lines.each do |reason|
- next unless reason.strip.length > 0
@ -25,11 +19,10 @@
.row
.col-md-6.col-sm-4.col-xs-6.text-left
%a.btn.btn-primary{href: content_url(report)}
View reported
= report.type.sub('Reports::', '')
= t('views.moderation.moderationbox.view', content: report.type.sub('Reports::', ''))
- if report.target.respond_to? :user and not report.target.user.nil?
%a.btn.btn-primary{href: show_user_profile_path(report.target.user.screen_name)}
View reported User
= t('views.moderation.moderationbox.view', content: t('views.general.user'))
.col-md-6.col-sm-8.col-xs-6.text-right
%span.mod-count{id: "mod-count-#{report.id}"}
= report.votes

View file

@ -8,12 +8,7 @@
%h6.media-heading.notification--user
= user_screen_name notification.target.user
%p.notification--text
answered
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.id), title: "#{notification.target.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
your question
%span{title: notification.target.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words notification.target.created_at
ago
= raw t('views.notifications.answer.body', question: link_to(t('views.notifications.answer.question'), show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.id)), time: time_tooltip(notification.target))
.notification--icon
%i.fa.fa-exclamation
- when "Relationship"
@ -23,10 +18,7 @@
%h6.media-heading.notification--user
= user_screen_name notification.target.source
%p.notification--text
followed you
%span{title: notification.target.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words notification.target.created_at
ago
= raw t('views.notifications.relationship.body', time: time_tooltip(notification.target))
.notification--icon
%i.fa.fa-users
- when "Smile"
@ -36,12 +28,7 @@
%h6.media-heading.notification--user
= user_screen_name notification.target.user
%p.notification--text
smiled at
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id), title: "#{notification.target.answer.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
your answer
%span{title: notification.target.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words notification.target.created_at
ago
= raw t('views.notifications.smile.body', content: link_to(t('views.notifications.smile.answer'), show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id)), time: time_tooltip(notification.target))
.notification--icon
%i.fa.fa-smile-o
- when "CommentSmile"
@ -51,12 +38,7 @@
%h6.media-heading.notification--user
= user_screen_name notification.target.user
%p.notification--text
smiled at
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.comment.answer.id), title: "#{notification.target.comment.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
your comment
%span{title: notification.target.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words notification.target.created_at
ago
= raw t('views.notifications.smile.body', content: link_to(t('views.notifications.smile.comment'), show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id)), time: time_tooltip(notification.target))
.notification--icon
%i.fa.fa-smile-o
- when "Comment"
@ -66,17 +48,11 @@
%h6.media-heading.notification--user
= user_screen_name notification.target.user
%p.notification--text
commented on
%a{href: show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id), title: "#{notification.target.answer.content[0..40]}...", data: { toggle: :tooltip, placement: :top }}
- if notification.target.answer.user == current_user
your
- elsif notification.target.user == notification.target.answer.user
their
- else
= user_screen_name(notification.target.answer.user, false, false) + "'s"
answer
%span{title: notification.target.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words notification.target.created_at
ago
- if notification.target.answer.user == current_user
= raw t('views.notifications.comment.body', content: link_to(t('views.notifications.comment.your', user: user_screen_name(current_user, false, false)), show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id)), time: time_tooltip(notification.target))
- elsif notification.target.user == notification.target.answer.user
= raw t('views.notifications.comment.body', content: link_to(t('views.notifications.comment.their', user: user_screen_name(notification.target.answer.user, false, false)), show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id)), time: time_tooltip(notification.target))
- else
= raw t('views.notifications.comment.body', content: link_to(t('views.notifications.comment.user', user: user_screen_name(notification.target.user, false, false)), show_user_answer_path(username: notification.target.user.screen_name, id: notification.target.answer.id)), time: time_tooltip(notification.target))
.notification--icon
%i.fa.fa-comments

View file

@ -6,12 +6,12 @@
%span.icon-bar
%span.icon-bar
%span.icon-bar
%a.navbar-brand{href: "/"} Notifications
%a.navbar-brand{href: notifications_path} Notifications
#j2-tl-navbar-collapse.collapse.navbar-collapse
%ul.nav.navbar-nav
= nav_entry "All notifications", notifications_path
= nav_entry "Answers", notifications_path('answer')
= nav_entry "Smiles", notifications_path('smile')
= nav_entry "Comments", notifications_path('comment')
= nav_entry "Comment Smiles", notifications_path('commentsmile')
= nav_entry "Followers", notifications_path('relationship')
= nav_entry t('views.notifications.tabs.all'), notifications_path
= nav_entry t('views.notifications.tabs.answer'), notifications_path('answer')
= nav_entry t('views.notifications.tabs.smile'), notifications_path('smile')
= nav_entry t('views.notifications.tabs.comment'), notifications_path('comment')
= nav_entry t('views.notifications.tabs.commentsmile'), notifications_path('commentsmile')
= nav_entry t('views.notifications.tabs.relationship'), notifications_path('relationship')

View file

@ -1,9 +1,9 @@
.col-md-3.col-xs-12.col-sm-3
.panel.panel-default.hidden-xs
.list-group
= list_group_item "All notifications", notifications_path, badge: Notification.for(current_user).where(new: true).count
= list_group_item "Answers", notifications_path('answer'), badge: Notification.for(current_user).where(target_type: "Answer", new: true).count
= list_group_item "Smiles", notifications_path('smile'), badge: Notification.for(current_user).where(target_type: "Smile", new: true).count
= list_group_item "Comments", notifications_path('comment'), badge: Notification.for(current_user).where(target_type: "Comment", new: true).count
= list_group_item "Comment Smiles", notifications_path('commentsmile'), badge: Notification.for(current_user).where(target_type: "CommentSmile", new: true).count
= list_group_item "Followers", notifications_path('relationship'), badge: Notification.for(current_user).where(target_type: "Relationship", new: true).count
= list_group_item t('views.notifications.tabs.all'), notifications_path, badge: Notification.for(current_user).where(new: true).count
= list_group_item t('views.notifications.tabs.answer'), notifications_path('answer'), badge: Notification.for(current_user).where(target_type: "Answer", new: true).count
= list_group_item t('views.notifications.tabs.smile'), notifications_path('smile'), badge: Notification.for(current_user).where(target_type: "Smile", new: true).count
= list_group_item t('views.notifications.tabs.comment'), notifications_path('comment'), badge: Notification.for(current_user).where(target_type: "Comment", new: true).count
= list_group_item t('views.notifications.tabs.commentsmile'), notifications_path('commentsmile'), badge: Notification.for(current_user).where(target_type: "CommentSmile", new: true).count
= list_group_item t('views.notifications.tabs.relationship'), notifications_path('relationship'), badge: Notification.for(current_user).where(target_type: "Relationship", new: true).count

View file

@ -17,14 +17,13 @@
- if user_signed_in? and !current_user.answered? @question and current_user != @question.user and @question.user.privacy_allow_stranger_answers
.panel.panel-default#q-answer-box
.panel-heading
%h3.panel-title This question was not in your inbox? Answer it here!
%h3.panel-title= t('views.question.title')
.panel-body
%textarea#q-answer.form-control{placeholder: 'Write your answer here...', data: { id: @question.id }}
%textarea#q-answer.form-control{placeholder: t('views.placeholder.inbox'), data: { id: @question.id }}
%br/
%button#q-answer.btn.btn-success{data: { q_id: @question.id }}
Answer
= t('views.actions.answer')
- current_user.services.each do |service|
%label
%input{type: 'checkbox', name: 'share', checked: :checked, data: { q_id: @question.id, service: service.provider }}
Post to
= service.provider.capitalize
= t('views.inbox.entry.sharing.post', service: service.provider.capitalize)

View file

@ -6,13 +6,13 @@
.panel.panel-default
.panel-body
- if @services.count > 0
Sharing is enabled for the following services:
= t 'views.settings.service.enabled'
- else
You have not connected any services yet.
= t 'views.settings.service.none'
- APP_CONFIG['sharing'].each do |service, service_options|
- if service_options['enabled'] and !@services.any? { |x| x.provider == service.to_s }
%p=link_to "Connect to #{service.capitalize}", "/auth/#{service}"
%p=link_to t('views.settings.service.connect', service: service.capitalize), "/auth/#{service}"
- if @services.count > 0
%ul.list-group
@ -21,4 +21,4 @@
%i{class: "fa fa-#{service.provider}"}
%strong= service.provider.capitalize
(#{service.nickname})
= link_to 'Disconnect', service_path(service), data: { confirm: "Really disconnect service #{service.provider.capitalize}?" }, method: :delete
= link_to t('views.settings.service.disconnect'), service_path(service), data: { confirm: t('views.settings.service.confirm', service: service.provider.capitalize) }, method: :delete

View file

@ -16,28 +16,19 @@
%li.text-danger
%a{href: '#', tabindex: -1, data: { action: 'ab-question-destroy', q_id: a.question.id }}
%i.fa.fa-trash-o
Delete Question
= t 'views.actions.delete'
- unless a.question.user == current_user
%li
%a{href: '#', tabindex: -1, data: { action: 'ab-question-report', q_id: a.question.id }}
%i.fa.fa-exclamation-triangle
Report
= t 'views.actions.report'
%h6.text-muted.media-heading.answerbox--question-user
= user_screen_name a.question.user, a.question.author_is_anonymous
asked
- if @user.nil? or a.question.author_is_anonymous
%span{title: a.question.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words(a.question.created_at)
- else
%a{href: show_user_question_path(a.question.user.screen_name, a.question.id)}
%span{title: a.question.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words(a.question.created_at)
ago
= raw t('views.answerbox.asked', user: user_screen_name(a.question.user, a.question.author_is_anonymous), time: time_tooltip(a.question))
- unless a.question.author_is_anonymous
- if a.question.answer_count > 1
·
%a{href: show_user_question_path(a.question.user.screen_name, a.question.id)}
#{a.question.answer_count} answers
= pluralize(a.question.answer_count, t('views.general.answer'))
.answerbox--question-text
= a.question.content
.panel-body
@ -48,7 +39,7 @@
[...]
%p
%a.btn.btn-primary{href: show_user_answer_path(a.user.screen_name, a.id)}
Read the entire answer
= t 'views.answerbox.read'
- else
.answerbox--answer-text
= markdown a.content
@ -61,24 +52,16 @@
%img.img-rounded.answerbox--img{src: gravatar_url(a.user)}
.media-body
%h6.media-heading.answerbox--answer-user
%span.hidden-xs
Answered by
= user_screen_name a.user
= raw t('views.answerbox.answered', hide: hidespan(t('views.answerbox.hide'), "xs"), user: user_screen_name(a.user))
.answerbox--answer-date
%a{href: show_user_answer_path(a.user.screen_name, a.id)}
%span{title: a.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words(a.created_at)
ago
= link_to(raw(t('views.answerbox.time', time: time_tooltip(a))))
.col-md-6.col-sm-8.col-xs-6.text-right
= render 'shared/answerbox_buttons', a: a
- else
.row
.col-md-6.col-sm-4.col-xs-6.text-left.text-muted
%i.fa.fa-clock-o
%a{href: show_user_answer_path(a.user.screen_name, a.id)}
%span{title: a.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words(a.created_at)
ago
= link_to(raw(t('views.answerbox.time', time: time_tooltip(a))))
.col-md-6.col-sm-8.col-xs-6.text-right
= render 'shared/answerbox_buttons', a: a
.panel-footer{id: "ab-comments-section-#{a.id}", style: @display_all.nil? ? 'display: none' : nil }

View file

@ -27,19 +27,19 @@
-# fun joke should subscribe?
%a{href: '#', data: { a_id: a.id, action: 'ab-submarine', torpedo: "no" }}
%i.fa.fa-anchor
Unsubscribe
= t 'views.actions.unsubscribe'
- else
%li
%a{href: '#', data: { a_id: a.id, action: 'ab-submarine', torpedo: "yes" }}
%i.fa.fa-anchor
Subscribe
= t 'views.actions.subscribe'
- if privileged? a.user
%li.text-danger
%a{href: '#', data: { a_id: a.id, action: 'ab-destroy' }}
%i.fa.fa-trash-o
Return to Inbox
= t 'views.actions.return'
- unless a.user == current_user
%li
%a{href: '#', data: { a_id: a.id, action: 'ab-report' }}
%i.fa.fa-exclamation-triangle
Report
= t 'views.actions.report'

View file

@ -5,10 +5,10 @@
%button.close{"data-dismiss" => "modal", :type => "button"}
%span{"aria-hidden" => "true"} ×
%span.sr-only Close
%h4#modal-ask-followers-label.modal-title People who smiled this comment
%h4#modal-ask-followers-label.modal-title= t 'views.answerbox.commentsmile'
.modal-body
- if comment.smiles.all.count == 0
No one smiled this, yet.
= t 'views.answerbox.no_smile'
- else
%ul.user-list.user-list-smiles
- comment.smiles.all.each do |smile|

View file

@ -1,5 +1,5 @@
- if a.comments.all.count == 0
There are no comments yet.
= t 'views.answerbox.no_comment'
- else
%ul.comments
- a.comments.order(:created_at).each do |comment|
@ -36,20 +36,20 @@
%li
%a{href: '#', type: :button, data: { target: "#modal-view-comment#{comment.id}-smiles", toggle: :modal}}
%i.fa.fa-smile-o
View comment smiles
= t 'views.actions.view'
- if privileged?(comment.user) or privileged?(a.user)
%li.text-danger
%a{href: '#', data: { action: 'ab-comment-destroy', c_id: comment.id }}
%i.fa.fa-trash-o
Delete
= t 'views.actions.delete'
- unless comment.user == current_user
%li
%a{href: '#', data: { action: 'ab-comment-report', c_id: comment.id }}
%i.fa.fa-exclamation-triangle
Report
= t 'views.acions.report'
.comments--content
= markdown comment.content
- if user_signed_in?
.form-group.has-feedback{name: 'ab-comment-new-group', data: { a_id: a.id }}
%input.form-control.comments--box{type: :text, placeholder: 'Comment...', name: 'ab-comment-new', data: {a_id: a.id }}
%input.form-control.comments--box{type: :text, placeholder: t('views.placeholder.comment'), name: 'ab-comment-new', data: {a_id: a.id }}
%span.text-muted.form-control-feedback.comments--count{id: "ab-comment-charcount-#{a.id}"} 160

View file

@ -3,10 +3,10 @@
= Date.today.year
= APP_CONFIG['site_name']
·
= link_to "About", about_path
= link_to t('views.general.about'), about_path
·
= link_to "Github", 'https://github.com/retrospring/retrospring'
·
= link_to "Terms of Service", terms_path
= link_to t('views.general.terms'), terms_path
·
= link_to "Privacy Policy", privacy_policy_path
= link_to t('views.general.privacy'), privacy_policy_path

View file

@ -4,18 +4,18 @@
.modal-header
%button.close{"data-dismiss" => "modal", :type => "button"}
%span{"aria-hidden" => "true"} ×
%span.sr-only Close
%h4#modal-ask-followers-label.modal-title Ask your followers
%span.sr-only= t 'views.actions.close'
%h4#modal-ask-followers-label.modal-title= t 'views.modal.ask.title'
.modal-body
%textarea.form-control{:name => "qb-all-question", :placeholder => "Type your question here…"}
%textarea.form-control{:name => "qb-all-question", :placeholder => t('views.placeholder.question')}
.modal-footer
- if current_user.groups.count > 0
%label
Choose group:
= t 'views.modal.ask.choose'
%select{name: 'qb-all-rcpt', class: 'form-control', autocomplete: 'off'}
%option{value: 'followers', selected: true} Followers
%optgroup{label: 'Groups'}
%option{value: 'followers', selected: true}= t('views.general.follower').pluralize(2)
%optgroup{label: t('views.group.title').pluralize(2)}
- current_user.groups.each do |group|
%option{value: "grp:#{group.name}"}= group.display_name
%button.btn.btn-default{"data-dismiss" => "modal", :type => "button"} Cancel
%button.btn.btn-primary{name: 'qb-all-ask', :type => "button", data: {loading_text: 'Asking...' }} Ask
%button.btn.btn-default{"data-dismiss" => "modal", :type => "button"}= t 'views.actions.cancel'
%button.btn.btn-primary{name: 'qb-all-ask', :type => "button", data: {loading_text: t('views.modal.ask.loading') }}= t 'views.actions.ask'

View file

@ -16,22 +16,17 @@
%li.text-danger
%a{href: '#', tabindex: -1, data: { action: 'ab-question-destroy', q_id: q.id }}
%i.fa.fa-trash-o
Delete Question
= t 'views.actions.delete'
- unless q.user == current_user
%li
%a{href: '#', tabindex: -1, data: { action: 'ab-question-report', q_id: q.id }}
%i.fa.fa-exclamation-triangle
Report
= t 'views.actions.report'
%h6.media-heading.text-muted.answerbox--question-user
= user_screen_name q.user
asked
%a{href: show_user_question_path(q.user.screen_name, q.id)}
%span{title: q.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words(q.created_at)
ago
= raw t('views.answerbox.asked', user: user_screen_name(q.user), time: time_tooltip(q))
- if q.answer_count > 1
·
%a{href: show_user_question_path(q.user.screen_name, q.id)}
#{q.answer_count} answers
= pluralize(q.answer_count, t('views.general.answer'))
%p.answerbox--question-text
= q.content

View file

@ -17,17 +17,15 @@
%li.text-danger
%a{href: '#', tabindex: -1, data: { action: 'ab-question-destroy', q_id: question.id, redirect: if question.author_is_anonymous? then "/" else show_user_questions_path(question.user.screen_name) end }}
%i.fa.fa-trash-o
Delete Question
= t 'views.actions.delete'
- unless question.user == current_user
%li
%a{href: '#', tabindex: -1, data: { action: 'ab-question-report', q_id: question.id }}
%i.fa.fa-exclamation-triangle
Report
= t 'views.actions.report'
%h6.text-muted.media-heading.answerbox--question-user
= user_screen_name question.user, question.author_is_anonymous, !hidden
- unless hidden
asked
%span{title: question.created_at, data: { toggle: :tooltip, placement: :bottom }}
= time_ago_in_words(question.created_at)
ago
- if hidden
= user_screen_name question.user, question.author_is_anonymous, false
- else
= raw t('views.answerbox.asked', user: user_screen_name(question.user, question.author_is_anonymous), time: time_tooltip(question))
%p.answerbox--question-text= question.content

View file

@ -2,56 +2,50 @@
.panel-heading
%h3.panel-title
- if @user.motivation_header.blank?
Ask something!
= t 'views.questionbox.title'
- else
= @user.motivation_header
.panel-body
- if @user.banned?
.row
.col-xs-12.text-center
%strong This user got hit with ye olde banhammer.
%strong= t 'views.questionbox.banned'
- else
- if user_signed_in? or @user.privacy_allow_anonymous_questions?
#question-box
.row
.col-xs-12
%textarea.form-control{:name => "qb-question", :placeholder => "Type your question here…"}
%textarea.form-control{:name => "qb-question", :placeholder => t('views.placeholder.question')}
.row{:style => "padding-top: 5px; padding-left: 5px; padding-right: 5px;"}
.col-xs-6
- if user_signed_in?
- if @user.privacy_allow_anonymous_questions?
%input{:name => "qb-anonymous", :type => "checkbox"}/
Hide your name
= t 'views.actions.anonymous'
%br/
- else
%input{:name => "qb-anonymous", :type => "hidden", :value => "false"}/
.col-xs-6
%p.pull-right
%input{name: 'qb-to', type: 'hidden', :value => @user.id}/
%button.btn.btn-primary{name: 'qb-ask', :type => "button", data: {loading_text: 'Asking...', promote: user_signed_in? ? "false" : "true" }} Ask
%button.btn.btn-primary{name: 'qb-ask', :type => "button", data: {loading_text: t('views.questionbox.load'), promote: user_signed_in? ? "false" : "true" }} Ask
- unless user_signed_in?
- if @user.privacy_allow_anonymous_questions?
#question-box-promote.row{:style => "display: none;"}
.row
.col-xs-12.text-center
%strong Your question has been sent.
%strong= t 'views.questionbox.promote.message'
.row
.col-sm-1
.col-sm-5
%button#create-account.btn.btn-block.btn-primary Create an account
%button#create-account.btn.btn-block.btn-primary= t 'views.questionbox.promote.create'
.col-sm-5
%button#new-question.btn.btn-block.btn-default Ask another question
%button#new-question.btn.btn-block.btn-default= t 'views.questionbox.promote.another'
.col-sm-1
.row
.col-sm-1
.col-xs-12.col-sm-10
%small
Join
= APP_CONFIG['site_name']
today! You'll be able to follow and ask people you know and a lot more.
.col-xs-12.col-sm-10.text-center
%small= t('views.questionbox.promote.join', app_title: APP_CONFIG['site_name'])
.col-sm-1
- else
%p
This user does not want to get asked by strangers. Why don't you
= succeed "?" do
%a{:href => "{{ url_for('register') }}"} sign up
%p= raw t 'views.questionbox.required', signup: link_to(t('views.sessions.new'),new_user_registration_path)

View file

@ -1,9 +1,5 @@
.panel.panel-default.hidden-xs
%img.profile--avatar{src: current_user.profile_picture.url(:large)}
- unless inbox_count.nil?
.profile--panel-badge.panel-badge-info
%i.fa.fa-envelope
= pluralize(inbox_count, 'new question')
.panel-body
- if current_user.display_name.blank?
.profile--displayname
@ -17,21 +13,21 @@
%a{href: show_user_followers_path(current_user.screen_name)}
.col-md-6.col-sm-6.col-xs-6
%h4.entry-text#follower-count= current_user.follower_count
%h6.entry-subtext Followers
%h6.entry-subtext= t('views.general.follower').pluralize(current_user.follower_count)
%a{href: show_user_friends_path(current_user.screen_name)}
.col-md-6.col-sm-6.col-xs-6
%h4.entry-text#friend-count= current_user.friend_count
%h6.entry-subtext Following
%h6.entry-subtext= t('views.general.following')
.panel.panel-default.hidden-xs
%ul.nav.nav-pills.nav-stacked
= list_group_item "Timeline", root_path
= list_group_item "Public", public_timeline_path
= list_group_item t('views.general.timeline'), root_path
= list_group_item t('views.general.public'), public_timeline_path
- current_user.groups.each do |group|
= list_group_item group.display_name, group_timeline_path(group.name)
- unless @group.nil?
.panel.panel-default.profile--panel.hidden-xs
.panel-heading
%h3.panel-title Members
%h3.panel-title= t('views.group.members')
.panel-body
- @group.members.each do |member|
%a{href: show_user_profile_path(member.user.screen_name), title: member.user.screen_name, data: { toggle: :tooltip, placement: :top }}

View file

@ -3,7 +3,7 @@
%i.fa.fa-smile-o
.media-body
- if a.smiles.all.count == 0
No one smiled this, yet.
= t 'views.answerbox.no_smile'
- else
- a.smiles.all.each do |smile|
%a{href: show_user_profile_path(smile.user.screen_name), title: smile.user.screen_name, data: { toggle: :tooltip, placement: :top, smile_id: smile.id }}

View file

@ -18,8 +18,8 @@
.row
.col-md-6.col-sm-6.col-xs-6
%h4.entry-text#asked-count= user.asked_count
%h6.entry-subtext Questions
%h6.entry-subtext= t('views.general.question').pluralize(user.asked_count)
.col-md-6.col-sm-6.col-xs-6
%h4.entry-text#answered-count= user.answered_count
%h6.entry-subtext Answers
= render 'user/actions', user: user, type: type
%h6.entry-subtext= t('views.general.answer').pluralize(user.answered_count)
= render 'user/actions', user: user, type: type

View file

@ -4,7 +4,7 @@
.container
= render 'layouts/messages'
%h1= APP_CONFIG['site_name']
%p Ask questions, give answers and learn more about your friends.
%p= t 'views.front.subtitle'
%p
%a.btn.btn-primary.btn-lg{href: url_for(new_user_registration_path)}
Register now
@ -16,24 +16,16 @@
.col-md-4.col-sm-4.col-xs-12
.icon-showcase
%i.fa.fa-comments
%h3.heading-showcase
Ask and answer questions
%p
With
= APP_CONFIG['site_name']
you can ask people questions and answer questions from other users or unregistered people. Want to know something more? Keep the discussion ongoing in the comments!
%h3.heading-showcase= t 'views.front.ask.title'
%p= t('views.front.ask.desc', app_title: APP_CONFIG['site_name'])
.col-md-4.col-sm-4.col-xs-12
.icon-showcase
%i.fa.fa-users
%h3.heading-showcase
Follow users and get followed
%p
Following users allows you to get a personalized feed of all people you want to know more about. You can also send a question to all your followers at once!
%h3.heading-showcase= t 'views.front.follow.title'
%p= t 'views.front.follow.desc'
.col-md-4.col-sm-4.col-xs-12
.icon-showcase
%i.fa.fa-share-square-o
%h3.heading-showcase
Sharing to other networks
%p
Want to share your answer to a question so that more people read it? With a simple click on the answer button, your answer is shared wherever you want!
%h3.heading-showcase= t 'views.front.share.title'
%p= t 'views.front.share.desc'
= render "shared/links"

View file

@ -3,14 +3,14 @@
#particles
.particle-content
%h1= APP_CONFIG['site_name']
%p About our service, features and other information
%p= t 'views.about.subtitle'
.container
.panel.panel-default
.panel-body
.row
.col-md-3
%h3 Links
%p Important pages and social media profiles from the Retrospring team, which are recommended to visit!
%h3= t 'views.about.links.title'
%p= t('views.about.links.desc', app_title: APP_CONFIG['site_name'])
.col-md-3.col-sm-4
%a{href: "https://twitter.com/retro_spring"}
.icon-showcase
@ -33,34 +33,20 @@
.panel-body
.row
.col-md-4
%h3 Open Source
%p
= APP_CONFIG['site_name']
is running on unfinished code, full of bugs. Caveat emptor.
%p
Want to contribute? If you are a Ruby developer, CoffeeScript coder or frontend designer, you can now help
= APP_CONFIG['site_name']
to get the features everyone wanted by forking our
= succeed '.' do
= link_to "GitHub repository", 'https://github.com/retrospring/retrospring'
If that's not the case, you can still report bugs and request features at our
= succeed '.' do
= link_to "bug tracker", 'https://github.com/retrospring/bugs'
%h3= t 'views.about.opensource.title'
%p= t('views.about.opensource.warning', app_title: APP_CONFIG['site_name'])
%p= raw t('views.about.opensource.desc', app_title: APP_CONFIG['site_name'], github: link_to(t('views.about.opensource.github'), "https://github.com/Retrospring/retrospring"), bugtracker: link_to(t('views.about.opensource.bugtracker'), "https://github.com/Retrospring/bugs"))
.col-md-4
%a{href: "https://github.com/Retrospring/retrospring"}
.icon-showcase
%i.fa.fa-github
%h4.heading-about.text-center
Main Repository
%h4.heading-about.text-center= t 'views.about.repository.title'
%p.text-center
%em The place where all the code magic and fixing happens!
%em= t 'views.about.repository.desc'
.col-md-4
%h3 Contributors
%p These people have contributed to #{APP_CONFIG['site_name']}'s source code.
%p
Want to get listed here?
= link_to "Fork this repo", 'https://github.com/retrospring/retrospring'
and create a new pull request with your changes.
%h3= t 'views.about.contributors.title'
%p= t('views.about.contributors.desc', app_title: APP_CONFIG['site_name'])
%p= raw t('views.about.contributors.howto', fork: link_to(t('views.about.contributors.fork'), "https://github.com/retrospring/retrospring"))
%ul.about--moderator
- User.where(contributor: true).each do |sup|
%a{href: show_user_profile_path(sup.screen_name), title: sup.screen_name, data: { toggle: :tooltip, placement: :top }}
@ -69,10 +55,8 @@
.panel-body
.row
.col-md-4
%h3 The Team
The people behind
= succeed '!' do
= APP_CONFIG['site_name']
%h3= t 'views.about.team.title'
= t('views.about.team.desc', app_title: APP_CONFIG['site_name'])
%br/
- APP_CONFIG['admins'].each do |adm|
.media
@ -83,18 +67,15 @@
%h4.entry-text.entry-about= adm['about_text']
%h6.entry-subtext= adm['subtext']
.col-md-4
%h3 Moderators
%p
The people on
= APP_CONFIG['site_name']
that look after you!
%h3= t 'views.about.moderators.title'
%p= t('views.about.moderators.desc', app_title: APP_CONFIG['site_name'])
%ul.about--moderator
- User.where(moderator: true).each do |mod|
%a{href: show_user_profile_path(mod.screen_name), title: mod.screen_name, data: { toggle: :tooltip, placement: :top }}
%img.img-rounded.answerbox--img{src: mod.profile_picture.url(:medium)}
.col-md-4
%h3 Funding
%p People which (previously) donated to Retrospring!
%h3= t 'views.about.funding.title'
%p= t('views.about.funding.desc', app_title: APP_CONFIG['site_name'])
%ul.about--moderator
- User.where(supporter: true).each do |sup|
%a{href: show_user_profile_path(sup.screen_name), title: sup.screen_name, data: { toggle: :tooltip, placement: :top }}
@ -103,24 +84,20 @@
.panel-body
.row
.col-md-3.col-sm-12.col-xs-12
%h3 Statistics
%p
All-time statistics for
= succeed ',' do
= APP_CONFIG['site_name']
updated every time you refresh the page!
%h3= t 'views.about.statistics.title'
%p= t('views.about.statistics.desc', app_title: APP_CONFIG['site_name'])
.col-md-3.col-sm-6.col-xs-6.statistics
%h2.entry-text#asked-count= Question.count
%h4.entry-subtext Questions
%h4.entry-subtext= t('views.general.question').pluralize(Question.count)
%h2.entry-text#answered-count= Answer.count
%h4.entry-subtext Answers
%h4.entry-subtext= t('views.general.answer').pluralize(Answer.count)
.col-md-3.col-sm-6.col-xs-6.statistics
%h2.entry-text#asked-count= Comment.count
%h4.entry-subtext Comments
%h4.entry-subtext= t('views.general.comment').pluralize(Comment.count)
%h2.entry-text#answered-count= Smile.count + CommentSmile.count
%h4.entry-subtext Smiles
%h4.entry-subtext= t('views.general.smile').pluralize(Smile.count)
.col-md-3.col-sm-12.col-xs-12.users
.entry-text#follower-count= User.count
%h6.entry-subtext Users
%h6.entry-subtext= t('views.general.user').pluralize(User.count)
= render "shared/links"

View file

@ -13,34 +13,33 @@
.modal-header
%button.close{"data-dismiss" => "modal", :type => "button"}
%span{"aria-hidden" => "true"} ×
%span.sr-only Close
%h4#modal-passwd-label.modal-title Save account changes
%span.sr-only= t 'views.actions.close'
%h4#modal-passwd-label.modal-title= t 'views.settings.account.modal.title'
.modal-body
= f.password_field :current_password, autocomplete: "off", label: "Current password", help: "We need your current password to confirm your changes"
= f.password_field :current_password, autocomplete: "off", label: t('views.settings.account.password_current'), help: t('views.settings.account.password_current_help')
.modal-footer
%button.btn.btn-default{"data-dismiss" => "modal", :type => "button"} Cancel
%button.btn.btn-primary{:type => "submit"} Save changes
%button.btn.btn-default{"data-dismiss" => "modal", :type => "button"}= t 'views.actions.cancel'
%button.btn.btn-primary{:type => "submit"}= t 'views.actions.save'
= devise_error_messages!
= f.text_field :screen_name, autofocus: true, label: "User name"
= f.text_field :screen_name, autofocus: true, label: t('views.settings.account.username')
= f.email_field :email, label: "Email address"
= f.email_field :email, label: t('views.settings.account.email')
- if devise_mapping.confirmable? && resource.pending_reconfirmation?
%div
Currently waiting confirmation for: #{resource.unconfirmed_email}
%div= raw t('views.settings.account.email_confirm', resource: resource.unconfirmed_email)
= f.password_field :password, autocomplete: "off", label: "Password", help: "Leave this blank if you don't want to change it"
= f.password_field :password_confirmation, autocomplete: "off", label: "Confirm password"
= f.password_field :password, autocomplete: "off", label: t('views.settings.account.password'), help: t('views.settings.account.password_help')
= f.password_field :password_confirmation, autocomplete: "off", label: t('views.settings.account.password_confirm')
%button.btn.btn-primary{"data-target" => "#modal-passwd", "data-toggle" => "modal", :type => "button"}
Save changes
= t 'views.actions.save'
%hr/
%p
Unsatisfied?
=button_to "Delete my account", '/settings/account', data: { confirm: "Are you sure?" }, method: :delete, class: "btn btn-danger btn-xs"
= t 'views.settings.account.unsatisfied'
=button_to t('views.settings.account.delete'), '/settings/account', data: { confirm: "Are you sure?" }, method: :delete, class: "btn btn-danger btn-xs"
= link_to "Back", :back
= link_to t('views.settings.account.back'), :back
.visible-xs= render "shared/links"

View file

@ -5,14 +5,14 @@
- else
- if current_user.following? user
%button#editprofile.btn.btn-default.btn-block.profile--follow-btn{type: :button, name: 'user-action', data: { action: :unfollow, type: type, target: user.screen_name }}
Unfollow
= t 'views.actions.unfollow'
- else
%button#editprofile.btn.btn-primary.btn-block.profile--follow-btn{type: :button, name: 'user-action', data: { action: :follow, type: type, target: user.screen_name }}
Follow
= t 'views.actions.follow'
- unless user == current_user
.btn-group.btn-block
%button.btn.btn-default.btn-block.btn-sm.dropdown-toggle{data: { toggle: :dropdown }, aria: { expanded: :false }}
Actions
= t 'views.actions.title'
%span.caret
%ul.dropdown-menu
/
@ -23,21 +23,18 @@
%li.visible-xs
%a{href: '#', data: { target: "#modal-group-memberships", toggle: :modal }}
%i.fa.fa-users
Manage group memberships
= t 'views.actions.group'
%li
%a{href: '#', data: { action: 'report-user', target: user.screen_name }}
%i.fa.fa-exclamation-triangle
Report
= t 'views.actions.report'
- if current_user.mod?
%li
%a{href: '#', data: { target: "#modal-privileges", toggle: :modal }}
%i.fa.fa-wrench
Check
= succeed "'s" do
= user.screen_name
privileges
= raw t('views.actions.privilege', user: user.screen_name)
- unless user.admin?
%li
%a{href: '#', data: { target: "#modal-ban", toggle: :modal }}
%i.fa.fa-ban
Ban Control
= t 'views.actions.ban'

View file

@ -6,16 +6,16 @@
%span{"aria-hidden" => "true"} ×
%span.sr-only Close
%h4#modal-ban-label.modal-title
Ban Control Center
= t 'views.modal.bancontrol.title'
= bootstrap_form_tag(url: '/mod/ban', html: { method: :post, novalidate: "novalidate" }) do |f|
= f.hidden_field :user, value: @user.screen_name
#ban-control-super.modal-body
= f.check_box :ban, label: "Ban?", checked: @user.banned?
= f.check_box :ban, label: t('views.modal.bancontrol.ban'), checked: @user.banned?
#ban-controls{style: "#{"display: none" unless @user.banned?}"}
= f.check_box :permaban, label: "Permanently?", checked: @user.permanently_banned?
= f.check_box :permaban, label: t('views.modal.bancontrol.permanent'), checked: @user.permanently_banned?
#ban-controls-time{style: "#{"display: none" unless not @user.permanently_banned?}"}
= f.text_field :until, label: "", required: true, value: (@user.banned_until || DateTime.current).strftime("%m/%d/%Y %I:%M %p")
= f.text_field :reason, placeholder: "Reason", value: @user.ban_reason
= f.text_field :reason, placeholder: t('views.modal.bancontrol.reason'), value: @user.ban_reason
.modal-footer
%button.btn.btn-default{name: 'stop-time', type: :button, data: { dismiss: :modal }} Close
= f.submit "Hammer Time", class: "btn btn-primary", name: 'hammer-time'
%button.btn.btn-default{name: 'stop-time', type: :button, data: { dismiss: :modal }}= t 'views.actions.close'
= f.submit t('views.modal.bancontrol.hammertime'), class: "btn btn-primary", name: 'hammer-time'

View file

@ -6,7 +6,8 @@
.list-group-item-heading= group.display_name
.list-group-item-text.text-muted.j2-up
%span{id: "#{group.name}-members"}= group.members.count
members ·
= t 'views.modal.group.members'
·
%a.j2-delete#delete-group{href: "#", data: { group: group.name }}
%i.fa.fa-close
Delete
= t 'views.actions.delete'

View file

@ -4,16 +4,16 @@
.modal-header
%button.close{"data-dismiss" => "modal", :type => "button"}
%span{"aria-hidden" => "true"} ×
%span.sr-only Close
%h4#modal-group-memberships-label.modal-title Manage group memberships
%span.sr-only= t 'views.actions.close'
%h4#modal-group-memberships-label.modal-title= t 'views.modal.group.title'
%div{role: "tabpanel"}
%ul.nav.nav-tabs{role: "tablist"}
%li.active{role: "presentation"}
%a{href: "#grouplist", aria: {controls: "grouplist"}, data: {toggle: "tab"}, role: "tab"}
Groups
= t 'views.modal.group.tabs.main'
%li{role: "presentation"}
%a{href: "#create", aria: {controls: "create"}, data: {toggle: "tab"}, role: "tab"}
Create new group
= t 'views.modal.group.tabs.create'
.tab-content
.tab-pane.active{role:"tabpanel", id: "grouplist"}
@ -22,7 +22,7 @@
= render 'user/modal_group_item', group: group, user: @user
.tab-pane{role:"tabpanel", id: "create"}
.modal-body
%input#new-group-name.form-control{type: :text, placeholder: 'Group name'}
%button#create-group.btn.btn-primary{type: :button, data: { user: @user.screen_name }} Create group
%input#new-group-name.form-control{type: :text, placeholder: t('views.modal.group.name')}
%button#create-group.btn.btn-primary{type: :button, data: { user: @user.screen_name }}= t('views.modal.group.create')
.modal-footer
%button.btn.btn-primary{name: 'gm-save', type: :button, data: { dismiss: :modal }} Done
%button.btn.btn-primary{name: 'gm-save', type: :button, data: { dismiss: :modal }}= t 'views.actions.done'

View file

@ -4,18 +4,15 @@
.modal-header
%button.close{"data-dismiss" => "modal", :type => "button"}
%span{"aria-hidden" => "true"} ×
%span.sr-only Close
%span.sr-only= t 'views.actions.close'
%h4#modal-privileges-label.modal-title
Check
= succeed "'s" do
= @user.screen_name
privileges
= raw t('views.actions.privilege', user: @user.screen_name)
%ul.list-group.groups--list
= render 'user/modal_privileges_item', privilege: 'blogger', description: 'The user gets that privilege if they blogged something (nice) about Retrospring.', user: @user
= render 'user/modal_privileges_item', privilege: 'contributor', description: "This user has contributed to justask#{" (the software behind #{APP_CONFIG['site_name']})" unless APP_CONFIG['site_name'] == 'justask'}.", user: @user
= render 'user/modal_privileges_item', privilege: 'blogger', description: t('views.modal.privilege.blogger'), user: @user
= render 'user/modal_privileges_item', privilege: 'contributor', description: t('views.modal.privilege.contributor'), user: @user
- if current_user.admin?
= render 'user/modal_privileges_item', privilege: 'supporter', description: 'This user monetarily supports the site', user: @user
= render 'user/modal_privileges_item', privilege: 'moderator', description: 'Someone trustworthy enough to help managing reports',user: @user
= render 'user/modal_privileges_item', privilege: 'admin', description: 'This user is part of the core team', user: @user
= render 'user/modal_privileges_item', privilege: 'supporter', description: t('views.modal.privilege.supporter'), user: @user
= render 'user/modal_privileges_item', privilege: 'moderator', description: t('views.modal.privilege.moderator'),user: @user
= render 'user/modal_privileges_item', privilege: 'admin', description: t('views.modal.privilege.admin'), user: @user
.modal-footer
%button.btn.btn-primary{name: 'checked-privileges', type: :button, data: { dismiss: :modal }} Done
%button.btn.btn-primary{name: 'checked-privileges', type: :button, data: { dismiss: :modal }}= t 'views.actions.done'

View file

@ -3,30 +3,30 @@
- if @user.admin?
.profile--panel-badge.panel-badge-danger
%i.fa.fa-flask
Admin
= t 'views.user.title.admin'
- if @user.moderator?
.profile--panel-badge.panel-badge-success
%i.fa.fa-users
Mod
= t 'views.user.title.moderator'
- if @user.supporter?
.profile--panel-badge.panel-badge-warning
%i.fa.fa-star
Supporter
= t 'views.user.title.supporter'
- if @user.contributor?
.profile--panel-badge.panel-badge-primary
%i.fa.fa-github
Contributor
= t 'views.user.title.contributor'
- if @user.blogger?
.profile--panel-badge.panel-badge-info
%i.fa.fa-pencil
Blogger
= t 'views.user.title.blogger'
- if @user.banned?
.profile--panel-badge.panel-badge-default
%i.fa.fa-ban
Banned
= t 'views.user.title.banned'
- if @user.following? current_user
.profile--panel-badge.panel-badge-default
Follows you
= t 'views.user.follows_you'
.panel-body
.profile--panel-name
- if @user.display_name.blank?

View file

@ -1,10 +1,10 @@
.col-md-3.col-xs-12.col-sm-3
.panel.panel-default
.list-group
= list_group_item "Account", edit_user_registration_path
= list_group_item "Profile", edit_user_profile_path
= list_group_item "Privacy", edit_user_privacy_path
= list_group_item "Sharing", services_path
= list_group_item t('views.settings.tabs.account'), edit_user_registration_path
= list_group_item t('views.settings.tabs.profile'), edit_user_profile_path
= list_group_item t('views.settings.tabs.privacy'), edit_user_privacy_path
= list_group_item t('views.settings.tabs.sharing'), services_path
.hidden-xs= render "shared/links"
.hidden-xs= render "shared/links"

View file

@ -6,17 +6,17 @@
%a{href: show_user_followers_path(@user.screen_name)}
.col-md-6.col-sm-6.col-xs-6
%h4.entry-text#follower-count= @user.follower_count
%h6.entry-subtext Followers
%h6.entry-subtext= t('views.general.follower').pluralize(@user.follower_count)
%a{href: show_user_friends_path(@user.screen_name)}
.col-md-6.col-sm-6.col-xs-6
%h4.entry-text#friend-count= @user.friend_count
%h6.entry-subtext Following
%h6.entry-subtext= t('views.general.following')
.row
%a{href: show_user_questions_path(@user.screen_name)}
.col-md-6.col-sm-6.col-xs-6
%h4.entry-text#asked-count= @user.asked_count
%h6.entry-subtext Questions
%h6.entry-subtext= t('views.general.question').pluralize(@user.asked_count)
%a{href: show_user_profile_path(@user.screen_name)}
.col-md-6.col-sm-6.col-xs-6
%h4.entry-text#answered-count= @user.answered_count
%h6.entry-subtext Answers
%h6.entry-subtext= t('views.general.answer').pluralize(@user.answered_count)

View file

@ -7,17 +7,17 @@
.panel-body
= bootstrap_form_for(current_user, url: {action: "edit"}, :html => { :multipart => true }, method: "patch") do |f|
= f.text_field :display_name, label: "Your name"
= f.text_field :display_name, label: t('views.settings.profile.displayname')
.media#profile-picture-media
.pull-left
%img.img-rounded.profile--img{src: current_user.profile_picture.url(:medium)}
.media-body
= f.file_field :profile_picture
= f.file_field :profile_picture, label: t('views.settings.profile.avatar')
.row#profile-picture-crop-controls{style: 'display: none;'}
.col-sm-10.col-md-8
%strong Adjust your new avatar
%strong= t('views.settings.profile.avatar_adjust')
%img#profile-picture-cropper{src: current_user.profile_picture.url(:medium)}
.col-sm-2.col-md-4
.btn-group
@ -30,11 +30,11 @@
.pull-left
%img.img-rounded.header--img{src: current_user.profile_header.url(:mobile)}
.media-body
= f.file_field :profile_header
= f.file_field :profile_header, label: t('views.settings.profile.header')
.row#profile-header-crop-controls{style: 'display: none;'}
.col-sm-10.col-md-8
%strong Adjust your new header
%strong= t('views.settings.profile.header_adjust')
%img#profile-header-cropper{src: current_user.profile_header.url(:web)}
.col-sm-2.col-md-4
.btn-group
@ -43,13 +43,13 @@
%button#cropper-header-zoom-in.btn.btn-inverse{type: :button}
%i.fa.fa-search-plus
= f.text_field :motivation_header, label: "Motivation header", placeholder: 'Ask me anything!'
= f.text_field :motivation_header, label: t('views.settings.profile.motivation'), placeholder: t('views.settings.profile.placeholder.motivation')
= f.text_field :website, label: "Website", placeholder: 'http://example.com'
= f.text_field :website, label: t('views.settings.profile.website'), placeholder: 'http://example.com'
= f.text_field :location, label: "Location", placeholder: 'Where are you?'
= f.text_field :location, label: t('views.settings.profile.location'), placeholder: t('views.settings.profile.placeholder.location')
= f.text_area :bio, label: "Bio", placeholder: 'Tell us something nice about you!'
= f.text_area :bio, label: t('views.settings.profile.bio'), placeholder: t('views.settings.profile.placeholder.bio')
- for attrib in %i(crop_x crop_y crop_w crop_h)
= f.hidden_field attrib, id: attrib
@ -57,4 +57,4 @@
- for attrib in %i(crop_h_x crop_h_y crop_h_w crop_h_h)
= f.hidden_field attrib, id: attrib
= f.submit "Save settings", class: 'btn btn-primary'
= f.submit t('views.actions.save'), class: 'btn btn-primary'

View file

@ -7,8 +7,8 @@
.panel-body
= bootstrap_form_for(current_user, url: {action: "edit_privacy"}, method: "patch") do |f|
= f.check_box :privacy_allow_anonymous_questions, label: "Allow anonymous questions"
= f.check_box :privacy_allow_public_timeline, label: "Show your answers in the public timeline"
= f.check_box :privacy_allow_stranger_answers, label: "Allow other people to answer your questions"
= f.check_box :privacy_allow_anonymous_questions, label: t('views.settings.privacy.anonymous')
= f.check_box :privacy_allow_public_timeline, label: t('views.settings.privacy.public')
= f.check_box :privacy_allow_stranger_answers, label: t('views.settings.privacy.stranger')
= f.submit "Save settings", class: 'btn btn-primary'
= f.submit t('views.actions.save'), class: 'btn btn-primary'

View file

@ -15,5 +15,5 @@
- if @questions.next_page
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @questions.current_page }}
Load more
= t 'views.actions.load'
.visible-xs= render 'shared/links'

View file

@ -18,7 +18,7 @@
- if @answers.next_page
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @answers.current_page }}
Load more
= t 'views.actions.load'
.visible-xs= render 'shared/links'
- if user_signed_in?
= render 'user/modal_group_memberships'

View file

@ -16,7 +16,7 @@
- if @users.next_page
%button#load-more-btn.btn.btn-default{type: :button, data: { current_page: @users.current_page }}
Load more
= t 'views.actions.load'
.visible-xs= render 'shared/links'
- if user_signed_in?
= render 'user/modal_group_memberships'

View file

@ -24,6 +24,11 @@ module Justask
# Use Sidekiq for background jobs
config.active_job.queue_adapter = :sidekiq
config.i18n.default_locale = "en"
config.i18n.fallbacks = true
config.i18n.enforce_available_locales = false
# DEPRECATION WARNING: Currently, Active Record suppresses errors raised
# within `after_rollback`/`after_commit` callbacks and only print them to the logs.
# In the next version, these errors will no longer be suppressed.

28
config/i18n-js.yml Normal file
View file

@ -0,0 +1,28 @@
# Split context in several files.
#
# By default only one file with all translations is exported and
# no configuration is required. Your settings for asset pipeline
# are automatically recognized.
#
# If you want to split translations into several files or specify
# locale contexts that will be exported, just use this file to do
# so.
#
# For more informations about the export options with this file, please
# refer to the README
#
#
# If you're going to use the Rails 3.1 asset pipeline, change
# the following configuration to something like this:
#
# translations:
# - file: "app/assets/javascripts/i18n/translations.js"
#
# If you're running an old version, you can use something
# like this:
#
fallbacks: :default_locale
translations:
- file: 'public/javascripts/i18n/%{locale}.js'
only: ['*.frontend.*', '*.views.actions.*']

View file

@ -6,3 +6,4 @@ Rails.application.config.assets.version = '1.0'
# Precompile additional assets.
# application.js, application.css, and all non-JS/CSS in app/assets folder are already added.
Rails.application.config.assets.precompile += %w( moderation.js )
Rails.application.config.assets.precompile += %w( i18n.js )

View file

@ -1,59 +0,0 @@
# Additional translations at https://github.com/plataformatec/devise/wiki/I18n
en:
devise:
confirmations:
confirmed: "Your account was successfully confirmed."
send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive an email with instructions about how to confirm your account in a few minutes."
failure:
already_authenticated: "You are already signed in."
inactive: "Your account is not activated yet."
invalid: "Invalid user name or password."
locked: "Your account is locked."
last_attempt: "You have one more attempt before your account will be locked."
not_found_in_database: "Invalid user name or password."
timeout: "Your session expired. Please sign in again to continue."
unauthenticated: "You need to sign in or sign up before continuing."
unconfirmed: "You have to confirm your account before continuing."
mailer:
confirmation_instructions:
subject: "Confirmation instructions"
reset_password_instructions:
subject: "Reset password instructions"
unlock_instructions:
subject: "Unlock Instructions"
omniauth_callbacks:
failure: "Could not authenticate you from %{kind} because \"%{reason}\"."
success: "Successfully authenticated from %{kind} account."
passwords:
no_token: "You can't access this page without coming from a password reset email. If you do come from a password reset email, please make sure you used the full URL provided."
send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
send_paranoid_instructions: "If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes."
updated: "Your password was changed successfully. You are now signed in."
updated_not_active: "Your password was changed successfully."
registrations:
destroyed: "Bye! Your account was successfully cancelled. We hope to see you again soon."
signed_up: "Welcome! You have signed up successfully."
signed_up_but_inactive: "You have signed up successfully. However, we could not sign you in because your account is not yet activated."
signed_up_but_locked: "You have signed up successfully. However, we could not sign you in because your account is locked."
signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please open the link to activate your account."
update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm link to finalize confirming your new email address."
updated: "You updated your account successfully."
sessions:
signed_in: "Signed in successfully."
signed_out: "Signed out successfully."
unlocks:
send_instructions: "You will receive an email with instructions about how to unlock your account in a few minutes."
send_paranoid_instructions: "If your account exists, you will receive an email with instructions about how to unlock it in a few minutes."
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
errors:
messages:
already_confirmed: "was already confirmed, please try signing in"
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
expired: "has expired, please request a new one"
not_found: "not found"
not_locked: "was not locked"
not_saved:
one: "1 error prohibited this %{resource} from being saved:"
other: "%{count} errors prohibited this %{resource} from being saved:"

View file

@ -20,4 +20,453 @@
# available at http://guides.rubyonrails.org/i18n.html.
en:
hello: "Hello world"
frontend:
load: "Load more"
success:
title: "Success!"
error:
title: "Uh-oh..."
message: "An error occurred, a developer should check the console for details"
subscription:
subscribe: "Successfully subscribed."
unsubscribe: "Successfully unsubscribed."
fail:
subscribe: "Failed to subscribe to answer."
unsubscribe: "Failed to unsubscribe from answer."
group:
confirm:
title: "Really delete this group?"
text: "You will not be able to recover this group."
destroy_question:
confirm:
title: "Are you sure?"
text: "The question will be moved back to your inbox, but it won't delete any posts to social media."
destroy_comment:
confirm:
title: "Really delete?"
text: "You will not be able to recover this comment."
destroy_report:
confirm:
title: "Really delete?"
text: "You will not be able to recover this report."
destroy_own:
confirm:
title: "Are you sure?"
text: "The question will be removed."
inbox:
empty: "Nothing to see here."
confirm_all:
title: "Really delete %{count} questions?"
text: "They will be gone forever."
confirm:
title: "Really delete?"
text: "This question will be gone forever."
report:
confirm:
title: "Really report this %{type}?"
text: "A moderator will review your report and decide what happens.\nIf you'd like, you can also specify a reason."
input: "Specify a reason..."
flash:
ban:
error: "I'm sorry, %{name}, I'm afraid I can't do that."
reason: "Ban reason: %{reason}"
until: "Banned until: %{time}"
service:
create:
success: "Successfully added service"
error: "Could not add service :("
failure: "An error occurred"
destroy: "Successfully removed service"
user:
update:
text: "Your profile has been updated!"
avatar: " It might take a few minutes until your new profile picture is shown everywhere."
header: " It might take a few minutes until your new profile header is shown everywhere."
error: "An error occurred. ;_;"
update_privacy:
success: "Your privacy settings have been updated!"
error: "An error occurred. ;_;"
messages:
noscript: "Please activate JavaScript."
error: "An error occurred."
parameter_error: "%{parameter} is required."
noauth: "requires authentication"
answer:
create:
fail: "Question is not in your inbox."
privacy_stronk: "This user does not want other users to answer their question."
peter_dinklage: "Answer is too short."
okay: "Successfully answered question."
destroy:
nopriv: "can't delete other people's answers"
okay: "Successfully deleted answer."
comment:
create:
rec_inv: "Your comment is too long."
okay: "Comment posted successfully."
destroy:
nopriv: "can't delete other people's comments"
okay: "Successfully deleted comment."
friend:
create:
fail: "You are already following that user."
okay: "Successfully followed user."
destroy:
fail: "You are not following that user."
okay: "Successfully unfollowed user."
group:
create:
noname: "Please give that group a name."
toolong: "Group name too long (30 characters max.)"
notfound: "Could not find user."
exists: "Group already exists."
okay: "Successfully created group."
destroy:
notfound: "Could not find group."
okay: "Successfully deleted group."
membership:
notfound: "Group not found."
add: "Successfully added user to group."
remove: "Successfully removed user from group."
inbox:
create:
okay: "Successfully added new question."
remove:
fail: "question not in your inbox"
okay: "Successfully deleted question."
remove_all:
okay: "Successfully deleted questions."
moderation:
vote:
fail: "You have already voted on this report."
okay: "Successfully voted on report."
destroy_vote:
fail: "You have not voted on that report."
okay: "Successfully removed vote from report."
destroy_report:
fail: "Something bad happened!"
okay: "WHERE DID IT GO??? OH NO!!!"
create_comment:
rec_inv: "Your comment is too long."
okay: "Comment posted successfully."
destroy_comment:
nopriv: "can't delete other people's comments"
okay: "Successfully deleted comment."
ban:
error: "Weird..."
nopriv: "You cannot ban an administrator!"
unban: "Unbanned user."
perma: "Permanently banned user."
temp: "Banned user until %{date}"
privilege:
nope: "nope!"
nopriv: "You'd better check YOUR privileges first!"
checked: "Successfully checked this user's %{privilege} privilege."
question:
destroy:
not_found: "Question does not exist"
not_authorized: "You are not allowed to delete this question"
okay: "Successfully deleted question."
create:
rec_inv: "Your question is too long."
not_found: "Group not found"
okay: "Question asked successfully."
preview:
fail: "Failed to render markdown."
okay: "Successfully rendered markdown."
report:
create:
login: "login required"
unknown: "unknown type"
not_found: "Could not find %{parameter}"
okay: "%{parameter} reported. A moderator will decide what happens with the #{parameter}."
smile:
create:
fail: "You have already smiled that answer."
okay: "Successfully smiled answer."
destroy:
fail: "You have not smiled that answer."
okay: "Successfully unsmiled answer."
create_comment:
fail: "You have already smiled that comment."
okay: "Successfully smiled comment."
destroy_comment:
fail: "You have not smiled that comment."
okay: "Successfully unsmiled comment."
subscription:
torpedo: "418 I'm a torpedo"
views:
placeholder:
inbox: "Write your answer here..."
comment: "Comment..."
question: "Type your question here…"
notifications:
show: "Show all notifications"
mark: " and mark them as read"
answer:
body: "answered %{question} %{time} ago"
question: "your question"
relationship:
body: "followed you %{time} ago"
smile:
body: "smiled at %{content} %{time} ago" # see below for 'content' vvvv
answer: "your answer" # content if smile, 'smiled at your answer'
comment: "your comment" # content if commentsmile, 'smiled at your comment'
comment:
body: "commented on %{content} %{time} ago" # see below for 'content' vvvv
your: "your answer" # 'commented on your answer'
their: "their answer" # 'commented on their answer'
user: "%{user}'s answer" # 'commented on user's asnwer'
# all three have the 'user' variable
tabs:
all: "All notifications"
answer: "Answers"
smile: "Smiles"
comment: "Comments"
commentsmile: "Comment Smiles"
relationship: "Followers"
inbox:
empty: "Nothing to see here."
sidebar:
questions:
title: "Out of questions?"
button: "Get new question"
share:
title: "Share"
button: "Share on %{service}"
actions:
title: "Actions"
button: "Delete all questions"
entry:
asked: "%{user} asked %{time} ago"
response: "response"
sharing:
title: "Sharing"
post: "Post to %{service}"
none: "You have not connected any services yet. Visit your %{settings} to connect one."
settings: "service settings"
general:
answer: "Answer"
question: "Question"
comment: "Comment"
smile: "Smile"
follower: "Follower"
following: "Following"
timeline: "Timeline"
public: "Public"
user: "User"
terms: "Terms of Service"
privacy: "Privacy Policy"
about: "About"
group:
title: "Group"
members: "Members"
actions:
title: "Actions"
ask: "Ask"
ask_question: "Ask a question"
answer: "Answer"
options: "Options"
anonymous: "Hide your name"
delete: "Delete"
report: "Report"
return: "Return to Inbox"
subscribe: "Subscribe"
unsubscribe: "Unsubscribe"
view: "View comment smiles"
load: "Load more"
follow: "Follow"
unfollow: "Unfollow"
group: "Manage group memberships"
ban: "Ban Control"
privilege: "Check %{user}'s privileges"
save: "Save changes"
cancel: "Cancel"
close: "Close"
done: "Done"
y: "Yes"
n: "No"
sessions:
destroy: "Logout"
create: "Sign in"
new: "Sign up"
info: "With signing up you accept our %{terms}"
moderation:
tabs:
all: "All reports"
moderationbox:
reported: "%{user} reported a %{content} %{time} ago"
reason: "Reason:"
view: "View reported %{content}"
question:
title: "This question was not in your inbox? Answer it here!"
navigation:
timeline: "Timeline"
inbox: "Inbox"
discover: "Discover"
notifications: "Notifications"
show: "View profile"
settings: "Settings"
admin: "Kontrollzentrum"
sidekiq: "Sidekiq"
moderation: "Moderation Panel"
front:
subtitle: "Ask questions, give answers and learn more about your friends."
ask:
title: "Ask and answer questions"
desc: "With %{app_title} you can ask people questions and answer questions from other users or unregistered people. Want to know something more? Keep the discussion ongoing in the comments!"
follow:
title: "Follow users and get followed"
desc: "Following users allows you to get a personalized feed of all people you want to know more about. You can also send a question to all your followers at once!"
share:
title: "Sharing to other networks"
desc: "Want to share your answer to a question so that more people read it? With a simple click on the answer button, your answer is shared wherever you want!"
about:
subtitle: "About our service, features and other information"
links:
title: "Links"
desc: "Important pages and social media profiles from the %{app_title} team, which are recommended to visit!"
opensource:
title: "Open Source"
warning: "%{app_title} is running on unfinished code, full of bugs. Caveat emptor."
desc: "Want to contribute? If you are a Ruby developer, CoffeeScript coder or frontend designer, you can now help %{app_title} to get the features everyone wanted by forking our %{github}. If that's not the case, you can still report bugs and request features at our %{bugtracker}."
github: "Github repository"
bugtracker: "bug tracker"
repository:
title: "Main Repository"
desc: "The place where all the code magic and fixing happens!"
contributors:
title: "Contributors"
desc: "These people have contributed to %{app_title}'s source code."
howto: "Want to get listed here? %{fork} and create a new pull request with your changes."
fork: "Fork this repo"
team:
title: "The Team"
desc: "The people behind %{app_title}!"
moderators:
title: "Moderators"
desc: "The people on %{app_title} that look after you!"
funding:
title: "Funding"
desc: "People which (previously) donated to %{app_title}!"
statistics:
title: "Statistics"
desc: "All-time statistics for %{app_title}, updated every time you refresh the page!"
discover:
title: "Discover"
subtitle: "The perfect place to find interesting content from the last week on %{app_title}!"
content:
title: "Popular Content"
desc: "Answers with most smiles and most answered questions"
tab:
answers: "Most Liked"
questions: "Most Answers"
comments: "Most Controversial"
people:
title: "People"
desc: "Newcomers and people who asked the most questions"
tab:
new: "New Users"
questions: "Active Askers"
answers: "Most Answers"
userbox:
new: "registered %{time} ago"
answers: "answered %{questions}"
questions: "asked %{questions}"
answerbox:
asked: "%{user} asked %{time} ago"
read: "Read the entire answer"
answered: "%{hide} %{user}" # resolves into "Answered by %{user}"
hide: "Answered by" # ^
time: "%{time} ago"
no_smile: "No one smiled this, yet."
no_comment: "There are no comments yet."
commentsmile: "People who smiled this comment"
questionbox:
title: "Ask something!"
banned: "This user got hit with ye olde banhammer."
required: "This user does not want to get asked by strangers. Why don't you %{signup}?"
load: "Asking..."
promote:
message: "Your question has been sent."
create: "Create an account"
another: "Ask another question"
join: "Join %{app_title} today! You'll be able to follow and ask people you know and a lot more."
settings:
tabs:
account: "Account"
profile: "Profile"
privacy: "Privacy"
sharing: "Sharing"
account:
modal:
title: "Save account changes"
username: "User name"
email: "Email address"
email_confirm: "Currently awaiting confirmation for %{resource}"
password: "Password"
password_confirm: "Confirm password"
password_help: "Leave this blank if you don't want to change it"
password_current: "Current password"
password_current_help: "We need your current password to confirm your changes"
delete: "Delete my account"
unsatisfied: "Unsatisfied?"
back: "Back"
profile:
displayname: "Your name"
avatar: "Profile picture"
avatar_adjust: "Adjust your new avatar"
header: "Profile header"
header_adjust: "Adjust your new header"
motivation: "Motivation header"
website: "Website"
location: "Location"
bio: "Bio"
placeholder:
motivation: "Ask me anything!"
location: "Where are you?"
bio: "Tell us something nice about you!"
privacy:
anonymous: "Allow anonymous questions"
public: "Show your answers in the public timeline"
stranger: "Allow other people to answer your questions"
service:
enabled: "Sharing is enabled for the following services:"
none: "You have not connected any services yet."
connect: "Connect to %{service}"
disconnect: "Disconnect"
confirm: "Really disconnect service %{service}?"
modal:
ask:
title: "Ask your followers"
choose: "Choose group:"
loading: "Asking..."
bancontrol:
title: "Ban Control Center"
ban: "Ban?"
permanent: "Permanently?"
reason: "Reason"
hammertime: "Hammer Time"
group:
title: "Manage group memberships"
tabs:
main: "Groups"
create: "Create new group"
create: "Create group"
name: "Group name"
members: "members"
privilege:
blogger: "The user gets that privilege if they blogged something (nice) about Retrospring."
contributor: "This user has contributed to justask (the software behind Retrospring)."
supporter: "This user monetarily supports the site."
moderator: "Someone trustworthy enough to help managing reports."
admin: "This user is part of the core team."
user:
follows_you: "Follows you"
title:
admin: "Admin"
moderator: "Moderator"
supporter: "Supporter"
contributor: "Contributor"
blogger: "Blogger"
banned: "Banned"

View file

@ -0,0 +1,5 @@
class AddLocaleToUser < ActiveRecord::Migration
def change
add_column :users, :locale, :string
end
end

View file

@ -21,7 +21,7 @@ feature "User profile page", :devise do
expect(page).to have_text("FOLLOWING")
click_link 'Followers'
click_link 'Follower'
page.driver.render Rails.root.join("tmp/#{Time.now.to_i}_3.png"), full: true
expect(page).to have_text(me.screen_name)
end

View file

@ -24,8 +24,6 @@ feature "Inbox", :devise do
login_as me, scope: :user
visit root_path
expect(page).to have_text('1 new question'.upcase)
page.driver.render Rails.root.join("tmp/#{Time.now.to_i}_1.png"), full: true
click_link "Inbox"
expect(page).to have_text(question.content)

137
vendor/assets/javascripts/js.cookie.js vendored Normal file
View file

@ -0,0 +1,137 @@
/*!
* JavaScript Cookie v2.0.0-pre
* https://github.com/js-cookie/js-cookie
*
* Copyright 2006, 2015 Klaus Hartl
* Released under the MIT license
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
define(factory);
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
var _OldCookies = window.Cookies;
var api = window.Cookies = factory(window.jQuery);
api.noConflict = function () {
window.Cookies = _OldCookies;
return api;
};
}
}(function () {
function extend () {
var i = 0;
var result = {};
for (; i < arguments.length; i++) {
var attributes = arguments[ i ];
for (var key in attributes) {
result[key] = attributes[key];
}
}
return result;
}
function init (converter) {
function api (key, value, attributes) {
var result;
// Write
if (arguments.length > 1) {
attributes = extend({
path: '/'
}, api.defaults, attributes);
if (typeof attributes.expires === 'number') {
var expires = new Date();
expires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);
attributes.expires = expires;
}
try {
result = JSON.stringify(value);
if (/^[\{\[]/.test(result)) {
value = result;
}
} catch (e) {}
value = encodeURIComponent(String(value));
value = value.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
key = encodeURIComponent(String(key));
key = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);
key = key.replace(/[\(\)]/g, escape);
return (document.cookie = [
key, '=', value,
attributes.expires && '; expires=' + attributes.expires.toUTCString(), // use expires attribute, max-age is not supported by IE
attributes.path && '; path=' + attributes.path,
attributes.domain && '; domain=' + attributes.domain,
attributes.secure && '; secure'
].join(''));
}
// Read
if (!key) {
result = {};
}
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling "get()"
var cookies = document.cookie ? document.cookie.split('; ') : [];
var rdecode = /(%[0-9A-Z]{2})+/g;
var i = 0;
for (; i < cookies.length; i++) {
var parts = cookies[i].split('=');
var name = parts[0].replace(rdecode, decodeURIComponent);
var cookie = parts.slice(1).join('=');
if (cookie.charAt(0) === '"') {
cookie = cookie.slice(1, -1);
}
cookie = converter && converter(cookie, name) || cookie.replace(rdecode, decodeURIComponent);
if (this.json) {
try {
cookie = JSON.parse(cookie);
} catch (e) {}
}
if (key === name) {
result = cookie;
break;
}
if (!key) {
result[name] = cookie;
}
}
return result;
}
api.get = api.set = api;
api.getJSON = function () {
return api.apply({
json: true
}, [].slice.call(arguments));
};
api.defaults = {};
api.remove = function (key, attributes) {
api(key, '', extend(attributes, {
expires: -1
}));
};
api.withConverter = init;
return api;
}
return init();
}));