Merge branch 'master' into production

This commit is contained in:
Matt Lott 2015-04-23 18:07:48 -07:00
commit 8d6819e970
16 changed files with 374 additions and 359 deletions

View file

@ -1,6 +1,6 @@
module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "German (Switzerland)", translation: module.exports = nativeDescription: "Dütsch (Schwiiz)", englishDescription: "German (Switzerland)", translation:
home: home:
slogan: "Lern, wiemer JavaScript programmiert, indem du es Spiel spielsch!" slogan: "Lern, wiemer JavaScript programmiert, indem du spielsch!"
no_ie: "CodeCombat funktioniert uf InternetExplorer 8 und älter nid. Sorry!" # Warning that only shows up in IE8 and older no_ie: "CodeCombat funktioniert uf InternetExplorer 8 und älter nid. Sorry!" # Warning that only shows up in IE8 and older
no_mobile: "CodeCombat isch nid für mobili Grät entwicklet worde und funktioniert vilicht nid!" # Warning that shows up on mobile devices no_mobile: "CodeCombat isch nid für mobili Grät entwicklet worde und funktioniert vilicht nid!" # Warning that shows up on mobile devices
play: "Spiele" # The big play button that opens up the campaign view. play: "Spiele" # The big play button that opens up the campaign view.
@ -56,28 +56,28 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
unlock: "Freischalte" # For purchasing items and heroes unlock: "Freischalte" # For purchasing items and heroes
confirm: "Bestätige" confirm: "Bestätige"
owned: "Scho gkauft" # For items you own owned: "Scho gkauft" # For items you own
locked: "Nonig freischaltbar" locked: "Nonig kauft"
# purchasable: "Purchasable" # For a hero you unlocked but haven't purchased purchasable: "kaufen" # For a hero you unlocked but haven't purchased
available: "vorhandä" available: "vorhandä"
# skills_granted: "Skills Granted" # Property documentation details skills_granted: "Fähigkeite" # Property documentation details
heroes: "Helde" # Tooltip on hero shop button from /play heroes: "Helde" # Tooltip on hero shop button from /play
achievements: "Achievements" # Tooltip on achievement list button from /play achievements: "Erfolg" # Tooltip on achievement list button from /play
account: "Account" # Tooltip on account button from /play account: "Account" # Tooltip on account button from /play
settings: "Istellige" # Tooltip on settings button from /play settings: "Istellige" # Tooltip on settings button from /play
# poll: "Poll" # Tooltip on poll button from /play poll: "Pool" # Tooltip on poll button from /play
next: "Wiiter" # Go from choose hero to choose inventory before playing a level next: "Wiiter" # Go from choose hero to choose inventory before playing a level
change_hero: "Held wächsle" # Go back from choose inventory to choose hero change_hero: "Held wächsle" # Go back from choose inventory to choose hero
# choose_inventory: "Equip Items" choose_inventory: "Items uusrüschte"
# buy_gems: "Buy Gems" buy_gems: "Edelstei chaufä"
# subscription_required: "Subscription Required" subscription_required: "Abonnement benötigt"
older_campaigns: "Älteri Kampagne" older_campaigns: "Älteri Kampagne"
anonymous: "Anonyme Spieler" anonymous: "Anonyme Spieler"
level_difficulty: "Schwierigkeit: " level_difficulty: "Schwierigkeit: "
campaign_beginner: "Afängerkampagne" campaign_beginner: "Afängerkampagne"
# awaiting_levels_adventurer_prefix: "We release five levels per week." awaiting_levels_adventurer_prefix: "Mier möched 5 Levels pro Wuche"
# awaiting_levels_adventurer: "Sign up as an Adventurer" awaiting_levels_adventurer: "Mäld dich a as en Abendtüürer"
# awaiting_levels_adventurer_suffix: "to be the first to play new levels." awaiting_levels_adventurer_suffix: "um de erscht zii vo die neue Levels spiilt"
# adjust_volume: "Adjust volume" adjust_volume: "Luutsterchi apasse"
choose_your_level: "Wähl dis Level us" # The rest of this section is the old play view at /play-old and isn't very important. choose_your_level: "Wähl dis Level us" # The rest of this section is the old play view at /play-old and isn't very important.
adventurer_prefix: "Du chasch zu de untere Level zrugg goh oder die kommende Level diskutiere im " adventurer_prefix: "Du chasch zu de untere Level zrugg goh oder die kommende Level diskutiere im "
adventurer_forum: "Abentürer-Forum" adventurer_forum: "Abentürer-Forum"
@ -90,16 +90,16 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
campaign_multiplayer_description: "... i dene du Chopf a Chopf geg anderi Spieler spielsch." campaign_multiplayer_description: "... i dene du Chopf a Chopf geg anderi Spieler spielsch."
campaign_player_created: "Vo Spieler erstellti Level" campaign_player_created: "Vo Spieler erstellti Level"
campaign_player_created_description: "... i dene du gege d Kreativität vome <a href=\"/contribute#artisan\">Handwerker Zauberer</a> kämpfsch." campaign_player_created_description: "... i dene du gege d Kreativität vome <a href=\"/contribute#artisan\">Handwerker Zauberer</a> kämpfsch."
# campaign_classic_algorithms: "Classic Algorithms" campaign_classic_algorithms: "Klassischi Algorithme"
# campaign_classic_algorithms_description: "... in which you learn the most popular algorithms in Computer Science." campaign_classic_algorithms_description: "... wo du die beliebtischte Algorithmue vode Computer Welt lernsch.."
share_progress_modal: share_progress_modal:
blurb: "Du machsch grossi Fortschritts! Verzells öperem wieviel du glernt häsch mit CodeCombat." blurb: "Du machsch grossi Fortschritts! Verzells öperem wieviel du glernt häsch mit CodeCombat."
email_invalid: "Email Adrässä isch falsch." email_invalid: "Email Adrässä isch falsch."
# form_blurb: "Enter your parent's email below and well show them!" form_blurb: "Gib bitte dEmail Adrässe vo dine Eltere aa"
form_label: "Email Adrässä" form_label: "Email Adrässä"
placeholder: "Email Adrässä" placeholder: "Email Adrässä"
# title: "Excellent Work, Apprentice" title: "Gueti Arbeit!"
login: login:
sign_up: "Account erstelle" sign_up: "Account erstelle"
@ -107,8 +107,8 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
logging_in: "Am Ilogge" logging_in: "Am Ilogge"
log_out: "Uslogge" log_out: "Uslogge"
forgot_password: "Passwort vergässe?" forgot_password: "Passwort vergässe?"
# authenticate_gplus: "Authenticate G+" authenticate_gplus: "Mit G+ audentifiziere"
# load_profile: "Load G+ Profile" load_profile: "G+ Profil ladä"
finishing: "Fertigstelle" finishing: "Fertigstelle"
sign_in_with_facebook: "Mit Facebook aamelde" sign_in_with_facebook: "Mit Facebook aamelde"
sign_in_with_gplus: "Mit G+ aamelde" sign_in_with_gplus: "Mit G+ aamelde"
@ -125,20 +125,20 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
recover: recover:
recover_account_title: "Account wiederherstelle" recover_account_title: "Account wiederherstelle"
send_password: "Recovery Password sende" send_password: "Widerherstelligs Passwort sende"
# recovery_sent: "Recovery email sent." recovery_sent: "Widerherstelligs Passwort isch gsendet"
items: items:
# primary: "Primary" primary: "Primär"
# secondary: "Secondary" secondary: "Sekundär"
# armor: "Armor" armor: "Rüschtig"
# accessories: "Accessories" accessories: "Accessories"
misc: "Diverses" misc: "Diverses"
books: "Büecher" books: "Büecher"
common: common:
# back: "Back" # When used as an action verb, like "Navigate backward" back: "Zrugg" # When used as an action verb, like "Navigate backward"
# continue: "Continue" # When used as an action verb, like "Continue forward" continue: "Wiiterfare" # When used as an action verb, like "Continue forward"
loading: "Lade..." loading: "Lade..."
saving: "Speichere..." saving: "Speichere..."
sending: "Sende..." sending: "Sende..."
@ -151,36 +151,36 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# fork: "Fork" # fork: "Fork"
play: "Spiele" # When used as an action verb, like "Play next level" play: "Spiele" # When used as an action verb, like "Play next level"
retry: "nomol versuche" retry: "nomol versuche"
# actions: "Actions" actions: "Aktione"
info: "Info" info: "Info"
help: "Hilf" help: "Hilf"
# watch: "Watch" watch: "Aluege"
# unwatch: "Unwatch" unwatch: "Nüm Aluege"
submit_patch: "Patch ireiche" submit_patch: "Patch ireiche"
# submit_changes: "Submit Changes" submit_changes: "Wechsel ireiche"
general: general:
and: "und" and: "und"
name: "Name" name: "Name"
date: "Datum" date: "Datum"
# body: "Body" body: "Body"
version: "Version" version: "Version"
# pending: "Pending" pending: "in Bearbeitig"
# accepted: "Accepted" accepted: "Akzeptiert"
# rejected: "Rejected" rejected: "Nid akzeptiert"
# withdrawn: "Withdrawn" withdrawn: "Zruggzie"
# submitter: "Submitter" submitter: "Sender"
# submitted: "Submitted" submitted: "Gesendet"
# commit_msg: "Commit Message" commit_msg: "Nachricht abschicke"
# review: "Review" review: "Review"
version_history: "Versionsverlauf" version_history: "Versionsverlauf"
# version_history_for: "Version History for: " version_history_for: "Versionsverlauf für: "
# select_changes: "Select two changes below to see the difference." select_changes: "Wähl zwei Verändrige um unne Ihre Unterschid zgse."
# undo_prefix: "Undo" undo_prefix: "Eis zrugg"
# undo_shortcut: "(Ctrl+Z)" undo_shortcut: "(Ctrl+Z)"
# redo_prefix: "Redo" redo_prefix: "Nomal mache"
# redo_shortcut: "(Ctrl+Shift+Z)" redo_shortcut: "(Ctrl+Shift+Z)"
# play_preview: "Play preview of current level" play_preview: "Spiel dPreview vom aktuelle Level"
result: "Resultat" result: "Resultat"
results: "Resultat" results: "Resultat"
description: "Beschriibig" description: "Beschriibig"
@ -204,7 +204,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
player: "Spieler" player: "Spieler"
player_level: "Stufe" # Like player level 5, not like level: Dungeons of Kithgard player_level: "Stufe" # Like player level 5, not like level: Dungeons of Kithgard
warrior: "Krieger" warrior: "Krieger"
# ranger: "Ranger" ranger: "Ranger"
wizard: "Zauberer" wizard: "Zauberer"
units: units:
@ -247,7 +247,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
reload_really: "Bisch sicher du willsch level neu lade bis zrugg zum Afang?" reload_really: "Bisch sicher du willsch level neu lade bis zrugg zum Afang?"
reload_confirm: "Alles neu lade" reload_confirm: "Alles neu lade"
victory: "Gwunne" victory: "Gwunne"
# victory_title_prefix: "" victory_title_prefix: ""
victory_title_suffix: " Vollständig" victory_title_suffix: " Vollständig"
victory_sign_up: "Meld dich ah zum din Fortschritt speichere" victory_sign_up: "Meld dich ah zum din Fortschritt speichere"
victory_sign_up_poke: "Wötsch din Code speichere? Erstell gratis en Account!" victory_sign_up_poke: "Wötsch din Code speichere? Erstell gratis en Account!"
@ -259,21 +259,21 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
victory_review: "Verzell üs meh!" # Only in old-style levels. victory_review: "Verzell üs meh!" # Only in old-style levels.
victory_hour_of_code_done: "Bisch fertig?" victory_hour_of_code_done: "Bisch fertig?"
victory_hour_of_code_done_yes: "Jo, ich bin fertig mit mim Hour of Code™!" victory_hour_of_code_done_yes: "Jo, ich bin fertig mit mim Hour of Code™!"
# victory_experience_gained: "XP Gained" victory_experience_gained: "Erfarig bechoo"
# victory_gems_gained: "Gems Gained" victory_gems_gained: "Edelstei bechoo"
# victory_viking_code_school: "Holy smokes, that was a hard level you just beat! If you aren't already a software developer, you should be. You just got fast-tracked for acceptance with Viking Code School, where you can take your skills to the next level and become a professional web developer in 14 weeks." victory_viking_code_school: "Oh mein Gott, dass isch aber es stregs Level gsi und du heschs gschafft! Also wen du nu kei Software-Entwickler bisch, sötsch eine sii! Du hesch en Iiladig becho um at Viking Code Schuel zgha wodu dini Fähigkeite chasch wiiterentwickle und en professionele Entwickel in nur 14 Täg werde!"
# victory_become_a_viking: "Become a Viking" victory_become_a_viking: "Werd en Vikinger!"
guide_title: "Handbuech" guide_title: "Handbuech"
tome_minion_spells: "Zaubersprüch vo dine Minions" # Only in old-style levels. tome_minion_spells: "Zaubersprüch vo dine Minions" # Only in old-style levels.
tome_read_only_spells: "Read-Only Zaubersprüch" # Only in old-style levels. tome_read_only_spells: "Read-Only Zaubersprüch" # Only in old-style levels.
tome_other_units: "Anderi Einheite" # Only in old-style levels. tome_other_units: "Anderi Einheite" # Only in old-style levels.
# tome_cast_button_run: "Run" tome_cast_button_run: "Renn"
# tome_cast_button_running: "Running" tome_cast_button_running: "Renne"
# tome_cast_button_ran: "Ran" tome_cast_button_ran: "grennt"
# tome_submit_button: "Submit" tome_submit_button: "Abschicke"
# tome_reload_method: "Reload original code for this method" # Title text for individual method reload button. tome_reload_method: "Lad de Orginal Code für die Methode" # Title text for individual method reload button.
tome_select_method: "Wähl a Methodä" tome_select_method: "Wähl a Methodä"
# tome_see_all_methods: "See all methods you can edit" # Title text for method list selector (shown when there are multiple programmable methdos). tome_see_all_methods: "Lueg alli Methode a wot chasch bearbeite" # Title text for method list selector (shown when there are multiple programmable methdos).
tome_select_a_thang: "Wähl öpper us für" tome_select_a_thang: "Wähl öpper us für"
tome_available_spells: "Verfüegbari Zaubersprüch" tome_available_spells: "Verfüegbari Zaubersprüch"
tome_your_skills: "Dini Fähigkaitä" tome_your_skills: "Dini Fähigkaitä"
@ -321,153 +321,153 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
tip_hardware_problem: "F: Wie viel Programmierer bruuchts zum e Glüehbire uswechsle? A: Keine, da isch es Hardware Problem." tip_hardware_problem: "F: Wie viel Programmierer bruuchts zum e Glüehbire uswechsle? A: Keine, da isch es Hardware Problem."
# tip_hofstadters_law: "Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law." # tip_hofstadters_law: "Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law."
# tip_premature_optimization: "Premature optimization is the root of all evil. - Donald Knuth" # tip_premature_optimization: "Premature optimization is the root of all evil. - Donald Knuth"
# tip_brute_force: "When in doubt, use brute force. - Ken Thompson" tip_brute_force: "Went am verzwifle bisch, bruch brute force. - Ken Thompson"
# tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..." # tip_extrapolation: "There are only two kinds of people: those that can extrapolate from incomplete data..."
# tip_superpower: "Coding is the closest thing we have to a superpower." tip_superpower: "Coding isch snöchte wo mier hend was ane Superchraaft ane chund!"
# 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: "Kei Code isch schneller als kei 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 //"
# tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates" # tip_lines_of_code: "Measuring programming progress by lines of code is like measuring aircraft building progress by weight. — Bill Gates"
# tip_source_code: "I want to change the world but they would not give me the source code." tip_source_code: "Ich wet dWält verändere aber die wend mier de Source Code nid gää."
# tip_javascript_java: "Java is to JavaScript what Car is to Carpet. - Chris Heilmann" tip_javascript_java: "Java isch zu JavaScript wie es Auto zume Automat. - Chris Heilmann"
# tip_move_forward: "Whatever you do, keep moving forward. - Martin Luther King Jr." tip_move_forward: "Was immer du machsch, mach immer me Fortschritt. - Martin Luther King Jr."
# tip_google: "Have a problem you can't solve? Google it!" tip_google: "Hesch es Problem und chunsch nüm wiiter? Googles doch mal!"
# tip_adding_evil: "Adding a pinch of evil." # tip_adding_evil: "Adding a pinch of evil."
# tip_hate_computers: "That's the thing about people who think they hate computers. What they really hate is lousy programmers. - Larry Niven" # tip_hate_computers: "That's the thing about people who think they hate computers. What they really hate is lousy programmers. - Larry Niven"
# tip_open_source_contribute: "You can help CodeCombat improve!" tip_open_source_contribute: "Du chasch helfe CodeCombat zverbessere!"
# tip_recurse: "To iterate is human, to recurse divine. - L. Peter Deutsch" # tip_recurse: "To iterate is human, to recurse divine. - L. Peter Deutsch"
game_menu: game_menu:
# inventory_tab: "Inventory" inventory_tab: "Inventar"
save_load_tab: "Spaicherä/Ladä" save_load_tab: "Spaicherä/Ladä"
options_tab: "Optionä" options_tab: "Optionä"
# guide_tab: "Guide" guide_tab: "Guide"
# guide_video_tutorial: "Video Tutorial" guide_video_tutorial: "Vidio Tutorial"
guide_tips: "Tipps" guide_tips: "Tipps"
multiplayer_tab: "Multiplayer" multiplayer_tab: "Multiplayer"
# auth_tab: "Sign Up" auth_tab: "Regischtriere"
# inventory_caption: "Equip your hero" inventory_caption: "Rüscht din Held uus"
# choose_hero_caption: "Choose hero, language" choose_hero_caption: "Wähl din Held und dini Sprach"
# save_load_caption: "... and view history" save_load_caption: "... und lueg dini Gschicht aa."
# options_caption: "Configure settings" options_caption: "Iistellige apasse"
guide_caption: "Doku und Tipps" guide_caption: "Doku und Tipps"
# multiplayer_caption: "Play with friends!" multiplayer_caption: "Spil mid dini Fründe!"
# auth_caption: "Save your progress." auth_caption: "Speichere din Fortschritt."
# leaderboard: leaderboard:
# leaderboard: "Leaderboard" leaderboard: "Ranglischte"
# view_other_solutions: "View Leaderboards" view_other_solutions: "Lueg der dRanglischte aa!"
# scores: "Scores" scores: "Pünkt"
# top_players: "Top Players by" top_players: "Beschti Speiler"
# day: "Today" day: "Hüt"
# week: "This Week" week: "Die Wuuche"
# all: "All-Time" all: "Vo immer"
# time: "Time" time: "Ziit"
# damage_taken: "Damage Taken" damage_taken: "Schade gnoo"
# damage_dealt: "Damage Dealt" damage_dealt: "Schade uusteilt"
# difficulty: "Difficulty" difficulty: "Schwirigkeitsgrad"
# gold_collected: "Gold Collected" gold_collected: "Gold gsammlet"
# inventory: inventory:
# choose_inventory: "Equip Items" choose_inventory: "Items uusrüschte"
# equipped_item: "Equipped" equipped_item: "Uusgrüschteti Items"
# required_purchase_title: "Required" required_purchase_title: "Benötigt"
# available_item: "Available" available_item: "Verfüegbar"
# restricted_title: "Restricted" restricted_title: "Verbote"
# should_equip: "(double-click to equip)" should_equip: "(2mal Klicke zum uusrüschte)"
# equipped: "(equipped)" equipped: "(usgrüschtet)"
# locked: "(locked)" locked: "(geschperrt)"
# restricted: "(restricted in this level)" restricted: "(verbote i dem Level)"
# equip: "Equip" equip: "Uusrüschte"
# unequip: "Unequip" unequip: "Nüm Uusrüschte"
# buy_gems: buy_gems:
# few_gems: "A few gems" few_gems: "Es paar Edelstei"
# pile_gems: "Pile of gems" pile_gems: "En hufe vo Edelstei"
# chest_gems: "Chest of gems" chest_gems: "En ganzi True voll Edelstei"
# purchasing: "Purchasing..." purchasing: "Kaufen..."
# declined: "Your card was declined" declined: "Dini Charte isch leider abglehnt worde."
# retrying: "Server error, retrying." retrying: "Server Fehler, probiere nochmals."
# prompt_title: "Not Enough Gems" prompt_title: "Nid gnug Edelstei!"
# prompt_body: "Do you want to get more?" prompt_body: "Wetsch mee chaufe?"
# prompt_button: "Enter Shop" prompt_button: "zum Shop"
# recovered: "Previous gems purchase recovered. Please refresh the page." recovered: "Früenere Ichauf zruggerstatet. Bitte dSite neu lade!"
# price: "x3500 / mo" # price: "x3500 / mo"
# subscribe: subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!" comparison_blurb: "Verschärf dins Chönne midme CodeCombat Abonement."
# feature1: "80+ basic levels across 4 worlds" feature1: "80+ basis levels in 4 Weltete!"
# feature2: "7 powerful <strong>new heroes</strong> with unique skills!" # feature2: "7 powerful <strong>new heroes</strong> with unique skills!"
# feature3: "50+ bonus levels" feature3: "50+ bonus levels"
# feature4: "<strong>3500 bonus gems</strong> every month!" # feature4: "<strong>3500 bonus gems</strong> every month!"
# feature5: "Video tutorials" feature5: "Video Aleitige"
# feature6: "Premium email support" feature6: "Premium Email Hilf"
# free: "Free" free: "Gratis"
# month: "month" month: "Monät"
# subscribe_title: "Subscribe" subscribe_title: "Aboniere"
# unsubscribe: "Unsubscribe" unsubscribe: "Deaboniere"
# confirm_unsubscribe: "Confirm Unsubscribe" confirm_unsubscribe: "Deaboniere beschtätige"
# never_mind: "Never Mind, I Still Love You" never_mind: "Keis Problem, ich lieb dich trotzdem."
# thank_you_months_prefix: "Thank you for supporting us these last" thank_you_months_prefix: "Danke das du üs die Monät"
# thank_you_months_suffix: "months." thank_you_months_suffix: "so unterschtütz hesch."
# thank_you: "Thank you for supporting CodeCombat." thank_you: "Danke, dass du CodeCombat so unterschtüzisch."
# 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: "Schad, dass du gasch! Bitte seg üs doch was mier hetted chönne besser mache."
# unsubscribe_feedback_placeholder: "O, what have we done?" unsubscribe_feedback_placeholder: "Ohaletz, was hemmer gmacht?"
# parent_button: "Ask your parent" parent_button: "Frag dini Eltere"
# parent_email_description: "We'll email them so they can buy you a CodeCombat subscription." 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_invalid: "Email Adrässi ungültig"
# parent_email_input_label: "Parent email address" parent_email_input_label: "Email Adrässi vo dine Eltere"
# parent_email_input_placeholder: "Enter parent email" parent_email_input_placeholder: "Bitte gib dMail Adrässi vo dine Eltere a"
# parent_email_send: "Send Email" parent_email_send: "Email sände"
# parent_email_sent: "Email sent!" parent_email_sent: "Email gsändet!"
# parent_email_title: "What's your parent's email?" parent_email_title: "Wie isch dEmail Adrässi vo dine Eltere?"
# parents: "For Parents" parents: "Für Eltere"
# parents_title: "Dear Parent: Your child is learning to code. Will you help them continue?" parents_title: "Liebi Eltere, Ihres Chind isch am Lerne wieme programmiert. Wen Sie im helfe?"
# parents_blurb1: "Your child has played __nLevels__ levels and learned programming basics. Help cultivate their interest and buy them a subscription so they can keep playing." parents_blurb1: "Ihres CHind hed __nLevels__ levels gschpilt und hed programmier Basics glernd. Helfed Sie soch dInträssi für sProgrammiere ufrecht zhalte und unterschtützed Sie in idem Sie es Abo chaufed."
# parents_blurb1a: "Computer programming is an essential skill that your child will undoubtedly use as an adult. By 2020, basic software skills will be needed by 77% of jobs, and software engineers are in high demand across the world. Did you know that Computer Science is the highest-paid university degree?" parents_blurb1a: "Programmiere isch en wichtigi Begabig wo Ihres Chind als Erwachsene sicher wird bruche. Ab 2020 werded 77% vo allne Jobs eifachi Programmierkentniss benötige und die wos behersched werded uf de ganze Welt gsuecht. Hend Sie gwüsst das Programmiere de best bezallti Uni abschluss isch?"
# parents_blurb2: "For $9.99 USD/mo, your child will get new challenges every week and personal email support from professional programmers." parents_blurb2: "Für $9.99 USD/im Monät, würd Ihres Chind jedes Wuche neue und spannendi Challenges becho und professionelle E-Mail Support!"
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe." parents_blurb3: "Kei Risikos, 100% Geld zrugg Garantie und ganz eifaches deaboniere mid eim Klick"
# payment_methods: "Payment Methods" payment_methods: "Zalligs Methode"
# payment_methods_title: "Accepted Payment Methods" payment_methods_title: "Akzeptierti Zalligs Methode"
# payment_methods_blurb1: "We currently accept credit cards and Alipay." payment_methods_blurb1: "Mier akzeptiered immoment Kreditchartene und Alipay."
# payment_methods_blurb2: "If you require an alternate form of payment, please contact" # payment_methods_blurb2: "If you require an alternate form of payment, please contact"
# 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: "Du bruchsch es Abo um das Level zspile."
# unlock_help_videos: "Subscribe to unlock all video tutorials." # unlock_help_videos: "Subscribe to unlock all video tutorials."
# personal_sub: "Personal Subscription" # Accounts Subscription View below # personal_sub: "Personal Subscription" # Accounts Subscription View below
# loading_info: "Loading subscription information..." loading_info: "Lade Abo Informatione..."
# managed_by: "Managed by" managed_by: "Verwaltet vo"
# will_be_cancelled: "Will be cancelled on" will_be_cancelled: "Wird abbroche am"
# currently_free: "You currently have a free subscription" currently_free: "Du hesch jetzt grad es frii Abo"
# currently_free_until: "You currently have a free subscription until" # currently_free_until: "You currently have a free subscription until"
# was_free_until: "You had a free subscription until" # was_free_until: "You had a free subscription until"
# managed_subs: "Managed Subscriptions" managed_subs: "Abos verwalte"
# managed_subs_desc: "Add subscriptions for other players (students, children, etc.)" # managed_subs_desc: "Add subscriptions for other players (students, children, etc.)"
# group_discounts: "Group discounts" # group_discounts: "Group discounts"
# group_discounts_1: "We also offer group discounts for bulk subscriptions." # group_discounts_1: "We also offer group discounts for bulk subscriptions."
# group_discounts_1st: "1st subscription" group_discounts_1st: "Erstes Abonement"
# group_discounts_full: "Full price" group_discounts_full: "de ganz Priis"
# group_discounts_2nd: "Subscriptions 2-11" group_discounts_2nd: "Aboniere 2-11"
# group_discounts_20: "20% off" group_discounts_20: "20% billiger"
# group_discounts_12th: "Subscriptions 12+" group_discounts_12th: "Aboniere 12+"
# group_discounts_40: "40% off" group_discounts_40: "40% billiger"
# subscribing: "Subscribing..." subscribing: "Am Aboniere..."
# recipient_emails_placeholder: "Enter email address to subscribe, one per line." recipient_emails_placeholder: "Gib dini Mails zum Aboniere i, eine pro Linie:"
# subscribe_users: "Subscribe Users" subscribe_users: "Abonier Users"
# users_subscribed: "Users subscribed:" users_subscribed: "Users aboniert:"
# no_users_subscribed: "No users subscribed, please double check your email addresses." # no_users_subscribed: "No users subscribed, please double check your email addresses."
# current_recipients: "Current Recipients" # current_recipients: "Current Recipients"
# unsubscribing: "Unsubscribing..." unsubscribing: "Am Abo chünde"
# subscribe_prepaid: "Click Subscribe to use prepaid code" subscribe_prepaid: "Klick Aboniere um en PrePaid Code izlöse"
# using_prepaid: "Using prepaid code for monthly subscription" using_prepaid: "Bruch en PrePaid Code um en Monet zAboniere"
choose_hero: choose_hero:
# choose_hero: "Choose Your Hero" choose_hero: "Wähl din Held"
# programming_language: "Programming Language" programming_language: "Programmiersprach"
# programming_language_description: "Which programming language do you want to use?" programming_language_description: "Weli Programmiersprach wetsch benutze?"
# default: "Default" default: "Standard"
# experimental: "Experimental" # experimental: "Experimental"
python_blurb: "Eifach und doch mächtig." python_blurb: "Eifach und doch mächtig."
javascript_blurb: "D Internetsproch." javascript_blurb: "D Internetsproch."
@ -476,22 +476,22 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
lua_blurb: "D Sproch für Game Scripts." lua_blurb: "D Sproch für Game Scripts."
io_blurb: "Eifach aber undurchsichtig." io_blurb: "Eifach aber undurchsichtig."
# status: "Status" # status: "Status"
# hero_type: "Type" hero_type: "Typ"
# weapons: "Weapons" weapons: "Waffene"
# weapons_warrior: "Swords - Short Range, No Magic" weapons_warrior: "Schwärter - churzi Richwiti, kei Magie"
# weapons_ranger: "Crossbows, Guns - Long Range, No Magic" weapons_ranger: "Armbrüscht, Knarre - grossi Richwiti, kei Magie"
# weapons_wizard: "Wands, Staffs - Long Range, Magic" weapons_wizard: "Zauberstäb - grossi Richwiti, Magie"
# attack: "Damage" # Can also translate as "Attack" attack: "Schadä" # Can also translate as "Attack"
# health: "Health" health: "Läbä"
# speed: "Speed" speed: "Schnelligkeit"
# regeneration: "Regeneration" regeneration: "Regeneration"
# range: "Range" # As in "attack or visual range" range: "Richwiti" # As in "attack or visual range"
# blocks: "Blocks" # As in "this shield blocks this much damage" # blocks: "Blocks" # As in "this shield blocks this much damage"
# backstab: "Backstab" # As in "this dagger does this much backstab damage" # backstab: "Backstab" # As in "this dagger does this much backstab damage"
# skills: "Skills" skills: "Fähigkeite"
# attack_1: "Deals" # attack_1: "Deals"
# attack_2: "of listed" # attack_2: "of listed"
# attack_3: "weapon damage." attack_3: "Waffeschade."
# health_1: "Gains" # health_1: "Gains"
# health_2: "of listed" # health_2: "of listed"
# health_3: "armor health." # health_3: "armor health."
@ -501,15 +501,15 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# level_to_unlock: "Level to unlock:" # Label for which level you have to beat to unlock a particular hero (click a locked hero in the store to see) # level_to_unlock: "Level to unlock:" # Label for which level you have to beat to unlock a particular hero (click a locked hero in the store to see)
# restricted_to_certain_heroes: "Only certain heroes can play this level." # restricted_to_certain_heroes: "Only certain heroes can play this level."
# skill_docs: skill_docs:
# writable: "writable" # Hover over "attack" in Your Skills while playing a level to see most of this # writable: "writable" # Hover over "attack" in Your Skills while playing a level to see most of this
# read_only: "read-only" # read_only: "read-only"
# action_name: "name" action_name: "name"
# action_cooldown: "Takes" # action_cooldown: "Takes"
# action_specific_cooldown: "Cooldown" action_specific_cooldown: "Abklingziit"
# action_damage: "Damage" action_damage: "Schade"
# action_range: "Range" action_range: "Richwiti"
# action_radius: "Radius" action_radius: "Radius"
# action_duration: "Duration" # action_duration: "Duration"
# example: "Example" # example: "Example"
# ex: "ex" # Abbreviation of "example" # ex: "ex" # Abbreviation of "example"
@ -519,16 +519,16 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# returns: "Returns" # returns: "Returns"
# granted_by: "Granted by" # granted_by: "Granted by"
# save_load: save_load:
# granularity_saved_games: "Saved" granularity_saved_games: "Gschpeicheret"
# granularity_change_history: "History" granularity_change_history: "Verlauf"
options: options:
# general_options: "General Options" # Check out the Options tab in the Game Menu while playing a level # general_options: "General Options" # Check out the Options tab in the Game Menu while playing a level
# volume_label: "Volume" volume_label: "Luutstärchi"
# music_label: "Music" music_label: "Musig"
# music_description: "Turn background music on/off." # music_description: "Turn background music on/off."
# autorun_label: "Autorun" autorun_label: "Autorun"
# autorun_description: "Control automatic code execution." # autorun_description: "Control automatic code execution."
# editor_config: "Editor Config" # editor_config: "Editor Config"
editor_config_title: "Editor Konfiguration" editor_config_title: "Editor Konfiguration"
@ -568,21 +568,21 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# scott_blurb: "Reasonable One" # scott_blurb: "Reasonable One"
# nick_title: "Cofounder" # nick_title: "Cofounder"
# nick_blurb: "Motivation Guru" # nick_blurb: "Motivation Guru"
# michael_title: "Programmer" michael_title: "Programmierer"
# michael_blurb: "Sys Admin" michael_blurb: "System Admin"
# matt_title: "Programmer" matt_title: "Programmierer"
# matt_blurb: "Bicyclist" # matt_blurb: "Bicyclist"
# cat_title: "Chief Artisan" # cat_title: "Chief Artisan"
# cat_blurb: "Airbender" cat_blurb: "Luftbändiger"
# josh_title: "Game Designer" josh_title: "Game Designer"
# josh_blurb: "Floor Is Lava" josh_blurb: "De Bode isch Lava"
# jose_title: "Music" jose_title: "Musig"
# jose_blurb: "Taking Off" # jose_blurb: "Taking Off"
# retrostyle_title: "Illustration" # retrostyle_title: "Illustration"
# retrostyle_blurb: "RetroStyle Games" # retrostyle_blurb: "RetroStyle Games"
# teachers: teachers:
# title: "CodeCombat: Info for Teachers" title: "CodeCombat: Info für Lehrer"
# intro_1: "CodeCombat is an online game that teaches programming. Students write code in real programming languages." # intro_1: "CodeCombat is an online game that teaches programming. Students write code in real programming languages."
# intro_2: "No experience required!" # intro_2: "No experience required!"
# free_title: "How much does it cost?" # free_title: "How much does it cost?"
@ -618,11 +618,11 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
versions: versions:
save_version_title: "Neui Version speichere" save_version_title: "Neui Version speichere"
new_major_version: "Neui Hauptversion" new_major_version: "Neui Hauptversion"
# submitting_patch: "Submitting Patch..." submitting_patch: "Patch am abgee"
# cla_prefix: "To save changes, first you must agree to our" # cla_prefix: "To save changes, first you must agree to our"
# cla_url: "CLA" cla_url: "CLA"
# cla_suffix: "." cla_suffix: "."
# cla_agree: "I AGREE" cla_agree: "Ich bi iverstandee"
contact: contact:
contact_us: "CodeCombat kontaktiere" contact_us: "CodeCombat kontaktiere"
@ -630,8 +630,8 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
forum_prefix: "Für öffentlichi Sache versuechs mol stattdesse i " forum_prefix: "Für öffentlichi Sache versuechs mol stattdesse i "
forum_page: "üsem Forum" forum_page: "üsem Forum"
forum_suffix: "." forum_suffix: "."
# faq_prefix: "There's also a" faq_prefix: "Es gid au es"
# faq: "FAQ" faq: "FAQ"
# subscribe_prefix: "If you need help figuring out a level, please" # subscribe_prefix: "If you need help figuring out a level, please"
# subscribe: "buy a CodeCombat subscription" # subscribe: "buy a CodeCombat subscription"
# subscribe_suffix: "and we'll be happy to help you with your code." # subscribe_suffix: "and we'll be happy to help you with your code."
@ -648,11 +648,11 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
autosave: "Änderige werded automatisch gspeicheret" autosave: "Änderige werded automatisch gspeicheret"
me_tab: "Ich" me_tab: "Ich"
picture_tab: "Bild" picture_tab: "Bild"
# delete_account_tab: "Delete Your Account" delete_account_tab: "Din Account lösche"
# wrong_email: "Wrong Email" wrong_email: "Falschi Email Adrässe"
upload_picture: "Es Bild ufelade" upload_picture: "Es Bild ufelade"
# delete_this_account: "Delete this account permanently" delete_this_account: "Dä Account für immer Lösche"
# god_mode: "God Mode" god_mode: "Gott Modus"
password_tab: "Passwort" password_tab: "Passwort"
emails_tab: "E-Mails" emails_tab: "E-Mails"
admin: "Admin" admin: "Admin"
@ -667,7 +667,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
email_notifications_summary: "Istellige für personalisierti, automatischi E-Mail Notifikatione im Zemehang mit dine CodeCombat Aktivitäte" email_notifications_summary: "Istellige für personalisierti, automatischi E-Mail Notifikatione im Zemehang mit dine CodeCombat Aktivitäte"
email_any_notes: "Alli Notifikatione" email_any_notes: "Alli Notifikatione"
email_any_notes_description: "Deaktiviere zum kei Aktivitäts-Notifikatione meh per E-Mail becho." email_any_notes_description: "Deaktiviere zum kei Aktivitäts-Notifikatione meh per E-Mail becho."
# email_news: "News" email_news: "Neuigkeite"
# email_recruit_notes: "Job Opportunities" # email_recruit_notes: "Job Opportunities"
# email_recruit_notes_description: "If you play really well, we may contact you about getting you a (better) job." # email_recruit_notes_description: "If you play really well, we may contact you about getting you a (better) job."
# contributor_emails: "Contributor Class Emails" # contributor_emails: "Contributor Class Emails"
@ -683,16 +683,16 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks." # job_profile_approved: "Your job profile has been approved by CodeCombat. Employers will be able to see it until you either mark it inactive or it has not been changed for four weeks."
# job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job." # job_profile_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
# sample_profile: "See a sample profile" # sample_profile: "See a sample profile"
# view_profile: "View Your Profile" view_profile: "Dis Profil aluege"
keyboard_shortcuts: keyboard_shortcuts:
keyboard_shortcuts: "Shortcuts uf de Tastatur" keyboard_shortcuts: "Shortcuts uf de Tastatur"
space: "Space" space: "Space"
enter: "Enter" enter: "Enter"
escape: "Escape" escape: "Escape"
# shift: "Shift" shift: "Shift"
# run_code: "Run current code." run_code: "De jetzig Code laufe laa."
# run_real_time: "Run in real time." run_real_time: "In Echtziit laufe laa."
continue_script: "Nochem aktuelle Script fortsetze." continue_script: "Nochem aktuelle Script fortsetze."
skip_scripts: "Alli überspringbare Scripts überspringe." skip_scripts: "Alli überspringbare Scripts überspringe."
toggle_playback: "Play/Pause istelle." toggle_playback: "Play/Pause istelle."
@ -703,7 +703,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
toggle_grid: "Gitter ischalte/usschalte." toggle_grid: "Gitter ischalte/usschalte."
toggle_pathfinding: "Wegfinder ischalte/usschalte." toggle_pathfinding: "Wegfinder ischalte/usschalte."
beautify: "Mach din Code schöner, indem du sini Formatierig standartisiersch." beautify: "Mach din Code schöner, indem du sini Formatierig standartisiersch."
# maximize_editor: "Maximize/minimize code editor." maximize_editor: "Maximize/minimize de code editor."
community: community:
main_title: "CodeCombat Community" main_title: "CodeCombat Community"
@ -1289,7 +1289,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# player_code: "Player Code" # player_code: "Player Code"
employers: employers:
# deprecation_warning_title: "Sorry, CodeCombat is not recruiting right now." deprecation_warning_title: "Sorry, CodeCombat rekrutiert grad nid."
# deprecation_warning: "We are focusing on beginner levels instead of finding expert developers for the time being." # deprecation_warning: "We are focusing on beginner levels instead of finding expert developers for the time being."
hire_developers_not_credentials: "Stell Entwickler ah, nid Zügnis." # We are not actively recruiting right now, so there's no need to add new translations for the rest of this section. hire_developers_not_credentials: "Stell Entwickler ah, nid Zügnis." # We are not actively recruiting right now, so there's no need to add new translations for the rest of this section.
# get_started: "Get Started" # get_started: "Get Started"

