Merge remote-tracking branch 'upstream/master'

Conflicts:
	app/locale/zh-HANT.coffee
This commit is contained in:
newmilktea 2015-02-06 20:52:02 +08:00
commit 1752f12b32
97 changed files with 2099 additions and 430 deletions
app
karma.conf.js
scripts/analytics
server
server_config.coffee

Binary file not shown.

After

(image error) Size: 58 KiB

Binary file not shown.

After

(image error) Size: 4.6 KiB

Binary file not shown.

After

(image error) Size: 516 KiB

View file

@ -1,8 +1,10 @@
// Helper for running tests through Karma. // Helper for running tests through Karma.
// Hooks into the test view logic for running tests. // Hooks into the test view logic for running tests.
window.userObject = {_id:'1'}
initialize = require('core/initialize'); initialize = require('core/initialize');
initialize.init(); initialize.init();
console.debug = function() {}; // Karma conf doesn't seem to work? Debug messages are still emitted when they shouldn't be. console.debug = function() {}; // Karma conf doesn't seem to work? Debug messages are still emitted when they shouldn't be.
TestView = require('views/TestView'); TestView = require('views/TestView');
TestView.runTests(); TestView.runTests();

View file

@ -43,6 +43,8 @@ init = ->
handleNormalUrls() handleNormalUrls()
setUpMoment() # Set up i18n for moment setUpMoment() # Set up i18n for moment
module.exports.init = init
handleNormalUrls = -> handleNormalUrls = ->
# http://artsy.github.com/blog/2012/06/25/replacing-hashbang-routes-with-pushstate/ # http://artsy.github.com/blog/2012/06/25/replacing-hashbang-routes-with-pushstate/
$(document).on 'click', "a[href^='/']", (event) -> $(document).on 'click', "a[href^='/']", (event) ->

View file

@ -32,6 +32,7 @@ module.exports = class LevelLoader extends CocoClass
@team = options.team @team = options.team
@headless = options.headless @headless = options.headless
@spectateMode = options.spectateMode ? false @spectateMode = options.spectateMode ? false
@observing = options.observing
@worldNecessities = [] @worldNecessities = []
@listenTo @supermodel, 'resource-loaded', @onWorldNecessityLoaded @listenTo @supermodel, 'resource-loaded', @onWorldNecessityLoaded
@ -389,6 +390,8 @@ module.exports = class LevelLoader extends CocoClass
@world.submissionCount = @session?.get('state')?.submissionCount ? 0 @world.submissionCount = @session?.get('state')?.submissionCount ? 0
@world.flagHistory = @session?.get('state')?.flagHistory ? [] @world.flagHistory = @session?.get('state')?.flagHistory ? []
@world.difficulty = @session?.get('state')?.difficulty ? 0 @world.difficulty = @session?.get('state')?.difficulty ? 0
if @observing
@world.difficulty = Math.max 0, @world.difficulty - 1 # Show the difficulty they won, not the next one.
serializedLevel = @level.serialize(@supermodel, @session, @opponentSession) serializedLevel = @level.serialize(@supermodel, @session, @opponentSession)
@world.loadFromLevel serializedLevel, false @world.loadFromLevel serializedLevel, false
console.log 'World has been initialized from level loader.' console.log 'World has been initialized from level loader.'

View file

@ -204,39 +204,45 @@ module.exports = Lank = class Lank extends CocoClass
@handledDisplayEvents[event] = true @handledDisplayEvents[event] = true
args = JSON.parse(event[4...]) args = JSON.parse(event[4...])
key = 'aoe-' + JSON.stringify(args[2..]) key = 'aoe-' + JSON.stringify(args[2..])
layerName = args[6] ? 'ground' # Can also specify 'floating'.
unless layer = @options[layerName + 'Layer']
console.error "#{@thang.id} couldn't find layer #{layerName}Layer for AOE effect #{key}; using ground layer."
layer = @options.groundLayer
unless key in @options.groundLayer.spriteSheet.getAnimations() unless key in layer.spriteSheet.getAnimations()
args = JSON.parse(event[4...])
circle = new createjs.Shape() circle = new createjs.Shape()
radius = args[2] * Camera.PPM radius = args[2] * Camera.PPM
if args.length is 4 if args.length is 4
circle.graphics.beginFill(args[3]).drawCircle(0, 0, radius) circle.graphics.beginFill(args[3]).drawCircle(0, 0, radius)
else else
startAngle = args[4] startAngle = args[4] or 0
endAngle = args[5] endAngle = args[5] or 2 * Math.PI
if startAngle is endAngle
startAngle = 0
endAngle = 2 * Math.PI
circle.graphics.beginFill(args[3]) circle.graphics.beginFill(args[3])
.lineTo(0, 0) .lineTo(0, 0)
.lineTo(radius * Math.cos(startAngle), radius * Math.sin(startAngle)) .lineTo(radius * Math.cos(startAngle), radius * Math.sin(startAngle))
.arc(0, 0, radius, startAngle, endAngle) .arc(0, 0, radius, startAngle, endAngle)
.lineTo(0, 0) .lineTo(0, 0)
@options.groundLayer.addCustomGraphic(key, circle, [-radius, -radius, radius*2, radius*2]) layer.addCustomGraphic(key, circle, [-radius, -radius, radius*2, radius*2])
circle = new createjs.Sprite(@options.groundLayer.spriteSheet) circle = new createjs.Sprite(layer.spriteSheet)
circle.gotoAndStop(key) circle.gotoAndStop(key)
pos = @options.camera.worldToSurface {x: args[0], y: args[1]} pos = @options.camera.worldToSurface {x: args[0], y: args[1]}
circle.x = pos.x circle.x = pos.x
circle.y = pos.y circle.y = pos.y
resFactor = @options.groundLayer.resolutionFactor resFactor = layer.resolutionFactor
circle.scaleY = @options.camera.y2x * 0.7 / resFactor circle.scaleY = @options.camera.y2x * 0.7 / resFactor
circle.scaleX = 0.7 / resFactor circle.scaleX = 0.7 / resFactor
circle.alpha = 0.2 circle.alpha = 0.2
@options.groundLayer.addChild circle layer.addChild circle
createjs.Tween.get(circle) createjs.Tween.get(circle)
.to({alpha: 0.6, scaleY: @options.camera.y2x / resFactor, scaleX: 1 / resFactor}, 100, createjs.Ease.circOut) .to({alpha: 0.6, scaleY: @options.camera.y2x / resFactor, scaleX: 1 / resFactor}, 100, createjs.Ease.circOut)
.to({alpha: 0, scaleY: 0, scaleX: 0}, 700, createjs.Ease.circIn) .to({alpha: 0, scaleY: 0, scaleX: 0}, 700, createjs.Ease.circIn)
.call => .call =>
return if @destroyed return if @destroyed
@options.groundLayer.removeChild circle layer.removeChild circle
delete @handledDisplayEvents[event] delete @handledDisplayEvents[event]
showTextEvents: -> showTextEvents: ->

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "العربية", englishDescription: "Arabi
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "български език", englishDescri
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "български език", englishDescri
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "български език", englishDescri
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
subscribe_title: "Subscriu-te" subscribe_title: "Subscriu-te"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Català", englishDescription: "Catalan", tr
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
recovered: "Obnovení již zakoupených drahokamů proběhlo úspěšně. Aktualizujte stránku prosím." recovered: "Obnovení již zakoupených drahokamů proběhlo úspěšně. Aktualizujte stránku prosím."
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
subscribe_title: "Předplacení" subscribe_title: "Předplacení"
unsubscribe: "Zrušit předplacení" unsubscribe: "Zrušit předplacení"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,6 +403,14 @@ module.exports = nativeDescription: "čeština", englishDescription: "Czech", tr
heroes: "Více silnějších hrdinů!" heroes: "Více silnějších hrdinů!"
gems: "3500 bonusových drahokamů každý měsíc!" gems: "3500 bonusových drahokamů každý měsíc!"
items: "Více než 250 bonusových předmětů!" items: "Více než 250 bonusových předmětů!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
parents: "Pro rodiče" parents: "Pro rodiče"
parents_title: "Vaše dítě se naučí programovat." parents_title: "Vaše dítě se naučí programovat."
parents_blurb1: "Pomocí CodeCombat se vaše dítě učí psaním opravdového kódu. Začínají učením se základním příkazů a postupně se přidávají pokročilejší témata." parents_blurb1: "Pomocí CodeCombat se vaše dítě učí psaním opravdového kódu. Začínají učením se základním příkazů a postupně se přidávají pokročilejší témata."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "dansk", englishDescription: "Danish", trans
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
recovered: "Voriger Juwelenkauf wiederhergestellt. Bitte die Seite neu laden." recovered: "Voriger Juwelenkauf wiederhergestellt. Bitte die Seite neu laden."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Deutsch (Österreich)", englishDescription:
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -341,18 +341,19 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
multiplayer_caption: "Spiele mit Freunden!" multiplayer_caption: "Spiele mit Freunden!"
auth_caption: "Fortschritt speichern." auth_caption: "Fortschritt speichern."
# leaderboard: leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" day: "Heute"
# week: "This Week" week: "Diese Woche"
# all: "All-Time" # all: "All-Time"
# time: "Time" time: "Zeit"
# damage_taken: "Damage Taken" # damage_taken: "Damage Taken"
# damage_dealt: "Damage Dealt" # damage_dealt: "Damage Dealt"
# difficulty: "Difficulty" difficulty: "Schwierigkeit"
# gold_collected: "Gold Collected" gold_collected: "Gold gesammelt"
inventory: inventory:
choose_inventory: "Gegenstände ausrüsten" choose_inventory: "Gegenstände ausrüsten"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
recovered: "Vorhergegangener Edelsteinkauf rückgängig gemacht. Aktualisiere bitte die Seite." recovered: "Vorhergegangener Edelsteinkauf rückgängig gemacht. Aktualisiere bitte die Seite."
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
free: "Kostenlos"
month: "Monate"
subscribe_title: "Abonnieren" subscribe_title: "Abonnieren"
unsubscribe: "Abmelden" unsubscribe: "Abmelden"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,6 +403,14 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
heroes: "Stärkere Helden!" heroes: "Stärkere Helden!"
gems: "3500 bonus Edelsteine jeden Monat!" gems: "3500 bonus Edelsteine jeden Monat!"
items: "Über 250 bonus Gegenstände!" items: "Über 250 bonus Gegenstände!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
parents: "Für Eltern" parents: "Für Eltern"
parents_title: "Dein Kind lernt zu programmieren." parents_title: "Dein Kind lernt zu programmieren."
parents_blurb1: "Mit CodeCombat, lernt dein Kind richtige Programme zu schreiben. Es fängt mit einfachen Befehlen an, und schreitet ganz unmerklich zu schwierigeren Themen fort." parents_blurb1: "Mit CodeCombat, lernt dein Kind richtige Programme zu schreiben. Es fängt mit einfachen Befehlen an, und schreitet ganz unmerklich zu schwierigeren Themen fort."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Ελληνικά", englishDescription: "Gre
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "English (AU)", englishDescription: "English
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "English (UK)", englishDescription: "English
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "English (US)", englishDescription: "English
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -381,6 +381,15 @@
recovered: "Previous gems purchase recovered. Please refresh the page." recovered: "Previous gems purchase recovered. Please refresh the page."
subscribe: subscribe:
comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
feature1: "60+ basic levels across 4 worlds"
feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
feature3: "30+ bonus levels"
feature4: "<strong>3500 bonus gems</strong> every month!"
feature5: "Video tutorials"
feature6: "Premium email support"
free: "Free"
month: "month"
subscribe_title: "Subscribe" subscribe_title: "Subscribe"
unsubscribe: "Unsubscribe" unsubscribe: "Unsubscribe"
confirm_unsubscribe: "Confirm Unsubscribe" confirm_unsubscribe: "Confirm Unsubscribe"
@ -390,16 +399,19 @@
thank_you: "Thank you for supporting CodeCombat." thank_you: "Thank you for supporting CodeCombat."
sorry_to_see_you_go: "Sorry to see you go! Please let us know what we could have done better." sorry_to_see_you_go: "Sorry to see you go! Please let us know what we could have done better."
unsubscribe_feedback_placeholder: "O, what have we done?" unsubscribe_feedback_placeholder: "O, what have we done?"
levels: "Get more practice with bonus levels!" parent_button: "Ask your parent"
heroes: "More powerful heroes!" parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
gems: "3500 bonus gems every month!" parent_email_input_invalid: "Email address invalid."
items: "Over 250 bonus items!" parent_email_input_label: "Parent email address"
parent_email_input_placeholder: "Enter parent email"
parent_email_send: "Send Email"
parent_email_sent: "Email sent!"
parent_email_title: "What's your parent's email?"
parents: "For Parents" parents: "For Parents"
parents_title: "Your child will learn to code." parents_title: "Your child will learn to code."
parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
subscribe_button: "Subscribe Now"
stripe_description: "Monthly Subscription" stripe_description: "Monthly Subscription"
subscription_required_to_play: "You'll need a subscription to play this level." subscription_required_to_play: "You'll need a subscription to play this level."
unlock_help_videos: "Subscribe to unlock all video tutorials." unlock_help_videos: "Subscribe to unlock all video tutorials."
@ -986,6 +998,7 @@
play_counts: "Play Counts" play_counts: "Play Counts"
feedback: "Feedback" feedback: "Feedback"
payment_info: "Payment Info" payment_info: "Payment Info"
campaigns: "Campaigns"
delta: delta:
added: "Added" added: "Added"

View file

