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:
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_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.
@ -56,28 +56,28 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
unlock: "Freischalte" # For purchasing items and heroes
confirm: "Bestätige"
owned: "Scho gkauft" # For items you own
locked: "Nonig freischaltbar"
# purchasable: "Purchasable" # For a hero you unlocked but haven't purchased
locked: "Nonig kauft"
purchasable: "kaufen" # For a hero you unlocked but haven't purchased
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
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
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
change_hero: "Held wächsle" # Go back from choose inventory to choose hero
# choose_inventory: "Equip Items"
# buy_gems: "Buy Gems"
# subscription_required: "Subscription Required"
choose_inventory: "Items uusrüschte"
buy_gems: "Edelstei chaufä"
subscription_required: "Abonnement benötigt"
older_campaigns: "Älteri Kampagne"
anonymous: "Anonyme Spieler"
level_difficulty: "Schwierigkeit: "
campaign_beginner: "Afängerkampagne"
# awaiting_levels_adventurer_prefix: "We release five levels per week."
# awaiting_levels_adventurer: "Sign up as an Adventurer"
# awaiting_levels_adventurer_suffix: "to be the first to play new levels."
# adjust_volume: "Adjust volume"
awaiting_levels_adventurer_prefix: "Mier möched 5 Levels pro Wuche"
awaiting_levels_adventurer: "Mäld dich a as en Abendtüürer"
awaiting_levels_adventurer_suffix: "um de erscht zii vo die neue Levels spiilt"
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.
adventurer_prefix: "Du chasch zu de untere Level zrugg goh oder die kommende Level diskutiere im "
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_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_classic_algorithms: "Classic Algorithms"
# campaign_classic_algorithms_description: "... in which you learn the most popular algorithms in Computer Science."
campaign_classic_algorithms: "Klassischi Algorithme"
campaign_classic_algorithms_description: "... wo du die beliebtischte Algorithmue vode Computer Welt lernsch.."
share_progress_modal:
blurb: "Du machsch grossi Fortschritts! Verzells öperem wieviel du glernt häsch mit CodeCombat."
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ä"
placeholder: "Email Adrässä"
# title: "Excellent Work, Apprentice"
title: "Gueti Arbeit!"
login:
sign_up: "Account erstelle"
@ -107,8 +107,8 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
logging_in: "Am Ilogge"
log_out: "Uslogge"
forgot_password: "Passwort vergässe?"
# authenticate_gplus: "Authenticate G+"
# load_profile: "Load G+ Profile"
authenticate_gplus: "Mit G+ audentifiziere"
load_profile: "G+ Profil ladä"
finishing: "Fertigstelle"
sign_in_with_facebook: "Mit Facebook aamelde"
sign_in_with_gplus: "Mit G+ aamelde"
@ -125,20 +125,20 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
recover:
recover_account_title: "Account wiederherstelle"
send_password: "Recovery Password sende"
# recovery_sent: "Recovery email sent."
send_password: "Widerherstelligs Passwort sende"
recovery_sent: "Widerherstelligs Passwort isch gsendet"
items:
# primary: "Primary"
# secondary: "Secondary"
# armor: "Armor"
# accessories: "Accessories"
primary: "Primär"
secondary: "Sekundär"
armor: "Rüschtig"
accessories: "Accessories"
misc: "Diverses"
books: "Büecher"
common:
# back: "Back" # When used as an action verb, like "Navigate backward"
# continue: "Continue" # When used as an action verb, like "Continue forward"
back: "Zrugg" # When used as an action verb, like "Navigate backward"
continue: "Wiiterfare" # When used as an action verb, like "Continue forward"
loading: "Lade..."
saving: "Speichere..."
sending: "Sende..."
@ -151,36 +151,36 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# fork: "Fork"
play: "Spiele" # When used as an action verb, like "Play next level"
retry: "nomol versuche"
# actions: "Actions"
actions: "Aktione"
info: "Info"
help: "Hilf"
# watch: "Watch"
# unwatch: "Unwatch"
watch: "Aluege"
unwatch: "Nüm Aluege"
submit_patch: "Patch ireiche"
# submit_changes: "Submit Changes"
submit_changes: "Wechsel ireiche"
general:
and: "und"
name: "Name"
date: "Datum"
# body: "Body"
body: "Body"
version: "Version"
# pending: "Pending"
# accepted: "Accepted"
# rejected: "Rejected"
# withdrawn: "Withdrawn"
# submitter: "Submitter"
# submitted: "Submitted"
# commit_msg: "Commit Message"
# review: "Review"
pending: "in Bearbeitig"
accepted: "Akzeptiert"
rejected: "Nid akzeptiert"
withdrawn: "Zruggzie"
submitter: "Sender"
submitted: "Gesendet"
commit_msg: "Nachricht abschicke"
review: "Review"
version_history: "Versionsverlauf"
# version_history_for: "Version History for: "
# select_changes: "Select two changes below to see the difference."
# undo_prefix: "Undo"
# undo_shortcut: "(Ctrl+Z)"
# redo_prefix: "Redo"
# redo_shortcut: "(Ctrl+Shift+Z)"
# play_preview: "Play preview of current level"
version_history_for: "Versionsverlauf für: "
select_changes: "Wähl zwei Verändrige um unne Ihre Unterschid zgse."
undo_prefix: "Eis zrugg"
undo_shortcut: "(Ctrl+Z)"
redo_prefix: "Nomal mache"
redo_shortcut: "(Ctrl+Shift+Z)"
play_preview: "Spiel dPreview vom aktuelle Level"
result: "Resultat"
results: "Resultat"
description: "Beschriibig"
@ -204,7 +204,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
player: "Spieler"
player_level: "Stufe" # Like player level 5, not like level: Dungeons of Kithgard
warrior: "Krieger"
# ranger: "Ranger"
ranger: "Ranger"
wizard: "Zauberer"
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_confirm: "Alles neu lade"
victory: "Gwunne"
# victory_title_prefix: ""
victory_title_prefix: ""
victory_title_suffix: " Vollständig"
victory_sign_up: "Meld dich ah zum din Fortschritt speichere"
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_hour_of_code_done: "Bisch fertig?"
victory_hour_of_code_done_yes: "Jo, ich bin fertig mit mim Hour of Code™!"
# victory_experience_gained: "XP Gained"
# victory_gems_gained: "Gems Gained"
# 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_become_a_viking: "Become a Viking"
victory_experience_gained: "Erfarig bechoo"
victory_gems_gained: "Edelstei bechoo"
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: "Werd en Vikinger!"
guide_title: "Handbuech"
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_other_units: "Anderi Einheite" # Only in old-style levels.
# tome_cast_button_run: "Run"
# tome_cast_button_running: "Running"
# tome_cast_button_ran: "Ran"
# tome_submit_button: "Submit"
# tome_reload_method: "Reload original code for this method" # Title text for individual method reload button.
tome_cast_button_run: "Renn"
tome_cast_button_running: "Renne"
tome_cast_button_ran: "grennt"
tome_submit_button: "Abschicke"
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_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_available_spells: "Verfüegbari Zaubersprüch"
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_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_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_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_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_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_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_javascript_java: "Java is to JavaScript what Car is to Carpet. - Chris Heilmann"
# tip_move_forward: "Whatever you do, keep moving forward. - Martin Luther King Jr."
# tip_google: "Have a problem you can't solve? Google it!"
tip_source_code: "Ich wet dWält verändere aber die wend mier de Source Code nid gää."
tip_javascript_java: "Java isch zu JavaScript wie es Auto zume Automat. - Chris Heilmann"
tip_move_forward: "Was immer du machsch, mach immer me Fortschritt. - Martin Luther King Jr."
tip_google: "Hesch es Problem und chunsch nüm wiiter? Googles doch mal!"
# 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_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"
game_menu:
# inventory_tab: "Inventory"
inventory_tab: "Inventar"
save_load_tab: "Spaicherä/Ladä"
options_tab: "Optionä"
# guide_tab: "Guide"
# guide_video_tutorial: "Video Tutorial"
guide_tab: "Guide"
guide_video_tutorial: "Vidio Tutorial"
guide_tips: "Tipps"
multiplayer_tab: "Multiplayer"
# auth_tab: "Sign Up"
# inventory_caption: "Equip your hero"
# choose_hero_caption: "Choose hero, language"
# save_load_caption: "... and view history"
# options_caption: "Configure settings"
auth_tab: "Regischtriere"
inventory_caption: "Rüscht din Held uus"
choose_hero_caption: "Wähl din Held und dini Sprach"
save_load_caption: "... und lueg dini Gschicht aa."
options_caption: "Iistellige apasse"
guide_caption: "Doku und Tipps"
# multiplayer_caption: "Play with friends!"
# auth_caption: "Save your progress."
multiplayer_caption: "Spil mid dini Fründe!"
auth_caption: "Speichere din Fortschritt."
# leaderboard:
# leaderboard: "Leaderboard"
# view_other_solutions: "View Leaderboards"
# scores: "Scores"
# top_players: "Top Players by"
# day: "Today"
# week: "This Week"
# all: "All-Time"
# time: "Time"
# damage_taken: "Damage Taken"
# damage_dealt: "Damage Dealt"
# difficulty: "Difficulty"
# gold_collected: "Gold Collected"
leaderboard:
leaderboard: "Ranglischte"
view_other_solutions: "Lueg der dRanglischte aa!"
scores: "Pünkt"
top_players: "Beschti Speiler"
day: "Hüt"
week: "Die Wuuche"
all: "Vo immer"
time: "Ziit"
damage_taken: "Schade gnoo"
damage_dealt: "Schade uusteilt"
difficulty: "Schwirigkeitsgrad"
gold_collected: "Gold gsammlet"
# inventory:
# choose_inventory: "Equip Items"
# equipped_item: "Equipped"
# required_purchase_title: "Required"
# available_item: "Available"
# restricted_title: "Restricted"
# should_equip: "(double-click to equip)"
# equipped: "(equipped)"
# locked: "(locked)"
# restricted: "(restricted in this level)"
# equip: "Equip"
# unequip: "Unequip"
inventory:
choose_inventory: "Items uusrüschte"
equipped_item: "Uusgrüschteti Items"
required_purchase_title: "Benötigt"
available_item: "Verfüegbar"
restricted_title: "Verbote"
should_equip: "(2mal Klicke zum uusrüschte)"
equipped: "(usgrüschtet)"
locked: "(geschperrt)"
restricted: "(verbote i dem Level)"
equip: "Uusrüschte"
unequip: "Nüm Uusrüschte"
# buy_gems:
# few_gems: "A few gems"
# pile_gems: "Pile of gems"
# chest_gems: "Chest of gems"
# purchasing: "Purchasing..."
# declined: "Your card was declined"
# retrying: "Server error, retrying."
# prompt_title: "Not Enough Gems"
# prompt_body: "Do you want to get more?"
# prompt_button: "Enter Shop"
# recovered: "Previous gems purchase recovered. Please refresh the page."
buy_gems:
few_gems: "Es paar Edelstei"
pile_gems: "En hufe vo Edelstei"
chest_gems: "En ganzi True voll Edelstei"
purchasing: "Kaufen..."
declined: "Dini Charte isch leider abglehnt worde."
retrying: "Server Fehler, probiere nochmals."
prompt_title: "Nid gnug Edelstei!"
prompt_body: "Wetsch mee chaufe?"
prompt_button: "zum Shop"
recovered: "Früenere Ichauf zruggerstatet. Bitte dSite neu lade!"
# price: "x3500 / mo"
# subscribe:
# comparison_blurb: "Sharpen your skills with a CodeCombat subscription!"
# feature1: "80+ basic levels across 4 worlds"
subscribe:
comparison_blurb: "Verschärf dins Chönne midme CodeCombat Abonement."
feature1: "80+ basis levels in 4 Weltete!"
# 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!"
# feature5: "Video tutorials"
# feature6: "Premium email support"
# free: "Free"
# month: "month"
# subscribe_title: "Subscribe"
# unsubscribe: "Unsubscribe"
# confirm_unsubscribe: "Confirm Unsubscribe"
# never_mind: "Never Mind, I Still Love You"
# thank_you_months_prefix: "Thank you for supporting us these last"
# thank_you_months_suffix: "months."
# 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."
# unsubscribe_feedback_placeholder: "O, what have we done?"
# 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: "Dear Parent: Your child is learning to code. Will you help them continue?"
# 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_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_blurb2: "For $9.99 USD/mo, your child will get new challenges every week and personal email support from professional programmers."
# parents_blurb3: "No Risk: 100% money back guarantee, easy 1-click unsubscribe."
# payment_methods: "Payment Methods"
# payment_methods_title: "Accepted Payment Methods"
# payment_methods_blurb1: "We currently accept credit cards and Alipay."
feature5: "Video Aleitige"
feature6: "Premium Email Hilf"
free: "Gratis"
month: "Monät"
subscribe_title: "Aboniere"
unsubscribe: "Deaboniere"
confirm_unsubscribe: "Deaboniere beschtätige"
never_mind: "Keis Problem, ich lieb dich trotzdem."
thank_you_months_prefix: "Danke das du üs die Monät"
thank_you_months_suffix: "so unterschtütz hesch."
thank_you: "Danke, dass du CodeCombat so unterschtüzisch."
sorry_to_see_you_go: "Schad, dass du gasch! Bitte seg üs doch was mier hetted chönne besser mache."
unsubscribe_feedback_placeholder: "Ohaletz, was hemmer gmacht?"
parent_button: "Frag dini Eltere"
parent_email_description: "We'll email them so they can buy you a CodeCombat subscription."
parent_email_input_invalid: "Email Adrässi ungültig"
parent_email_input_label: "Email Adrässi vo dine Eltere"
parent_email_input_placeholder: "Bitte gib dMail Adrässi vo dine Eltere a"
parent_email_send: "Email sände"
parent_email_sent: "Email gsändet!"
parent_email_title: "Wie isch dEmail Adrässi vo dine Eltere?"
parents: "Für Eltere"
parents_title: "Liebi Eltere, Ihres Chind isch am Lerne wieme programmiert. Wen Sie im helfe?"
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: "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: "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: "Kei Risikos, 100% Geld zrugg Garantie und ganz eifaches deaboniere mid eim Klick"
payment_methods: "Zalligs Methode"
payment_methods_title: "Akzeptierti Zalligs Methode"
payment_methods_blurb1: "Mier akzeptiered immoment Kreditchartene und Alipay."
# payment_methods_blurb2: "If you require an alternate form of payment, please contact"
# 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."
# personal_sub: "Personal Subscription" # Accounts Subscription View below
# loading_info: "Loading subscription information..."
# managed_by: "Managed by"
# will_be_cancelled: "Will be cancelled on"
# currently_free: "You currently have a free subscription"
loading_info: "Lade Abo Informatione..."
managed_by: "Verwaltet vo"
will_be_cancelled: "Wird abbroche am"
currently_free: "Du hesch jetzt grad es frii Abo"
# currently_free_until: "You currently have 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.)"
# group_discounts: "Group discounts"
# group_discounts_1: "We also offer group discounts for bulk subscriptions."
# group_discounts_1st: "1st subscription"
# group_discounts_full: "Full price"
# group_discounts_2nd: "Subscriptions 2-11"
# group_discounts_20: "20% off"
# group_discounts_12th: "Subscriptions 12+"
# group_discounts_40: "40% off"
# subscribing: "Subscribing..."
# recipient_emails_placeholder: "Enter email address to subscribe, one per line."
# subscribe_users: "Subscribe Users"
# users_subscribed: "Users subscribed:"
group_discounts_1st: "Erstes Abonement"
group_discounts_full: "de ganz Priis"
group_discounts_2nd: "Aboniere 2-11"
group_discounts_20: "20% billiger"
group_discounts_12th: "Aboniere 12+"
group_discounts_40: "40% billiger"
subscribing: "Am Aboniere..."
recipient_emails_placeholder: "Gib dini Mails zum Aboniere i, eine pro Linie:"
subscribe_users: "Abonier Users"
users_subscribed: "Users aboniert:"
# no_users_subscribed: "No users subscribed, please double check your email addresses."
# current_recipients: "Current Recipients"
# unsubscribing: "Unsubscribing..."
# subscribe_prepaid: "Click Subscribe to use prepaid code"
# using_prepaid: "Using prepaid code for monthly subscription"
unsubscribing: "Am Abo chünde"
subscribe_prepaid: "Klick Aboniere um en PrePaid Code izlöse"
using_prepaid: "Bruch en PrePaid Code um en Monet zAboniere"
choose_hero:
# choose_hero: "Choose Your Hero"
# programming_language: "Programming Language"
# programming_language_description: "Which programming language do you want to use?"
# default: "Default"
choose_hero: "Wähl din Held"
programming_language: "Programmiersprach"
programming_language_description: "Weli Programmiersprach wetsch benutze?"
default: "Standard"
# experimental: "Experimental"
python_blurb: "Eifach und doch mächtig."
javascript_blurb: "D Internetsproch."
@ -476,22 +476,22 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
lua_blurb: "D Sproch für Game Scripts."
io_blurb: "Eifach aber undurchsichtig."
# status: "Status"
# hero_type: "Type"
# weapons: "Weapons"
# weapons_warrior: "Swords - Short Range, No Magic"
# weapons_ranger: "Crossbows, Guns - Long Range, No Magic"
# weapons_wizard: "Wands, Staffs - Long Range, Magic"
# attack: "Damage" # Can also translate as "Attack"
# health: "Health"
# speed: "Speed"
# regeneration: "Regeneration"
# range: "Range" # As in "attack or visual range"
hero_type: "Typ"
weapons: "Waffene"
weapons_warrior: "Schwärter - churzi Richwiti, kei Magie"
weapons_ranger: "Armbrüscht, Knarre - grossi Richwiti, kei Magie"
weapons_wizard: "Zauberstäb - grossi Richwiti, Magie"
attack: "Schadä" # Can also translate as "Attack"
health: "Läbä"
speed: "Schnelligkeit"
regeneration: "Regeneration"
range: "Richwiti" # As in "attack or visual range"
# blocks: "Blocks" # As in "this shield blocks this much damage"
# backstab: "Backstab" # As in "this dagger does this much backstab damage"
# skills: "Skills"
skills: "Fähigkeite"
# attack_1: "Deals"
# attack_2: "of listed"
# attack_3: "weapon damage."
attack_3: "Waffeschade."
# health_1: "Gains"
# health_2: "of listed"
# 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)
# 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
# read_only: "read-only"
# action_name: "name"
action_name: "name"
# action_cooldown: "Takes"
# action_specific_cooldown: "Cooldown"
# action_damage: "Damage"
# action_range: "Range"
# action_radius: "Radius"
action_specific_cooldown: "Abklingziit"
action_damage: "Schade"
action_range: "Richwiti"
action_radius: "Radius"
# action_duration: "Duration"
# example: "Example"
# ex: "ex" # Abbreviation of "example"
@ -519,16 +519,16 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# returns: "Returns"
# granted_by: "Granted by"
# save_load:
# granularity_saved_games: "Saved"
# granularity_change_history: "History"
save_load:
granularity_saved_games: "Gschpeicheret"
granularity_change_history: "Verlauf"
options:
# general_options: "General Options" # Check out the Options tab in the Game Menu while playing a level
# volume_label: "Volume"
# music_label: "Music"
volume_label: "Luutstärchi"
music_label: "Musig"
# music_description: "Turn background music on/off."
# autorun_label: "Autorun"
autorun_label: "Autorun"
# autorun_description: "Control automatic code execution."
# editor_config: "Editor Config"
editor_config_title: "Editor Konfiguration"
@ -568,21 +568,21 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# scott_blurb: "Reasonable One"
# nick_title: "Cofounder"
# nick_blurb: "Motivation Guru"
# michael_title: "Programmer"
# michael_blurb: "Sys Admin"
# matt_title: "Programmer"
michael_title: "Programmierer"
michael_blurb: "System Admin"
matt_title: "Programmierer"
# matt_blurb: "Bicyclist"
# cat_title: "Chief Artisan"
# cat_blurb: "Airbender"
# josh_title: "Game Designer"
# josh_blurb: "Floor Is Lava"
# jose_title: "Music"
cat_blurb: "Luftbändiger"
josh_title: "Game Designer"
josh_blurb: "De Bode isch Lava"
jose_title: "Musig"
# jose_blurb: "Taking Off"
# retrostyle_title: "Illustration"
# retrostyle_blurb: "RetroStyle Games"
# teachers:
# title: "CodeCombat: Info for Teachers"
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_2: "No experience required!"
# free_title: "How much does it cost?"
@ -618,11 +618,11 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
versions:
save_version_title: "Neui Version speichere"
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_url: "CLA"
# cla_suffix: "."
# cla_agree: "I AGREE"
cla_url: "CLA"
cla_suffix: "."
cla_agree: "Ich bi iverstandee"
contact:
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_page: "üsem Forum"
forum_suffix: "."
# faq_prefix: "There's also a"
# faq: "FAQ"
faq_prefix: "Es gid au es"
faq: "FAQ"
# subscribe_prefix: "If you need help figuring out a level, please"
# subscribe: "buy a CodeCombat subscription"
# 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"
me_tab: "Ich"
picture_tab: "Bild"
# delete_account_tab: "Delete Your Account"
# wrong_email: "Wrong Email"
delete_account_tab: "Din Account lösche"
wrong_email: "Falschi Email Adrässe"
upload_picture: "Es Bild ufelade"
# delete_this_account: "Delete this account permanently"
# god_mode: "God Mode"
delete_this_account: "Dä Account für immer Lösche"
god_mode: "Gott Modus"
password_tab: "Passwort"
emails_tab: "E-Mails"
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_any_notes: "Alli Notifikatione"
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_description: "If you play really well, we may contact you about getting you a (better) job."
# 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_explanation: "Hi! Fill this out, and we will get in touch about finding you a software developer job."
# sample_profile: "See a sample profile"
# view_profile: "View Your Profile"
view_profile: "Dis Profil aluege"
keyboard_shortcuts:
keyboard_shortcuts: "Shortcuts uf de Tastatur"
space: "Space"
enter: "Enter"
escape: "Escape"
# shift: "Shift"
# run_code: "Run current code."
# run_real_time: "Run in real time."
shift: "Shift"
run_code: "De jetzig Code laufe laa."
run_real_time: "In Echtziit laufe laa."
continue_script: "Nochem aktuelle Script fortsetze."
skip_scripts: "Alli überspringbare Scripts überspringe."
toggle_playback: "Play/Pause istelle."
@ -703,7 +703,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
toggle_grid: "Gitter ischalte/usschalte."
toggle_pathfinding: "Wegfinder ischalte/usschalte."
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:
main_title: "CodeCombat Community"
@ -1289,7 +1289,7 @@ module.exports = nativeDescription: "Deutsch (Schweiz)", englishDescription: "Ge
# player_code: "Player Code"
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."
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"