View file

@ -588,7 +588,7 @@
intro_2: "No experience required!" intro_2: "No experience required!"
free_title: "How much does it cost?" free_title: "How much does it cost?"
cost_china: "CodeCombat in China is free for the first five levels, after which it costs $9.99 per month for access to our other 120+ levels on our exclusive China servers." cost_china: "CodeCombat in China is free for the first five levels, after which it costs $9.99 per month for access to our other 120+ levels on our exclusive China servers."
free_1: "CodeCombat Basic is FREE! There are 70+ free levels which cover every concept." free_1: "CodeCombat Basic is FREE! There are 80+ free levels which cover every concept." # {change}
free_2: "A monthly subscription provides access to video tutorials and extra practice levels." free_2: "A monthly subscription provides access to video tutorials and extra practice levels."
teacher_subs_title: "Teachers get free subscriptions!" teacher_subs_title: "Teachers get free subscriptions!"
teacher_subs_1: "Please contact" teacher_subs_1: "Please contact"

View file

@ -15,12 +15,12 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
nav: nav:
play: "Levels" # The top nav bar entry where players choose which levels to play play: "Levels" # The top nav bar entry where players choose which levels to play
community: "Community" community: "Komunitas"
editor: "Editor" editor: "Editor"
blog: "Blog" blog: "Blog"
forum: "Forum" forum: "Forum"
account: "Akun" account: "Akun"
profile: "Profile" profile: "Profil"
stats: "Mulai" stats: "Mulai"
code: "Code" code: "Code"
admin: "Admin" # Only shows up when you are an admin admin: "Admin" # Only shows up when you are an admin
@ -33,7 +33,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# teachers: "Teachers" # teachers: "Teachers"
modal: modal:
close: "Close" close: "Tutup"
okay: "Okay" okay: "Okay"
not_found: not_found:
@ -42,8 +42,8 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
diplomat_suggestion: diplomat_suggestion:
# title: "Help translate CodeCombat!" # This shows up when a player switches to a non-English language using the language selector. # title: "Help translate CodeCombat!" # This shows up when a player switches to a non-English language using the language selector.
# sub_heading: "We need your language skills." # sub_heading: "We need your language skills."
pitch_body: "We develop CodeCombat in English, but we already have players all over the world. Many of them want to play in Indonesian but don't speak English, so if you can speak both, please consider signing up to be a Diplomat and help translate both the CodeCombat website and all the levels into Indonesian." pitch_body: "Kami mengembangkan CodeCombat dalam bahasa Inggris, tapi kami sudah memiliki pemain di seluruh dunia. Banyak dari mereka ingin bermain di Indonesia, tetapi tidak berbicara bahasa Inggris, jadi jika Anda dapat berbicara, silakan mempertimbangkan untuk mendaftar untuk menjadi Diplomat dan membantu menerjemahkan kedua situs CodeCombat dan semua tingkatan ke Indonesia."
missing_translations: "Until we can translate everything into Indonesian, you'll see English when Indonesian isn't available." missing_translations: "Hingga kami bisa menerjemahkan semuanya ke dalam bahasa Indonesia, Anda akan melihat bahasa Inggris ketika Indonesia belum tersedia."
# learn_more: "Learn more about being a Diplomat" # learn_more: "Learn more about being a Diplomat"
# subscribe_as_diplomat: "Subscribe as a Diplomat" # subscribe_as_diplomat: "Subscribe as a Diplomat"
@ -58,12 +58,12 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# owned: "Owned" # For items you own # owned: "Owned" # For items you own
locked: "Terkunci" locked: "Terkunci"
# purchasable: "Purchasable" # For a hero you unlocked but haven't purchased # purchasable: "Purchasable" # For a hero you unlocked but haven't purchased
available: "Trsedia" available: "Tersedia"
# skills_granted: "Skills Granted" # Property documentation details # skills_granted: "Skills Granted" # Property documentation details
heroes: "Heroes" # Tooltip on hero shop button from /play heroes: "Heroes" # Tooltip on hero shop button from /play
# achievements: "Achievements" # Tooltip on achievement list button from /play # achievements: "Achievements" # Tooltip on achievement list button from /play
account: "Akun" # Tooltip on account button from /play account: "Akun" # Tooltip on account button from /play
settings: "Settings" # Tooltip on settings button from /play settings: "Pengaturan" # Tooltip on settings button from /play
# poll: "Poll" # Tooltip on poll button from /play # poll: "Poll" # Tooltip on poll button from /play
# next: "Next" # Go from choose hero to choose inventory before playing a level # next: "Next" # Go from choose hero to choose inventory before playing a level
# change_hero: "Change Hero" # Go back from choose inventory to choose hero # change_hero: "Change Hero" # Go back from choose inventory to choose hero