@ -322,7 +322,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
tip_lines_of_code: "Medir el progreso en la programación en líneas de código es como medir el progreso de construcción de una aeronave por su peso. — Bill Gates" tip_lines_of_code: "Medir el progreso en la programación en líneas de código es como medir el progreso de construcción de una aeronave por su peso. — Bill Gates"
tip_source_code: "Quisiera cambiar el mundo, pero no me dan el código fuente." tip_source_code: "Quisiera cambiar el mundo, pero no me dan el código fuente."
tip_javascript_java: "Java es a Javascript lo mismo que Comer es a Comercial. - Chris Heilmann" tip_javascript_java: "Java es a Javascript lo mismo que Comer es a Comercial. - Chris Heilmann"
# tip_move_forward: "Whatever you do, keep moving forward. - Martin Luther King Jr." tip_move_forward: "Hagas lo que hagas, siempre sigue hacia delante. - Martin Luther King Jr."
game_menu: game_menu:
inventory_tab: "Inventario" inventory_tab: "Inventario"
@ -344,6 +344,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
recovered: "Se recuperaron las anteriores compras de gemas. Por favor recarga la página" recovered: "Se recuperaron las anteriores compras de gemas. Por favor recarga la página"
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
subscribe_title: "Suscribirse" subscribe_title: "Suscribirse"
unsubscribe: "Des-suscribirse" unsubscribe: "Des-suscribirse"
confirm_unsubscribe: "Confirmar cancelacion de suscripción" confirm_unsubscribe: "Confirmar cancelacion de suscripción"
@ -393,6 +403,14 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
heroes: "Héroes más poderosos!" heroes: "Héroes más poderosos!"
gems: "Bonus de 3500 todos los meses!" gems: "Bonus de 3500 todos los meses!"
items: "Más de 250 ítems de bonus!" items: "Más de 250 ítems de bonus!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
parents: "Para padres" parents: "Para padres"
parents_title: "Su hijo aprenderá a programar." parents_title: "Su hijo aprenderá a programar."
parents_blurb1: "Con CodeCombat, su hijo aprenderá a escribiendo código real. Empezaran aprendiendo comandos simples avanzando a temas más complejos." parents_blurb1: "Con CodeCombat, su hijo aprenderá a escribiendo código real. Empezaran aprendiendo comandos simples avanzando a temas más complejos."
@ -504,45 +522,45 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
matt_title: "Programador" matt_title: "Programador"
matt_blurb: "Bicicletero" matt_blurb: "Bicicletero"
# teachers: teachers:
# title: "CodeCombat for Teachers" title: "CodeCombat para Profesores"
# preparation_title: "Preparation" preparation_title: "Preparación"
# preparation_1: "CodeCombat is free to play for the core level progression and does not require students to sign up. We encourage teachers to" preparation_1: "CodeCombat es gratuito para jugar en la progresión de nivel básico y no requiere el registro de los usuarios. Alentamos a los profesores a"
# preparation_play_campaign: "play through the campaign" preparation_play_campaign: "jugar a través de la campaña"
# preparation_2: "to try it out, but the only thing you absolutely need to do to be ready is ensure students have access to a computer." preparation_2: "para probarlo, la única cosa que necesitas para estar listo es asegurarte que los estudiantes tengan acceso a una computadora con internet."
# preparation_3: "It is not necessary for teachers to be comfortable with computer science concepts for students to have fun learning with CodeCombat." preparation_3: "No es necesario que los maestros se sienten cómodos con los conceptos informáticos para que los estudiantes se divierten aprendiendo con CodeCombat."
# violent_title: "Is it violent?" violent_title: "¿Es violento?"
# violent_1: "We get this from teachers a lot due to our name. Although CodeCombat does contain cartoon violence, there is nothing graphic in either the visuals or language." violent_1: "Nos preguntan esto debido a nuestro nombre. Sin embargo CodeCombat solo contiene violencia de dibujos animados, no hay nada gráfico en las imágenes o el lenguaje."
# violent_2: "If you are comfortable having your students play Angry Birds, you will be comfortable with CodeCombat." violent_2: "Si te sientes cómodo cuanto tus estudiantes juegan Angry Bird, entonces estaras cómodo con CodeCombat."
# for_girls_title: "Is it for girls?" for_girls_title: "¿Es para chicas?"
# for_girls_1: "There are three game modes in CodeCombat: building, puzzles, and combat. We have intentionally designed each to appeal to both boys and girls and think that the building and puzzle levels especially differentiate the game from violent triple A titles that repel female players." for_girls_1: "Existen tres modos de juego en CodeCombat: Edificación, rompecabezas, y combate. Hemos diseñado intencionalmente cada uno para atraer tanto a los niños como a las niñas, y creemos en que los niveles de construcción y rompecabezas diferencia el juego de los títulos triple A ultra violentos que repelen a las jugadoras."
# what_cover_title: "What do we cover?" what_cover_title: "¿Qué es lo que cubrimos?"
# what_cover_1: "There are 20 levels in the Hour of Code tutorial that teach and reinforce 6 specific computer science concepts:" what_cover_1: "Hay 20 niveles en nuestro tutorial Hora del Código que enseña y refuerza 6 conceptos especifico de las ciencias computacionales:"
# what_cover_notation_1: "Formal notation" what_cover_notation_1: "Notación Formal"
# what_cover_notation_2: "- builds an understanding of the importance of syntax in programming." what_cover_notation_2: "- construye una comprensión de la importancia de la sintaxis en la programación."
# what_cover_methods_1: "Calling methods" what_cover_methods_1: "Metodos de llamada"
# what_cover_methods_2: "- familiarizes students with the syntax of object-oriented method calls." what_cover_methods_2: "- familiariza a los estudiantes con la sintaxis de las llamadas a métodos orientados a objetos."
# what_cover_parameters_1: "Parameters" what_cover_parameters_1: "Parametros"
# what_cover_parameters_2: "- trains how to pass parameters to functions." what_cover_parameters_2: "- entrena en cómo pasar parámetros a funciones."
# what_cover_strings_1: "Strings" what_cover_strings_1: "Cadenas"
# what_cover_strings_2: "- teaches students about string notation and passing strings as parameters." what_cover_strings_2: "- enseña a los estudiantes acerca de la notación en cadena y como pasar estas cadenas como parámetros."
# what_cover_loops_1: "Loops" what_cover_loops_1: "Bucles"
# what_cover_loops_2: "- develops the abstraction of designing short programs with loops." what_cover_loops_2: "- desarrolla la abstracción del diseño de programas cortos con bucles."
# what_cover_variables_1: "Variables" what_cover_variables_1: "Variables"
# what_cover_variables_2: "- adds the skill of referencing values that change over time." what_cover_variables_2: "- añade la habilidad de referenciar valores que cambian con el tiempo."
# what_cover_2: "Students may continue past level 20, depending on their speed and interest, to learn two additional concepts in later levels:" what_cover_2: "Los estudiantes pueden continuar más allá del nivel 20, dependiendo de su velocidad e interés, para aprender dos conceptos adicionales en los niveles tardíos:"
# what_cover_logic_1: "Conditional logic" what_cover_logic_1: "Condicionales lógicos"
# what_cover_logic_2: "- when and how to use if/else to control in-game outcomes." what_cover_logic_2: "- cuándo y cómo utilizar if / else para controlar los resultados del juego."
# what_cover_input_1: "Handling player input" what_cover_input_1: "Manipulación de eventos de entrada"
# what_cover_input_2: "- responding to input events to create a user interface." what_cover_input_2: "- responder a eventos de entrada para crear una interfaz de usuario."
# sys_requirements_title: "System Requirements" sys_requirements_title: "Requerimientos del sistema"
# sys_requirements_1: "Because CodeCombat is a game, it is more intensive for computers to run smoothly than video or written tutorials. We have optimized it to run quickly on all modern browsers and on older machines so that everyone can play. That said, here are our suggestions for getting the most out of your Hour of Code experience:" sys_requirements_1: "Debido que CodeCombat es un juego, es más difícil para las computadoras correrlo en relación a un tutorial escrito o un video. Para que todos puedan jugar, hemos optimizado la web para correr rápidamente en todos los navegadores modernos y en maquinas antiguas. Dicho esto, aquí están nuestras sugerencias para sacar el máximo provecho de su experiencia en la Hora del Código:"
# sys_requirements_2: "Use newer versions of Chrome or Firefox." sys_requirements_2: "Usar una versión actualizada del navegador Chrome o Firefox."
# sys_requirements_3: "Although CodeCombat will work on browsers as old as IE9, the performance is not as good. Chrome is best." sys_requirements_3: "Aunque CodeCombat funcionará en navegadores tan antiguas como IE9, el rendimiento no es tan bueno. Chrome es la mejor opción."
# sys_requirements_4: "Use newer computers." sys_requirements_4: "Usar computadoras nuevas."
# sys_requirements_5: "Older computers, Chromebooks, and netbooks tend to have very few system resources, which makes for a less enjoyable experience. At least 2GB of RAM is required." sys_requirements_5: "Cumputadoras viejas, Chromebooks y netbooks tienden a tener menos recursos del sistema, lo que los convierte en una experiencia menos agradable. Se requiere al menos 2 GB de RAM."
# sys_requirements_6: "Allow players to wear headphones/earbuds to hear the audio." sys_requirements_6: "Permitir a los estudiantes usar auriculares / audífonos para escuchar el audio."
# sys_requirements_7: "We help players learn through voiceover and sound effects, which will make classrooms noisy and distracting." sys_requirements_7: "Ayudamos a los jugadores mediante efectos de sonidos y voces en off, lo que podría hacer a las aulas espacios ruidosos y molestos."
versions: versions:
save_version_title: "Guardar nueva versión" save_version_title: "Guardar nueva versión"
@ -610,7 +628,7 @@ module.exports = nativeDescription: "Español (América Latina)", englishDescrip
view_profile: "Ver tu perfil" view_profile: "Ver tu perfil"
keyboard_shortcuts: keyboard_shortcuts:
keyboard_shortcuts: "Keyboard Shortcuts" keyboard_shortcuts: "Atajos de teclado"
space: "Barra espaciadora" space: "Barra espaciadora"
enter: "Enter" enter: "Enter"
escape: "Escape" escape: "Escape"

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
recovered: "Las gemas compradas con anterioridad han sido recuperadas. Por favor, refresca la página." recovered: "Las gemas compradas con anterioridad han sido recuperadas. Por favor, refresca la página."
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
subscribe_title: "Suscríbete" subscribe_title: "Suscríbete"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,6 +403,14 @@ module.exports = nativeDescription: "español (ES)", englishDescription: "Spanis
heroes: "¡Más heroes poderosos!" heroes: "¡Más heroes poderosos!"
gems: "¡3500 joyas adicionales cada mes!" gems: "¡3500 joyas adicionales cada mes!"
items: "¡Más de 250 artículos adicionales!" items: "¡Más de 250 artículos adicionales!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
parents: "Para Padres" parents: "Para Padres"
parents_title: "Tus hijos aprenderan a programar." parents_title: "Tus hijos aprenderan a programar."
parents_blurb1: "Con CodeCombat, tus hijos aprendes a desarrollar código real. Al inicio aprenden comandos simples, y avanzan a temas más avanzados." parents_blurb1: "Con CodeCombat, tus hijos aprendes a desarrollar código real. Al inicio aprenden comandos simples, y avanzan a temas más avanzados."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "فارسی", englishDescription: "Persian",
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "suomi", englishDescription: "Finnish", tran
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -315,7 +315,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
tip_extrapolation: "Il y a seulement deux types de personnes : celles qui peuvent extrapoler à partir de données incomplètes..." tip_extrapolation: "Il y a seulement deux types de personnes : celles qui peuvent extrapoler à partir de données incomplètes..."
# tip_superpower: "Coding is the closest thing we have to a superpower." # tip_superpower: "Coding is the closest thing we have to a superpower."
# tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds" # tip_control_destiny: "In real open source, you have the right to control your own destiny. - Linus Torvalds"
# tip_no_code: "No code is faster than no code." tip_no_code: "Aucun code n'est plus rapide qu'aucun code."
# tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries" # tip_code_never_lies: "Code never lies, comments sometimes do. — Ron Jeffries"
# tip_reusable_software: "Before software can be reusable it first has to be usable." # tip_reusable_software: "Before software can be reusable it first has to be usable."
# tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //" # tip_optimization_operator: "Every language has an optimization operator. In most languages that operator is //"
@ -341,18 +341,19 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
multiplayer_caption: "Jouer avec des amis!" multiplayer_caption: "Jouer avec des amis!"
auth_caption: "Sauvegarder votre progression." auth_caption: "Sauvegarder votre progression."
# leaderboard: leaderboard:
# leaderboard: "Leaderboard" leaderboard: "classement"
# view_other_solutions: "View Other Solutions" view_other_solutions: "Voir les autres solutions"
# top_solutions: "Top Solutions" scores: "Scores"
# day: "Today" top_solutions: "Meilleures solutions"
# week: "This Week" day: "Aujourd'hui"
# all: "All-Time" week: "Cette semaine"
# time: "Time" all: "Tous les temps"
# damage_taken: "Damage Taken" time: "Temps"
# damage_dealt: "Damage Dealt" damage_taken: "Dégât subis"
# difficulty: "Difficulty" damage_dealt: "Dégât infligés"
# gold_collected: "Gold Collected" difficulty: "Difficulté"
gold_collected: "Or collecté"
inventory: inventory:
choose_inventory: "Équiper des Objets" choose_inventory: "Équiper des Objets"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
recovered: "Gemmes précédemment achetées récupérées. Merci de rafraîchir la page." recovered: "Gemmes précédemment achetées récupérées. Merci de rafraîchir la page."
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
subscribe_title: "Inscription" subscribe_title: "Inscription"
unsubscribe: "Désinscription" unsubscribe: "Désinscription"
confirm_unsubscribe: "Confirmer la désinscription" confirm_unsubscribe: "Confirmer la désinscription"
@ -393,6 +403,14 @@ module.exports = nativeDescription: "français", englishDescription: "French", t
heroes: "Héros plus puissants!" heroes: "Héros plus puissants!"
gems: "3500 gemmes en bonus chaque mois !" gems: "3500 gemmes en bonus chaque mois !"
items: "Plus de 250 objets en bonus !" items: "Plus de 250 objets en bonus !"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
parents: "Pour les parents" parents: "Pour les parents"
parents_title: "Votre enfant va apprendre à programmer." parents_title: "Votre enfant va apprendre à programmer."
parents_blurb1: "Avec CodeCombat, votre enfant apprend en écrisant de vrais programmes. Ils commencent en apprenant des instructions simples, puis progressent sur des thèmes plus complexes." parents_blurb1: "Avec CodeCombat, votre enfant apprend en écrisant de vrais programmes. Ils commencent en apprenant des instructions simples, puis progressent sur des thèmes plus complexes."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Galego", englishDescription: "Galician", tr
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Galego", englishDescription: "Galician", tr
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Galego", englishDescription: "Galician", tr
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "עברית", englishDescription: "Hebrew",
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "मानक हिन्दी", englishDe
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
subscribe_title: "Feliratkozás" subscribe_title: "Feliratkozás"
unsubscribe: "Leiratkozás" unsubscribe: "Leiratkozás"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,6 +403,14 @@ module.exports = nativeDescription: "magyar", englishDescription: "Hungarian", t
heroes: "Még erősebb hősök!" heroes: "Még erősebb hősök!"
gems: "3500 búnusz drágakő havonta!" gems: "3500 búnusz drágakő havonta!"
items: "Több mint 250 bónusz tárgy!" items: "Több mint 250 bónusz tárgy!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
parents: "Szülőknek" parents: "Szülőknek"
parents_title: "A gyereke programozni tanul majd." parents_title: "A gyereke programozni tanul majd."
parents_blurb1: "A CodeCombattal a gyereke valódi programozási feladatokon keresztül tanul. Egyszerű utasításokkal kezdenek, aztán további témákba is betekintést kapnak." parents_blurb1: "A CodeCombattal a gyereke valódi programozási feladatokon keresztül tanul. Egyszerű utasításokkal kezdenek, aztán további témákba is betekintést kapnak."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
recovered: "Acquisto precedente recuperato. Ricaricare la pagina." recovered: "Acquisto precedente recuperato. Ricaricare la pagina."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Italiano", englishDescription: "Italian", t
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
recovered: "前のジェム購入をリカバリーしました。ページを更新してください。" recovered: "前のジェム購入をリカバリーしました。ページを更新してください。"
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "한국어", englishDescription: "Korean", t
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "lietuvių kalba", englishDescription: "Lith
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Македонски", englishDescription:
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Македонски", englishDescription:
recovered: "Претходното купување на скапоцени камења е вратено од загуба. Те молам 'освежи' ја страната." recovered: "Претходното купување на скапоцени камења е вратено од загуба. Те молам 'освежи' ја страната."
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
subscribe_title: "Зачлени се" subscribe_title: "Зачлени се"
unsubscribe: "Откажи членство" unsubscribe: "Откажи членство"
confirm_unsubscribe: "Потврди откажување на членство" confirm_unsubscribe: "Потврди откажување на членство"
@ -393,6 +403,14 @@ module.exports = nativeDescription: "Македонски", englishDescription:
heroes: "Помоќни херои!" heroes: "Помоќни херои!"
gems: "3500 скапоцени камења секој месец!" gems: "3500 скапоцени камења секој месец!"
items: "Над 250 дополнителни предмети и опрема!" items: "Над 250 дополнителни предмети и опрема!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
parents: "За родители" parents: "За родители"
parents_title: "Вашето дете ќе научи да програмира." parents_title: "Вашето дете ќе научи да програмира."
parents_blurb1: "Со CodeCombat, вашите деца учат преку пишување на вистински програмски код. Почнуваат со учење на едноставни команди, по што се продолжува на понапредни теми." parents_blurb1: "Со CodeCombat, вашите деца учат преку пишување на вистински програмски код. Почнуваат со учење на едноставни команди, по што се продолжува на понапредни теми."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Bahasa Melayu", englishDescription: "Bahasa
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Norsk Bokmål", englishDescription: "Norweg
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Nederlands (België)", englishDescription:
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
gems: "Elke maand 3500 bonus juwelen!" gems: "Elke maand 3500 bonus juwelen!"
items: "Meer dan 250 bonus items!" items: "Meer dan 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
parents: "Voor ouders" parents: "Voor ouders"
parents_title: "Uw kind zal de code leren." parents_title: "Uw kind zal de code leren."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
subscribe_title: "Abonneren" subscribe_title: "Abonneren"
unsubscribe: "Abonnement pzeggen" unsubscribe: "Abonnement pzeggen"
confirm_unsubscribe: "Opzegging Bevestigen" confirm_unsubscribe: "Opzegging Bevestigen"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Nederlands (Nederland)", englishDescription
heroes: "Sterkere helden!" heroes: "Sterkere helden!"
gems: "3500 extra edelstenen elke maand!" gems: "3500 extra edelstenen elke maand!"
items: "Meer dan 250 bonus items!" items: "Meer dan 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
parents: "Voor ouders" parents: "Voor ouders"
parents_title: "Uw kind leert programmeren." parents_title: "Uw kind leert programmeren."
parents_blurb1: "Met CodeCombat leert uw kind door echte code te schrijven. Ze beginnen met simpele instructies en naarmate ze verder komen, komen er moeilijkere onderwerpen aan bod." parents_blurb1: "Met CodeCombat leert uw kind door echte code te schrijven. Ze beginnen met simpele instructies en naarmate ze verder komen, komen er moeilijkere onderwerpen aan bod."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Norwegian Nynorsk", englishDescription: "No
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Norsk", englishDescription: "Norwegian", tr
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "język polski", englishDescription: "Polish
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Português do Brasil", englishDescription:
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Português do Brasil", englishDescription:
recovered: "Gems de compras anteriores Recuperadas. Por favor atualize a pagina." recovered: "Gems de compras anteriores Recuperadas. Por favor atualize a pagina."
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
subscribe_title: "Inscrever-se" subscribe_title: "Inscrever-se"
unsubscribe: "Desinscrever-se" unsubscribe: "Desinscrever-se"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,6 +403,14 @@ module.exports = nativeDescription: "Português do Brasil", englishDescription:
heroes: "Mais poderosos heróis!" heroes: "Mais poderosos heróis!"
gems: "3500 gemas bônus todo mês!" gems: "3500 gemas bônus todo mês!"
items: "Mais de 250 itens bônus!" items: "Mais de 250 itens bônus!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
parents: "Para os pais" parents: "Para os pais"
parents_title: "Seus filhos aprenderam código." parents_title: "Seus filhos aprenderam código."
parents_blurb1: "Com o CodeCombat, seus filhos aprendem a codificar de verdade. Eles começam a aprender comandos simples, e progridem para tópicos avançados." parents_blurb1: "Com o CodeCombat, seus filhos aprendem a codificar de verdade. Eles começam a aprender comandos simples, e progridem para tópicos avançados."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
leaderboard: leaderboard:
leaderboard: "Tabela de Classificação" leaderboard: "Tabela de Classificação"
view_other_solutions: "Ver Outras Soluções" view_other_solutions: "Ver Outras Soluções"
scores: "Pontuações"
top_solutions: "Melhores Soluções" top_solutions: "Melhores Soluções"
day: "Hoje" day: "Hoje"
week: "Esta Semana" week: "Esta Semana"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
recovered: "Recuperada a compra de gemas anterior. Por favor atualiza a página." recovered: "Recuperada a compra de gemas anterior. Por favor atualiza a página."
subscribe: subscribe:
comparison_blurb: "Aperfeiçoa as tuas habilidades com uma subscrição do CodeCombat!"
feature1: "60+ níveis básicos dispersos por 4 mundos"
feature2: "7 <strong>heróis novos</strong> e poderosos com habilidades únicas!"
feature3: "30+ níveis de bónus"
feature4: "<strong>3500 gemas de bónus</strong> por mês!"
feature5: "Tutoriais em vídeo"
feature6: "Apoio por e-mail superior"
free: "Grátis"
month: "mês"
subscribe_title: "Subscrever" subscribe_title: "Subscrever"
unsubscribe: "Cancelar Subscrição" unsubscribe: "Cancelar Subscrição"
confirm_unsubscribe: "Confirmar Cancelamento da Subscrição" confirm_unsubscribe: "Confirmar Cancelamento da Subscrição"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Português (Portugal)", englishDescription:
heroes: "Heróis mais poderosos!" heroes: "Heróis mais poderosos!"
gems: "3500 gemas de bónus todos os meses!" gems: "3500 gemas de bónus todos os meses!"
items: "Mais de 250 itens de bónus!" items: "Mais de 250 itens de bónus!"
parent_button: "Pergunta ao teu educador"
parent_email_description: "Vamos mandar-lhe um e-mail para que ele possa comprar-te uma subscrição do CodeCombat."
parent_email_input_invalid: "Endereço de e-mail inválido."
parent_email_input_label: "Endereço de e-mail do educador"
parent_email_input_placeholder: "Introduz o e-mail do educador"
parent_email_send: "Enviar E-mail"
parent_email_sent: "E-mail enviado!"
parent_email_title: "Qual é o e-mail do teu educador?"
parents: "Para Educadores" parents: "Para Educadores"
parents_title: "O teu educando vai aprender a programar." parents_title: "O teu educando vai aprender a programar."
parents_blurb1: "Com o CodeCombat, o teu educando aprende ao escrever código real. Começa por aprender comandos simples e progride para tópicos mais avançados." parents_blurb1: "Com o CodeCombat, o teu educando aprende ao escrever código real. Começa por aprender comandos simples e progride para tópicos mais avançados."
parents_blurb2: "Por $9.99 USD/mês, recebe novos desafios todas as semanas e suporte pessoal, via e-mail, de programadores profissionais." parents_blurb2: "Por $9.99 USD/mês, recebe novos desafios todas as semanas e suporte pessoal, via e-mail, de programadores profissionais."
parents_blurb3: "Sem Risco: 100% de garantia de devolução do dinheiro, com anulação fácil de 1 clique." parents_blurb3: "Sem Risco: 100% de garantia de devolução do dinheiro, com anulação fácil de 1 clique."
subscribe_button: "Subscrever Agora" subscribe_button: "Subscrever"
stripe_description: "Subscrição Mensal" stripe_description: "Subscrição Mensal"
subscription_required_to_play: "Precisas de uma subscrição para jogares este nível." subscription_required_to_play: "Precisas de uma subscrição para jogares este nível."
unlock_help_videos: "Subscreve-te para desbloqueares todos os tutoriais em vídeo." unlock_help_videos: "Subscreve-te para desbloqueares todos os tutoriais em vídeo."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "limba română", englishDescription: "Roman
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -322,7 +322,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
tip_lines_of_code: "Измерение прогресса программирования в строках кода - это как измерять прогресс построения самолета по его весу. — Bill Gates" tip_lines_of_code: "Измерение прогресса программирования в строках кода - это как измерять прогресс построения самолета по его весу. — Bill Gates"
tip_source_code: "Я хочу изменить мир, но они вряд ли дадут мне исходники." tip_source_code: "Я хочу изменить мир, но они вряд ли дадут мне исходники."
tip_javascript_java: "Java к JavaScript относится так же, как кол относится к колготкам. - Chris Heilmann (перефраз.)" tip_javascript_java: "Java к JavaScript относится так же, как кол относится к колготкам. - Chris Heilmann (перефраз.)"
# tip_move_forward: "Whatever you do, keep moving forward. - Martin Luther King Jr." tip_move_forward: "Что бы вы ни делали, вы должны двигаться вперед. - Martin Luther King Jr"
game_menu: game_menu:
inventory_tab: "Инвентарь" inventory_tab: "Инвентарь"
@ -344,6 +344,7 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
leaderboard: leaderboard:
leaderboard: "Таблица лидеров" leaderboard: "Таблица лидеров"
view_other_solutions: "Посмотреть другие решения" view_other_solutions: "Посмотреть другие решения"
scores: "Рейтинг"
top_solutions: "Лучшие решения" top_solutions: "Лучшие решения"
day: "Сегодня" day: "Сегодня"
week: "На этой неделе" week: "На этой неделе"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
recovered: "Предыдущие покупки самоцветов восстановлены. Пожалуйста, обновите страницу." recovered: "Предыдущие покупки самоцветов восстановлены. Пожалуйста, обновите страницу."
subscribe: subscribe:
comparison_blurb: "Отточите свое мастерство багодаря подписке на CodeCombat!"
feature1: "60+ основных уровней на просторах 4-х миров"
feature2: "7 могущественных <strong>новых героев</strong> с уникальными способностями!"
feature3: "30+ дополнительных уровней"
feature4: "<strong>3500 бонусных самоцветов</strong> каждый месяц!"
feature5: "Обучающие видеоролики"
feature6: "Эксклюзивная поддержка по электронной почте"
free: "Бесплатно"
month: "месяц"
subscribe_title: "Подпишись" subscribe_title: "Подпишись"
unsubscribe: "Отписаться" unsubscribe: "Отписаться"
confirm_unsubscribe: "Подтвердить отмену подписки" confirm_unsubscribe: "Подтвердить отмену подписки"
@ -393,6 +403,14 @@ module.exports = nativeDescription: "русский", englishDescription: "Russi
heroes: "Более сильные герои!" heroes: "Более сильные герои!"
gems: "3500 бонусных самоцветов каждый месяц!" gems: "3500 бонусных самоцветов каждый месяц!"
items: "Более 250 бонусных предметов!" items: "Более 250 бонусных предметов!"
parent_button: "Спросить у родителей"
parent_email_description: "Мы отправим им электронное письмо, чтобы они смогли приобрести тебе подписку на CodeCombat."
parent_email_input_invalid: "Адрес электронной почты введен неправильно."
parent_email_input_label: "Адрес электронной почты родителей"
parent_email_input_placeholder: "Введи адрес электронной почты родителей"
parent_email_send: "Отправить письмо"
parent_email_sent: "Письмо отправлено!"
parent_email_title: "Какой у твоих родителей адрес электронной почты?"
parents: "Для Родителей" parents: "Для Родителей"
parents_title: "Ваш ребенок научится программировать." parents_title: "Ваш ребенок научится программировать."
parents_blurb1: "С CodeCombat ваш ребенок учится через написание реального кода. Начиная с изучения простых команд, продолжая более продвинутыми темами." parents_blurb1: "С CodeCombat ваш ребенок учится через написание реального кода. Начиная с изучения простых команд, продолжая более продвинутыми темами."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "slovenčina", englishDescription: "Slovak",
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "slovenščina", englishDescription: "Sloven
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "српски", englishDescription: "Serbian
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Svenska", englishDescription: "Swedish", tr
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "ไทย", englishDescription: "Thai", tra
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Türkçe", englishDescription: "Turkish", t
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Українська", englishDescription:
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Українська", englishDescription:
recovered: "Попередні покупки самоцвітів відновлені. Будь ласка, поновіть сторінку." recovered: "Попередні покупки самоцвітів відновлені. Будь ласка, поновіть сторінку."
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
subscribe_title: "Взяти абонемент" subscribe_title: "Взяти абонемент"
unsubscribe: "Скасувати абонемент" unsubscribe: "Скасувати абонемент"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,6 +403,14 @@ module.exports = nativeDescription: "Українська", englishDescription:
heroes: "Більше могутніх героїв!" heroes: "Більше могутніх героїв!"
gems: "Щомісячний бонус 3500 самоцвітів!" gems: "Щомісячний бонус 3500 самоцвітів!"
items: "Більше 250-ти бонусних предметів!" items: "Більше 250-ти бонусних предметів!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
parents: "Батькам" parents: "Батькам"
parents_title: "Ваша дитина вчитиметься програмувати." parents_title: "Ваша дитина вчитиметься програмувати."
parents_blurb1: "Разом з CodeCombat Ваша дитина писатиме реальний код. Почне з простих команд та поступово буде розвиватись до складніших тем." parents_blurb1: "Разом з CodeCombat Ваша дитина писатиме реальний код. Почне з простих команд та поступово буде розвиватись до складніших тем."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "اُردُو", englishDescription: "Urdu",
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "Tiếng Việt", englishDescription: "Vietn
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
recovered: "之前购买的宝石已恢复。请刷新页面。" recovered: "之前购买的宝石已恢复。请刷新页面。"
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
subscribe_title: "订阅" subscribe_title: "订阅"
unsubscribe: "取消订阅" unsubscribe: "取消订阅"
confirm_unsubscribe: "确认取消订阅" confirm_unsubscribe: "确认取消订阅"
@ -393,6 +403,14 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
heroes: "更多强大的英雄!" heroes: "更多强大的英雄!"
gems: "每月多3500宝石奖励" gems: "每月多3500宝石奖励"
items: "超过250个物品奖励" items: "超过250个物品奖励"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
parents: "致家长" parents: "致家长"
parents_title: "您的孩子将要学习编写程序。" parents_title: "您的孩子将要学习编写程序。"
parents_blurb1: "通过使用CodeCombat您的孩子将学习编写真正的程序代码。他们将学到简单指令进而处理更复杂的问题。" parents_blurb1: "通过使用CodeCombat您的孩子将学习编写真正的程序代码。他们将学到简单指令进而处理更复杂的问题。"

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
recovered: "先前購買的寶石已回復. 請重新載入頁面." recovered: "先前購買的寶石已回復. 請重新載入頁面."
subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
subscribe_title: "訂閱" subscribe_title: "訂閱"
unsubscribe: "取消訂閱" unsubscribe: "取消訂閱"
confirm_unsubscribe: "確認訂閱" confirm_unsubscribe: "確認訂閱"
@ -387,6 +397,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
thank_you_months_prefix: "感謝您這幾個" thank_you_months_prefix: "感謝您這幾個"
thank_you_months_suffix: "月來的支持" thank_you_months_suffix: "月來的支持"
thank_you: "感謝您支持CodeCombat." thank_you: "感謝您支持CodeCombat."
<<<<<<< HEAD
sorry_to_see_you_go: "捨不得您離開! 請讓我們知道我們如何做得更好." sorry_to_see_you_go: "捨不得您離開! 請讓我們知道我們如何做得更好."
unsubscribe_feedback_placeholder: "O, 我們做錯事了嗎?" unsubscribe_feedback_placeholder: "O, 我們做錯事了嗎?"
levels: "獲得更多新關卡來磨練!" levels: "獲得更多新關卡來磨練!"
@ -398,6 +409,27 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
parents_blurb1: "使用CodeCombat, 您的孩子學習真正的編寫程式. 他們學習從簡單的指令,漸進到更加進階的課題." parents_blurb1: "使用CodeCombat, 您的孩子學習真正的編寫程式. 他們學習從簡單的指令,漸進到更加進階的課題."
parents_blurb2: "每月支付$9.99美金, 他們每週獲得新挑戰以及使用信件取得專業程式員的幫助." parents_blurb2: "每月支付$9.99美金, 他們每週獲得新挑戰以及使用信件取得專業程式員的幫助."
parents_blurb3: "沒有風險: 保證100%退費, 一步取消訂閱." parents_blurb3: "沒有風險: 保證100%退費, 一步取消訂閱."
=======
# sorry_to_see_you_go: "Sorry to see you go! Please let us know what we could have done better."
# unsubscribe_feedback_placeholder: "O, what have we done?"
# levels: "Get more practice with bonus levels!"
# heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents"
# parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
>>>>>>> upstream/master
subscribe_button: "現在訂閱" subscribe_button: "現在訂閱"
stripe_description: "每月訂閱" stripe_description: "每月訂閱"
subscription_required_to_play: "你將需要訂閱來開啟這關." subscription_required_to_play: "你將需要訂閱來開啟這關."
@ -1234,7 +1266,7 @@ module.exports = nativeDescription: "繁体中文", englishDescription: "Chinese
# other_developers: "Other Developers" # other_developers: "Other Developers"
# inactive_developers: "Inactive Developers" # inactive_developers: "Inactive Developers"
# admin: admin:
# av_espionage: "Espionage" # Really not important to translate /admin controls. # av_espionage: "Espionage" # Really not important to translate /admin controls.
av_espionage_placeholder: "信箱或用戶名" av_espionage_placeholder: "信箱或用戶名"
av_usersearch: "用戶搜尋" av_usersearch: "用戶搜尋"

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "吴语", englishDescription: "Wuu (Simplifi
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -344,6 +344,7 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
# leaderboard: # leaderboard:
# leaderboard: "Leaderboard" # leaderboard: "Leaderboard"
# view_other_solutions: "View Other Solutions" # view_other_solutions: "View Other Solutions"
# scores: "Scores"
# top_solutions: "Top Solutions" # top_solutions: "Top Solutions"
# day: "Today" # day: "Today"
# week: "This Week" # week: "This Week"
@ -380,6 +381,15 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
# recovered: "Previous gems purchase recovered. Please refresh the page." # recovered: "Previous gems purchase recovered. Please refresh the page."
# subscribe: # subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "60+ basic levels across 4 worlds"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "30+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe" # subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe" # unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe" # confirm_unsubscribe: "Confirm Unsubscribe"
@ -393,12 +403,20 @@ module.exports = nativeDescription: "吳語", englishDescription: "Wuu (Traditio
# heroes: "More powerful heroes!" # heroes: "More powerful heroes!"
# gems: "3500 bonus gems every month!" # gems: "3500 bonus gems every month!"
# items: "Over 250 bonus items!" # items: "Over 250 bonus items!"
# parent_button: "Ask your parent"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
# parent_email_input_invalid: "Email address invalid."
# parent_email_input_label: "Parent email address"
# parent_email_input_placeholder: "Enter parent email"
# parent_email_send: "Send Email"
# parent_email_sent: "Email sent!"
# parent_email_title: "What's your parent's email?"
# parents: "For Parents" # parents: "For Parents"
# parents_title: "Your child will learn to code." # parents_title: "Your child will learn to code."
# parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics." # parents_blurb1: "With CodeCombat, your child learns by writing real code. They start by learning simple commands, and progress to more advanced topics."
# parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers." # parents_blurb2: "For $9.99 USD/mo, they get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." # parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# subscribe_button: "Subscribe Now" # subscribe_button: "Subscribe"
# stripe_description: "Monthly Subscription" # stripe_description: "Monthly Subscription"
# subscription_required_to_play: "You'll need a subscription to play this level." # subscription_required_to_play: "You'll need a subscription to play this level."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."