View file

@ -588,7 +588,7 @@
intro_2: "No experience required!"
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."
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."
teacher_subs_title: "Teachers get free subscriptions!"
teacher_subs_1: "Please contact"

View file

@ -15,12 +15,12 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
nav:
play: "Levels" # The top nav bar entry where players choose which levels to play
community: "Community"
community: "Komunitas"
editor: "Editor"
blog: "Blog"
forum: "Forum"
account: "Akun"
profile: "Profile"
profile: "Profil"
stats: "Mulai"
code: "Code"
admin: "Admin" # Only shows up when you are an admin
@ -33,7 +33,7 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# teachers: "Teachers"
modal:
close: "Close"
close: "Tutup"
okay: "Okay"
not_found:
@ -42,8 +42,8 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
diplomat_suggestion:
# 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."
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."
missing_translations: "Until we can translate everything into Indonesian, you'll see English when Indonesian isn't available."
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: "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"
# subscribe_as_diplomat: "Subscribe as a Diplomat"
@ -58,12 +58,12 @@ module.exports = nativeDescription: "Bahasa Indonesia", englishDescription: "Ind
# owned: "Owned" # For items you own
locked: "Terkunci"
# purchasable: "Purchasable" # For a hero you unlocked but haven't purchased
available: "Trsedia"
available: "Tersedia"
# skills_granted: "Skills Granted" # Property documentation details
heroes: "Heroes" # Tooltip on hero shop button from /play
# achievements: "Achievements" # Tooltip on achievement list 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
# 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