View file

@ -358,7 +358,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
leaderboard: leaderboard:
leaderboard: "リーダーボード" leaderboard: "リーダーボード"
view_other_solutions: "他のソリューションを見る" # {change} view_other_solutions: "リーダーボードを見る"
scores: "スコア" scores: "スコア"
top_players: "上位プレイヤー順" top_players: "上位プレイヤー順"
day: "今日" day: "今日"
@ -836,8 +836,8 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
contribute: contribute:
page_title: "コントリビュート" page_title: "コントリビュート"
intro_blurb: "CodeCombat は100%オープンソースです!何百もの熱心なプレイヤーが私たちがゲームを作るのを手伝っています。私たちと一緒に CodeCombat の次のチャプターを作って世界中のプレイヤーにプログラミングを教えましょう!" intro_blurb: "CodeCombat は100%オープンソースです!何百もの熱心なプレイヤーが私たちがゲームを作るのを手伝っています。私たちと一緒に CodeCombat の次のチャプターを作って世界中のプレイヤーにプログラミングを教えましょう!"
# alert_account_message_intro: "Hey there!" alert_account_message_intro: "やあ、こんにちは!"
# alert_account_message: "To subscribe for class emails, you'll need to be logged in first." alert_account_message: "クラスのメールを購読するには,まずログインが必要です。"
archmage_introduction: "ゲームを作る上で一番重要なのは、たくさんの要素を合成することです。グラフィック、サウンド、リアルタイムネットワーキング、ソーシャルネットワーキング、一般的なプログラミング、ローレベルのデータベースマネジメント、管理画面のデザインやインターフェイスなど多岐に渡ります。やらなくてはいけないことはたくさんあります。もしあなたが経験豊富なプログラマであればアーキメイジになって CodeCombat のコアにコミットしましょう。ぜひとも私たちの最高のプログラミングゲームを手伝ってください。" archmage_introduction: "ゲームを作る上で一番重要なのは、たくさんの要素を合成することです。グラフィック、サウンド、リアルタイムネットワーキング、ソーシャルネットワーキング、一般的なプログラミング、ローレベルのデータベースマネジメント、管理画面のデザインやインターフェイスなど多岐に渡ります。やらなくてはいけないことはたくさんあります。もしあなたが経験豊富なプログラマであればアーキメイジになって CodeCombat のコアにコミットしましょう。ぜひとも私たちの最高のプログラミングゲームを手伝ってください。"
class_attributes: "クラスの属性" class_attributes: "クラスの属性"
archmage_attribute_1_pref: "" archmage_attribute_1_pref: ""
@ -851,17 +851,17 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
join_url_email: "メール" join_url_email: "メール"
join_url_hipchat: "公開の HipChat のルーム" join_url_hipchat: "公開の HipChat のルーム"
archmage_subscribe_desc: "コーディングの機会やアナウンスをメールで受け取る" archmage_subscribe_desc: "コーディングの機会やアナウンスをメールで受け取る"
# artisan_introduction_pref: "We must construct additional levels! People be clamoring for more content, and we can only build so many ourselves. Right now your workstation is level one; our level editor is barely usable even by its creators, so be wary. If you have visions of campaigns spanning for-loops to" artisan_introduction_pref: "私たちは、追加のレベルを建設しなければなりません皆さんはもっとコンテンツを、と叫んでいますが、私達がつくれるのは自分たちの分だけです。今、あなたのワークステーションはレベルです。私達のレベルエディタをつかえばそんなクリエイターでもギリギリ使えます、そう警戒しないで。あなたがfor-loopにまたがるキャンペーンのビジョンを"
# artisan_introduction_suf: ", then this class might be for you." artisan_introduction_suf: "にもっているなら、このクラスはあなたのためになるかもしれません。"
# artisan_attribute_1: "Any experience in building content like this would be nice, such as using Blizzard's level editors. But not required!" artisan_attribute_1: "Blizzardのレベルエディタなどの構築経験は歓迎しますが、必須ではありません!"
# artisan_attribute_2: "A hankering to do a whole lot of testing and iteration. To make good levels, you need to take it to others and watch them play it, and be prepared to find a lot of things to fix." artisan_attribute_2: "全体のテストを何度もすることを願ってます。 よいレベルを作るには 他の人のを真似て見てプレイしてみることが必要です。そしてそこから修正のための多くのものを見つけて準備しましょう。"
# artisan_attribute_3: "For the time being, endurance en par with an Adventurer. Our Level Editor is super preliminary and frustrating to use. You have been warned!" artisan_attribute_3: "時間がかかることで, 冒険者と並ぶくらい我慢しなければなりません。 私達のレベルエディターは予備動作が長く使っているとイライラするかもしれません。気をつけてくださいね!"
# artisan_join_desc: "Use the Level Editor in these steps, give or take:" artisan_join_desc: "レベルエディタを使うために以下のステップを利用してください。"
# artisan_join_step1: "Read the documentation." artisan_join_step1: "ドキュメントを読む"
# artisan_join_step2: "Create a new level and explore existing levels." artisan_join_step2: "新しいレベルを作成し、すでにあるレベルか探す"
# artisan_join_step3: "Find us in our public HipChat room for help." artisan_join_step3: "ヘルプが必要なとき公開HipChatルームで私達を探す"
# artisan_join_step4: "Post your levels on the forum for feedback." artisan_join_step4: "フィードバックのためフォーラムにあなたのレベルを投稿する"
# artisan_subscribe_desc: "Get emails on level editor updates and announcements." artisan_subscribe_desc: "レベルエディタアップデートやアナウンスをメールで受け取る"
# adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you." # adventurer_introduction: "Let's be clear about your role: you are the tank. You're going to take heavy damage. We need people to try out brand-new levels and help identify how to make things better. The pain will be enormous; making good games is a long process and no one gets it right the first time. If you can endure and have a high constitution score, then this class might be for you."
# adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though." # adventurer_attribute_1: "A thirst for learning. You want to learn how to code and we want to teach you how to code. You'll probably be doing most of the teaching in this case, though."
# adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve." # adventurer_attribute_2: "Charismatic. Be gentle but articulate about what needs improving, and offer suggestions on how to improve."
@ -912,17 +912,17 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
# games_simulated_for: "Games simulated for you:" # games_simulated_for: "Games simulated for you:"
# games_simulated: "Games simulated" # games_simulated: "Games simulated"
# games_played: "Games played" # games_played: "Games played"
# ratio: "Ratio" ratio: "比率 "
# leaderboard: "Leaderboard" leaderboard: "リーダーボード"
# battle_as: "Battle as " # battle_as: "Battle as "
summary_your: "あなたの " summary_your: "あなたの "
summary_matches: "戦闘数 - " summary_matches: "戦闘数 - "
summary_wins: " 勝利数, " summary_wins: " 勝利数, "
summary_losses: " 敗北数" summary_losses: " 敗北数"
# rank_no_code: "No New Code to Rank" rank_no_code: "新しいコードがランクにありません"
# rank_my_game: "Rank My Game!" # rank_my_game: "Rank My Game!"
# rank_submitting: "Submitting..." rank_submitting: "送信中..."
# rank_submitted: "Submitted for Ranking" rank_submitted: "ランキングに送信されました。"
# rank_failed: "Failed to Rank" # rank_failed: "Failed to Rank"
# rank_being_ranked: "Game Being Ranked" # rank_being_ranked: "Game Being Ranked"
# rank_last_submitted: "submitted " # rank_last_submitted: "submitted "