View file

@ -148,6 +148,14 @@ module.exports = class User extends CocoModel
application.tracker.identify leaderboardsGroup: @leaderboardsGroup unless me.isAdmin() application.tracker.identify leaderboardsGroup: @leaderboardsGroup unless me.isAdmin()
@leaderboardsGroup @leaderboardsGroup
getShowsPortal: ->
return @showsPortal if @showsPortal?
group = me.get('testGroupNumber')
@showsPortal = if group < 128 then true else false
@showsPortal = true if me.isAdmin()
application.tracker.identify showsPortal: @showsPortal unless me.isAdmin()
@showsPortal
getVideoTutorialStylesIndex: (numVideos=0)-> getVideoTutorialStylesIndex: (numVideos=0)->
# A/B Testing video tutorial styles # A/B Testing video tutorial styles
# Not a constant number of videos available (e.g. could be 0, 1, 3, or 4 currently) # Not a constant number of videos available (e.g. could be 0, 1, 3, or 4 currently)

View file

@ -91,5 +91,6 @@ AchievementSchema.definitions = {}
AchievementSchema.definitions['mongoQueryOperator'] = MongoQueryOperatorSchema AchievementSchema.definitions['mongoQueryOperator'] = MongoQueryOperatorSchema
AchievementSchema.definitions['mongoFindQuery'] = MongoFindQuerySchema AchievementSchema.definitions['mongoFindQuery'] = MongoFindQuerySchema
c.extendTranslationCoverageProperties AchievementSchema c.extendTranslationCoverageProperties AchievementSchema
c.extendPatchableProperties AchievementSchema
module.exports = AchievementSchema module.exports = AchievementSchema

View file

