diff --git a/.gitignore b/.gitignore index e21f5f45..e701ee4e 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/Gemfile b/Gemfile index e60d4714..e265cbbc 100644 --- a/Gemfile +++ b/Gemfile @@ -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' diff --git a/Gemfile.lock b/Gemfile.lock index 089e06d2..041fa292 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -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 diff --git a/app/assets/javascripts/answerbox/comment.coffee b/app/assets/javascripts/answerbox/comment.coffee index f81de95a..4b93cdb2 100644 --- a/app/assets/javascripts/answerbox/comment.coffee +++ b/app/assets/javascripts/answerbox/comment.coffee @@ -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' diff --git a/app/assets/javascripts/answerbox/comment/destroy.coffee b/app/assets/javascripts/answerbox/comment/destroy.coffee index 36505fa8..277dea8c 100644 --- a/app/assets/javascripts/answerbox/comment/destroy.coffee +++ b/app/assets/javascripts/answerbox/comment/destroy.coffee @@ -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) -> \ No newline at end of file + showNotification translate('frontend.error.message'), false + complete: (jqxhr, status) -> diff --git a/app/assets/javascripts/answerbox/comment/smile.coffee b/app/assets/javascripts/answerbox/comment/smile.coffee index d713de7a..6b25dfa6 100644 --- a/app/assets/javascripts/answerbox/comment/smile.coffee +++ b/app/assets/javascripts/answerbox/comment/smile.coffee @@ -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 diff --git a/app/assets/javascripts/answerbox/destroy.coffee b/app/assets/javascripts/answerbox/destroy.coffee index b164012a..5a7f5188 100644 --- a/app/assets/javascripts/answerbox/destroy.coffee +++ b/app/assets/javascripts/answerbox/destroy.coffee @@ -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) -> diff --git a/app/assets/javascripts/answerbox/smile.coffee b/app/assets/javascripts/answerbox/smile.coffee index ee029193..ed26ec5f 100644 --- a/app/assets/javascripts/answerbox/smile.coffee +++ b/app/assets/javascripts/answerbox/smile.coffee @@ -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 diff --git a/app/assets/javascripts/answerbox/subscribe.coffee b/app/assets/javascripts/answerbox/subscribe.coffee index 4c937dd4..febfc965 100644 --- a/app/assets/javascripts/answerbox/subscribe.coffee +++ b/app/assets/javascripts/answerbox/subscribe.coffee @@ -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) -> diff --git a/app/assets/javascripts/application.js.erb.coffee b/app/assets/javascripts/application.js.erb.coffee index 1cfd3fa2..6f7b98f3 100644 --- a/app/assets/javascripts/application.js.erb.coffee +++ b/app/assets/javascripts/application.js.erb.coffee @@ -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" diff --git a/app/assets/javascripts/groups.coffee b/app/assets/javascripts/groups.coffee index 6b88bb41..9e2f86d1 100644 --- a/app/assets/javascripts/groups.coffee +++ b/app/assets/javascripts/groups.coffee @@ -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) -> diff --git a/app/assets/javascripts/inbox.coffee b/app/assets/javascripts/inbox.coffee index 0741ce09..d6440e07 100644 --- a/app/assets/javascripts/inbox.coffee +++ b/app/assets/javascripts/inbox.coffee @@ -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' \ No newline at end of file + btn[0].dataset.state = 'hidden' diff --git a/app/assets/javascripts/moderation/ban.coffee b/app/assets/javascripts/moderation/ban.coffee index ebb4d7b8..0529a8af 100644 --- a/app/assets/javascripts/moderation/ban.coffee +++ b/app/assets/javascripts/moderation/ban.coffee @@ -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", -> diff --git a/app/assets/javascripts/moderation/comment.coffee b/app/assets/javascripts/moderation/comment.coffee index 5fe965c0..f3be655b 100644 --- a/app/assets/javascripts/moderation/comment.coffee +++ b/app/assets/javascripts/moderation/comment.coffee @@ -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) -> diff --git a/app/assets/javascripts/moderation/destroy.coffee b/app/assets/javascripts/moderation/destroy.coffee index cd52437e..ba35315f 100644 --- a/app/assets/javascripts/moderation/destroy.coffee +++ b/app/assets/javascripts/moderation/destroy.coffee @@ -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) -> \ No newline at end of file + showNotification translate('frontend.error.message'), false + complete: (jqxhr, status) -> diff --git a/app/assets/javascripts/moderation/privileges.coffee b/app/assets/javascripts/moderation/privileges.coffee index c64c4c38..268b29b3 100644 --- a/app/assets/javascripts/moderation/privileges.coffee +++ b/app/assets/javascripts/moderation/privileges.coffee @@ -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" diff --git a/app/assets/javascripts/moderation/vote.coffee b/app/assets/javascripts/moderation/vote.coffee index 812a1838..3c6cf999 100644 --- a/app/assets/javascripts/moderation/vote.coffee +++ b/app/assets/javascripts/moderation/vote.coffee @@ -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' \ No newline at end of file + other_btn[0].dataset.action = 'vote' diff --git a/app/assets/javascripts/question.coffee b/app/assets/javascripts/question.coffee index 09c26ecb..d07cb337 100644 --- a/app/assets/javascripts/question.coffee +++ b/app/assets/javascripts/question.coffee @@ -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" diff --git a/app/assets/javascripts/questionbox/all.coffee b/app/assets/javascripts/questionbox/all.coffee index f458b601..ea884283 100644 --- a/app/assets/javascripts/questionbox/all.coffee +++ b/app/assets/javascripts/questionbox/all.coffee @@ -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" diff --git a/app/assets/javascripts/questionbox/destroy.coffee b/app/assets/javascripts/questionbox/destroy.coffee index 63f590e5..521e6705 100644 --- a/app/assets/javascripts/questionbox/destroy.coffee +++ b/app/assets/javascripts/questionbox/destroy.coffee @@ -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) -> diff --git a/app/assets/javascripts/questionbox/user.coffee b/app/assets/javascripts/questionbox/user.coffee index 32577b9d..507372f5 100644 --- a/app/assets/javascripts/questionbox/user.coffee +++ b/app/assets/javascripts/questionbox/user.coffee @@ -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' \ No newline at end of file + ($ "button[name=qb-ask]").trigger 'click' diff --git a/app/assets/javascripts/report.coffee b/app/assets/javascripts/report.coffee index cd77eb1e..66cf0a3f 100644 --- a/app/assets/javascripts/report.coffee +++ b/app/assets/javascripts/report.coffee @@ -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 diff --git a/app/assets/javascripts/user.coffee b/app/assets/javascripts/user.coffee index 5a2cf991..e2b07a99 100644 --- a/app/assets/javascripts/user.coffee +++ b/app/assets/javascripts/user.coffee @@ -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 diff --git a/app/controllers/ajax/answer_controller.rb b/app/controllers/ajax/answer_controller.rb index b55c8856..d35ff3e9 100644 --- a/app/controllers/ajax/answer_controller.rb +++ b/app/controllers/ajax/answer_controller.rb @@ -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 diff --git a/app/controllers/ajax/comment_controller.rb b/app/controllers/ajax/comment_controller.rb index daa87c05..c854ff9d 100644 --- a/app/controllers/ajax/comment_controller.rb +++ b/app/controllers/ajax/comment_controller.rb @@ -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 diff --git a/app/controllers/ajax/friend_controller.rb b/app/controllers/ajax/friend_controller.rb index 51aaf4a6..965a7876 100644 --- a/app/controllers/ajax/friend_controller.rb +++ b/app/controllers/ajax/friend_controller.rb @@ -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 diff --git a/app/controllers/ajax/group_controller.rb b/app/controllers/ajax/group_controller.rb index 79fa383f..0c803c4f 100644 --- a/app/controllers/ajax/group_controller.rb +++ b/app/controllers/ajax/group_controller.rb @@ -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 diff --git a/app/controllers/ajax/inbox_controller.rb b/app/controllers/ajax/inbox_controller.rb index 36ef0124..9a8a2f3e 100644 --- a/app/controllers/ajax/inbox_controller.rb +++ b/app/controllers/ajax/inbox_controller.rb @@ -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 diff --git a/app/controllers/ajax/moderation_controller.rb b/app/controllers/ajax/moderation_controller.rb index de458089..d0ca6629 100644 --- a/app/controllers/ajax/moderation_controller.rb +++ b/app/controllers/ajax/moderation_controller.rb @@ -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 diff --git a/app/controllers/ajax/question_controller.rb b/app/controllers/ajax/question_controller.rb index b0af3ae7..c07305d2 100644 --- a/app/controllers/ajax/question_controller.rb +++ b/app/controllers/ajax/question_controller.rb @@ -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 diff --git a/app/controllers/ajax/report_controller.rb b/app/controllers/ajax/report_controller.rb index 47a1c581..7a8c53e2 100644 --- a/app/controllers/ajax/report_controller.rb +++ b/app/controllers/ajax/report_controller.rb @@ -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 diff --git a/app/controllers/ajax/smile_controller.rb b/app/controllers/ajax/smile_controller.rb index e7e10f5c..93aab9f4 100644 --- a/app/controllers/ajax/smile_controller.rb +++ b/app/controllers/ajax/smile_controller.rb @@ -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 diff --git a/app/controllers/ajax/subscription_controller.rb b/app/controllers/ajax/subscription_controller.rb index 40016e64..aaca19bb 100644 --- a/app/controllers/ajax/subscription_controller.rb +++ b/app/controllers/ajax/subscription_controller.rb @@ -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 diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index beed49fb..ffaae5e1 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -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 diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index d49a55a5..376efc52 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -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 diff --git a/app/controllers/user_controller.rb b/app/controllers/user_controller.rb index a3d3f416..33cad9e1 100644 --- a/app/controllers/user_controller.rb +++ b/app/controllers/user_controller.rb @@ -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 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 438ed29c..56f90b2d 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -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 diff --git a/app/views/devise/registrations/new.html.haml b/app/views/devise/registrations/new.html.haml index 3d5792d3..b90aee45 100644 --- a/app/views/devise/registrations/new.html.haml +++ b/app/views/devise/registrations/new.html.haml @@ -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" diff --git a/app/views/devise/sessions/new.html.haml b/app/views/devise/sessions/new.html.haml index e6e4e0d2..3ef2cdf2 100644 --- a/app/views/devise/sessions/new.html.haml +++ b/app/views/devise/sessions/new.html.haml @@ -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" diff --git a/app/views/discover/_userbox.html.haml b/app/views/discover/_userbox.html.haml index 3637a2a4..f6e99400 100644 --- a/app/views/discover/_userbox.html.haml +++ b/app/views/discover/_userbox.html.haml @@ -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'))) diff --git a/app/views/discover/index.html.haml b/app/views/discover/index.html.haml index 525f572e..810b577a 100644 --- a/app/views/discover/index.html.haml +++ b/app/views/discover/index.html.haml @@ -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 diff --git a/app/views/group/index.html.haml b/app/views/group/index.html.haml index 1ce3ecac..0d8493a8 100644 --- a/app/views/group/index.html.haml +++ b/app/views/group/index.html.haml @@ -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' diff --git a/app/views/inbox/_entry.html.haml b/app/views/inbox/_entry.html.haml index c93e7817..93adc252 100644 --- a/app/views/inbox/_entry.html.haml +++ b/app/views/inbox/_entry.html.haml @@ -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. \ No newline at end of file + %p= raw t('views.inbox.entry.sharing.none', settings: link_to(t('views.inbox.entry.sharing.settings'), services_path)) diff --git a/app/views/inbox/_sidebar.html.haml b/app/views/inbox/_sidebar.html.haml index dedb5906..b12bc91f 100644 --- a/app/views/inbox/_sidebar.html.haml +++ b/app/views/inbox/_sidebar.html.haml @@ -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 \ No newline at end of file + %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' diff --git a/app/views/inbox/show.html.haml b/app/views/inbox/show.html.haml index c597545b..b93fd016 100644 --- a/app/views/inbox/show.html.haml +++ b/app/views/inbox/show.html.haml @@ -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' diff --git a/app/views/layouts/_header.html.haml b/app/views/layouts/_header.html.haml index 106e06bd..6296893c 100644 --- a/app/views/layouts/_header.html.haml +++ b/app/views/layouts/_header.html.haml @@ -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' diff --git a/app/views/layouts/_messages.html.haml b/app/views/layouts/_messages.html.haml index 86ce825b..73ba513d 100644 --- a/app/views/layouts/_messages.html.haml +++ b/app/views/layouts/_messages.html.haml @@ -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"} × - %span.sr-only Close - = value \ No newline at end of file + %span.sr-only= t 'views.actions.close' + = value diff --git a/app/views/layouts/_notifications.html.haml b/app/views/layouts/_notifications.html.haml index 2bed92ba..93a442c4 100644 --- a/app/views/layouts/_notifications.html.haml +++ b/app/views/layouts/_notifications.html.haml @@ -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 diff --git a/app/views/layouts/_profile.html.haml b/app/views/layouts/_profile.html.haml index b7ab872a..24ca3437 100644 --- a/app/views/layouts/_profile.html.haml +++ b/app/views/layouts/_profile.html.haml @@ -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 \ No newline at end of file + = t 'views.sessions.destroy' diff --git a/app/views/layouts/application.html.haml b/app/views/layouts/application.html.haml index 291159f8..d381ce8f 100644 --- a/app/views/layouts/application.html.haml +++ b/app/views/layouts/application.html.haml @@ -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? diff --git a/app/views/moderation/_discussion.html.haml b/app/views/moderation/_discussion.html.haml index 231bb0f4..66a41285 100644 --- a/app/views/moderation/_discussion.html.haml +++ b/app/views/moderation/_discussion.html.haml @@ -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 diff --git a/app/views/moderation/_moderation_nav.html.haml b/app/views/moderation/_moderation_nav.html.haml index f33f013a..081abced 100644 --- a/app/views/moderation/_moderation_nav.html.haml +++ b/app/views/moderation/_moderation_nav.html.haml @@ -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') \ No newline at end of file + = 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') diff --git a/app/views/moderation/_moderation_tabs.html.haml b/app/views/moderation/_moderation_tabs.html.haml index 51363d73..f933578b 100644 --- a/app/views/moderation/_moderation_tabs.html.haml +++ b/app/views/moderation/_moderation_tabs.html.haml @@ -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') diff --git a/app/views/moderation/_moderationbox.html.haml b/app/views/moderation/_moderationbox.html.haml index 2e44b39e..60676dc8 100644 --- a/app/views/moderation/_moderationbox.html.haml +++ b/app/views/moderation/_moderationbox.html.haml @@ -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 diff --git a/app/views/notifications/_notification.html.haml b/app/views/notifications/_notification.html.haml index 4f569859..1cfd3de2 100644 --- a/app/views/notifications/_notification.html.haml +++ b/app/views/notifications/_notification.html.haml @@ -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 diff --git a/app/views/notifications/_notification_nav.html.haml b/app/views/notifications/_notification_nav.html.haml index f7aaa51e..513877dc 100644 --- a/app/views/notifications/_notification_nav.html.haml +++ b/app/views/notifications/_notification_nav.html.haml @@ -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') diff --git a/app/views/notifications/_notification_tabs.html.haml b/app/views/notifications/_notification_tabs.html.haml index 138ae2ff..e03b699b 100644 --- a/app/views/notifications/_notification_tabs.html.haml +++ b/app/views/notifications/_notification_tabs.html.haml @@ -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 diff --git a/app/views/question/show.html.haml b/app/views/question/show.html.haml index 5ccbc6c4..dbca8da0 100644 --- a/app/views/question/show.html.haml +++ b/app/views/question/show.html.haml @@ -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) diff --git a/app/views/services/index.html.haml b/app/views/services/index.html.haml index a198bce9..803ed7ac 100644 --- a/app/views/services/index.html.haml +++ b/app/views/services/index.html.haml @@ -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 diff --git a/app/views/shared/_answerbox.html.haml b/app/views/shared/_answerbox.html.haml index d1b4d95e..1878406b 100644 --- a/app/views/shared/_answerbox.html.haml +++ b/app/views/shared/_answerbox.html.haml @@ -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 } diff --git a/app/views/shared/_answerbox_buttons.html.haml b/app/views/shared/_answerbox_buttons.html.haml index f37b6738..b8de32c4 100644 --- a/app/views/shared/_answerbox_buttons.html.haml +++ b/app/views/shared/_answerbox_buttons.html.haml @@ -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' diff --git a/app/views/shared/_comment_smiles.html.haml b/app/views/shared/_comment_smiles.html.haml index 5aaa36b2..7eaee04d 100644 --- a/app/views/shared/_comment_smiles.html.haml +++ b/app/views/shared/_comment_smiles.html.haml @@ -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| diff --git a/app/views/shared/_comments.html.haml b/app/views/shared/_comments.html.haml index d302687b..aa22431d 100644 --- a/app/views/shared/_comments.html.haml +++ b/app/views/shared/_comments.html.haml @@ -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 diff --git a/app/views/shared/_links.html.haml b/app/views/shared/_links.html.haml index 2d3294a9..66245fbe 100644 --- a/app/views/shared/_links.html.haml +++ b/app/views/shared/_links.html.haml @@ -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 \ No newline at end of file + = link_to t('views.general.privacy'), privacy_policy_path diff --git a/app/views/shared/_modal_ask_followers.html.haml b/app/views/shared/_modal_ask_followers.html.haml index 1df6e78d..c7d14b21 100644 --- a/app/views/shared/_modal_ask_followers.html.haml +++ b/app/views/shared/_modal_ask_followers.html.haml @@ -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 \ No newline at end of file + %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' diff --git a/app/views/shared/_question.html.haml b/app/views/shared/_question.html.haml index a34f9dc6..393fad72 100644 --- a/app/views/shared/_question.html.haml +++ b/app/views/shared/_question.html.haml @@ -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 diff --git a/app/views/shared/_question_header.haml b/app/views/shared/_question_header.haml index 61400c46..5dcefad7 100644 --- a/app/views/shared/_question_header.haml +++ b/app/views/shared/_question_header.haml @@ -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 diff --git a/app/views/shared/_questionbox.html.haml b/app/views/shared/_questionbox.html.haml index 34c79e0a..30ecb92f 100644 --- a/app/views/shared/_questionbox.html.haml +++ b/app/views/shared/_questionbox.html.haml @@ -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 \ No newline at end of file + %p= raw t 'views.questionbox.required', signup: link_to(t('views.sessions.new'),new_user_registration_path) diff --git a/app/views/shared/_sidebar.html.haml b/app/views/shared/_sidebar.html.haml index d9304d8d..b8375a6a 100644 --- a/app/views/shared/_sidebar.html.haml +++ b/app/views/shared/_sidebar.html.haml @@ -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 }} diff --git a/app/views/shared/_smiles.html.haml b/app/views/shared/_smiles.html.haml index 2625f3bf..4e3db771 100644 --- a/app/views/shared/_smiles.html.haml +++ b/app/views/shared/_smiles.html.haml @@ -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 }} diff --git a/app/views/shared/_userbox.html.haml b/app/views/shared/_userbox.html.haml index 74d1222a..2c5e5e67 100644 --- a/app/views/shared/_userbox.html.haml +++ b/app/views/shared/_userbox.html.haml @@ -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 \ No newline at end of file + %h6.entry-subtext= t('views.general.answer').pluralize(user.answered_count) + = render 'user/actions', user: user, type: type diff --git a/app/views/static/_front.html.haml b/app/views/static/_front.html.haml index 5a281a59..fcf2be06 100644 --- a/app/views/static/_front.html.haml +++ b/app/views/static/_front.html.haml @@ -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" diff --git a/app/views/static/about.html.haml b/app/views/static/about.html.haml index 65e78eb8..9eb7760f 100644 --- a/app/views/static/about.html.haml +++ b/app/views/static/about.html.haml @@ -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" diff --git a/app/views/user/_account.html.haml b/app/views/user/_account.html.haml index 208d4d1f..70c0eeca 100644 --- a/app/views/user/_account.html.haml +++ b/app/views/user/_account.html.haml @@ -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" diff --git a/app/views/user/_actions.html.haml b/app/views/user/_actions.html.haml index 6b28cbac..ec19de32 100644 --- a/app/views/user/_actions.html.haml +++ b/app/views/user/_actions.html.haml @@ -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' diff --git a/app/views/user/_modal_ban.html.haml b/app/views/user/_modal_ban.html.haml index cdfb1fb8..63b374bd 100644 --- a/app/views/user/_modal_ban.html.haml +++ b/app/views/user/_modal_ban.html.haml @@ -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' diff --git a/app/views/user/_modal_group_item.html.haml b/app/views/user/_modal_group_item.html.haml index 406496be..820d88d8 100644 --- a/app/views/user/_modal_group_item.html.haml +++ b/app/views/user/_modal_group_item.html.haml @@ -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' diff --git a/app/views/user/_modal_group_memberships.html.haml b/app/views/user/_modal_group_memberships.html.haml index 6da03d2b..b8b1265a 100644 --- a/app/views/user/_modal_group_memberships.html.haml +++ b/app/views/user/_modal_group_memberships.html.haml @@ -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 \ No newline at end of file + %button.btn.btn-primary{name: 'gm-save', type: :button, data: { dismiss: :modal }}= t 'views.actions.done' diff --git a/app/views/user/_modal_privileges.html.haml b/app/views/user/_modal_privileges.html.haml index 265a3330..ae9988cf 100644 --- a/app/views/user/_modal_privileges.html.haml +++ b/app/views/user/_modal_privileges.html.haml @@ -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' diff --git a/app/views/user/_profile_info.html.haml b/app/views/user/_profile_info.html.haml index 0d1d866e..7e96f469 100644 --- a/app/views/user/_profile_info.html.haml +++ b/app/views/user/_profile_info.html.haml @@ -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? diff --git a/app/views/user/_settings_tabs.html.haml b/app/views/user/_settings_tabs.html.haml index 5583da38..f2f8ea41 100644 --- a/app/views/user/_settings_tabs.html.haml +++ b/app/views/user/_settings_tabs.html.haml @@ -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" \ No newline at end of file + .hidden-xs= render "shared/links" diff --git a/app/views/user/_stats.html.haml b/app/views/user/_stats.html.haml index 7ca49232..41446e44 100644 --- a/app/views/user/_stats.html.haml +++ b/app/views/user/_stats.html.haml @@ -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) diff --git a/app/views/user/edit.html.haml b/app/views/user/edit.html.haml index a2409b3a..d04ee81e 100644 --- a/app/views/user/edit.html.haml +++ b/app/views/user/edit.html.haml @@ -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' diff --git a/app/views/user/edit_privacy.html.haml b/app/views/user/edit_privacy.html.haml index 26aad1cc..5ac2c7ea 100644 --- a/app/views/user/edit_privacy.html.haml +++ b/app/views/user/edit_privacy.html.haml @@ -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' diff --git a/app/views/user/questions.html.haml b/app/views/user/questions.html.haml index e8f5d435..4691417f 100644 --- a/app/views/user/questions.html.haml +++ b/app/views/user/questions.html.haml @@ -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' diff --git a/app/views/user/show.html.haml b/app/views/user/show.html.haml index 00f5b723..8e2d714a 100644 --- a/app/views/user/show.html.haml +++ b/app/views/user/show.html.haml @@ -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' diff --git a/app/views/user/show_follow.html.haml b/app/views/user/show_follow.html.haml index d1d3878f..9c410115 100644 --- a/app/views/user/show_follow.html.haml +++ b/app/views/user/show_follow.html.haml @@ -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' diff --git a/config/application.rb b/config/application.rb index 4f627bb4..9d5f6122 100644 --- a/config/application.rb +++ b/config/application.rb @@ -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. diff --git a/config/i18n-js.yml b/config/i18n-js.yml new file mode 100644 index 00000000..50b4a08e --- /dev/null +++ b/config/i18n-js.yml @@ -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.*'] diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 1f4fa74b..0c0205fe 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -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 ) diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml deleted file mode 100644 index 3afc05cd..00000000 --- a/config/locales/devise.en.yml +++ /dev/null @@ -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:" diff --git a/config/locales/en.yml b/config/locales/en.yml index 06539571..3f38a62d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -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" diff --git a/db/migrate/20150526031159_add_locale_to_user.rb b/db/migrate/20150526031159_add_locale_to_user.rb new file mode 100644 index 00000000..fdea9cfd --- /dev/null +++ b/db/migrate/20150526031159_add_locale_to_user.rb @@ -0,0 +1,5 @@ +class AddLocaleToUser < ActiveRecord::Migration + def change + add_column :users, :locale, :string + end +end diff --git a/spec/features/users/follow_user_spec.rb b/spec/features/users/follow_user_spec.rb index 3d03347f..f2e71848 100644 --- a/spec/features/users/follow_user_spec.rb +++ b/spec/features/users/follow_user_spec.rb @@ -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 diff --git a/spec/features/users/inbox_spec.rb b/spec/features/users/inbox_spec.rb index 84844425..573c55de 100644 --- a/spec/features/users/inbox_spec.rb +++ b/spec/features/users/inbox_spec.rb @@ -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) diff --git a/vendor/assets/javascripts/js.cookie.js b/vendor/assets/javascripts/js.cookie.js new file mode 100644 index 00000000..116e62d8 --- /dev/null +++ b/vendor/assets/javascripts/js.cookie.js @@ -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(); +}));