View file

@ -47,7 +47,14 @@
background-color: blanchedalmond background-color: blanchedalmond
font-size: 10pt font-size: 10pt
.subscribers-thead
font-size: 10pt
th
padding: 2px
.subscribers-tbody .subscribers-tbody
font-size: 9pt font-size: 9pt
td td
padding: 2px padding: 2px
max-width: 220px
overflow: hidden

View file

@ -51,7 +51,7 @@
.level-progression-cell .level-progression-cell
background-color: lightblue background-color: lightblue
border: 1px solid gray border: 1px solid gray
// cursor: pointer cursor: pointer
padding: 4px padding: 4px
.level-popup-container .level-popup-container

View file

@ -36,14 +36,12 @@ block content
each value in point.values each value in point.values
div #{value} div #{value}
div *Stripe APIs do not return information about inactive subs.
h2 Recent Subscribers h2 Recent Subscribers
if !subscribers || subscribers.length < 1 if !subscribers || subscribers.length < 1
h4 Fetching recent subscribers... h4 Fetching recent subscribers...
else else
table.table.table-striped.table-condensed table.table.table-striped.table-condensed
thead thead.subscribers-thead
tr tr
th Sub ID th Sub ID
th User Start th User Start
@ -52,19 +50,22 @@ block content
th Cancelled th Cancelled
else else
th th
if subscriberSponsored
th Sponsored
else
th th
//- th Name
th Email th Email
th Hero th Hero
th Level th Level
th Last Level th Last Level
th Age th Age
th Spoken th Spoken
th Clans
tbody.subscribers-tbody tbody.subscribers-tbody
each subscriber in subscribers each subscriber in subscribers
tr tr
td td
a(href="https://dashboard.stripe.com/customers/#{subscriber.customerID}", target="_blank")= subscriber.subscriptionID a(href="https://dashboard.stripe.com/customers/#{subscriber.customerID}", target="_blank")= subscriber.subID
td= subscriber.user.dateCreated.substring(0, 10) td= subscriber.user.dateCreated.substring(0, 10)
td= subscriber.start.substring(0, 10) td= subscriber.start.substring(0, 10)
td td
@ -72,15 +73,17 @@ block content
span= subscriber.cancel.substring(0, 10) span= subscriber.cancel.substring(0, 10)
td td
if subscriber.user.stripe.sponsorID if subscriber.user.stripe.sponsorID
span Sponsored span Yes
//- td
//- a(href="/user/#{subscriber.user._id}")= subscriber.user.name || 'Anoner'
td= subscriber.user.emailLower td= subscriber.user.emailLower
td= subscriber.hero td= subscriber.hero
td= subscriber.level td= subscriber.level
td= subscriber.user.lastLevel td= subscriber.user.lastLevel
td= subscriber.user.ageRange td= subscriber.user.ageRange
td= subscriber.user.preferredLanguage td= subscriber.user.preferredLanguage
if subscriber.user.clans
td= subscriber.user.clans.length
else
td
h2 Subscriptions h2 Subscriptions
if !subs || subs.length < 1 if !subs || subs.length < 1
@ -93,8 +96,9 @@ block content
th Total th Total
th Started th Started
th Cancelled th Cancelled
th Net th Net (cancelled)
th Ended th Ended
th Net (ended)
tbody tbody
each sub in subs each sub in subs
tr tr
@ -104,3 +108,4 @@ block content
td= sub.cancelled td= sub.cancelled
td= sub.started - sub.cancelled td= sub.started - sub.cancelled
td= sub.ended td= sub.ended
td= sub.started - sub.ended