View file

@ -358,7 +358,7 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
leaderboard:
leaderboard: "リーダーボード"
view_other_solutions: "他のソリューションを見る" # {change}
view_other_solutions: "リーダーボードを見る"
scores: "スコア"
top_players: "上位プレイヤー順"
day: "今日"
@ -836,8 +836,8 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
contribute:
page_title: "コントリビュート"
intro_blurb: "CodeCombat は100%オープンソースです!何百もの熱心なプレイヤーが私たちがゲームを作るのを手伝っています。私たちと一緒に CodeCombat の次のチャプターを作って世界中のプレイヤーにプログラミングを教えましょう!"
# alert_account_message_intro: "Hey there!"
# alert_account_message: "To subscribe for class emails, you'll need to be logged in first."
alert_account_message_intro: "やあ、こんにちは!"
alert_account_message: "クラスのメールを購読するには,まずログインが必要です。"
archmage_introduction: "ゲームを作る上で一番重要なのは、たくさんの要素を合成することです。グラフィック、サウンド、リアルタイムネットワーキング、ソーシャルネットワーキング、一般的なプログラミング、ローレベルのデータベースマネジメント、管理画面のデザインやインターフェイスなど多岐に渡ります。やらなくてはいけないことはたくさんあります。もしあなたが経験豊富なプログラマであればアーキメイジになって CodeCombat のコアにコミットしましょう。ぜひとも私たちの最高のプログラミングゲームを手伝ってください。"
class_attributes: "クラスの属性"
archmage_attribute_1_pref: ""
@ -851,17 +851,17 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
join_url_email: "メール"
join_url_hipchat: "公開の HipChat のルーム"
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_suf: ", then this class might be for you."
# 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_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_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_join_desc: "Use the Level Editor in these steps, give or take:"
# artisan_join_step1: "Read the documentation."
# artisan_join_step2: "Create a new level and explore existing levels."
# artisan_join_step3: "Find us in our public HipChat room for help."
# artisan_join_step4: "Post your levels on the forum for feedback."
# artisan_subscribe_desc: "Get emails on level editor updates and announcements."
artisan_introduction_pref: "私たちは、追加のレベルを建設しなければなりません皆さんはもっとコンテンツを、と叫んでいますが、私達がつくれるのは自分たちの分だけです。今、あなたのワークステーションはレベルです。私達のレベルエディタをつかえばそんなクリエイターでもギリギリ使えます、そう警戒しないで。あなたがfor-loopにまたがるキャンペーンのビジョンを"
artisan_introduction_suf: "にもっているなら、このクラスはあなたのためになるかもしれません。"
artisan_attribute_1: "Blizzardのレベルエディタなどの構築経験は歓迎しますが、必須ではありません!"
artisan_attribute_2: "全体のテストを何度もすることを願ってます。 よいレベルを作るには 他の人のを真似て見てプレイしてみることが必要です。そしてそこから修正のための多くのものを見つけて準備しましょう。"
artisan_attribute_3: "時間がかかることで, 冒険者と並ぶくらい我慢しなければなりません。 私達のレベルエディターは予備動作が長く使っているとイライラするかもしれません。気をつけてくださいね!"
artisan_join_desc: "レベルエディタを使うために以下のステップを利用してください。"
artisan_join_step1: "ドキュメントを読む"
artisan_join_step2: "新しいレベルを作成し、すでにあるレベルか探す"
artisan_join_step3: "ヘルプが必要なとき公開HipChatルームで私達を探す"
artisan_join_step4: "フィードバックのためフォーラムにあなたのレベルを投稿する"
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_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."
@ -912,17 +912,17 @@ module.exports = nativeDescription: "日本語", englishDescription: "Japanese",
# games_simulated_for: "Games simulated for you:"
# games_simulated: "Games simulated"
# games_played: "Games played"
# ratio: "Ratio"
# leaderboard: "Leaderboard"
ratio: "比率 "
leaderboard: "リーダーボード"
# battle_as: "Battle as "
summary_your: "あなたの "
summary_matches: "戦闘数 - "
summary_wins: " 勝利数, "
summary_losses: " 敗北数"
# rank_no_code: "No New Code to Rank"
rank_no_code: "新しいコードがランクにありません"
# rank_my_game: "Rank My Game!"
# rank_submitting: "Submitting..."
# rank_submitted: "Submitted for Ranking"
rank_submitting: "送信中..."
rank_submitted: "ランキングに送信されました。"
# rank_failed: "Failed to Rank"
# rank_being_ranked: "Game Being Ranked"
# rank_last_submitted: "submitted "