@ -124,5 +124,6 @@ _.extend CampaignSchema.properties, {
c.extendBasicProperties CampaignSchema, 'campaign' c.extendBasicProperties CampaignSchema, 'campaign'
c.extendTranslationCoverageProperties CampaignSchema c.extendTranslationCoverageProperties CampaignSchema
c.extendPatchableProperties CampaignSchema
module.exports = CampaignSchema module.exports = CampaignSchema

View file

@ -1,6 +1,6 @@
c = require './../schemas' c = require './../schemas'
patchables = ['level', 'thang_type', 'level_system', 'level_component', 'article'] patchables = ['level', 'thang_type', 'level_system', 'level_component', 'article', 'achievement', 'campaign']
PatchSchema = c.object({title: 'Patch', required: ['target', 'delta', 'commitMessage']}, { PatchSchema = c.object({title: 'Patch', required: ['target', 'delta', 'commitMessage']}, {
delta: {title: 'Delta', type: ['array', 'object']} delta: {title: 'Delta', type: ['array', 'object']}

View file

@ -85,6 +85,12 @@ _.extend UserSchema.properties,
recruitNotes: {$ref: '#/definitions/emailSubscription'} recruitNotes: {$ref: '#/definitions/emailSubscription'}
employerNotes: {$ref: '#/definitions/emailSubscription'} employerNotes: {$ref: '#/definitions/emailSubscription'}
oneTimes: c.array {title: 'One-time emails'},
c.object {title: 'One-time email', required: ['type', 'targetEmail']},
type: c.shortString() # E.g 'subscribe modal parent'
targetEmail: c.shortString()
sent: c.date() # Set when sent
# server controlled # server controlled
permissions: c.array {}, c.shortString() permissions: c.array {}, c.shortString()
dateCreated: c.date({title: 'Date Joined'}) dateCreated: c.date({title: 'Date Joined'})
@ -272,7 +278,7 @@ _.extend UserSchema.properties,
purchased: c.RewardSchema 'purchased with gems or money' purchased: c.RewardSchema 'purchased with gems or money'
spent: {type: 'number'} spent: {type: 'number'}
stripeCustomerID: { type: 'string' } # TODO: Migrate away from this property stripeCustomerID: { type: 'string' } # TODO: Migrate away from this property
stripe: c.object {}, { stripe: c.object {}, {
customerID: { type: 'string' } customerID: { type: 'string' }
planID: { enum: ['basic'] } planID: { enum: ['basic'] }

View file

@ -51,36 +51,11 @@
&:hover &:hover
color: yellow color: yellow
//- Popovers
//- Selling points
#selling-points
position: absolute
left: 65px
top: 335px
width: 650px
font-weight: bold
line-height: 18px
color: black
font-family: $headings-font-family
font-size: 18px
.point
width: 150px
overflow: none
float: left
text-align: center
margin-right: 10px
#parents-info
position: absolute
right: 7px
top: 56px
text-decoration: underline
cursor: pointer
.popover .popover
z-index: 1050 z-index: 1050
min-width: 400px
h3 h3
background: transparent background: transparent
@ -88,13 +63,67 @@
font-size: 30px font-size: 30px
color: black color: black
//- Sales image
.subscribe-image
position: absolute
top: 114px
right: 65px
//- Feature comparison table
.comparison-blurb
position: absolute
left: 10%
top: 132px
width: 450px
background: rgba(0, 0, 0, 0.0)
font-weight: normal
line-height: 18px
color: black
font-family: $headings-font-family
font-size: 18px
.comparison-table
position: absolute
left: 10%
top: 160px
width: 450px
background: rgba(0, 0, 0, 0.0)
thead
tr
th
font-size: 24px
font-variant: small-caps
font-family: "Open Sans Condensed", "Helvetica Neue", Helvetica, Arial, sans-serif
font-weight: 700
line-height: 1.1
color: #317EAC
tbody
font-size: 14px
.center-ok
text-align: center
//- Parent info popover link
#parents-info
position: absolute
left: 38px
top: 389px
text-decoration: underline
cursor: pointer
font-weight: bold
line-height: 18px
color: black
font-family: $headings-font-family
font-size: 18px
//- Purchase button //- Purchase button
.purchase-button .purchase-button
position: absolute position: absolute
left: 73px right: 24px
width: 600px width: 400px
height: 70px height: 70px
top: 430px top: 430px
font-size: 32px font-size: 32px
@ -116,6 +145,28 @@
padding: 2px 0 0 2px padding: 2px 0 0 2px
color: white color: white
//- Parent button
//- TODO: Add hover and active effects
.parent-button
position: absolute
left: 24px
width: 250px
height: 70px
top: 430px
font-size: 28px
line-height: 38px
border-style: solid
border-image: url(/images/common/button-background-warning-disabled.png) 14 20 20 20 fill round
border-width: 14px 20px 20px 20px
color: darken(white, 5%)
#email-parent-form
.email_invalid
color: red
display: none
#email-parent-complete
display: none
//- Errors //- Errors

View file

@ -243,6 +243,21 @@ $gameControlMargin: 30px
min-width: 200px min-width: 200px
display: block display: block
margin: 10px auto 0 auto margin: 10px auto 0 auto
position: relative
.badge
position: absolute
top: initial
left: initial
right: -25px
bottom: -25px
font-size: 20px
color: black
border: 1px solid black
background-color: rgb(232, 217, 87)
border-radius: 50%
opacity: 1
padding: 3px 9px
&.complete &.complete
.start-level, .view-solutions .start-level, .view-solutions
@ -433,6 +448,21 @@ $gameControlMargin: 30px
&.vol-down .glyphicon.glyphicon-volume-down &.vol-down .glyphicon.glyphicon-volume-down
display: inline-block display: inline-block
#back-button
position: absolute
left: 70px
left: -webkit-calc(1% + 55px)
left: calc(1% + 55px)
top: 1%
padding: 3px 8px
@include opacity(0.75)
&:hover
@include opacity(1.0)
.glyphicon
font-size: 32px
#campaign-status #campaign-status
position: absolute position: absolute
left: 0 left: 0
@ -463,6 +493,78 @@ $gameControlMargin: 30px
.particle-man .particle-man
z-index: 2 z-index: 2
.portal
position: relative
width: 100%
height: 100%
background: transparent url(/images/pages/play/portal-background.png)
display: flex
align-items: center
justify-content: center
.portals
$campaignWidth: 317px
$campaignHeight: 634px
$campaignHoverScale: 1.2
width: 6 * $campaignWidth
height: $campaignHeight * $campaignHoverScale
flex-wrap: nowrap
display: flex
overflow: hidden
.campaign
width: $campaignWidth
height: $campaignHeight
margin-top: $campaignHeight * ($campaignHoverScale - 1) / 2
background: transparent url(/images/pages/play/portal-campaigns.png) no-repeat 0 0
display: inline-block
flex-shrink: 0
position: relative
cursor: pointer
// http://easings.net/#easeOutBack plus tweaked a bit: http://cubic-bezier.com/#.11,.67,.08,1.42
@include transition(0.25s cubic-bezier(0.11, 0.67, 0.8, 1.42))
&:hover
@include scale($campaignHoverScale)
&.silhouette
@include filter(contrast(50%) brightness(65%))
pointer-events: none
&.locked
@include filter(contrast(80%) brightness(80%))
pointer-events: none
&.forest
background-position: (-1 * $campaignWidth) 0
&.desert
background-position: (-2 * $campaignWidth) 0
&.mountain
background-position: (-3 * $campaignWidth) 0
&.ice
background-position: (-4 * $campaignWidth) 0
&.volcano
background-position: (-5 * $campaignWidth) 0
.campaign-label
position: absolute
top: 55%
width: 100%
text-align: center
.campaign-name, .levels-completed, .campaign-locked
margin: 0
color: white
text-shadow: black 2px 2px 0, black -2px -2px 0, black 2px -2px 0, black -2px 2px 0, black 2px 0px 0, black 0px -2px 0, black -2px 0px 0, black 0px 2px 0
.levels-completed
font-size: 22px
.play-button
margin-top: 30px
min-width: 100px
body.ipad #campaign-view body.ipad #campaign-view
// iPad only supports up to Kithgard Gates for now. // iPad only supports up to Kithgard Gates for now.

View file

@ -7,27 +7,67 @@
#retrying-alert.alert.alert-danger(data-i18n="buy_gems.retrying") #retrying-alert.alert.alert-danger(data-i18n="buy_gems.retrying")
else else
img(src="/images/pages/play/modal/subscribe-background.png")#subscribe-background img#subscribe-background(src="/images/pages/play/modal/subscribe-background-blank.png")
img.subscribe-image(src="/images/pages/play/modal/subscribe-heroes.png")
h1(data-i18n="subscribe.subscribe_title") Subscribe h1(data-i18n="subscribe.subscribe_title") Subscribe
div#close-modal div#close-modal
span.glyphicon.glyphicon-remove span.glyphicon.glyphicon-remove
#selling-points div.comparison-blurb(data-i18n="subscribe.comparison_blurb")
#point-levels.point table.table.table-condensed.table-bordered.comparison-table
.blurb(data-i18n="subscribe.levels") thead
#point-heroes.point tr
.blurb(data-i18n="subscribe.heroes") th
#point-gems.point th(data-i18n="subscribe.free")
.blurb(data-i18n="subscribe.gems") th
#point-items.point //- TODO: find a better way to localize '$9.99/month'
.blurb(data-i18n="subscribe.items") span $#{price}/
span(data-i18n="subscribe.month")
tbody
tr
td.feature-description
span(data-i18n="subscribe.feature1")
td.center-ok
span.glyphicon.glyphicon-ok
td.center-ok
span.glyphicon.glyphicon-ok
tr
td.feature-description
span(data-i18n="[html]subscribe.feature2")
td
td.center-ok
span.glyphicon.glyphicon-ok
tr
td.feature-description
span(data-i18n="subscribe.feature3")
td
td.center-ok
span.glyphicon.glyphicon-ok
tr
td.feature-description
span(data-i18n="[html]subscribe.feature4")
td
td.center-ok
span.glyphicon.glyphicon-ok
tr
td.feature-description
span(data-i18n="subscribe.feature5")
td
td.center-ok
span.glyphicon.glyphicon-ok
tr
td.feature-description
span(data-i18n="subscribe.feature6")
td
td.center-ok
span.glyphicon.glyphicon-ok
#parents-info(data-i18n="subscribe.parents")
#parents-info(data-i18n="subscribe.parents") button.btn.btn-lg.btn-illustrated.purchase-button(data-i18n="subscribe.subscribe_title")
button.btn.btn-lg.btn-illustrated.parent-button(data-i18n="subscribe.parent_button")
button.btn.btn-lg.btn-illustrated.purchase-button(data-i18n="subscribe.subscribe_button")
if state === 'declined' if state === 'declined'
#declined-alert.alert.alert-danger.alert-dismissible #declined-alert.alert.alert-danger.alert-dismissible
span(data-i18n="buy_gems.declined") span(data-i18n="buy_gems.declined")

View file

@ -59,6 +59,7 @@
td Playtime td Playtime
td Complete td Complete
td Changed td Changed
td Replay
tbody tbody
- for (var i = 0; i < analytics.recentSessions.data.length; i++) - for (var i = 0; i < analytics.recentSessions.data.length; i++)
tr.recent-session(data-player-id=analytics.recentSessions.data[i].creator, data-session-id=analytics.recentSessions.data[i]._id) tr.recent-session(data-player-id=analytics.recentSessions.data[i].creator, data-session-id=analytics.recentSessions.data[i]._id)
@ -71,6 +72,9 @@
else else
td false td false
td= analytics.recentSessions.data[i].changed td= analytics.recentSessions.data[i].changed
td
button.btn.replay-button.btn-xs
.glyphicon.glyphicon-eye-open
h4 Completion Rates h4 Completion Rates
if analytics.levelCompletions.loading if analytics.levelCompletions.loading

View file

@ -1,54 +1,77 @@
.map if campaign
.gradient.horizontal-gradient.top-gradient .map
.gradient.vertical-gradient.right-gradient .gradient.horizontal-gradient.top-gradient
.gradient.horizontal-gradient.bottom-gradient .gradient.vertical-gradient.right-gradient
.gradient.vertical-gradient.left-gradient .gradient.horizontal-gradient.bottom-gradient
.map-background(alt="", draggable="false") .gradient.vertical-gradient.left-gradient
.map-background(alt="", draggable="false")
each level in levels each level in levels
if !level.hidden if !level.hidden
div(style="left: #{level.position.x}%; bottom: #{level.position.y}%; background-color: #{level.color}", class="level" + (level.next ? " next" : "") + (level.disabled ? " disabled" : "") + (level.locked ? " locked" : "") + " " + (levelStatusMap[level.slug] || ""), data-level-slug=level.slug, data-level-original=level.original, title=i18n(level, 'name') + (level.disabled ? ' (Coming Soon to Adventurers)' : '')) div(style="left: #{level.position.x}%; bottom: #{level.position.y}%; background-color: #{level.color}", class="level" + (level.next ? " next" : "") + (level.disabled ? " disabled" : "") + (level.locked ? " locked" : "") + " " + (levelStatusMap[level.slug] || ""), data-level-slug=level.slug, data-level-original=level.original, title=i18n(level, 'name') + (level.disabled ? ' (Coming Soon to Adventurers)' : ''))
if level.unlocksHero && (!level.purchasedHero || editorMode) if level.unlocksHero && (!level.purchasedHero || editorMode)
img.hero-portrait(src="/file/db/thang.type/#{level.unlocksHero}/portrait.png") img.hero-portrait(src="/file/db/thang.type/#{level.unlocksHero}/portrait.png")
a(href=level.type == 'hero' ? '#' : level.disabled ? "/play" : "/play/#{level.levelPath || 'level'}/#{level.slug}", disabled=level.disabled, data-level-slug=level.slug, data-level-path=level.levelPath || 'level', data-level-name=level.name) a(href=level.type == 'hero' ? '#' : level.disabled ? "/play" : "/play/#{level.levelPath || 'level'}/#{level.slug}", disabled=level.disabled, data-level-slug=level.slug, data-level-path=level.levelPath || 'level', data-level-name=level.name)
if level.requiresSubscription if level.requiresSubscription
img.star(src="/images/pages/play/star.png") img.star(src="/images/pages/play/star.png")
if levelStatusMap[level.slug] === 'complete' if levelStatusMap[level.slug] === 'complete'
img.banner(src="/images/pages/play/level-banner-complete.png") img.banner(src="/images/pages/play/level-banner-complete.png")
if levelStatusMap[level.slug] === 'started' if levelStatusMap[level.slug] === 'started'
img.banner(src="/images/pages/play/level-banner-started.png") img.banner(src="/images/pages/play/level-banner-started.png")
div(style="left: #{level.position.x}%; bottom: #{level.position.y}%", class="level-shadow" + (level.next ? " next" : "") + " " + (levelStatusMap[level.slug] || "")) div(style="left: #{level.position.x}%; bottom: #{level.position.y}%", class="level-shadow" + (level.next ? " next" : "") + " " + (levelStatusMap[level.slug] || ""))
.level-info-container(data-level-slug=level.slug, data-level-path=level.levelPath || 'level', data-level-name=level.name) .level-info-container(data-level-slug=level.slug, data-level-path=level.levelPath || 'level', data-level-name=level.name)
- var playCount = levelPlayCountMap[level.slug] - var playCount = levelPlayCountMap[level.slug]
div(class="level-info " + (levelStatusMap[level.slug] || "") + (level.requiresSubscription ? " premium" : "")) div(class="level-info " + (levelStatusMap[level.slug] || "") + (level.requiresSubscription ? " premium" : ""))
.level-status .level-status
h3= i18n(level, 'name') + (level.disabled ? " (Coming soon!)" : (level.locked ? " (Locked)" : "")) h3= i18n(level, 'name') + (level.disabled ? " (Coming soon!)" : (level.locked ? " (Locked)" : ""))
- var description = i18n(level, 'description') || level.description || "" - var description = i18n(level, 'description') || level.description || ""
.level-description!= marked(description) .level-description!= marked(description)
if level.disabled if level.disabled
p p
span.spr(data-i18n="play.awaiting_levels_adventurer_prefix") We release five levels per week. span.spr(data-i18n="play.awaiting_levels_adventurer_prefix") We release five levels per week.
a.spr(href="/contribute/adventurer") a.spr(href="/contribute/adventurer")
strong(data-i18n="play.awaiting_levels_adventurer") Sign up as an Adventurer strong(data-i18n="play.awaiting_levels_adventurer") Sign up as an Adventurer
span.spl(data-i18n="play.awaiting_levels_adventurer_suffix") to be the first to play new levels. span.spl(data-i18n="play.awaiting_levels_adventurer_suffix") to be the first to play new levels.
if !level.disabled && !level.locked if !level.disabled && !level.locked
if playCount && playCount.sessions if playCount && playCount.sessions
.play-counts.hidden .play-counts.hidden
span.spl.spr= playCount.sessions span.spl.spr= playCount.sessions
span(data-i18n="play.players") players span(data-i18n="play.players") players
span.spr , #{Math.round(playCount.playtime / 3600)} span.spr , #{Math.round(playCount.playtime / 3600)}
span(data-i18n="play.hours_played") hours played span(data-i18n="play.hours_played") hours played
if levelStatusMap[level.slug] === 'complete' if levelStatusMap[level.slug] === 'complete'
button.btn.btn-warning.btn.btn-lg.btn-illustrated.view-solutions(data-level-slug=level.slug) button.btn.btn-warning.btn.btn-lg.btn-illustrated.view-solutions(data-level-slug=level.slug)
span(data-i18n="leaderboard.scores") span(data-i18n="leaderboard.scores")
button.btn.btn-success.btn.btn-lg.btn-illustrated.start-level(data-i18n="common.play") Play button.btn.btn-success.btn.btn-lg.btn-illustrated.start-level(data-i18n="common.play") Play
else if level.unlocksHero && !level.purchasedHero else if level.unlocksHero && !level.purchasedHero
img.hero-portrait(src="/file/db/thang.type/#{level.unlocksHero}/portrait.png", style="left: #{level.position.x}%; bottom: #{level.position.y}%;") img.hero-portrait(src="/file/db/thang.type/#{level.unlocksHero}/portrait.png", style="left: #{level.position.x}%; bottom: #{level.position.y}%;")
for adjacentCampaign in adjacentCampaigns for adjacentCampaign in adjacentCampaigns
a(href=(editorMode ? "/editor/campaign/" : "/play/") + adjacentCampaign.slug) a(href=(editorMode ? "/editor/campaign/" : "/play/") + adjacentCampaign.slug)
span.glyphicon.glyphicon-share-alt.campaign-switch(style=adjacentCampaign.style, title=adjacentCampaign.name, data-campaign-id=adjacentCampaign.id) span.glyphicon.glyphicon-share-alt.campaign-switch(style=adjacentCampaign.style, title=adjacentCampaign.name, data-campaign-id=adjacentCampaign.id)
else
.portal
.portals
for campaignSlug in ['dungeon', 'forest', 'desert', 'mountain', 'ice', 'volcano']
- var campaign = campaigns[campaignSlug];
div(class="campaign #{campaignSlug}" + (campaign ? "" : " silhouette") + (campaign && campaign.locked ? " locked" : ""), data-campaign-slug=campaignSlug)
.campaign-label
h2.campaign-name
if campaign
span= i18n(campaign.attributes, 'fullName')
else
span ???
if campaign && campaign.levelsTotal
h3.levels-completed
span= campaign.levelsCompleted
| /
span= campaign.levelsTotal
if campaign && campaign.locked
h3.campaign-locked(data-i18n="play.locked") Locked
else if campaign
btn(data-i18n="common.play").btn.btn-illustrated.btn-lg.btn-success.play-button
.game-controls.header-font .game-controls.header-font
button.btn.items(data-toggle='coco-modal', data-target='play/modal/PlayItemsModal', data-i18n="[title]play.items") button.btn.items(data-toggle='coco-modal', data-target='play/modal/PlayItemsModal', data-i18n="[title]play.items")
@ -85,7 +108,11 @@ button.btn.btn-lg.btn-inverse#volume-button(data-i18n="[title]play.adjust_volume
.glyphicon.glyphicon-volume-down .glyphicon.glyphicon-volume-down
.glyphicon.glyphicon-volume-up .glyphicon.glyphicon-volume-up
if campaign.loaded if campaign
.btn.btn-lg.btn-inverse#back-button(data-i18n="[title]resources.campaigns", title="Campaigns")
.glyphicon.glyphicon-globe
if campaign && campaign.loaded
h1#campaign-status h1#campaign-status
.campaign-status-background .campaign-status-background
.campaign-name .campaign-name

View file

@ -241,7 +241,7 @@ module.exports = class CocoView extends Backbone.View
showLoading: ($el=@$el) -> showLoading: ($el=@$el) ->
$el.find('>').addClass('hidden') $el.find('>').addClass('hidden')
$el.append loadingScreenTemplate() $el.append(loadingScreenTemplate()).i18n()
@_lastLoading = $el @_lastLoading = $el
hideLoading: -> hideLoading: ->

View file

@ -17,8 +17,9 @@ module.exports = class SubscribeModal extends ModalView
'stripe:received-token': 'onStripeReceivedToken' 'stripe:received-token': 'onStripeReceivedToken'
events: events:
'click .purchase-button': 'onClickPurchaseButton'
'click #close-modal': 'hide' 'click #close-modal': 'hide'
'click #parent-send': 'onClickParentSendButton'
'click .purchase-button': 'onClickPurchaseButton'
constructor: (options) -> constructor: (options) ->
super(options) super(options)
@ -34,6 +35,40 @@ module.exports = class SubscribeModal extends ModalView
afterRender: -> afterRender: ->
super() super()
@setupParentButtonPopover()
@setupParentInfoPopover()
setupParentButtonPopover: ->
popoverTitle = $.i18n.t 'subscribe.parent_email_title'
popoverTitle += '<button type="button" class="close" onclick="$(&#39;.parent-button&#39;).popover(&#39;hide&#39;);">&times;</button>'
popoverContent = "<div id='email-parent-form'>"
popoverContent += "<p>#{$.i18n.t('subscribe.parent_email_description')}</p>"
popoverContent += "<form>"
popoverContent += " <div class='form-group'>"
popoverContent += " <label>#{$.i18n.t('subscribe.parent_email_input_label')}</label>"
popoverContent += " <input id='parent-input' type='email' class='form-control' placeholder='#{$.i18n.t('subscribe.parent_email_input_placeholder')}'/>"
popoverContent += " <div id='parent-email-validator' class='email_invalid'>#{$.i18n.t('subscribe.parent_email_input_invalid')}</div>"
popoverContent += " </div>"
popoverContent += " <button id='parent-send' type='submit' class='btn btn-default'>#{$.i18n.t('subscribe.parent_email_send')}</button>"
popoverContent += "</form>"
popoverContent += "</div>"
popoverContent += "<div id='email-parent-complete'>"
popoverContent += " <p>#{$.i18n.t('subscribe.parent_email_sent')}</p>"
popoverContent += " <button type='button' onclick='$(&#39;.parent-button&#39;).popover(&#39;hide&#39;);'>#{$.i18n.t('modal.close')}</button>"
popoverContent += "</div>"
@$el.find('.parent-button').popover(
animation: true
html: true
placement: 'top'
trigger: 'click'
title: popoverTitle
content: popoverContent
container: @$el
).on 'shown.bs.popover', =>
application.tracker?.trackEvent 'Subscription ask parent button click', {}
setupParentInfoPopover: ->
popoverTitle = $.i18n.t 'subscribe.parents_title' popoverTitle = $.i18n.t 'subscribe.parents_title'
popoverContent = "<p>" + $.i18n.t('subscribe.parents_blurb1') + "</p>" popoverContent = "<p>" + $.i18n.t('subscribe.parents_blurb1') + "</p>"
popoverContent += "<p>" + $.i18n.t('subscribe.parents_blurb2') + "</p>" popoverContent += "<p>" + $.i18n.t('subscribe.parents_blurb2') + "</p>"
@ -50,6 +85,26 @@ module.exports = class SubscribeModal extends ModalView
).on 'shown.bs.popover', => ).on 'shown.bs.popover', =>
application.tracker?.trackEvent 'Subscription parent hover', {} application.tracker?.trackEvent 'Subscription parent hover', {}
onClickParentSendButton: (e) ->
# TODO: Popover sometimes dismisses immediately after send
email = $('#parent-input').val()
unless /[\w\.]+@\w+\.\w+/.test email
$('#parent-input').parent().addClass('has-error')
$('#parent-email-validator').show()
return false
request = @supermodel.addRequestResource 'send_one_time_email', {
url: '/db/user/-/send_one_time_email'
data: {email: email, type: 'subscribe modal parent'}
method: 'POST'
}, 0
request.load()
$('#email-parent-form').hide()
$('#email-parent-complete').show()
false
onClickPurchaseButton: (e) -> onClickPurchaseButton: (e) ->
@playSound 'menu-button-click' @playSound 'menu-button-click'
return @openModalView new AuthModal() if me.get('anonymous') return @openModalView new AuthModal() if me.get('anonymous')

View file

@ -16,6 +16,7 @@ module.exports = class CampaignLevelView extends CocoView
'dblclick .recent-session': 'onDblClickRecentSession' 'dblclick .recent-session': 'onDblClickRecentSession'
'mouseenter .graph-point': 'onMouseEnterPoint' 'mouseenter .graph-point': 'onMouseEnterPoint'
'mouseleave .graph-point': 'onMouseLeavePoint' 'mouseleave .graph-point': 'onMouseLeavePoint'
'click .replay-button': 'onClickReplay'
constructor: (options, @level) -> constructor: (options, @level) ->
super(options) super(options)
@ -77,6 +78,11 @@ module.exports = class CampaignLevelView extends CocoView
pointID = $(e.target).data('pointid') pointID = $(e.target).data('pointid')
@$el.find(".graph-point-info-container[data-pointid=#{pointID}]").hide() @$el.find(".graph-point-info-container[data-pointid=#{pointID}]").hide()
onClickReplay: (e) ->
sessionID = $(e.target).closest('tr').data 'session-id'
url = "/play/level/#{@level.get('slug')}?session=#{sessionID}&observing=true"
window.open url, '_blank'
updateAnalyticsGraphData: -> updateAnalyticsGraphData: ->
# console.log 'updateAnalyticsGraphData' # console.log 'updateAnalyticsGraphData'
# Build graphs based on available @analytics data # Build graphs based on available @analytics data

View file

@ -140,9 +140,14 @@ module.exports = class I18NEditModelView extends RootView
return _.isArray(delta.o) and delta.o.length is 1 and 'i18n' in delta.dataPath return _.isArray(delta.o) and delta.o.length is 1 and 'i18n' in delta.dataPath
) )
commitMessage = "Diplomat submission for lang #{@selectedLanguage}: #{flattened.length} change(s)."
save = false if @savedBefore
if save if save
modelToSave = @model.cloneNewMinorVersion() modelToSave = @model.cloneNewMinorVersion()
modelToSave.updateI18NCoverage() if modelToSave.get('i18nCoverage') modelToSave.updateI18NCoverage() if modelToSave.get('i18nCoverage')
if @modelClass.schema.properties.commitMessage
modelToSave.set 'commitMessage', commitMessage
else else
modelToSave = new Patch() modelToSave = new Patch()
@ -151,17 +156,21 @@ module.exports = class I18NEditModelView extends RootView
'collection': _.string.underscored @model.constructor.className 'collection': _.string.underscored @model.constructor.className
'id': @model.id 'id': @model.id
} }
if @modelClass.schema.properties.commitMessage
commitMessage = "Diplomat submission for lang #{@selectedLanguage}: #{flattened.length} change(s)."
modelToSave.set 'commitMessage', commitMessage modelToSave.set 'commitMessage', commitMessage
errors = modelToSave.validate() errors = modelToSave.validate()
button = $(e.target) button = $(e.target)
button.attr('disabled', 'disabled') button.attr('disabled', 'disabled')
return button.text('Failed to Submit Changes') if errors return button.text('Failed to Submit Changes') if errors
res = modelToSave.save(null, {type: 'POST'}) # Override PUT so we can trigger postNewVersion logic type = 'PUT'
if @modelClass.schema.properties.version or (not save)
# Override PUT so we can trigger postNewVersion logic
# or you're POSTing a Patch
type = 'POST'
res = modelToSave.save(null, {type: type})
return button.text('Failed to Submit Changes') unless res return button.text('Failed to Submit Changes') unless res
button.text('Submitting...') button.text('Submitting...')
res.error => button.text('Error Submitting Changes') res.error => button.text('Error Submitting Changes')
res.success => button.text('Submit Changes') res.success =>
@savedBefore = true
button.text('Submit Changes')

View file

@ -27,6 +27,11 @@ class LevelSessionsCollection extends CocoCollection
super() super()
@url = "/db/user/#{me.id}/level.sessions?project=state.complete,levelID" @url = "/db/user/#{me.id}/level.sessions?project=state.complete,levelID"
class CampaignsCollection extends CocoCollection
url: '/db/campaign'
model: Campaign
project: ['name', 'fullName', 'i18n']
module.exports = class CampaignView extends RootView module.exports = class CampaignView extends RootView
id: 'campaign-view' id: 'campaign-view'
template: template template: template
@ -41,18 +46,30 @@ module.exports = class CampaignView extends RootView
'click .level-info-container .start-level': 'onClickStartLevel' 'click .level-info-container .start-level': 'onClickStartLevel'
'click .level-info-container .view-solutions': 'onClickViewSolutions' 'click .level-info-container .view-solutions': 'onClickViewSolutions'
'click #volume-button': 'onToggleVolume' 'click #volume-button': 'onToggleVolume'
'click #back-button': 'onClickBack'
'click .portal .campaign': 'onClickPortalCampaign'
'mouseenter .portals': 'onMouseEnterPortals'
'mouseleave .portals': 'onMouseLeavePortals'
'mousemove .portals': 'onMouseMovePortals'
constructor: (options, @terrain='dungeon') -> constructor: (options, @terrain) ->
super options super options
options ?= {} @editorMode = options?.editorMode
if @editorMode
@campaign = new Campaign({_id:@terrain}) @terrain ?= 'dungeon'
@campaign = @supermodel.loadModel(@campaign, 'campaign').model else unless me.getShowsPortal()
@terrain ?= 'dungeon'
@editorMode = options.editorMode
@levelStatusMap = {} @levelStatusMap = {}
@levelPlayCountMap = {} @levelPlayCountMap = {}
@sessions = @supermodel.loadCollection(new LevelSessionsCollection(), 'your_sessions', null, 0).model @sessions = @supermodel.loadCollection(new LevelSessionsCollection(), 'your_sessions', null, 0).model
@listenToOnce @sessions, 'sync', @onSessionsLoaded
unless @terrain
@campaigns = @supermodel.loadCollection(new CampaignsCollection(), 'campaigns', null, 0).model
@listenToOnce @campaigns, 'sync', @onCampaignsLoaded
return
@campaign = new Campaign({_id:@terrain})
@campaign = @supermodel.loadModel(@campaign, 'campaign').model
# Temporary attempt to make sure all earned rewards are accounted for. Figure out a better solution... # Temporary attempt to make sure all earned rewards are accounted for. Figure out a better solution...
@earnedAchievements = new CocoCollection([], {url: '/db/earned_achievement', model:EarnedAchievement, project: ['earnedRewards']}) @earnedAchievements = new CocoCollection([], {url: '/db/earned_achievement', model:EarnedAchievement, project: ['earnedRewards']})
@ -69,7 +86,6 @@ module.exports = class CampaignView extends RootView
@supermodel.loadCollection(@earnedAchievements, 'achievements') @supermodel.loadCollection(@earnedAchievements, 'achievements')
@listenToOnce @sessions, 'sync', @onSessionsLoaded
@listenToOnce @campaign, 'sync', @getLevelPlayCounts @listenToOnce @campaign, 'sync', @getLevelPlayCounts
$(window).on 'resize', @onWindowResize $(window).on 'resize', @onWindowResize
@probablyCachedMusic = storage.load("loaded-menu-music") @probablyCachedMusic = storage.load("loaded-menu-music")
@ -91,7 +107,7 @@ module.exports = class CampaignView extends RootView
destroy: -> destroy: ->
@setupManager?.destroy() @setupManager?.destroy()
@$el.find('.ui-draggable').draggable 'destroy' @$el.find('.ui-draggable').off().draggable 'destroy'
$(window).off 'resize', @onWindowResize $(window).off 'resize', @onWindowResize
if ambientSound = @ambientSound if ambientSound = @ambientSound
# Doesn't seem to work; stops immediately. # Doesn't seem to work; stops immediately.
@ -99,6 +115,7 @@ module.exports = class CampaignView extends RootView
@musicPlayer?.destroy() @musicPlayer?.destroy()
clearTimeout @playMusicTimeout clearTimeout @playMusicTimeout
@particleMan?.destroy() @particleMan?.destroy()
clearInterval @portalScrollInterval
super() super()
getLevelPlayCounts: -> getLevelPlayCounts: ->
@ -124,6 +141,7 @@ module.exports = class CampaignView extends RootView
@fullyRendered = true @fullyRendered = true
@render() @render()
@preloadTopHeroes() unless me.get('heroConfig')?.thangType @preloadTopHeroes() unless me.get('heroConfig')?.thangType
@$el.find('#campaign-status').delay(4000).animate({top: "-=58"}, 1000) unless @terrain is 'dungeon'
setCampaign: (@campaign) -> setCampaign: (@campaign) ->
@render() @render()
@ -135,31 +153,16 @@ module.exports = class CampaignView extends RootView
getRenderData: (context={}) -> getRenderData: (context={}) ->
context = super(context) context = super(context)
context.campaign = @campaign context.campaign = @campaign
context.levels = _.values($.extend true, {}, @campaign.get('levels')) context.levels = _.values($.extend true, {}, @campaign?.get('levels') ? {})
context.levelsCompleted = context.levelsTotal = 0 @annotateLevel level for level in context.levels
for level in context.levels count = @countLevels context.levels
level.position ?= { x: 10, y: 10 } context.levelsCompleted = count.completed
level.locked = not me.ownsLevel level.original context.levelsTotal = count.total
level.locked = false if @levelStatusMap[level.slug] in ['started', 'complete']
level.locked = false if @editorMode
level.locked = false if @campaign.get('name') is 'Auditions'
level.disabled = true if level.adminOnly and @levelStatusMap[level.slug] not in ['started', 'complete']
level.color = 'rgb(255, 80, 60)'
if level.requiresSubscription
level.color = 'rgb(80, 130, 200)'
if unlocksHero = _.find(level.rewards, 'hero')?.hero
level.unlocksHero = unlocksHero
if level.unlocksHero
level.purchasedHero = level.unlocksHero in (me.get('purchased')?.heroes or [])
level.hidden = level.locked
unless level.disabled
++context.levelsTotal
++context.levelsCompleted if @levelStatusMap[level.slug] is 'complete'
@determineNextLevel context.levels if @sessions.loaded @determineNextLevel context.levels if @sessions?.loaded
# put lower levels in last, so in the world map they layer over one another properly. # put lower levels in last, so in the world map they layer over one another properly.
context.levels = (_.sortBy context.levels, (l) -> l.position.y).reverse() context.levels = (_.sortBy context.levels, (l) -> l.position.y).reverse()
@campaign.renderedLevels = context.levels @campaign.renderedLevels = context.levels if @campaign
context.levelStatusMap = @levelStatusMap context.levelStatusMap = @levelStatusMap
context.levelPlayCountMap = @levelPlayCountMap context.levelPlayCountMap = @levelPlayCountMap
@ -167,7 +170,7 @@ module.exports = class CampaignView extends RootView
context.mapType = _.string.slugify @terrain context.mapType = _.string.slugify @terrain
context.requiresSubscription = @requiresSubscription context.requiresSubscription = @requiresSubscription
context.editorMode = @editorMode context.editorMode = @editorMode
context.adjacentCampaigns = _.filter _.values(_.cloneDeep(@campaign.get('adjacentCampaigns') or {})), (ac) => context.adjacentCampaigns = _.filter _.values(_.cloneDeep(@campaign?.get('adjacentCampaigns') or {})), (ac) =>
return false if ac.showIfUnlocked and (ac.showIfUnlocked not in me.levels()) and not @editorMode return false if ac.showIfUnlocked and (ac.showIfUnlocked not in me.levels()) and not @editorMode
ac.name = utils.i18n ac, 'name' ac.name = utils.i18n ac, 'name'
styles = [] styles = []
@ -180,6 +183,26 @@ module.exports = class CampaignView extends RootView
return true return true
context.marked = marked context.marked = marked
context.i18n = utils.i18n context.i18n = utils.i18n
if @campaigns
context.campaigns = {}
for campaign in @campaigns.models
context.campaigns[campaign.get('slug')] = campaign
if @sessions.loaded
levels = _.values($.extend true, {}, campaign.get('levels') ? {})
count = @countLevels levels
campaign.levelsTotal = count.total
campaign.levelsCompleted = count.completed
if campaign.get('slug') is 'dungeon'
campaign.locked = false
else unless campaign.levelsTotal
campaign.locked = true
else
campaign.locked = true
for campaign in @campaigns.models
for acID, ac of campaign.get('adjacentCampaigns') ? {}
_.find(@campaigns.models, id: acID)?.locked = false if ac.showIfUnlocked in me.levels()
context context
afterRender: -> afterRender: ->
@ -189,7 +212,7 @@ module.exports = class CampaignView extends RootView
_.defer => @$el?.find('.game-controls .btn').addClass('has-tooltip').tooltip() # Have to defer or i18n doesn't take effect. _.defer => @$el?.find('.game-controls .btn').addClass('has-tooltip').tooltip() # Have to defer or i18n doesn't take effect.
view = @ view = @
@$el.find('.level, .campaign-switch').addClass('has-tooltip').tooltip().each -> @$el.find('.level, .campaign-switch').addClass('has-tooltip').tooltip().each ->
return unless me.isAdmin() return unless me.isAdmin() and view.editorMode
$(@).draggable().on 'dragstop', -> $(@).draggable().on 'dragstop', ->
bg = $('.map-background') bg = $('.map-background')
x = ($(@).offset().left - bg.offset().left + $(@).outerWidth() / 2) / bg.width() x = ($(@).offset().left - bg.offset().left + $(@).outerWidth() / 2) / bg.width()
@ -202,7 +225,7 @@ module.exports = class CampaignView extends RootView
unless window.currentModal or not @fullyRendered unless window.currentModal or not @fullyRendered
@highlightElement '.level.next', delay: 500, duration: 60000, rotation: 0, sides: ['top'] @highlightElement '.level.next', delay: 500, duration: 60000, rotation: 0, sides: ['top']
if @editorMode if @editorMode
for level in @campaign.renderedLevels for level in @campaign?.renderedLevels ? []
for nextLevelOriginal in level.nextLevels ? [] for nextLevelOriginal in level.nextLevels ? []
if nextLevel = _.find(@campaign.renderedLevels, original: nextLevelOriginal) if nextLevel = _.find(@campaign.renderedLevels, original: nextLevelOriginal)
@createLine level.position, nextLevel.position @createLine level.position, nextLevel.position
@ -219,6 +242,32 @@ module.exports = class CampaignView extends RootView
authModal.mode = 'signup' authModal.mode = 'signup'
@openModalView authModal @openModalView authModal
annotateLevel: (level) ->
level.position ?= { x: 10, y: 10 }
level.locked = not me.ownsLevel level.original
level.locked = false if @levelStatusMap[level.slug] in ['started', 'complete']
level.locked = false if @editorMode
level.locked = false if @campaign?.get('name') is 'Auditions'
level.disabled = true if level.adminOnly and @levelStatusMap[level.slug] not in ['started', 'complete']
level.color = 'rgb(255, 80, 60)'
if level.requiresSubscription
level.color = 'rgb(80, 130, 200)'
if unlocksHero = _.find(level.rewards, 'hero')?.hero
level.unlocksHero = unlocksHero
if level.unlocksHero
level.purchasedHero = level.unlocksHero in (me.get('purchased')?.heroes or [])
level.hidden = level.locked
level
countLevels: (levels) ->
count = total: 0, completed: 0
for level in levels
@annotateLevel level unless level.locked? # Annotate if we haven't already.
unless level.disabled
++count.total
++count.completed if @levelStatusMap[level.slug] is 'complete'
count
showLeaderboard: (levelSlug) -> showLeaderboard: (levelSlug) ->
#levelSlug ?= 'siege-of-stonehold' # Testing #levelSlug ?= 'siege-of-stonehold' # Testing
leaderboardModal = new LeaderboardModal supermodel: @supermodel, levelSlug: levelSlug leaderboardModal = new LeaderboardModal supermodel: @supermodel, levelSlug: levelSlug
@ -248,7 +297,7 @@ module.exports = class CampaignView extends RootView
line.append($('<div class="line">')).append($('<div class="point">')) line.append($('<div class="line">')).append($('<div class="point">'))
applyCampaignStyles: -> applyCampaignStyles: ->
return unless @campaign.loaded return unless @campaign?.loaded
if (backgrounds = @campaign.get 'backgroundImage') and backgrounds.length if (backgrounds = @campaign.get 'backgroundImage') and backgrounds.length
backgrounds = _.sortBy backgrounds, 'width' backgrounds = _.sortBy backgrounds, 'width'
backgrounds.reverse() backgrounds.reverse()
@ -266,7 +315,7 @@ module.exports = class CampaignView extends RootView
@playAmbientSound() @playAmbientSound()
testParticles: -> testParticles: ->
return unless @campaign.loaded and me.getForeshadowsLevels() return unless @campaign?.loaded and me.getForeshadowsLevels()
@particleMan ?= new ParticleMan() @particleMan ?= new ParticleMan()
@particleMan.removeEmitters() @particleMan.removeEmitters()
@particleMan.attach @$el.find('.map') @particleMan.attach @$el.find('.map')
@ -279,18 +328,62 @@ module.exports = class CampaignView extends RootView
continue if particleKey.length is 2 # Don't show basic levels continue if particleKey.length is 2 # Don't show basic levels
@particleMan.addEmitter level.position.x / 100, level.position.y / 100, particleKey.join('-') @particleMan.addEmitter level.position.x / 100, level.position.y / 100, particleKey.join('-')
onMouseEnterPortals: (e) ->
return unless @campaigns?.loaded and @sessions?.loaded
@portalScrollInterval = setInterval @onMouseMovePortals, 100
@onMouseMovePortals e
onMouseLeavePortals: (e) ->
return unless @portalScrollInterval
clearInterval @portalScrollInterval
@portalScrollInterval = null
onMouseMovePortals: (e) =>
return unless @portalScrollInterval
$portal = @$el.find('.portal')
$portals = @$el.find('.portals')
if e
@portalOffsetX = Math.round Math.max 0, e.clientX - $portal.offset().left
bodyWidth = $('body').innerWidth()
fraction = @portalOffsetX / bodyWidth
return if 0.2 < fraction < 0.8
direction = if fraction < 0.5 then 1 else -1
magnitude = 0.2 * bodyWidth * (if direction is -1 then fraction - 0.8 else 0.2 - fraction) / 0.2
portalsWidth = 1902 # TODO: if we add campaigns or change margins, this will get out of date...
scrollTo = $portals.offset().left + direction * magnitude
scrollTo = Math.max bodyWidth - portalsWidth, scrollTo
scrollTo = Math.min 0, scrollTo
$portals.stop().animate {marginLeft: scrollTo}, 100, 'linear'
onSessionsLoaded: (e) -> onSessionsLoaded: (e) ->
return if @editorMode return if @editorMode
for session in @sessions.models for session in @sessions.models
@levelStatusMap[session.get('levelID')] = if session.get('state')?.complete then 'complete' else 'started' @levelStatusMap[session.get('levelID')] = if session.get('state')?.complete then 'complete' else 'started'
@render() @render()
onCampaignsLoaded: (e) ->
@render()
preloadLevel: (levelSlug) ->
levelURL = "/db/level/#{levelSlug}"
level = new Level().setURL levelURL
level = @supermodel.loadModel(level, 'level', null, 0).model
sessionURL = "/db/level/#{levelSlug}/session"
#@preloadedSession = new LevelSession().setURL sessionURL
#@preloadedSession.levelSlug = levelSlug
#@preloadedSession.fetch()
#@listenToOnce @preloadedSession, 'sync', @onSessionPreloaded
onSessionPreloaded: (session) ->
levelElement = @$el.find('.level-info-container:visible')
return unless session.levelSlug is levelElement.data 'level-slug'
return unless difficulty = session.get('state')?.difficulty
badge = $("<span class='badge'>#{difficulty}</span>")
levelElement.find('.start-level .badge').remove()
levelElement.find('.start-level').append badge
onClickMap: (e) -> onClickMap: (e) ->
@$levelInfo?.hide() @$levelInfo?.hide()
# Easy-ish way of figuring out coordinates for placing level dots.
x = e.offsetX / @$el.find('.map-background').width()
y = (1 - e.offsetY / @$el.find('.map-background').height())
console.log " x: #{(100 * x).toFixed(2)}\n y: #{(100 * y).toFixed(2)}\n"
onClickLevel: (e) -> onClickLevel: (e) ->
e.preventDefault() e.preventDefault()
@ -304,6 +397,7 @@ module.exports = class CampaignView extends RootView
@$levelInfo = @$el.find(".level-info-container[data-level-slug=#{levelSlug}]").show() @$levelInfo = @$el.find(".level-info-container[data-level-slug=#{levelSlug}]").show()
@adjustLevelInfoPosition e @adjustLevelInfoPosition e
@endHighlight() @endHighlight()
@preloadLevel levelSlug
onDoubleClickLevel: (e) -> onDoubleClickLevel: (e) ->
return unless @editorMode return unless @editorMode
@ -326,7 +420,9 @@ module.exports = class CampaignView extends RootView
startLevel: (levelElement) -> startLevel: (levelElement) ->
@setupManager?.destroy() @setupManager?.destroy()
@setupManager = new LevelSetupManager supermodel: @supermodel, levelID: levelElement.data('level-slug'), levelPath: levelElement.data('level-path'), levelName: levelElement.data('level-name'), hadEverChosenHero: @hadEverChosenHero, parent: @ levelSlug = levelElement.data 'level-slug'
session = @preloadedSession if @preloadedSession?.loaded and @preloadedSession.levelSlug is levelSlug
@setupManager = new LevelSetupManager supermodel: @supermodel, levelID: levelSlug, levelPath: levelElement.data('level-path'), levelName: levelElement.data('level-name'), hadEverChosenHero: @hadEverChosenHero, parent: @, session: session
@setupManager.open() @setupManager.open()
@$levelInfo?.hide() @$levelInfo?.hide()
@ -421,9 +517,24 @@ module.exports = class CampaignView extends RootView
newI = 2 newI = 2
@updateVolume volumes[newI] @updateVolume volumes[newI]
onClickBack: (e) ->
Backbone.Mediator.publish 'router:navigate',
route: "/play"
viewClass: CampaignView
viewArgs: [{supermodel: @supermodel}]
updateHero: -> updateHero: ->
return unless hero = me.get('heroConfig')?.thangType return unless hero = me.get('heroConfig')?.thangType
for slug, original of ThangType.heroes when original is hero for slug, original of ThangType.heroes when original is hero
@$el.find('.player-hero-icon').removeClass().addClass('player-hero-icon ' + slug) @$el.find('.player-hero-icon').removeClass().addClass('player-hero-icon ' + slug)
return return
console.error "CampaignView hero update couldn't find hero slug for original:", hero console.error "CampaignView hero update couldn't find hero slug for original:", hero
onClickPortalCampaign: (e) ->
campaign = $(e.target).closest('.campaign')
return if campaign.is('.locked') or campaign.is('.silhouette')
campaignSlug = campaign.data('campaign-slug')
Backbone.Mediator.publish 'router:navigate',
route: "/play/#{campaignSlug}"
viewClass: CampaignView
viewArgs: [{supermodel: @supermodel}, campaignSlug]

View file

@ -64,6 +64,8 @@ module.exports = class ControlBarView extends CocoView
c.multiplayerStatus = @multiplayerStatusManager?.status c.multiplayerStatus = @multiplayerStatusManager?.status
if @level.get 'replayable' if @level.get 'replayable'
c.levelDifficulty = @session.get('state')?.difficulty ? 0 c.levelDifficulty = @session.get('state')?.difficulty ? 0
if @observing
c.levelDifficulty = Math.max 0, c.levelDifficulty - 1 # Show the difficulty they won, not the next one.
c.difficultyTitle = "#{$.i18n.t 'play.level_difficulty'}#{c.levelDifficulty}" c.difficultyTitle = "#{$.i18n.t 'play.level_difficulty'}#{c.levelDifficulty}"
@lastDifficulty = c.levelDifficulty @lastDifficulty = c.levelDifficulty
c.spectateGame = @spectateGame c.spectateGame = @spectateGame
@ -78,9 +80,8 @@ module.exports = class ControlBarView extends CocoView
@homeLink = c.homeLink = '/play' @homeLink = c.homeLink = '/play'
@homeViewClass = 'views/play/CampaignView' @homeViewClass = 'views/play/CampaignView'
campaign = @level.get 'campaign' campaign = @level.get 'campaign'
if campaign isnt 'dungeon' @homeLink += '/' + campaign
@homeLink += '/' + campaign @homeViewArgs.push campaign
@homeViewArgs.push campaign
else else
@homeLink = c.homeLink = '/' @homeLink = c.homeLink = '/'
@homeViewClass = 'views/HomeView' @homeViewClass = 'views/HomeView'

View file

@ -127,7 +127,7 @@ module.exports = class PlayLevelView extends RootView
load: -> load: ->
@loadStartTime = new Date() @loadStartTime = new Date()
@god = new God debugWorker: true @god = new God debugWorker: true
@levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, sessionID: @sessionID, opponentSessionID: @opponentSessionID, team: @getQueryVariable('team') @levelLoader = new LevelLoader supermodel: @supermodel, levelID: @levelID, sessionID: @sessionID, opponentSessionID: @opponentSessionID, team: @getQueryVariable('team'), observing: @observing
@listenToOnce @levelLoader, 'world-necessities-loaded', @onWorldNecessitiesLoaded @listenToOnce @levelLoader, 'world-necessities-loaded', @onWorldNecessitiesLoaded
trackLevelLoadEnd: -> trackLevelLoadEnd: ->

View file

@ -326,7 +326,7 @@ module.exports = class HeroVictoryModal extends ModalView
getNextLevelLink: -> getNextLevelLink: ->
link = '/play' link = '/play'
nextCampaign = @getNextLevelCampaign() nextCampaign = @getNextLevelCampaign()
link += '/' + nextCampaign unless nextCampaign is 'dungeon' link += '/' + nextCampaign
link link
onClickContinue: (e, extraOptions=null) -> onClickContinue: (e, extraOptions=null) ->

View file

@ -785,17 +785,14 @@ module.exports = class SpellView extends CocoView
if @_singleLineCommentRegex if @_singleLineCommentRegex
@_singleLineCommentRegex.lastIndex = 0 @_singleLineCommentRegex.lastIndex = 0
return @_singleLineCommentRegex return @_singleLineCommentRegex
commentStarts =
javascript: '//'
python: '#'
coffeescript: '#'
clojure: ';'
lua: '--'
io: '//'
commentStart = commentStarts[@spell.language] or '//' commentStart = commentStarts[@spell.language] or '//'
@_singleLineCommentRegex = new RegExp "[ \t]*#{commentStart}[^\"'\n]*", 'g' @_singleLineCommentRegex = new RegExp "[ \t]*#{commentStart}[^\"'\n]*", 'g'
@_singleLineCommentRegex @_singleLineCommentRegex
commentOutMyCode: ->
prefix = if @spell.language is 'javascript' then 'return; ' else 'return '
comment = prefix + commentStarts[@spell.language]
preload: -> preload: ->
# Send this code over to the God for preloading, but don't change the cast state. # Send this code over to the God for preloading, but don't change the cast state.
oldSource = @spell.source oldSource = @spell.source
@ -1096,3 +1093,11 @@ module.exports = class SpellView extends CocoView
@toolbarView?.destroy() @toolbarView?.destroy()
$(window).off 'resize', @onWindowResize $(window).off 'resize', @onWindowResize
super() super()
commentStarts =
javascript: '//'
python: '#'
coffeescript: '#'
clojure: ';'
lua: '--'
io: '//'

View file

@ -80,7 +80,7 @@ module.exports = class TomeView extends CocoView
onCommentMyCode: (e) -> onCommentMyCode: (e) ->
for spellKey, spell of @spells when spell.canWrite() for spellKey, spell of @spells when spell.canWrite()
console.log 'Commenting out', spellKey console.log 'Commenting out', spellKey
commentedSource = 'return; // Commented out to stop infinite loop.\n' + spell.getSource() commentedSource = spell.view.commentOutMyCode() + 'Commented out to stop infinite loop.\n' + spell.getSource()
spell.view.updateACEText commentedSource spell.view.updateACEText commentedSource
spell.view.recompile false spell.view.recompile false
@cast() @cast()
@ -166,7 +166,10 @@ module.exports = class TomeView extends CocoView
sessionState.flagHistory = _.filter sessionState.flagHistory ? [], (event) => event.team isnt (@options.session.get('team') ? 'humans') sessionState.flagHistory = _.filter sessionState.flagHistory ? [], (event) => event.team isnt (@options.session.get('team') ? 'humans')
sessionState.lastUnsuccessfulSubmissionTime = new Date() if @options.level.get 'replayable' sessionState.lastUnsuccessfulSubmissionTime = new Date() if @options.level.get 'replayable'
@options.session.set 'state', sessionState @options.session.set 'state', sessionState
Backbone.Mediator.publish 'tome:cast-spells', spells: @spells, preload: preload, realTime: realTime, submissionCount: sessionState.submissionCount ? 0, flagHistory: sessionState.flagHistory ? [], difficulty: sessionState.difficulty ? 0 difficulty = sessionState.difficulty ? 0
if @options.observing
difficulty = Math.max 0, difficulty - 1 # Show the difficulty they won, not the next one.
Backbone.Mediator.publish 'tome:cast-spells', spells: @spells, preload: preload, realTime: realTime, submissionCount: sessionState.submissionCount ? 0, flagHistory: sessionState.flagHistory ? [], difficulty: difficulty
onToggleSpellList: (e) -> onToggleSpellList: (e) ->
@spellList.rerenderEntries() @spellList.rerenderEntries()

View file

@ -9,6 +9,7 @@ module.exports = function(config) {
// list of files / patterns to load in the browser // list of files / patterns to load in the browser
files : [ files : [
'public/javascripts/vendor.js', // need for jade definition...
'public/javascripts/whole-vendor.js', 'public/javascripts/whole-vendor.js',
'public/lib/ace/ace.js', 'public/lib/ace/ace.js',
'public/javascripts/aether.js', 'public/javascripts/aether.js',

View file

@ -0,0 +1,156 @@
// Help button and video usage
// Usage:
// mongo <address>:<port>/<database> <script file> -u <username> -p <password>
// What do we want to know?
// For each level, how many clicks, starts, finishes
// Individual users only counted once for a level/event combo
try {
var scriptStartTime = new Date();
var analyticsStringCache = {};
// Look at last 30 days, same as Mixpanel
var numDays = 30;
var startDay = new Date();
today = startDay.toISOString().substr(0, 10);
startDay.setUTCDate(startDay.getUTCDate() - numDays);
startDay = startDay.toISOString().substr(0, 10);
log("Today is " + today);
log("Start day is " + startDay);
var events = ['Problem alert help clicked', 'Spell palette help clicked', 'Start help video', 'Finish help video'];
var helpData = getHelpData(startDay, events);
helpData.sort(function (a,b) {
var clickedA = a['Problem alert help clicked'] || 0;
clickedA += a['Spell palette help clicked'] || 0;
var clickedB = b['Problem alert help clicked'] || 0;
clickedB += b['Spell palette help clicked'] || 0;
return clickedA < clickedB ? 1 : -1;
});
log('Help Clicks\tVideo Starts\tStart Rate\tVideo Finishes\tFinish Rate\tLevel')
for(var i = 0; i < helpData.length; i++) {
var level = helpData[i].level;
var clicked = helpData[i]['Problem alert help clicked'] || 0;
clicked += helpData[i]['Spell palette help clicked'] || 0;
var started = helpData[i]['Start help video'] || 0;
var startRate = clicked > 0 ? started / clicked * 100 : 0.0;
var finished = helpData[i]['Finish help video'] || 0;
var finishRate = clicked > 0 ? finished / clicked * 100 : 0.0;
if (started > 1) {
log(clicked + '\t' + started + '\t' + startRate.toFixed(2) + '%\t' + finished + '\t' + finishRate.toFixed(2) + '%\t' + level);
}
}
log("Script runtime: " + (new Date() - scriptStartTime));
}
catch(err) {
log("ERROR: " + err);
printjson(err);
}
// *** Helper functions ***
function log(str) {
print(new Date().toISOString() + " " + str);
}
function objectIdWithTimestamp(timestamp) {
// Convert string date to Date object (otherwise assume timestamp is a date)
if (typeof(timestamp) == 'string') timestamp = new Date(timestamp);
// Convert date object to hex seconds since Unix epoch
var hexSeconds = Math.floor(timestamp/1000).toString(16);
// Create an ObjectId with that hex timestamp
var constructedObjectId = ObjectId(hexSeconds + "0000000000000000");
return constructedObjectId
}
function getAnalyticsString(str) {
if (analyticsStringCache[str]) return analyticsStringCache[str];
// Find existing string
var doc = db['analytics.strings'].findOne({v: str});
if (doc) {
analyticsStringCache[str] = doc._id;
return analyticsStringCache[str];
}
// TODO: Not sure we want to always insert strings here.
// // Insert string
// // http://docs.mongodb.org/manual/tutorial/create-an-auto-incrementing-field/#auto-increment-optimistic-loop
// doc = {v: str};
// while (true) {
// var cursor = db['analytics.strings'].find({}, {_id: 1}).sort({_id: -1}).limit(1);
// var seq = cursor.hasNext() ? cursor.next()._id + 1 : 1;
// doc._id = seq;
// var results = db['analytics.strings'].insert(doc);
// if (results.hasWriteError()) {
// if ( results.writeError.code == 11000 /* dup key */ ) continue;
// else throw new Error("ERROR: Unexpected error inserting data: " + tojson(results));
// }
// break;
// }
//
// // Find new string entry
// doc = db['analytics.strings'].findOne({v: str});
// if (doc) {
// analyticsStringCache[str] = doc._id;
// return analyticsStringCache[str];
// }
throw new Error("ERROR: Did not find analytics.strings insert for: " + str);
}
function getHelpData(startDay, events) {
if (!startDay || !events || events.length === 0) return {};
var startObj = objectIdWithTimestamp(ISODate(startDay + "T00:00:00.000Z"));
var queryParams = {$and: [{_id: {$gte: startObj}},{"event": {$in: events}}]};
var cursor = db['analytics.log.events'].find(queryParams);
// Map ordering: level, user, event
var levelUserEventMap = {};
while (cursor.hasNext()) {
var doc = cursor.next();
var created = doc._id.getTimestamp().toISOString();
var event = doc.event;
var user = doc.user.valueOf();
var properties = doc.properties;
var level = properties.level || properties.levelID;
if (!levelUserEventMap[level]) levelUserEventMap[level] = {};
if (!levelUserEventMap[level][user]) levelUserEventMap[level][user] = {};
if (!levelUserEventMap[level][user][event]) levelUserEventMap[level][user][event] = 1;
}
// printjson(levelUserEventMap);
// Data: level, event, count
var levelEventMap = {};
for (level in levelUserEventMap) {
for (user in levelUserEventMap[level]) {
for (event in levelUserEventMap[level][user]) {
if (!levelEventMap[level]) levelEventMap[level] = {};
if (!levelEventMap[level][event]) levelEventMap[level][event] = 0;
levelEventMap[level][event] += levelUserEventMap[level][user][event];
}
}
}
// printjson(levelEventMap);
helpData = [];
for (level in levelEventMap) {
var data = {level: level};
for (event in levelEventMap[level]) {
data[event] = levelEventMap[level][event];
}
for (var i = 0; i < events.length; i++) {
if (!data[events[i]]) data[events[i]] = 0
}
helpData.push(data);
}
return helpData;
}

View file

@ -0,0 +1,69 @@
// To use: set the range you want below, make sure your environment has the stripe key, then run:
// node scripts/analytics/subscriptions.js
require('coffee-script');
require('coffee-script/register');
config = require('../../server_config');
if(config.stripe.secretKey.indexOf('sk_test_')==0) {
throw new Error('You should not run this on the test data... Get your environment in gear.');
}
stripe = require('stripe')(config.stripe.secretKey);
var range = {
gt: ''+(new Date('2015-01-01').getTime()/1000),
lt: ''+(new Date('2015-02-01').getTime()/1000)
};
begin = function(starting_after) {
var query = {date: range, limit: 100};
if(starting_after) {
query.starting_after = starting_after;
}
stripe.invoices.list(query, onInvoicesReceived);
}
customersPaid = []
onInvoicesReceived = function(err, invoices) {
for(var i in invoices.data) {
var invoice = invoices.data[i];
if(!invoice.paid) { continue; }
customersPaid.push(invoice.customer);
}
if(invoices.has_more) {
console.log('Loaded', customersPaid.length, 'invoices.')
begin(invoices.data[i].id);
}
else {
console.log('How many customers paid for a subscription:', customersPaid.length);
loadNewCustomers();
}
}
loadNewCustomers = function(starting_after) {
query = {created: range, limit: 100};
if(starting_after) {
query.starting_after = starting_after;
}
stripe.customers.list(query, onCustomersReceived);
}
newCustomersPaid = [];
onCustomersReceived = function(err, customers) {
for(var i in customers.data) {
var customer = customers.data[i];
if(customersPaid.indexOf(customer.id) == -1) { continue; }
newCustomersPaid.push(customer.id);
}
if(customers.has_more) {
console.log('Loaded', newCustomersPaid.length, 'new customers.');
loadNewCustomers(customers.data[i].id);
}
else {
console.log('How many new customers paid for a subscription:', newCustomersPaid.length);
}
}
begin();

View file

@ -81,6 +81,7 @@ AchievementSchema.post 'save', -> @constructor.loadAchievements()
AchievementSchema.plugin(plugins.NamedPlugin) AchievementSchema.plugin(plugins.NamedPlugin)
AchievementSchema.plugin(plugins.SearchablePlugin, {searchable: ['name']}) AchievementSchema.plugin(plugins.SearchablePlugin, {searchable: ['name']})
AchievementSchema.plugin plugins.TranslationCoveragePlugin AchievementSchema.plugin plugins.TranslationCoveragePlugin
AchievementSchema.plugin plugins.PatchablePlugin
module.exports = Achievement = mongoose.model('Achievement', AchievementSchema, 'achievements') module.exports = Achievement = mongoose.model('Achievement', AchievementSchema, 'achievements')

View file

@ -1,5 +1,7 @@
log = require 'winston'
mongoose = require 'mongoose' mongoose = require 'mongoose'
plugins = require '../plugins/plugins' plugins = require '../plugins/plugins'
utils = require '../lib/utils'
AnalyticsLogEventSchema = new mongoose.Schema({ AnalyticsLogEventSchema = new mongoose.Schema({
u: mongoose.Schema.Types.ObjectId u: mongoose.Schema.Types.ObjectId
@ -14,4 +16,102 @@ AnalyticsLogEventSchema = new mongoose.Schema({
AnalyticsLogEventSchema.index({event: 1, _id: 1}) AnalyticsLogEventSchema.index({event: 1, _id: 1})
AnalyticsLogEventSchema.statics.logEvent = (user, event, properties) ->
unless user?
log.warn 'No user given to analytics logEvent.'
return
saveDoc = (eventID, slimProperties) ->
doc = new AnalyticsLogEvent
u: user
e: eventID
p: slimProperties
# TODO: Remove these legacy properties after we stop querying for them (probably 30 days, ~2/16/15)
user: user
event: event
properties: properties
doc.save()
utils.getAnalyticsStringID event, (eventID) ->
if eventID > 0
# TODO: properties slimming is pretty ugly
slimProperties = _.cloneDeep properties
if event in ['Clicked Level', 'Show problem alert', 'Started Level', 'Saw Victory', 'Problem alert help clicked', 'Spell palette help clicked']
delete slimProperties.level if event is 'Saw Victory'
properties.ls = mongoose.Types.ObjectId properties.ls if properties.ls
slimProperties.ls = mongoose.Types.ObjectId slimProperties.ls if slimProperties.ls
if slimProperties.levelID?
# levelID: string => l: string ID
utils.getAnalyticsStringID slimProperties.levelID, (levelStringID) ->
if levelStringID > 0
delete slimProperties.levelID
slimProperties.l = levelStringID
saveDoc eventID, slimProperties
return
else if event in ['Script Started', 'Script Ended']
properties.ls = mongoose.Types.ObjectId properties.ls if properties.ls
slimProperties.ls = mongoose.Types.ObjectId slimProperties.ls if slimProperties.ls
if slimProperties.levelID? and slimProperties.label?
# levelID: string => l: string ID
# label: string => lb: string ID
utils.getAnalyticsStringID slimProperties.levelID, (levelStringID) ->
if levelStringID > 0
delete slimProperties.levelID
slimProperties.l = levelStringID
utils.getAnalyticsStringID slimProperties.label, (labelStringID) ->
if labelStringID > 0
delete slimProperties.label
slimProperties.lb = labelStringID
saveDoc eventID, slimProperties
return
else if event is 'Heard Sprite'
properties.ls = mongoose.Types.ObjectId properties.ls if properties.ls
slimProperties.ls = mongoose.Types.ObjectId slimProperties.ls if slimProperties.ls
if slimProperties.message?
# message: string => m: string ID
utils.getAnalyticsStringID slimProperties.message, (messageStringID) ->
if messageStringID > 0
delete slimProperties.message
slimProperties.m = messageStringID
saveDoc eventID, slimProperties
return
else if event in ['Start help video', 'Finish help video']
properties.ls = mongoose.Types.ObjectId properties.ls if properties.ls
slimProperties.ls = mongoose.Types.ObjectId slimProperties.ls if slimProperties.ls
if slimProperties.level and slimProperties.style?
# level: string => l: string ID
# style: string => s: string ID
utils.getAnalyticsStringID slimProperties.level, (levelStringID) ->
if levelStringID > 0
delete slimProperties.level
slimProperties.l = levelStringID
utils.getAnalyticsStringID slimProperties.style, (styleStringID) ->
if styleStringID > 0
delete slimProperties.style
slimProperties.s = styleStringID
saveDoc eventID, slimProperties
return
else if event is 'Show subscription modal'
delete properties.category
delete slimProperties.category
if slimProperties.label?
# label: string => lb: string ID
utils.getAnalyticsStringID slimProperties.label, (labelStringID) ->
if labelStringID > 0
delete slimProperties.label
slimProperties.lb = labelStringID
if slimProperties.level?
# level: string => l: string ID
utils.getAnalyticsStringID slimProperties.level, (levelStringID) ->
if levelStringID > 0
delete slimProperties.level
slimProperties.l = levelStringID
saveDoc eventID, slimProperties
return
saveDoc eventID, slimProperties
return
saveDoc eventID, slimProperties
else
log.warn "Unable to get analytics string ID for " + event
module.exports = AnalyticsLogEvent = mongoose.model('analytics.log.event', AnalyticsLogEventSchema) module.exports = AnalyticsLogEvent = mongoose.model('analytics.log.event', AnalyticsLogEventSchema)

View file

@ -39,102 +39,7 @@ class AnalyticsLogEventHandler extends Handler
event = req.query.event or req.body.event event = req.query.event or req.body.event
properties = req.query.properties or req.body.properties properties = req.query.properties or req.body.properties
@sendSuccess res # Return request immediately @sendSuccess res # Return request immediately
unless user? AnalyticsLogEvent.logEvent user, event, properties
log.warn 'No user given to analytics logEvent.'
return
saveDoc = (eventID, slimProperties) ->
doc = new AnalyticsLogEvent
u: user
e: eventID
p: slimProperties
# TODO: Remove these legacy properties after we stop querying for them (probably 30 days, ~2/16/15)
user: user
event: event
properties: properties
doc.save()
utils.getAnalyticsStringID event, (eventID) ->
if eventID > 0
# TODO: properties slimming is pretty ugly
slimProperties = _.cloneDeep properties
if event in ['Clicked Level', 'Show problem alert', 'Started Level', 'Saw Victory', 'Problem alert help clicked', 'Spell palette help clicked']
delete slimProperties.level if event is 'Saw Victory'
properties.ls = mongoose.Types.ObjectId properties.ls if properties.ls
slimProperties.ls = mongoose.Types.ObjectId slimProperties.ls if slimProperties.ls
if slimProperties.levelID?
# levelID: string => l: string ID
utils.getAnalyticsStringID slimProperties.levelID, (levelStringID) ->
if levelStringID > 0
delete slimProperties.levelID
slimProperties.l = levelStringID
saveDoc eventID, slimProperties
return
else if event in ['Script Started', 'Script Ended']
properties.ls = mongoose.Types.ObjectId properties.ls if properties.ls
slimProperties.ls = mongoose.Types.ObjectId slimProperties.ls if slimProperties.ls
if slimProperties.levelID? and slimProperties.label?
# levelID: string => l: string ID
# label: string => lb: string ID
utils.getAnalyticsStringID slimProperties.levelID, (levelStringID) ->
if levelStringID > 0
delete slimProperties.levelID
slimProperties.l = levelStringID
utils.getAnalyticsStringID slimProperties.label, (labelStringID) ->
if labelStringID > 0
delete slimProperties.label
slimProperties.lb = labelStringID
saveDoc eventID, slimProperties
return
else if event is 'Heard Sprite'
properties.ls = mongoose.Types.ObjectId properties.ls if properties.ls
slimProperties.ls = mongoose.Types.ObjectId slimProperties.ls if slimProperties.ls
if slimProperties.message?
# message: string => m: string ID
utils.getAnalyticsStringID slimProperties.message, (messageStringID) ->
if messageStringID > 0
delete slimProperties.message
slimProperties.m = messageStringID
saveDoc eventID, slimProperties
return
else if event in ['Start help video', 'Finish help video']
properties.ls = mongoose.Types.ObjectId properties.ls if properties.ls
slimProperties.ls = mongoose.Types.ObjectId slimProperties.ls if slimProperties.ls
if slimProperties.level and slimProperties.style?
# level: string => l: string ID
# style: string => s: string ID
utils.getAnalyticsStringID slimProperties.level, (levelStringID) ->
if levelStringID > 0
delete slimProperties.level
slimProperties.l = levelStringID
utils.getAnalyticsStringID slimProperties.style, (styleStringID) ->
if styleStringID > 0
delete slimProperties.style
slimProperties.s = styleStringID
saveDoc eventID, slimProperties
return
else if event is 'Show subscription modal'
delete properties.category
delete slimProperties.category
if slimProperties.label?
# label: string => lb: string ID
utils.getAnalyticsStringID slimProperties.label, (labelStringID) ->
if labelStringID > 0
delete slimProperties.label
slimProperties.lb = labelStringID
if slimProperties.level?
# level: string => l: string ID
utils.getAnalyticsStringID slimProperties.level, (levelStringID) ->
if levelStringID > 0
delete slimProperties.level
slimProperties.l = levelStringID
saveDoc eventID, slimProperties
return
saveDoc eventID, slimProperties
return
saveDoc eventID, slimProperties
else
log.warn "Unable to get analytics string ID for " + event
getLevelCompletionsBySlug: (req, res) -> getLevelCompletionsBySlug: (req, res) ->
# Returns an array of per-day level starts and finishes # Returns an array of per-day level starts and finishes
@ -204,7 +109,7 @@ class AnalyticsLogEventHandler extends Handler
for level of levelDateMap for level of levelDateMap
completions[level] = [] completions[level] = []
for created, item of levelDateMap[level] for created, item of levelDateMap[level]
completions[level].push completions[level].push
level: level level: level
created: created created: created
started: Object.keys(item.started).length started: Object.keys(item.started).length
@ -382,7 +287,7 @@ class AnalyticsLogEventHandler extends Handler
getUserEventData campaigns getUserEventData campaigns
getCampaignData = () => getCampaignData = () =>
# Get campaign data # Get campaign data
# Output: # Output:
# campaigns - per-campaign dictionary of ordered levelIDs # campaigns - per-campaign dictionary of ordered levelIDs
# campaignLevelIDs - dictionary of all campaign levelIDs # campaignLevelIDs - dictionary of all campaign levelIDs

View file

@ -97,7 +97,7 @@ class AnalyticsPerDayHandler extends Handler
@sendSuccess res, completions @sendSuccess res, completions
getLevelData = (campaignLevels) => getLevelData = (campaignLevels) =>
# 2. Get ordered level slugs and string ID to level slug mappping # 2. Get ordered level slugs and string ID to level slug mapping
# Input: # Input:
# campaignLevels - array of Level IDs # campaignLevels - array of Level IDs

View file

@ -8,5 +8,6 @@ CampaignSchema.index({slug: 1}, {name: 'slug index', sparse: true, unique: true}
CampaignSchema.plugin(plugins.NamedPlugin) CampaignSchema.plugin(plugins.NamedPlugin)
CampaignSchema.plugin(plugins.TranslationCoveragePlugin) CampaignSchema.plugin(plugins.TranslationCoveragePlugin)
CampaignSchema.plugin plugins.PatchablePlugin
module.exports = mongoose.model('campaign', CampaignSchema) module.exports = mongoose.model('campaign', CampaignSchema)

View file

@ -24,6 +24,15 @@ CampaignHandler = class CampaignHandler extends Handler
hasAccess: (req) -> hasAccess: (req) ->
req.method is 'GET' or req.user?.isAdmin() req.method is 'GET' or req.user?.isAdmin()
get: (req, res) ->
return @sendForbiddenError(res) if not @hasAccess(req)
# We don't have normal text search or anything set up to make /db/campaign work, so we'll just give them all campaigns, no problem.
q = @modelClass.find {}
q.exec (err, documents) =>
return @sendDatabaseError(res, err) if err
documents = (@formatEntity(req, doc) for doc in documents)
@sendSuccess(res, documents)
getByRelationship: (req, res, args...) -> getByRelationship: (req, res, args...) ->
relationship = args[1] relationship = args[1]
if relationship in ['levels', 'achievements'] if relationship in ['levels', 'achievements']

View file

@ -34,7 +34,7 @@ module.exports = class Handler
hasAccessToDocument: (req, document, method=null) -> hasAccessToDocument: (req, document, method=null) ->
return true if req.user?.isAdmin() return true if req.user?.isAdmin()
if @modelClass.schema.uses_coco_translation_coverage and (method or req.method).toLowerCase() is 'post' if @modelClass.schema.uses_coco_translation_coverage and (method or req.method).toLowerCase() in ['post', 'put']
return true if @isJustFillingTranslations(req, document) return true if @isJustFillingTranslations(req, document)
if @modelClass.schema.uses_coco_permissions if @modelClass.schema.uses_coco_permissions
@ -461,8 +461,9 @@ module.exports = class Handler
sendwithus.api.send context, (err, result) -> sendwithus.api.send context, (err, result) ->
sendChangedHipChatMessage: (options) -> sendChangedHipChatMessage: (options) ->
message = "#{options.creator.get('name')} saved a change to <a href=\"#{options.docLink}\">#{options.target.get('name')}</a>: #{options.target.get('commitMessage')}" message = "#{options.creator.get('name')} saved a change to <a href=\"#{options.docLink}\">#{options.target.get('name')}</a>: #{options.target.get('commitMessage') or '(no commit message)'}"
hipchat.sendHipChatMessage message rooms = if /Diplomat submission/.test(message) then ['main'] else ['main', 'artisans']
hipchat.sendHipChatMessage message, rooms
makeNewInstance: (req) -> makeNewInstance: (req) ->
model = new @modelClass({}) model = new @modelClass({})

View file

@ -2,32 +2,34 @@ config = require '../server_config'
request = require 'request' request = require 'request'
log = require 'winston' log = require 'winston'
module.exports.sendHipChatMessage = sendHipChatMessage = (message) -> roomIDMap =
return unless key = config.hipchatAPIKey main: 254598
return unless config.isProduction artisans: 1146994
roomID = 254598 tower: 318356
form =
color: 'yellow'
notify: false
message: message
messageFormat: 'html'
url = "https://api.hipchat.com/v2/room/#{roomID}/notification?auth_token=#{key}"
request.post {uri: url, json: form}, (err, res, body) ->
return log.error 'Error sending HipChat patch request:', err or body if err or /error/i.test body
#log.info "Got HipChat patch response:", body
module.exports.sendTowerHipChatMessage = sendTowerHipChatMessage = (message) -> module.exports.sendHipChatMessage = sendHipChatMessage = (message, rooms, options) ->
secondsFromEpoch = Math.floor(new Date().getTime() / 1000)
link = "<a href=\"https://papertrailapp.com/groups/488214/events?time=#{secondsFromEpoch}\">PaperTrail</a>"
message = "#{message} #{link}"
return unless key = config.hipchatTowerAPIKey
return unless config.isProduction return unless config.isProduction
roomID = 318356 rooms ?= ['main']
form = options ?= {}
color: 'red' for room in rooms
notify: true unless roomID = roomIDMap[room]
message: message log.error "Unknown HipChat room #{room}."
messageFormat: 'html' continue
url = "https://api.hipchat.com/v2/room/#{roomID}/notification?auth_token=#{key}" unless key = config.hipchat[room]
request.post {uri: url, json: form}, (err, res, body) -> log.info "No HipChat API key for room #{room}."
return log.error 'Error sending HipChat Tower message:', err or body if err or /error/i.test body continue
form =
color: options.color or 'yellow'
notify: false
message: message
messageFormat: 'html'
if options.papertrail
secondsFromEpoch = Math.floor(new Date().getTime() / 1000)
link = "<a href=\"https://papertrailapp.com/groups/488214/events?time=#{secondsFromEpoch}\">PaperTrail</a>"
form.message = "#{message} #{link}"
form.color = options.color or 'red'
form.notify = true
url = "https://api.hipchat.com/v2/room/#{roomID}/notification?auth_token=#{key}"
request.post {uri: url, json: form}, (err, res, body) ->
return log.error 'Error sending HipChat message:', err or body if err or /error/i.test body
#log.info "Got HipChat message response:", body

View file

@ -101,6 +101,6 @@ PatchHandler = class PatchHandler extends Handler
sendPatchCreatedHipChatMessage: (options) -> sendPatchCreatedHipChatMessage: (options) ->
message = "#{options.creator.get('name')} submitted a patch to <a href=\"#{options.docLink}\">#{options.target.get('name')}</a>: #{options.patch.get('commitMessage')}" message = "#{options.creator.get('name')} submitted a patch to <a href=\"#{options.docLink}\">#{options.target.get('name')}</a>: #{options.patch.get('commitMessage')}"
hipchat.sendHipChatMessage message hipchat.sendHipChatMessage message, ['main']
module.exports = new PatchHandler() module.exports = new PatchHandler()

View file

@ -35,7 +35,7 @@ PaymentHandler = class PaymentHandler extends Handler
editableProperties: [] editableProperties: []
postEditableProperties: ['purchased'] postEditableProperties: ['purchased']
jsonSchema: require '../../app/schemas/models/payment.schema' jsonSchema: require '../../app/schemas/models/payment.schema'
get: (req, res) -> get: (req, res) ->
return res.send([]) unless req.user return res.send([]) unless req.user
q = Payment.find({recipient:req.user._id}) q = Payment.find({recipient:req.user._id})
@ -43,7 +43,7 @@ PaymentHandler = class PaymentHandler extends Handler
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
res.send(payments) res.send(payments)
) )
logPaymentError: (req, msg) -> logPaymentError: (req, msg) ->
console.warn "Payment Error: #{req.user.get('slug')} (#{req.user._id}): '#{msg}'" console.warn "Payment Error: #{req.user.get('slug')} (#{req.user._id}): '#{msg}'"
@ -57,10 +57,10 @@ PaymentHandler = class PaymentHandler extends Handler
post: (req, res, pathName) -> post: (req, res, pathName) ->
if pathName is 'check-stripe-charges' if pathName is 'check-stripe-charges'
return @checkStripeCharges(req, res) return @checkStripeCharges(req, res)
if (not req.user) or req.user.isAnonymous() if (not req.user) or req.user.isAnonymous()
return @sendForbiddenError(res) return @sendForbiddenError(res)
appleReceipt = req.body.apple?.rawReceipt appleReceipt = req.body.apple?.rawReceipt
appleTransactionID = req.body.apple?.transactionID appleTransactionID = req.body.apple?.transactionID
appleLocalPrice = req.body.apple?.localPrice appleLocalPrice = req.body.apple?.localPrice
@ -146,7 +146,7 @@ PaymentHandler = class PaymentHandler extends Handler
if validation.valid is false if validation.valid is false
@logPaymentError(req, 'Invalid apple payment object.') @logPaymentError(req, 'Invalid apple payment object.')
return @sendBadInputError(res, validation.errors) return @sendBadInputError(res, validation.errors)
payment.save((err) => payment.save((err) =>
if err if err
@logPaymentError(req, 'Apple payment save error.'+err) @logPaymentError(req, 'Apple payment save error.'+err)
@ -170,24 +170,24 @@ PaymentHandler = class PaymentHandler extends Handler
# First, make sure we save the payment info as a Customer object, if we haven't already. # First, make sure we save the payment info as a Customer object, if we haven't already.
if token if token
customerID = req.user.get('stripe')?.customerID customerID = req.user.get('stripe')?.customerID
if customerID if customerID
# old customer, new token. Save it. # old customer, new token. Save it.
stripe.customers.update customerID, { card: token }, (err, customer) => stripe.customers.update customerID, { card: token }, (err, customer) =>
@beginStripePayment(req, res, timestamp, productID) @beginStripePayment(req, res, timestamp, productID)
else else
newCustomer = { newCustomer = {
card: token card: token
email: req.user.get('email') email: req.user.get('email')
metadata: { id: req.user._id + '', slug: req.user.get('slug') } metadata: { id: req.user._id + '', slug: req.user.get('slug') }
} }
stripe.customers.create newCustomer, (err, customer) => stripe.customers.create newCustomer, (err, customer) =>
if err if err
@logPaymentError(req, 'Stripe customer creation error. '+err) @logPaymentError(req, 'Stripe customer creation error. '+err)
return @sendDatabaseError(res, err) return @sendDatabaseError(res, err)
stripeInfo = _.cloneDeep(req.user.get('stripe') ? {}) stripeInfo = _.cloneDeep(req.user.get('stripe') ? {})
stripeInfo.customerID = customer.id stripeInfo.customerID = customer.id
req.user.set('stripe', stripeInfo) req.user.set('stripe', stripeInfo)
@ -223,7 +223,7 @@ PaymentHandler = class PaymentHandler extends Handler
((err, results) => ((err, results) =>
if err if err
@logPaymentError(req, 'Stripe async load db error. '+err) @logPaymentError(req, 'Stripe async load db error. '+err)
return @sendDatabaseError(res, err) return @sendDatabaseError(res, err)
[payment, charge] = results [payment, charge] = results
if not (payment or charge) if not (payment or charge)
@ -285,7 +285,7 @@ PaymentHandler = class PaymentHandler extends Handler
timestamp: parseInt(charge.metadata.timestamp) timestamp: parseInt(charge.metadata.timestamp)
chargeID: charge.id chargeID: charge.id
} }
validation = @validateDocumentInput(payment.toObject()) validation = @validateDocumentInput(payment.toObject())
if validation.valid is false if validation.valid is false
@logPaymentError(req, 'Invalid stripe payment object.') @logPaymentError(req, 'Invalid stripe payment object.')
@ -302,9 +302,9 @@ PaymentHandler = class PaymentHandler extends Handler
) )
) )
#- Confirm all Stripe charges are recorded on our server #- Confirm all Stripe charges are recorded on our server
checkStripeCharges: (req, res) -> checkStripeCharges: (req, res) ->
return @sendSuccess(res) unless customerID = req.user.get('stripe')?.customerID return @sendSuccess(res) unless customerID = req.user.get('stripe')?.customerID
async.parallel([ async.parallel([
@ -366,7 +366,7 @@ PaymentHandler = class PaymentHandler extends Handler
sendPaymentHipChatMessage: (options) -> sendPaymentHipChatMessage: (options) ->
try try
message = "#{options.user?.get('name')} bought #{options.payment?.get('amount')} via #{options.payment?.get('service')}." message = "#{options.user?.get('name')} bought #{options.payment?.get('amount')} via #{options.payment?.get('service')}."
hipchat.sendHipChatMessage message hipchat.sendHipChatMessage message, ['tower']
catch e catch e
log.error "Couldn't send HipChat message on payment because of error: #{e}" log.error "Couldn't send HipChat message on payment because of error: #{e}"

View file

@ -4,8 +4,6 @@ Handler = require '../commons/Handler'
{handlers} = require '../commons/mapping' {handlers} = require '../commons/mapping'
mongoose = require 'mongoose' mongoose = require 'mongoose'
log = require 'winston' log = require 'winston'
sendwithus = require '../sendwithus'
hipchat = require '../hipchat'
PurchaseHandler = class PurchaseHandler extends Handler PurchaseHandler = class PurchaseHandler extends Handler
modelClass: Purchase modelClass: Purchase
@ -19,22 +17,22 @@ PurchaseHandler = class PurchaseHandler extends Handler
purchase.set 'recipient', req.user._id purchase.set 'recipient', req.user._id
purchase.set 'created', new Date().toISOString() purchase.set 'created', new Date().toISOString()
purchase purchase
post: (req, res) -> post: (req, res) ->
purchased = req.body.purchased purchased = req.body.purchased
purchaser = req.user._id purchaser = req.user._id
purchasedOriginal = purchased?.original purchasedOriginal = purchased?.original
Handler = require '../commons/Handler' Handler = require '../commons/Handler'
return @sendBadInputError(res) if not Handler.isID(purchasedOriginal) return @sendBadInputError(res) if not Handler.isID(purchasedOriginal)
collection = purchased?.collection collection = purchased?.collection
return @sendBadInputError(res) if not collection in @jsonSchema.properties.purchased.properties.collection.enum return @sendBadInputError(res) if not collection in @jsonSchema.properties.purchased.properties.collection.enum
handler = require('../' + handlers[collection]) handler = require('../' + handlers[collection])
criteria = { 'original': purchasedOriginal } criteria = { 'original': purchasedOriginal }
sort = { 'version.major': -1, 'version.minor': -1 } sort = { 'version.major': -1, 'version.minor': -1 }
handler.modelClass.findOne(criteria).sort(sort).exec (err, purchasedItem) => handler.modelClass.findOne(criteria).sort(sort).exec (err, purchasedItem) =>
gemsOwned = req.user.get('earned')?.gems or 0 gemsOwned = req.user.get('earned')?.gems or 0
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
@ -51,7 +49,7 @@ PurchaseHandler = class PurchaseHandler extends Handler
if purchase if purchase
@addPurchaseToUser(req, res) @addPurchaseToUser(req, res)
return @sendSuccess(res, @formatEntity(req, purchase)) return @sendSuccess(res, @formatEntity(req, purchase))
else else
super(req, res) super(req, res)

View file

@ -48,7 +48,7 @@ module.exports.setup = (app) ->
log.error(error.stack) log.error(error.stack)
# TODO: Generally ignore this error: error: Error trying db method get route analytics.log.event from undefined: Error: Cannot find module '../undefined' # TODO: Generally ignore this error: error: Error trying db method get route analytics.log.event from undefined: Error: Cannot find module '../undefined'
unless "#{parts}" in ['analytics.users.active'] unless "#{parts}" in ['analytics.users.active']
hipchat.sendTowerHipChatMessage errorMessage hipchat.sendHipChatMessage errorMessage, ['tower'], papertrail: true
errors.notFound(res, "Route #{req?.path} not found.") errors.notFound(res, "Route #{req?.path} not found.")
getSchema = (req, res, moduleName) -> getSchema = (req, res, moduleName) ->

View file

@ -10,6 +10,7 @@ module.exports.api = new sendwithusAPI swuAPIKey, debug
if config.unittest if config.unittest
module.exports.api.send = -> module.exports.api.send = ->
module.exports.templates = module.exports.templates =
parent_subscribe_email: 'tem_2APERafogvwKhmcnouigud'
welcome_email: 'utnGaBHuSU4Hmsi7qrAypU' welcome_email: 'utnGaBHuSU4Hmsi7qrAypU'
ladder_update_email: 'JzaZxf39A4cKMxpPZUfWy4' ladder_update_email: 'JzaZxf39A4cKMxpPZUfWy4'
patch_created: 'tem_xhxuNosLALsizTNojBjNcL' patch_created: 'tem_xhxuNosLALsizTNojBjNcL'

View file

@ -9,6 +9,7 @@ errors = require '../commons/errors'
async = require 'async' async = require 'async'
log = require 'winston' log = require 'winston'
moment = require 'moment' moment = require 'moment'
AnalyticsLogEvent = require '../analytics/AnalyticsLogEvent'
LevelSession = require '../levels/sessions/LevelSession' LevelSession = require '../levels/sessions/LevelSession'
LevelSessionHandler = require '../levels/sessions/level_session_handler' LevelSessionHandler = require '../levels/sessions/level_session_handler'
SubscriptionHandler = require '../payments/subscription_handler' SubscriptionHandler = require '../payments/subscription_handler'
@ -17,6 +18,7 @@ EarnedAchievement = require '../achievements/EarnedAchievement'
UserRemark = require './remarks/UserRemark' UserRemark = require './remarks/UserRemark'
{isID} = require '../lib/utils' {isID} = require '../lib/utils'
hipchat = require '../hipchat' hipchat = require '../hipchat'
sendwithus = require '../sendwithus'
serverProperties = ['passwordHash', 'emailLower', 'nameLower', 'passwordReset', 'lastIP'] serverProperties = ['passwordHash', 'emailLower', 'nameLower', 'passwordReset', 'lastIP']
candidateProperties = [ candidateProperties = [
@ -232,6 +234,7 @@ UserHandler = class UserHandler extends Handler
return @getRemark(req, res, args[0]) if args[1] is 'remark' return @getRemark(req, res, args[0]) if args[1] is 'remark'
return @searchForUser(req, res) if args[1] is 'admin_search' return @searchForUser(req, res) if args[1] is 'admin_search'
return @getStripeInfo(req, res, args[0]) if args[1] is 'stripe' return @getStripeInfo(req, res, args[0]) if args[1] is 'stripe'
return @sendOneTimeEmail(req, res, args[0]) if args[1] is 'send_one_time_email'
return @sendNotFoundError(res) return @sendNotFoundError(res)
super(arguments...) super(arguments...)
@ -244,6 +247,37 @@ UserHandler = class UserHandler extends Handler
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
@sendSuccess(res, JSON.stringify(customer, null, '\t')) @sendSuccess(res, JSON.stringify(customer, null, '\t'))
sendOneTimeEmail: (req, res) ->
# TODO: should this API be somewhere else?
return @sendForbiddenError(res) unless req.user
email = req.query.email or req.body.email
type = req.query.type or req.body.type
return @sendBadInputError res, 'No email given.' unless email?
return @sendBadInputError res, 'No type given.' unless type?
return @sendBadInputError res, "Unknown one-time email type #{type}" unless type is 'subscribe modal parent'
emailParams =
email_id: sendwithus.templates.parent_subscribe_email
recipient:
address: email
email_data:
name: req.user.get('name') or ''
if codeLanguage = req.user.get('aceConfig.language')
codeLanguage = codeLanguage[0].toUpperCase() + codeLanguage.slice(1)
emailParams['email_data']['codeLanguage'] = codeLanguage
sendwithus.api.send emailParams, (err, result) =>
if err
log.error "sendwithus one-time email error: #{err}, result: #{result}"
return @sendError res, 500, 'send mail failed.'
req.user.update {$push: {"emails.oneTimes": {type: type, email: email, sent: new Date()}}}, (err) =>
return @sendDatabaseError(res, err) if err
req.user.save (err) =>
return @sendDatabaseError(res, err) if err
@sendSuccess(res, {result: 'success'})
hipchat.sendHipChatMessage "#{req.user.get('name')} #{req.user.get('email')} submitted a subscribe modal parent email #{email}", ['tower']
AnalyticsLogEvent.logEvent req.user, 'Sent one time email', email: email, type: type
agreeToCLA: (req, res) -> agreeToCLA: (req, res) ->
return @sendForbiddenError(res) unless req.user return @sendForbiddenError(res) unless req.user
doc = doc =
@ -260,7 +294,7 @@ UserHandler = class UserHandler extends Handler
req.user.save (err) => req.user.save (err) =>
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
@sendSuccess(res, {result: 'success'}) @sendSuccess(res, {result: 'success'})
hipchat.sendHipChatMessage "#{req.body.githubUsername or req.user.get('name')} just signed the CLA." hipchat.sendHipChatMessage "#{req.body.githubUsername or req.user.get('name')} just signed the CLA.", ['main']
avatar: (req, res, id) -> avatar: (req, res, id) ->
@modelClass.findById(id).exec (err, document) => @modelClass.findById(id).exec (err, document) =>

View file

@ -48,8 +48,11 @@ config.mail =
cronHandlerPublicIP: process.env.COCO_CRON_PUBLIC_IP or '' cronHandlerPublicIP: process.env.COCO_CRON_PUBLIC_IP or ''
cronHandlerPrivateIP: process.env.COCO_CRON_PRIVATE_IP or '' cronHandlerPrivateIP: process.env.COCO_CRON_PRIVATE_IP or ''
config.hipchatAPIKey = process.env.COCO_HIPCHAT_API_KEY or '' config.hipchat =
config.hipchatTowerAPIKey = process.env.COCO_HIPCHAT_TOWER_API_KEY or '' main: process.env.COCO_HIPCHAT_API_KEY or ''
tower: process.env.COCO_HIPCHAT_TOWER_API_KEY or ''
artisans: process.env.COCO_HIPCHAT_ARTISANS_API_KEY or ''
config.queue = config.queue =
accessKeyId: process.env.COCO_AWS_ACCESS_KEY_ID or '' accessKeyId: process.env.COCO_AWS_ACCESS_KEY_ID or ''
secretAccessKey: process.env.COCO_AWS_SECRET_ACCESS_KEY or '' secretAccessKey: process.env.COCO_AWS_SECRET_ACCESS_KEY or ''