View file

@ -103,11 +103,14 @@ block content
a(href="/user/#{member.id}")= member.get('name') || 'Anoner' a(href="/user/#{member.id}")= member.get('name') || 'Anoner'
if memberLevelProgression && memberLevelProgression[member.id] if memberLevelProgression && memberLevelProgression[member.id]
each levelInfo in memberLevelProgression[member.id] each levelInfo in memberLevelProgression[member.id]
td.level-progression-cell td.level-progression-cell(data-level-info=levelInfo)
.level-popup-container .level-popup-container
div Level: #{levelInfo.level} h3 #{levelInfo.level}
div Playtime: #{levelInfo.playtime} p
div Playtime: #{levelInfo.playtime}s
div Last played: #{levelInfo.changed} div Last played: #{levelInfo.changed}
if isOwner || me.isAdmin()
strong Click to view solution.
td.level-progression-cell-name(colspan="#{memberMaxLevelCount - memberLevelProgression[member.id].length + 1}")= memberLevelProgression[member.id][memberLevelProgression[member.id].length - 1].level td.level-progression-cell-name(colspan="#{memberMaxLevelCount - memberLevelProgression[member.id].length + 1}")= memberLevelProgression[member.id][memberLevelProgression[member.id].length - 1].level
else else
td(colspan="#{memberMaxLevelCount + 1}") td(colspan="#{memberMaxLevelCount + 1}")