View file

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

View file

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

View file

@ -36,14 +36,12 @@ block content
each value in point.values
div #{value}
div *Stripe APIs do not return information about inactive subs.
h2 Recent Subscribers
if !subscribers || subscribers.length < 1
h4 Fetching recent subscribers...
else
table.table.table-striped.table-condensed
thead
thead.subscribers-thead
tr
th Sub ID
th User Start
@ -52,19 +50,22 @@ block content
th Cancelled
else
th
th
//- th Name
if subscriberSponsored
th Sponsored
else
th
th Email
th Hero
th Level
th Last Level
th Age
th Spoken
th Clans
tbody.subscribers-tbody
each subscriber in subscribers
tr
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.start.substring(0, 10)
td
@ -72,15 +73,17 @@ block content
span= subscriber.cancel.substring(0, 10)
td
if subscriber.user.stripe.sponsorID
span Sponsored
//- td
//- a(href="/user/#{subscriber.user._id}")= subscriber.user.name || 'Anoner'
span Yes
td= subscriber.user.emailLower
td= subscriber.hero
td= subscriber.level
td= subscriber.user.lastLevel
td= subscriber.user.ageRange
td= subscriber.user.preferredLanguage
if subscriber.user.clans
td= subscriber.user.clans.length
else
td
h2 Subscriptions
if !subs || subs.length < 1
@ -93,8 +96,9 @@ block content
th Total
th Started
th Cancelled
th Net
th Net (cancelled)
th Ended
th Net (ended)
tbody
each sub in subs
tr
@ -104,3 +108,4 @@ block content
td= sub.cancelled
td= sub.started - sub.cancelled
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'
if memberLevelProgression && memberLevelProgression[member.id]
each levelInfo in memberLevelProgression[member.id]
td.level-progression-cell
td.level-progression-cell(data-level-info=levelInfo)
.level-popup-container
div Level: #{levelInfo.level}
div Playtime: #{levelInfo.playtime}
div Last played: #{levelInfo.changed}
h3 #{levelInfo.level}
p
div Playtime: #{levelInfo.playtime}s
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
else
td(colspan="#{memberMaxLevelCount + 1}")

