diff --git a/Gruntfile.js b/Gruntfile.js index d778230751..3376be4c61 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -58,7 +58,7 @@ module.exports = function(grunt) { build: { files: [ {expand: true, cwd: 'public/', src: 'favicon.ico', dest: 'build/'}, - {expand: true, cwd: 'public/', src: 'bower_components/habitrpg-shared/dist/spritesmith.png', dest: 'build/'}, + {expand: true, cwd: 'public/', src: 'bower_components/habitrpg-shared/dist/spritesmith*.png', dest: 'build/'}, {expand: true, cwd: 'public/', src: 'bower_components/habitrpg-shared/img/sprites/backer-only/*.gif', dest: 'build/'}, {expand: true, cwd: 'public/', src: 'bower_components/habitrpg-shared/img/sprites/npc_ian.gif', dest: 'build/'}, {expand: true, cwd: 'public/', src: 'bower_components/bootstrap/dist/fonts/*', dest: 'build/'} diff --git a/migrations/20150130_birthday_goodies.js b/migrations/20150130_birthday_goodies.js new file mode 100644 index 0000000000..6c7c2e08c5 --- /dev/null +++ b/migrations/20150130_birthday_goodies.js @@ -0,0 +1,36 @@ +db.users.update( + {'items.gear.owned.armor_special_birthday':{$ne:null}}, + {$set:{'items.gear.owned.armor_special_birthday2015':false}}, + {multi:1} +) + +db.users.update( + {'items.gear.owned.armor_special_birthday':null}, + {$set:{'items.gear.owned.armor_special_birthday':false}}, + {multi:1} +) + +db.users.update({},{$inc:{ + 'items.food.Cake_Skeleton':1, + 'items.food.Cake_Base':1, + 'items.food.Cake_CottonCandyBlue':1, + 'items.food.Cake_CottonCandyPink':1, + 'items.food.Cake_Shade':1, + 'items.food.Cake_White':1, + 'items.food.Cake_Golden':1, + 'items.food.Cake_Zombie':1, + 'items.food.Cake_Desert':1, + 'items.food.Cake_Red':1 +}},{multi:1}) + +db.users.update( + {'achievements.habitBirthday':true}, + {$set:{'achievements.habitBirthdays':1}}, + {multi:1} +) + +db.users.update( + {}, + {$inc:{'achievements.habitBirthdays':1}}, + {multi:1} +) \ No newline at end of file diff --git a/migrations/20150131_birthday_goodies_fix_remove_robe.js b/migrations/20150131_birthday_goodies_fix_remove_robe.js new file mode 100644 index 0000000000..997cd8bdc1 --- /dev/null +++ b/migrations/20150131_birthday_goodies_fix_remove_robe.js @@ -0,0 +1,60 @@ +var migrationName = '20150131_birthday_goodies_fix_remove_robe.js'; +var authorName = 'Alys'; // in case script author needs to know when their ... +var authorUuid = 'd904bd62-da08-416b-a816-ba797c9ee265'; //... own data is done + +/** + * remove new birthday robes from people who don't have original birthday achievement + */ + +var dbserver = 'localhost:27017' // CHANGE THIS FOR PRODUCTION DATABASE + +var mongo = require('mongoskin'); +var _ = require('lodash'); + +var dbUsers = mongo.db(dbserver + '/habitrpg?auto_reconnect').collection('users'); + +var query = { + 'achievements.habitBirthday':{$exists:false} + }; + +var fields = { + 'items.gear.owned.armor_special_birthday2015':1 + }; + +console.warn('Updating users...'); +var progressCount = 1000; +var count = 0; +dbUsers.findEach(query, fields, {batchSize:250}, function(err, user) { + if (err) { return exiting(1, 'ERROR! ' + err); } + if (!user) { + console.warn('All appropriate users found and modified.'); + return displayData(); + } + count++; + + var unset = {'items.gear.owned.armor_special_birthday2015': 1}; + var set = {'migration': migrationName}; + // var inc = {'xyz':1, _v:1}; + dbUsers.update({_id:user._id}, {$unset:unset, $set:set}); // , $inc:inc}); + + if (count%progressCount == 0) console.warn(count + ' ' + user._id); + if (user._id == authorUuid) console.warn(authorName + ' processed'); + if (user._id == '9' ) console.warn('lefnire' + ' processed'); +}); + + +function displayData() { + console.warn('\n' + count + ' users processed\n'); + return exiting(0); +} + + +function exiting(code, msg) { + code = code || 0; // 0 = success + if (code && !msg) { msg = 'ERROR!'; } + if (msg) { + if (code) { console.error(msg); } + else { console.log( msg); } + } + process.exit(code); +} diff --git a/migrations/20150201_recapture_emails_phase_update.js b/migrations/20150201_recapture_emails_phase_update.js new file mode 100644 index 0000000000..51fd73a6fa --- /dev/null +++ b/migrations/20150201_recapture_emails_phase_update.js @@ -0,0 +1,7 @@ +db.users.update({ + 'flags.recaptureEmailsPhase': { + $gt: 0 + } +},{$inc:{ + 'flags.recaptureEmailsPhase':1 +}},{multi:1}) \ No newline at end of file diff --git a/package.json b/package.json index 842237dbdb..adb9383150 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "loggly": "~1.0.8", "method-override": "~2.2.0", "moment": "~2.8.3", - "mongoose": "~3.8.17", + "mongoose": "~3.8.20", "mongoose-id-autoinc": "~2013.7.14-4", "nconf": "~0.6.9", "newrelic": "~1.11.2", @@ -67,8 +67,7 @@ "www.habitrpg.com" ], "engines": { - "node": "0.10.x", - "npm": "1.2.x" + "node": "0.10.x" }, "scripts": { "test": "./test/run_tests.sh", diff --git a/public/emails/images/one-day-v1.png b/public/emails/images/one-day-v1.png new file mode 100644 index 0000000000..dafd5cac8f Binary files /dev/null and b/public/emails/images/one-day-v1.png differ diff --git a/public/js/controllers/rootCtrl.js b/public/js/controllers/rootCtrl.js index 9360daf469..4560c58383 100644 --- a/public/js/controllers/rootCtrl.js +++ b/public/js/controllers/rootCtrl.js @@ -164,7 +164,7 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ $rootScope.charts[id] = (history.length == 0) ? false : !$rootScope.charts[id]; if (task && task._editing) task._editing = false; } - matrix = [['Date', 'Score']]; + matrix = [[env.t('date'), env.t('score')]]; _.each(history, function(obj) { matrix.push([moment(obj.date).format('MM/DD/YY'), obj.value]); }); @@ -220,7 +220,7 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ $http.post(ApiUrl.get() + '/api/v2/user/class/cast/'+spell.key+'?targetType='+type+'&targetId='+targetId) .success(function(){ - var msg = window.env.t('youCast', {spell: spell.text()}); + var msg = window.env.t('youCast', {spell: spell.text()}); switch (type) { case 'task': msg = window.env.t('youCastTarget', {spell: spell.text(), target: target.text});break; case 'user': msg = window.env.t('youCastTarget', {spell: spell.text(), target: target.profile.name});break; diff --git a/src/models/user.js b/src/models/user.js index a16f0936cf..23d97e88c2 100644 --- a/src/models/user.js +++ b/src/models/user.js @@ -49,7 +49,8 @@ var UserSchema = new Schema({ rebirths: Number, rebirthLevel: Number, perfect: Number, - habitBirthday: Boolean, + habitBirthday: Boolean, // TODO: Deprecate this. Superseded by habitBirthdays + habitBirthdays: Number, valentine: Number, costumeContest: Boolean, nye: Number @@ -130,7 +131,7 @@ var UserSchema = new Schema({ levelDrops: {type:Schema.Types.Mixed, 'default':{}}, chatRevoked: Boolean, // Used to track the status of recapture emails sent to each user, - // can be 0 - no email sent - 1, 2 or 3 - 3 means no more email will be sent to the user + // can be 0 - no email sent - 1, 2, 3 or 4 - 4 means no more email will be sent to the user recaptureEmailsPhase: {type: Number, 'default': 0}, communityGuidelinesAccepted: {type: Boolean, 'default': false} }, diff --git a/views/options/profile.jade b/views/options/profile.jade index 19a2ba48d1..300d207e0c 100644 --- a/views/options/profile.jade +++ b/views/options/profile.jade @@ -264,7 +264,7 @@ mixin backgrounds(mobile) +gemCost(7) button.btn.btn-xs(ng-click="unlock(setKeys('background',#{JSON.stringify(bgs)}))")!= env.t('unlockSet',{cost:15}) + ' ' each bg,k in bgs - button.customize-option(type='button', class='background_#{k}', ng-class="user.purchased.background.#{k} ? 'background-unlocked' : 'background-locked'", ng-click='unlock("background.#{k}")', popover-title=bg.text(), popover=bg.notes(),popover-trigger='mouseenter') + button.customize-option(type='button', class='background_#{k}', ng-class="user.purchased.background.#{k} ? 'background-unlocked' : 'background-locked'", ng-click='unlock("background.#{k}")', popover-title=bg.text(env.language.code), popover=bg.notes(env.language.code),popover-trigger='mouseenter') i.glyphicon.glyphicon-lock(ng-if="!user.purchased.background.#{k}") - } diff --git a/views/options/settings.jade b/views/options/settings.jade index e0b150c850..b6208ffc88 100644 --- a/views/options/settings.jade +++ b/views/options/settings.jade @@ -11,7 +11,7 @@ script(id='partials/options.settings.html', type="text/ng-template") =env.t('dataExport') li(ng-class="{ active: $state.includes('options.settings.coupon') }") a(ui-sref='options.settings.coupon') - | Coupon + =env.t('coupon') li(ng-class="{ active: $state.includes('options.settings.subscription') }") a(ui-sref='options.settings.subscription')=env.t('subscription') @@ -138,12 +138,12 @@ script(type='text/ng-template', id='partials/options.settings.coupon.html') .container-fluid .row .col-md-6 - h2 Coupon + h2= env.t('coupon') form.form-inline(role='form',ng-submit='enterCoupon(_couponCode)') - input.form-control(type='text', ng-model='_couponCode', placeholder='Enter Coupon Code') + input.form-control(type='text', ng-model='_couponCode', placeholder=env.t('couponPlaceholder')) button.btn.btn-primary(type='submit') Submit div - small We sometimes have events and give out coupon codes for special gear. (eg, those who stop by our Wondercon booth) + small= env.t('couponText') div(ng-if='user.contributor.sudo') hr h4 Generate Codes @@ -247,7 +247,7 @@ script(id='partials/options.settings.subscription.html',type='text/ng-template') .container-fluid(ng-init='_subscription={key:"basic_earned"}') .row .col-md-6 - h3 Benefits + h3= env.t('benefits') +subPerks() .col-md-6 @@ -270,13 +270,15 @@ script(id='partials/options.settings.subscription.html',type='text/ng-template') li Mystic Hourglasses: {{user.purchased.plan.consecutive.trinkets}} div(ng-if='!user.purchased.plan.customerId || (user.purchased.plan.customerId && user.purchased.plan.dateTerminated)') .form-group - .radio(ng-repeat='block in Content.subscriptionBlocks | toArray | omit:"discount==true" | orderBy:"months"') + .radio(ng-repeat='block in Content.subscriptionBlocks | toArray | omit: "discount==true" | orderBy:"months"') label input(type="radio", name="subRadio", ng-value="block.key", ng-model='_subscription.key') span(ng-show='block.original') - | Recurring ${{block.original}} ${{block.price}} each {{block.months}} Month(s) + span.label.label-success.line-through + | ${{:: block.original }} + =env.t('subscriptionRateText', {price:'{{::block.price}}', months: '{{::block.months}}'}) span(ng-hide='block.original') - | Recurring ${{block.price}} each {{block.months}} Month(s) + =env.t('subscriptionRateText', {price: '{{::block.price}}', months: '{{block.months}}'}) .form-inline .form-group diff --git a/views/options/social/chat-box.jade b/views/options/social/chat-box.jade index 76d9ae8339..c30dc9184e 100644 --- a/views/options/social/chat-box.jade +++ b/views/options/social/chat-box.jade @@ -12,7 +12,7 @@ div.chat-form.guidelines-not-accepted(ng-if='!user.flags.communityGuidelinesAcce form.chat-form(ng-if='user.flags.communityGuidelinesAccepted' ng-submit='postChat(group,message.content)') div(ng-controller='AutocompleteCtrl') - textarea.form-control(rows=4, ui-keydown='{"meta-enter":"postChat(group,message.content)"}', ui-keypress='{13:"postChat(group,message.content)"}', ng-model='message.content', updateinterval='250', flag='@', at-user, auto-complete) + textarea.form-control(rows=4, ui-keydown='{"meta-enter":"postChat(group,message.content)"}', ui-keypress='{13:"postChat(group,message.content)"}', ng-model='message.content', updateinterval='250', flag='@', at-user, auto-complete placeholder="{{group._id == 'habitrpg' ? env.t('tavernCommunityGuidelinesPlaceholder') : ''}}") span.user-list(ng-show='!isAtListHidden') ul.list-at-user li(ng-repeat='user in response | filter:query.text | limitTo: 5', ng-click='autoComplete(user)') diff --git a/views/shared/mixins.jade b/views/shared/mixins.jade index 9fd46f2273..722fe51259 100644 --- a/views/shared/mixins.jade +++ b/views/shared/mixins.jade @@ -6,3 +6,9 @@ mixin gemButton(isGemsModal) .Pet_Currency_Gem2x.Gems | {{user.balance * 4 | number:0}} =env.t('gems') + +mixin aLink(url, label) + if mobile + a(href="", ng-click="externalLink('#{url}')")= label + else + a(href='#{url}', target='_blank')= label \ No newline at end of file diff --git a/views/shared/modals/quest-rewards.jade b/views/shared/modals/quest-rewards.jade index ffa90622ab..f5dc816501 100644 --- a/views/shared/modals/quest-rewards.jade +++ b/views/shared/modals/quest-rewards.jade @@ -9,4 +9,4 @@ script(id='partials/options.social.party.quest-rewards.html', type='text/ng-temp =env.t('experience') tr td {{quest.drop.gp}} - =env.t('gold') \ No newline at end of file + =env.t('gold') diff --git a/views/shared/modals/quests.jade b/views/shared/modals/quests.jade index d0ec6ae203..8e7152f10a 100644 --- a/views/shared/modals/quests.jade +++ b/views/shared/modals/quests.jade @@ -31,7 +31,7 @@ script(type='text/ng-template', id='modals/showQuest.html') | {{::selectedQuest.collect[k].count}} {{::selectedQuest.collect[k].text()}} div(ng-bind-html='::selectedQuest.notes()') - quest-rewards(key='{{::selectedQuest.key}}') + quest-rewards(key='{{::selectedQuest.key}}', header=env.t('rewards')) hr .npc_ian.pull-left p=env.t('questSend') @@ -59,7 +59,7 @@ script(type='text/ng-template', id='modals/buyQuest.html') strong=env.t('collect') + ': ' | {{::selectedQuest.collect[k].count}} {{::selectedQuest.collect[k].text()}} div(ng-bind-html='::selectedQuest.notes()') - quest-rewards(key='{{::selectedQuest.key}}') + quest-rewards(key='{{::selectedQuest.key}}', header=env.t('rewards')) .modal-footer button.btn.btn-default(ng-click='closeQuest(); $close()')=env.t('neverMind') button.btn.btn-primary(ng-click='purchase("quests", quest); closeQuest(); $close()')=env.t('buyQuest') @@ -84,7 +84,7 @@ script(type='text/ng-template', id='modals/questInvitation.html') strong=env.t('collect') + ': ' | {{::Content.quests[party.quest.key].collect[k].count}} {{::Content.quests[party.quest.key].collect[k].text()}} div(ng-bind-html='::Content.quests[party.quest.key].notes()') - quest-rewards(key='{{::party.quest.key}}') + quest-rewards(key='{{::party.quest.key}}', header=env.t('rewards')) .modal-footer button.btn.btn-default(ng-click='questHold = true; $close()')=env.t('askLater') button.btn.btn-default(ng-click='party.$questReject(); $close()')=env.t('reject') diff --git a/views/shared/new-stuff.jade b/views/shared/new-stuff.jade index 727135e69d..b79c09166b 100644 --- a/views/shared/new-stuff.jade +++ b/views/shared/new-stuff.jade @@ -1,32 +1,53 @@ -h5 1/26/2015 - SUBSCRIBER OUTFIT REVEALED, NEW AUDIO THEME, QUEST SCROLL REDESIGN, AND SPREAD THE WORD CHALLENGE REMINDER +h5 1/30/2015 - HABITRPG BIRTHDAY BASH AND PARTY ROBES! PLUS, LAST CHANCE FOR STARRY KNIGHT ITEM SET, AND WINTER WONDERLAND OUTFITS AND HAIR COLORS! hr tr td - h5 Subscriber Outfit Revealed - .promo_mystery_201501.pull-right - p The January Subscriber Item has been revealed: the Starry Knight Item Set! All January subscribers will receive the Starry Helm and the Starry Armor. You still have five days to subscribe and receive the item set! Thank you so much for your support - we really do rely on you to keep HabitRPG free to use and running smoothly. - p.small.muted by Lemoness + .npc_alex.pull-left + h5 HabitRPG Birthday Bash + p January 31st is HabitRPG's Birthday! All of the NPCs are celebrating, and we've awarded you a bunch of cake for your pets and mounts! tr td - h5 New Audio Theme - p A new audio theme is available: Watts' Theme! You can toggle between Watts' Theme and Daniel the Bard's Theme by selecting the megaphone in the upper right-hand corner. Watts' Theme was created by Harry Pepe. You can visit his LinkedIn page here. - p.small.muted by Hpepe4 and Blade + h5 Party Robes + .shop_armor_special_birthday.pull-right + .shop_armor_special_birthday2015.pull-right + p Until February 1st only, there are Party Robes available for free in the Rewards store! If this is your first Birthday bash with us, you can find some Absurd Party Robes; if you already got some last year, then you will find the Silly Party Robes. tr td - h5 Quest Scroll Redesign - p We've redesigned the quest scrolls so that they are visually unique! Quest type and difficulty is determined by the scroll lining (Easy Boss = Green, Medium Boss = Yellow, Hard Boss = Red, Collection Quest = Blue, Rage Bar Boss = Purple speckles), and an icon symbolizing the quest is located in the lower left. - p.small.muted by UncommonCriminal and Rattify + .promo_mystery_201501.pull-left + h5 Last Chance for Starry Knight Item Set + p Reminder: this is the final day to subscribe and receive the Starry Knight Item Set! If you want the Starry Helm or the Starry Armor, now's the time! Thanks so much for your support <3 tr td - h5 Spread the Word Challenge Ending Soon - p Reminder: January 31st is the last day to enter the Spread the Word Challenge for your chance at winning 100 gems! We will stop accepting new applications on February 1st, but it will be some time before the winners are announced because we have to go over all the entries ourselves. Good luck! + h5 Last Chance for Winter Wonderland Outfits + Hair Colors + .promo_winterclasses2015.pull-right + p Tomorrow everything will be back to normal in Habitica, so if you still have any remaining Winter Wonderland Items that you want to buy, you'd better do it now! The Seasonal Edition items and Hair Colors won't be back until next December, and if the Limited Edition items return they will have increased prices or changed art, so strike while the iron is hot! hr a(href='/static/old-news', target='_blank') Read older news mixin oldNews + h5 1/26/2015 + tr + td + h5 Subscriber Outfit Revealed + .promo_mystery_201501.pull-right + p The January Subscriber Item has been revealed: the Starry Knight Item Set! All January subscribers will receive the Starry Helm and the Starry Armor. You still have five days to subscribe and receive the item set! Thank you so much for your support - we really do rely on you to keep HabitRPG free to use and running smoothly. + p.small.muted by Lemoness + tr + td + h5 New Audio Theme + p A new audio theme is available: Watts' Theme! You can toggle between Watts' Theme and Daniel the Bard's Theme by selecting the megaphone in the upper right-hand corner. Watts' Theme was created by Harry Pepe. You can visit his LinkedIn page here. + p.small.muted by Hpepe4 and Blade + tr + td + h5 Quest Scroll Redesign + p We've redesigned the quest scrolls so that they are visually unique! Quest type and difficulty is determined by the scroll lining (Easy Boss = Green, Medium Boss = Yellow, Hard Boss = Red, Collection Quest = Blue, Rage Bar Boss = Purple speckles), and an icon symbolizing the quest is located in the lower left. + p.small.muted by UncommonCriminal and Rattify + tr + td + h5 Spread the Word Challenge Ending Soon + p Reminder: January 31st is the last day to enter the Spread the Word Challenge for your chance at winning 100 gems! We will stop accepting new applications on February 1st, but it will be some time before the winners are announced because we have to go over all the entries ourselves. Good luck! h5 1/23/2015 - hr tr td h5 The Abominable Stressbeast is DEFEATED! diff --git a/views/shared/profiles/achievements.jade b/views/shared/profiles/achievements.jade index af414f15b5..c00fd417a1 100644 --- a/views/shared/profiles/achievements.jade +++ b/views/shared/profiles/achievements.jade @@ -32,7 +32,7 @@ div(ng-if='::profile.contributor.level || user._id == profile._id') small =env.t('contribText') |  - a(href='http://habitrpg.wikia.com/wiki/Contributing_to_HabitRPG', target='_blank')=env.t('readMore') + +aLink('http://habitrpg.wikia.com/wiki/Contributing_to_HabitRPG', env.t('readMore')) | . hr @@ -75,7 +75,8 @@ div(ng-if='profile.achievements.perfect || user._id == profile._id') div(ng-if='::user._id == profile._id') div.muted h5=env.t('ultimGearName') - small Returning soon + small + +aLink('https://github.com/HabitRPG/habitrpg/issues/2232', 'Returning soon') hr div(ng-if='profile.achievements.beastMaster || user._id == profile._id') @@ -121,7 +122,7 @@ div(ng-if='::profile.achievements.helpedHabit') small =env.t('helpedText1') |  - a(href='http://community.habitrpg.com/node/290', target='_blank')=env.t('helpedText2') + +aLink('http://community.habitrpg.com/node/290', env.t('helpedText2')) hr div(ng-if=':: profile.achievements.originalUser || profile.achievements.veteran') @@ -168,11 +169,13 @@ div(ng-if='profile.achievements.spookDust') =env.t('alarmingFriendsText', {spookDust: "{{profile.achievements.spookDust}}"}) hr -div(ng-if='::profile.achievements.habitBirthday') +div(ng-if='::profile.achievements.habitBirthdays') .achievement.achievement-habitBirthday h5=env.t('habitBirthday') - small + small(ng-if='::profile.achievements.habitBirthdays == 1') =env.t('habitBirthdayText') + small(ng-if='::profile.achievements.habitBirthdays > 1') + =env.t('habitBirthdayPluralText', {number: "{{profile.achievements.habitBirthdays}}"}) hr div(ng-if='::profile.achievements.valentine') diff --git a/views/static/layout.jade b/views/static/layout.jade index ae82efa1c8..ef214f415c 100644 --- a/views/static/layout.jade +++ b/views/static/layout.jade @@ -1,3 +1,5 @@ +include ../shared/mixins.jade + //-Trick needed to pass 'env' to ./layout block vars doctype html diff --git a/views/static/press-kit.jade b/views/static/press-kit.jade index 0548948888..7439cff41c 100644 --- a/views/static/press-kit.jade +++ b/views/static/press-kit.jade @@ -14,9 +14,11 @@ block extraHead } block content - h2 Press Kit - p Thanks for your interest in HabitRPG! The following images can be used for articles or videos about HabitRPG. For more information, please contact Siena Leslie at leslie@habitrpg.com. - p Download all image: presskit.zip + h2= env.t('presskit') + p= env.t('presskitText') + p= env.t('presskitDownload') + |   + a.btn.btn-success(href='/presskit/presskit.zip') presskit.zip - var imgs = ['habitrpg_pixel', 'HabitRPGdevices', 'Market Sample Screen', 'Challenges Sample Screen', 'Equipment Sample Screen', 'Guilds Sample Screen', 'HabitRPGPromoPostCard6', 'HabitRPGPromoThin', 'Laundromancer_by_Arcosine', 'promo mobile inventorySTILL1', 'promo mobile inventorySTILL2', 'PROMOdevices2', 'SnackLessMonster_by_Arcosine', 'stag_battle_by_leephon', 'stagnant_dishes_by_kiwibot', 'vice_reborn_by_baconsaur'] //-#carousel.carousel.slide(data-ride='carousel') @@ -30,12 +32,12 @@ block content //.carousel-caption=img a.left.carousel-control(href='#carousel', role='button', data-slide='prev') span.glyphicon.glyphicon-chevron-left(aria-hidden='true') - span.sr-only Previous + span.sr-only= env.t('previous') a.right.carousel-control(href='#carousel', role='button', data-slide='next') span.glyphicon.glyphicon-chevron-right(aria-hidden='true') - span.sr-only Next + span.sr-only= env.t('next') ul.list-unstyled each img in imgs li - img.press-img(src="/presskit/#{img}.png") \ No newline at end of file + img.press-img(src="/presskit/#{img}.png")