View file

@ -12,7 +12,7 @@ block content
a(href="/editor/level") a(href="/editor/level")
img(src="/images/pages/community/level.png") img(src="/images/pages/community/level.png")
h2 h2
a.spl(href="/editor/level", data-i18n="editor.level_title") a(href="/editor/level", data-i18n="editor.level_title")
p p
span.spr(data-i18n="community.level_editor_prefix") Use the CodeCombat span.spr(data-i18n="community.level_editor_prefix") Use the CodeCombat
a(href="/editor/level", data-i18n="editor.level_title") a(href="/editor/level", data-i18n="editor.level_title")
@ -22,7 +22,7 @@ block content
a(href="/editor/thang") a(href="/editor/thang")
img(src="/images/pages/community/thang.png") img(src="/images/pages/community/thang.png")
h2 h2
a.spl(href="/editor/thang", data-i18n="editor.thang_title") a(href="/editor/thang", data-i18n="editor.thang_title")
p p
span.spr(data-i18n="community.thang_editor_prefix") We call units within the game 'thangs'. Use the span.spr(data-i18n="community.thang_editor_prefix") We call units within the game 'thangs'. Use the
a(href="/editor/thang", data-i18n="editor.thang_title") a(href="/editor/thang", data-i18n="editor.thang_title")
@ -32,7 +32,7 @@ block content
a(href="/editor/article") a(href="/editor/article")
img(src="/images/pages/community/article.png") img(src="/images/pages/community/article.png")
h2 h2
a.spl(href="/editor/article", data-i18n="editor.article_title") a(href="/editor/article", data-i18n="editor.article_title")
p p
span.spr(data-i18n="community.article_editor_prefix") See a mistake in some of our docs? Want to make some instructions for your own creations? Check out the span.spr(data-i18n="community.article_editor_prefix") See a mistake in some of our docs? Want to make some instructions for your own creations? Check out the
a(href="/editor/article", data-i18n="editor.article_title") a(href="/editor/article", data-i18n="editor.article_title")