View file

@ -12,7 +12,7 @@ block content
a(href="/editor/level")
img(src="/images/pages/community/level.png")
h2
a.spl(href="/editor/level", data-i18n="editor.level_title")
a(href="/editor/level", data-i18n="editor.level_title")
p
span.spr(data-i18n="community.level_editor_prefix") Use the CodeCombat
a(href="/editor/level", data-i18n="editor.level_title")
@ -22,7 +22,7 @@ block content
a(href="/editor/thang")
img(src="/images/pages/community/thang.png")
h2
a.spl(href="/editor/thang", data-i18n="editor.thang_title")
a(href="/editor/thang", data-i18n="editor.thang_title")
p
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")
@ -32,7 +32,7 @@ block content
a(href="/editor/article")
img(src="/images/pages/community/article.png")
h2
a.spl(href="/editor/article", data-i18n="editor.article_title")
a(href="/editor/article", data-i18n="editor.article_title")
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
a(href="/editor/article", data-i18n="editor.article_title")

View file

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

View file

@ -14,7 +14,8 @@ block content
th Translated Name
th Type
th Specifically Covered
th Generally Covered
if showGeneralCoverage
th Generally Covered
if selectedLanguage
for model in collection.models
@ -29,4 +30,5 @@ block content
td= translatedName
td= model.constructor.className
td(class=model.specificallyCovered ? 'success' : 'danger')= model.specificallyCovered ? 'Yes' : 'No'
td(class=model.generallyCovered ? 'success' : 'danger')= model.generallyCovered ? 'Yes' : 'No'
if showGeneralCoverage
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
id: 'admin-analytics-subscriptions-view'
template: template
targetSubCount: 2000
targetSubCount: 1200
constructor: (options) ->
super options
@ -25,6 +25,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
context.subs = _.cloneDeep(@subs ? []).reverse()
context.subscribers = @subscribers ? []
context.subscriberCancelled = _.find context.subscribers, (subscriber) -> subscriber.cancel
context.subscriberSponsored = _.find context.subscribers, (subscriber) -> subscriber.user?.stripe?.sponsorID
context.total = @total ? 0
context.cancelled = @cancelled ? 0
context.monthlyChurn = @monthlyChurn ? 0.0
@ -46,9 +47,9 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
refreshData: ->
return unless me.isAdmin()
@resetSubscriptionsData()
@getSubscribers()
@getCancellations (cancellations) =>
@getSubscriptions(cancellations)
@getSubscriptions cancellations, (subscriptions) =>
@getSubscribers(subscriptions)
getCancellations: (done) ->
options =
@ -62,25 +63,34 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
done(cancellations)
@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 =
url: '/db/subscription/-/subscribers'
method: 'POST'
data: {maxCount: 30}
data: {ids: subscriberUserIDs}
options.error = (model, response, options) =>
return if @destroyed
console.error 'Failed to get subscribers', response
options.success = (subscribers, response, options) =>
options.success = (userMap, response, options) =>
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
if hero = subscriber.user.heroConfig?.thangType
subscriber.hero = _.invert(ThangType.heroes)[hero]
@subscribers = subscribers
@render?()
@supermodel.addRequestResource('get_subscribers', options, 0).load()
getSubscriptions: (cancellations=[]) ->
getSubscriptions: (cancellations=[], done) ->
options =
url: '/db/subscription/-/subscriptions'
method: 'GET'
@ -102,6 +112,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
subDayMap[endDay]['end']++
for cancellation in cancellations
if cancellation.subID is sub.subID
sub.cancel = cancellation.cancel
cancelDay = cancellation.cancel.substring(0, 10)
subDayMap[cancelDay] ?= {}
subDayMap[cancelDay]['cancel'] ?= 0
@ -132,6 +143,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
@monthlyGrowth = (endMonthTotal / startMonthTotal - 1) * 100
@updateAnalyticsGraphData()
@render?()
done(subs)
@supermodel.addRequestResource('get_subscriptions', options, 0).load()
updateAnalyticsGraphData: ->
@ -170,7 +182,7 @@ module.exports = class AnalyticsSubscriptionsView extends RootView
color: 'red'
strokeWidth: 1
lineMetadata[netSubsID] =
description: '7-day Average Net Subscriptions'
description: '7-day Average Net Subscriptions (started - ended)'
color: 'black'
strokeWidth: 4

View file

@ -23,6 +23,7 @@ module.exports = class ClanDetailsView extends RootView
'click .edit-name-save-btn': 'onEditNameSave'
'click .join-clan-btn': 'onJoinClan'
'click .leave-clan-btn': 'onLeaveClan'
'click .level-progression-cell': 'onClickLevel'
'click .remove-member-btn': 'onRemoveMember'
'mouseenter .level-progression-cell': 'onMouseEnterPoint'
'mouseleave .level-progression-cell': 'onMouseLeavePoint'
@ -131,8 +132,10 @@ module.exports = class ClanDetailsView extends RootView
@memberLevelProgression[user] ?= []
levelInfo =
level: levelSession.get('levelName')
levelID: levelSession.get('levelID')
changed: new Date(levelSession.get('changed')).toLocaleString()
playtime: levelSession.get('playtime')
sessionID: levelSession.id
@memberLevelProgression[user].push levelInfo
@memberMaxLevelCount = 0
@memberLanguageMap = {}
@ -161,6 +164,12 @@ module.exports = class ClanDetailsView extends RootView
onMouseLeavePoint: (e) ->
$(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) ->
return @openModalView(new AuthModal()) if me.isAnonymous()
return unless window.confirm("Delete Clan?")
@ -211,6 +220,7 @@ module.exports = class ClanDetailsView extends RootView
@supermodel.addRequestResource( 'leave_clan', options).load()
onRemoveMember: (e) ->
return unless window.confirm("Remove Hero?")
if memberID = $(e.target).data('id')
options =
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
total = @aggregateModels.models.length
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