View file

@ -9,9 +9,9 @@ block modal-body-content
for system in systems for system in systems
li.list-group-item li.list-group-item
div.item-title(data-toggle="collapse", data-target="##{system}").collapsed div.item-title(data-toggle="collapse", data-target="##{system}").collapsed
span.glyphicon.glyphicon-chevron-down.text-muted span.glyphicon.glyphicon-chevron-down.text-muted.spr
span.glyphicon.glyphicon-chevron-up.text-muted span.glyphicon.glyphicon-chevron-up.text-muted.spr
a.spl= system a= system
span.spl.text-muted= nameLists[system] span.spl.text-muted= nameLists[system]
.collapse-panel.collapse(id=system) .collapse-panel.collapse(id=system)
for component in components[system] for component in components[system]

View file

@ -14,6 +14,7 @@ block content
th Translated Name th Translated Name
th Type th Type
th Specifically Covered th Specifically Covered
if showGeneralCoverage
th Generally Covered th Generally Covered
if selectedLanguage if selectedLanguage
@ -29,4 +30,5 @@ block content
td= translatedName td= translatedName
td= model.constructor.className td= model.constructor.className
td(class=model.specificallyCovered ? 'success' : 'danger')= model.specificallyCovered ? 'Yes' : 'No' td(class=model.specificallyCovered ? 'success' : 'danger')= model.specificallyCovered ? 'Yes' : 'No'
if showGeneralCoverage
td(class=model.generallyCovered ? 'success' : 'danger')= model.generallyCovered ? 'Yes' : 'No' td(class=model.generallyCovered ? 'success' : 'danger')= model.generallyCovered ? 'Yes' : 'No'

View file

@ -10,7 +10,7 @@ require 'vendor/d3'
module.exports = class AnalyticsSubscriptionsView extends RootView module.exports = class AnalyticsSubscriptionsView extends RootView
id: 'admin-analytics-subscriptions-view' id: 'admin-analytics-subscriptions-view'
template: template template: template
targetSubCount: 2000 targetSubCount: 1200
constructor: (options) -> constructor: (options) ->
super options super options
@ -25,6 +25,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
context.subs = _.cloneDeep(@subs ? []).reverse() context.subs = _.cloneDeep(@subs ? []).reverse()
context.subscribers = @subscribers ? [] context.subscribers = @subscribers ? []
context.subscriberCancelled = _.find context.subscribers, (subscriber) -> subscriber.cancel context.subscriberCancelled = _.find context.subscribers, (subscriber) -> subscriber.cancel
context.subscriberSponsored = _.find context.subscribers, (subscriber) -> subscriber.user?.stripe?.sponsorID
context.total = @total ? 0 context.total = @total ? 0
context.cancelled = @cancelled ? 0 context.cancelled = @cancelled ? 0
context.monthlyChurn = @monthlyChurn ? 0.0 context.monthlyChurn = @monthlyChurn ? 0.0
@ -46,9 +47,9 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
refreshData: -> refreshData: ->
return unless me.isAdmin() return unless me.isAdmin()
@resetSubscriptionsData() @resetSubscriptionsData()
@getSubscribers()
@getCancellations (cancellations) => @getCancellations (cancellations) =>
@getSubscriptions(cancellations) @getSubscriptions cancellations, (subscriptions) =>
@getSubscribers(subscriptions)
getCancellations: (done) -> getCancellations: (done) ->
options = options =
@ -62,25 +63,34 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
done(cancellations) done(cancellations)
@supermodel.addRequestResource('get_cancellations', options, 0).load() @supermodel.addRequestResource('get_cancellations', options, 0).load()
getSubscribers: -> getSubscribers: (subscriptions) ->
maxSubscribers = 40
subscribers = _.filter subscriptions, (a) -> a.userID?
subscribers.sort (a, b) -> b.start.localeCompare(a.start)
subscribers = subscribers.slice(0, maxSubscribers)
subscriberUserIDs = _.map subscribers, (a) -> a.userID
options = options =
url: '/db/subscription/-/subscribers' url: '/db/subscription/-/subscribers'
method: 'POST' method: 'POST'
data: {maxCount: 30} data: {ids: subscriberUserIDs}
options.error = (model, response, options) => options.error = (model, response, options) =>
return if @destroyed return if @destroyed
console.error 'Failed to get subscribers', response console.error 'Failed to get subscribers', response
options.success = (subscribers, response, options) => options.success = (userMap, response, options) =>
return if @destroyed return if @destroyed
@subscribers = subscribers for subscriber in subscribers
for subscriber in @subscribers continue unless subscriber.userID of userMap
subscriber.user = userMap[subscriber.userID]
subscriber.level = User.levelFromExp subscriber.user.points subscriber.level = User.levelFromExp subscriber.user.points
if hero = subscriber.user.heroConfig?.thangType if hero = subscriber.user.heroConfig?.thangType
subscriber.hero = _.invert(ThangType.heroes)[hero] subscriber.hero = _.invert(ThangType.heroes)[hero]
@subscribers = subscribers
@render?() @render?()
@supermodel.addRequestResource('get_subscribers', options, 0).load() @supermodel.addRequestResource('get_subscribers', options, 0).load()
getSubscriptions: (cancellations=[]) -> getSubscriptions: (cancellations=[], done) ->
options = options =
url: '/db/subscription/-/subscriptions' url: '/db/subscription/-/subscriptions'
method: 'GET' method: 'GET'
@ -102,6 +112,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
subDayMap[endDay]['end']++ subDayMap[endDay]['end']++
for cancellation in cancellations for cancellation in cancellations
if cancellation.subID is sub.subID if cancellation.subID is sub.subID
sub.cancel = cancellation.cancel
cancelDay = cancellation.cancel.substring(0, 10) cancelDay = cancellation.cancel.substring(0, 10)
subDayMap[cancelDay] ?= {} subDayMap[cancelDay] ?= {}
subDayMap[cancelDay]['cancel'] ?= 0 subDayMap[cancelDay]['cancel'] ?= 0
@ -132,6 +143,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
@monthlyGrowth = (endMonthTotal / startMonthTotal - 1) * 100 @monthlyGrowth = (endMonthTotal / startMonthTotal - 1) * 100
@updateAnalyticsGraphData() @updateAnalyticsGraphData()
@render?() @render?()
done(subs)
@supermodel.addRequestResource('get_subscriptions', options, 0).load() @supermodel.addRequestResource('get_subscriptions', options, 0).load()
updateAnalyticsGraphData: -> updateAnalyticsGraphData: ->
@ -170,7 +182,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
color: 'red' color: 'red'
strokeWidth: 1 strokeWidth: 1
lineMetadata[netSubsID] = lineMetadata[netSubsID] =
description: '7-day Average Net Subscriptions' description: '7-day Average Net Subscriptions (started - ended)'
color: 'black' color: 'black'
strokeWidth: 4 strokeWidth: 4

View file

@ -23,6 +23,7 @@ module.exports = class ClanDetailsView extends RootView
'click .edit-name-save-btn': 'onEditNameSave' 'click .edit-name-save-btn': 'onEditNameSave'
'click .join-clan-btn': 'onJoinClan' 'click .join-clan-btn': 'onJoinClan'
'click .leave-clan-btn': 'onLeaveClan' 'click .leave-clan-btn': 'onLeaveClan'
'click .level-progression-cell': 'onClickLevel'
'click .remove-member-btn': 'onRemoveMember' 'click .remove-member-btn': 'onRemoveMember'
'mouseenter .level-progression-cell': 'onMouseEnterPoint' 'mouseenter .level-progression-cell': 'onMouseEnterPoint'
'mouseleave .level-progression-cell': 'onMouseLeavePoint' 'mouseleave .level-progression-cell': 'onMouseLeavePoint'
@ -131,8 +132,10 @@ module.exports = class ClanDetailsView extends RootView
@memberLevelProgression[user] ?= [] @memberLevelProgression[user] ?= []
levelInfo = levelInfo =
level: levelSession.get('levelName') level: levelSession.get('levelName')
levelID: levelSession.get('levelID')
changed: new Date(levelSession.get('changed')).toLocaleString() changed: new Date(levelSession.get('changed')).toLocaleString()
playtime: levelSession.get('playtime') playtime: levelSession.get('playtime')
sessionID: levelSession.id
@memberLevelProgression[user].push levelInfo @memberLevelProgression[user].push levelInfo
@memberMaxLevelCount = 0 @memberMaxLevelCount = 0
@memberLanguageMap = {} @memberLanguageMap = {}
@ -161,6 +164,12 @@ module.exports = class ClanDetailsView extends RootView
onMouseLeavePoint: (e) -> onMouseLeavePoint: (e) ->
$(e.target).find('.level-popup-container').hide() $(e.target).find('.level-popup-container').hide()
onClickLevel: (e) ->
levelInfo = $(e.target).data 'level-info'
return unless levelInfo?.levelID? and levelInfo?.sessionID?
url = "/play/level/#{levelInfo.levelID}?session=#{levelInfo.sessionID}&observing=true"
window.open url, '_blank'
onDeleteClan: (e) -> onDeleteClan: (e) ->
return @openModalView(new AuthModal()) if me.isAnonymous() return @openModalView(new AuthModal()) if me.isAnonymous()
return unless window.confirm("Delete Clan?") return unless window.confirm("Delete Clan?")
@ -211,6 +220,7 @@ module.exports = class ClanDetailsView extends RootView
@supermodel.addRequestResource( 'leave_clan', options).load() @supermodel.addRequestResource( 'leave_clan', options).load()
onRemoveMember: (e) -> onRemoveMember: (e) ->
return unless window.confirm("Remove Hero?")
if memberID = $(e.target).data('id') if memberID = $(e.target).data('id')
options = options =
url: "/db/clan/#{@clanID}/remove/#{memberID}" url: "/db/clan/#{@clanID}/remove/#{memberID}"