View file

@ -126,7 +126,7 @@ ClanHandler = class ClanHandler extends Handler
return @sendNotFoundError(res) unless clan
memberIDs = _.map clan.get('members') ? [], (memberID) -> memberID.toHexString?() or memberID
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?
cleandocs = (LevelSessionHandler.formatEntity(req, doc) for doc in documents)
@sendSuccess(res, cleandocs)

View file

@ -67,7 +67,7 @@ class SubscriptionHandler extends Handler
(done) =>
stripe.customers.retrieveSubscription customerID, subscriptionID, (err, subscription) =>
return done() if err
return unless subscription?.cancel_at_period_end
return done() unless subscription?.cancel_at_period_end
cancellations.push
cancel: new Date(subscription.canceled_at * 1000)
subID: subscription.id
@ -82,74 +82,18 @@ class SubscriptionHandler extends Handler
getSubscribers: (req, res) ->
# console.log 'subscription_handler getSubscribers'
return @sendForbiddenError(res) unless req.user?.isAdmin()
maxReturnCount = req.body.maxCount or 20
# @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) =>
subscriberUserIDs = req.body.ids or []
User.find {_id: {$in: subscriberUserIDs}}, (err, users) =>
return @sendDatabaseError(res, err) if err
User.find {_id: {$in: subscriberIDs}}, (err, users) =>
return @sendDatabaseError(res, err) if err
for user in users
subscriber.user = user for subscriber in @subscribers when subscriber.userID is user.id
@sendSuccess(res, @subscribers)
userMap = {}
userMap[user.id] = user for user in users
@sendSuccess(res, userMap)
getSubscriptions: (req, res) ->
# console.log 'subscription_handler getSubscriptions'
# Returns a list of active subscriptions
# TODO: does not track sponsored subs, only basic
# TODO: does not return free subs
# TODO: add tests
# TODO: aggregate this data daily instead of providing it on demand
# TODO: take date range as input
# 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.total > 0
continue unless invoice.lines?.data?[0]?.plan?.id is 'basic'
newInvoices.push
newInvoice =
customerID: invoice.customer
invoiceID: invoice.id
subscriptionID: invoice.subscription
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
# console.log 'Fetching more invoices', @invoices.length, newInvoices.length
return processInvoices(invoices.data[invoices.data.length - 1].id, done)
@ -193,20 +139,49 @@ class SubscriptionHandler extends Handler
first: invoice.date
last: invoice.date
customerID: invoice.customerID
subs = []
for subID of subMap
sub =
start: subMap[subID].first
subID: subID
customerID: subMap[subID].customerID
sub.cancel = subMap[subID].cancel if subMap[subID].cancel
oneMonthAgo = new Date()
oneMonthAgo.setUTCMonth(oneMonthAgo.getUTCMonth() - 1)
if subMap[subID].last < oneMonthAgo
sub.end = new Date(subMap[subID].last)
sub.end.setUTCMonth(sub.end.getUTCMonth() + 1)
subs.push sub
@sendSuccess(res, subs)
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 = []
for subID of subMap
sub =
start: subMap[subID].first
subID: subID
customerID: subMap[subID].customerID
sub.cancel = subMap[subID].cancel if subMap[subID].cancel
oneMonthAgo = new Date()
oneMonthAgo.setUTCMonth(oneMonthAgo.getUTCMonth() - 1)
if subMap[subID].end?
sub.end = subMap[subID].end
else if subMap[subID].last < oneMonthAgo
sub.end = new Date(subMap[subID].last)
sub.end.setUTCMonth(sub.end.getUTCMonth() + 1)
sub.userID = subMap[subID].userID if subMap[subID].userID
subs.push sub
@sendSuccess(res, subs)
subscribeUser: (req, user, done) ->
if (not req.user) or req.user.isAnonymous() or user.isAnonymous()