View file

@ -73,6 +73,7 @@ module.exports = class I18NHomeView extends RootView
covered = (m for m in @aggregateModels.models when m.specificallyCovered).length covered = (m for m in @aggregateModels.models when m.specificallyCovered).length
total = @aggregateModels.models.length total = @aggregateModels.models.length
c.progress = if total then parseInt(100 * covered / total) else 100 c.progress = if total then parseInt(100 * covered / total) else 100
c.showGeneralCoverage = /-/.test(@selectedLanguage ? 'en') # Only relevant for languages with more than one family, like zh-HANS
c c

View file

@ -126,7 +126,7 @@ ClanHandler = class ClanHandler extends Handler
return @sendNotFoundError(res) unless clan return @sendNotFoundError(res) unless clan
memberIDs = _.map clan.get('members') ? [], (memberID) -> memberID.toHexString?() or memberID memberIDs = _.map clan.get('members') ? [], (memberID) -> memberID.toHexString?() or memberID
memberIDs = memberIDs.slice 0, memberLimit memberIDs = memberIDs.slice 0, memberLimit
LevelSession.find {creator: {$in: memberIDs}}, 'changed codeLanguage creator creatorName levelName playtime state submittedCodeLanguage', (err, documents) => LevelSession.find {creator: {$in: memberIDs}}, 'changed codeLanguage creator creatorName levelID levelName playtime state submittedCodeLanguage', (err, documents) =>
return @sendDatabaseError(res, err) if err? return @sendDatabaseError(res, err) if err?
cleandocs = (LevelSessionHandler.formatEntity(req, doc) for doc in documents) cleandocs = (LevelSessionHandler.formatEntity(req, doc) for doc in documents)
@sendSuccess(res, cleandocs) @sendSuccess(res, cleandocs)

View file

@ -67,7 +67,7 @@ class SubscriptionHandler extends Handler
(done) => (done) =>
stripe.customers.retrieveSubscription customerID, subscriptionID, (err, subscription) => stripe.customers.retrieveSubscription customerID, subscriptionID, (err, subscription) =>
return done() if err return done() if err
return unless subscription?.cancel_at_period_end return done() unless subscription?.cancel_at_period_end
cancellations.push cancellations.push
cancel: new Date(subscription.canceled_at * 1000) cancel: new Date(subscription.canceled_at * 1000)
subID: subscription.id subID: subscription.id
@ -82,74 +82,18 @@ class SubscriptionHandler extends Handler
getSubscribers: (req, res) -> getSubscribers: (req, res) ->
# console.log 'subscription_handler getSubscribers' # console.log 'subscription_handler getSubscribers'
return @sendForbiddenError(res) unless req.user?.isAdmin() return @sendForbiddenError(res) unless req.user?.isAdmin()
subscriberUserIDs = req.body.ids or []
maxReturnCount = req.body.maxCount or 20 User.find {_id: {$in: subscriberUserIDs}}, (err, users) =>
# @subscribers ?= []
# return @sendSuccess(res, @subscribers) unless _.isEmpty(@subscribers)
@subscribers = []
subscriberIDs = []
customersProcessed = 0
nextBatch = (starting_after, done) =>
options = limit: 100
options.starting_after = starting_after if starting_after
stripe.customers.list options, (err, customers) =>
return done(err) if err
customersProcessed += customers.data.length
for customer in customers.data
break unless @subscribers.length < maxReturnCount
continue unless customer?.subscriptions?.data?.length > 0
for subscription in customer.subscriptions.data
continue unless subscription.plan.id is 'basic'
amount = subscription.plan.amount
if subscription?.discount?.coupon?
if subscription.discount.coupon.percent_off
amount = amount * (100 - subscription.discount.coupon.percent_off) / 100;
else if subscription.discount.coupon.amount_off
amount -= subscription.discount.coupon.amount_off
else if customer.discount?.coupon?
if customer.discount.coupon.percent_off
amount = amount * (100 - customer.discount.coupon.percent_off) / 100
else if customer.discount.coupon.amount_off
amount -= customer.discount.coupon.amount_off
continue unless amount > 0
subscriber =
customerID: customer.id
start: new Date(subscription.start * 1000)
subscriptionID: subscription.id
if subscription.metadata?.id?
subscriber.userID = subscription.metadata.id
subscriberIDs.push subscription.metadata.id
if subscription.cancel_at_period_end
subscriber.cancel = new Date(subscription.canceled_at * 1000)
subscriber.end = new Date(subscription.current_period_end * 1000)
@subscribers.push(subscriber)
if customers.has_more and @subscribers.length < maxReturnCount
return nextBatch(customers.data[customers.data.length - 1].id, done)
else
return done()
nextBatch null, (err) =>
return @sendDatabaseError(res, err) if err return @sendDatabaseError(res, err) if err
User.find {_id: {$in: subscriberIDs}}, (err, users) => userMap = {}
return @sendDatabaseError(res, err) if err userMap[user.id] = user for user in users
for user in users @sendSuccess(res, userMap)
subscriber.user = user for subscriber in @subscribers when subscriber.userID is user.id
@sendSuccess(res, @subscribers)
getSubscriptions: (req, res) -> getSubscriptions: (req, res) ->
# console.log 'subscription_handler getSubscriptions' # console.log 'subscription_handler getSubscriptions'
# Returns a list of active subscriptions # Returns a list of active subscriptions
# TODO: does not track sponsored subs, only basic
# TODO: does not return free subs # TODO: does not return free subs
# TODO: add tests # TODO: add tests
# TODO: aggregate this data daily instead of providing it on demand
# TODO: take date range as input # TODO: take date range as input
# TODO: are ended counts correct for today? E.g. retries may complicate things. # TODO: are ended counts correct for today? E.g. retries may complicate things.
@ -169,11 +113,13 @@ class SubscriptionHandler extends Handler
continue unless invoice.subscription continue unless invoice.subscription
continue unless invoice.total > 0 continue unless invoice.total > 0
continue unless invoice.lines?.data?[0]?.plan?.id is 'basic' continue unless invoice.lines?.data?[0]?.plan?.id is 'basic'
newInvoices.push newInvoice =
customerID: invoice.customer customerID: invoice.customer
invoiceID: invoice.id invoiceID: invoice.id
subscriptionID: invoice.subscription subscriptionID: invoice.subscription
date: new Date(invoice.date * 1000) date: new Date(invoice.date * 1000)
newInvoice.userID = invoice.lines.data[0].metadata.id if invoice.lines?.data?[0]?.metadata?.id
newInvoices.push newInvoice
if invoices.has_more if invoices.has_more
# console.log 'Fetching more invoices', @invoices.length, newInvoices.length # console.log 'Fetching more invoices', @invoices.length, newInvoices.length
return processInvoices(invoices.data[invoices.data.length - 1].id, done) return processInvoices(invoices.data[invoices.data.length - 1].id, done)
@ -193,6 +139,32 @@ class SubscriptionHandler extends Handler
first: invoice.date first: invoice.date
last: invoice.date last: invoice.date
customerID: invoice.customerID customerID: invoice.customerID
subMap[subID].userID = invoice.userID if invoice.userID
# Check sponsored subscriptions
User.find {"stripe.sponsorSubscriptionID": {$exists: true}}, (err, sponsors) =>
return @sendDatabaseError(res, err) if err
createCheckSubFn = (customerID, subscriptionID) =>
(done) =>
stripe.customers.retrieveSubscription customerID, subscriptionID, (err, subscription) =>
return done() if err
return done() unless subscription?
subMap[subscription.id] =
first: new Date(subscription.start * 1000)
subMap[subscription.id].userID = subscription.metadata.id if subscription.metadata?.id?
if subscription.cancel_at_period_end
subMap[subscription.id].cancel = new Date(subscription.canceled_at * 1000)
subMap[subscription.id].end = new Date(subscription.current_period_end * 1000)
done()
tasks = []
for user in sponsors
for recipient in user.get("stripe")?.recipients
tasks.push createCheckSubFn(user.get('stripe')?.customerID, recipient.subscriptionID)
async.parallel tasks, (err, results) =>
return @sendDatabaseError(res, err) if err
subs = [] subs = []
for subID of subMap for subID of subMap
sub = sub =
@ -202,9 +174,12 @@ class SubscriptionHandler extends Handler
sub.cancel = subMap[subID].cancel if subMap[subID].cancel sub.cancel = subMap[subID].cancel if subMap[subID].cancel
oneMonthAgo = new Date() oneMonthAgo = new Date()
oneMonthAgo.setUTCMonth(oneMonthAgo.getUTCMonth() - 1) oneMonthAgo.setUTCMonth(oneMonthAgo.getUTCMonth() - 1)
if subMap[subID].last < oneMonthAgo if subMap[subID].end?
sub.end = subMap[subID].end
else if subMap[subID].last < oneMonthAgo
sub.end = new Date(subMap[subID].last) sub.end = new Date(subMap[subID].last)
sub.end.setUTCMonth(sub.end.getUTCMonth() + 1) sub.end.setUTCMonth(sub.end.getUTCMonth() + 1)
sub.userID = subMap[subID].userID if subMap[subID].userID
subs.push sub subs.push sub
@sendSuccess(res, subs) @sendSuccess(res, subs)