diff --git a/Gruntfile.js b/Gruntfile.js index 81eb26c0c3..e2fc2b1083 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -51,17 +51,6 @@ module.exports = function(grunt) { } }, - browserify: { - dist: { - src: ["common/index.js"], - dest: "common/dist/scripts/habitrpg-shared.js" - }, - options: { - transform: ['coffeeify'] - //debug: true Huge data uri source map (400kb!) - } - }, - copy: { build: { files: [ @@ -134,8 +123,8 @@ module.exports = function(grunt) { }); // Register tasks. - grunt.registerTask('build:prod', ['loadManifestFiles', 'clean:build', 'browserify', 'uglify', 'stylus', 'cssmin', 'copy:build', 'hashres']); - grunt.registerTask('build:dev', ['browserify', 'cssmin', 'stylus']); + grunt.registerTask('build:prod', ['loadManifestFiles', 'clean:build', 'uglify', 'stylus', 'cssmin', 'copy:build', 'hashres']); + grunt.registerTask('build:dev', ['cssmin', 'stylus']); grunt.registerTask('build:test', ['test:prepare:translations', 'build:dev']); grunt.registerTask('test:prepare:translations', function() { @@ -148,7 +137,6 @@ module.exports = function(grunt) { }); // Load tasks - grunt.loadNpmTasks('grunt-browserify'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-clean'); grunt.loadNpmTasks('grunt-contrib-stylus'); diff --git a/common/index.js b/common/index.js index 6594ecc720..e6a9c9fb98 100644 --- a/common/index.js +++ b/common/index.js @@ -1,4 +1,4 @@ -module.exports = require('./script/index.coffee'); +module.exports = require('./script/index'); var _ = require('lodash'); var moment = require('moment'); diff --git a/common/locales/cs/challenge.json b/common/locales/cs/challenge.json index eee7b5bddb..4fce2a869c 100644 --- a/common/locales/cs/challenge.json +++ b/common/locales/cs/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "Nemáš oprávnění k upravování této výzvy", "noPermissionDeleteChallenge": "Nemáš oprávnění ke smazání této výzvy", "noPermissionCloseChallenge": "Nemáš oprávnění k ukončení této výzvy", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "bez majitele", "noChallengeOwnerPopover": "Tato Výzva nemá majitele, jelikož uživatel, který ji vytvořil, si smazal účet." } \ No newline at end of file diff --git a/common/locales/cs/character.json b/common/locales/cs/character.json index c50344dbcf..01ccd15da7 100644 --- a/common/locales/cs/character.json +++ b/common/locales/cs/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Vylepšil na maximální zbraň a set brnění pro následující povolání:", "level": "Úroveň", "levelUp": "Další úroveň!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "Zdraví", "mp": "MP", diff --git a/common/locales/cs/content.json b/common/locales/cs/content.json index 1ed711a392..4ace7c182d 100644 --- a/common/locales/cs/content.json +++ b/common/locales/cs/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "žabák", "questEggFrogMountText": "žabák", "questEggFrogAdjective": "princ", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Najdi líhnoucí lektvar, nalij ho na vejce a to se vylíhne v <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Základní", "hatchingPotionWhite": "Bílý", diff --git a/common/locales/cs/front.json b/common/locales/cs/front.json index c0b066f175..ad17f4fb2d 100644 --- a/common/locales/cs/front.json +++ b/common/locales/cs/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Program Habitica] mi opravdu pomohla dát mému životu nějakou strukturu.", "invalidEmail": "Aby mohlo proběhnout resetování hesla, musí být zadán platný email.", "irishfeet123Quote": "Měla jsem problém s úklidem. Nechávala jsem všude nádobí a skleničky. [Program Habitica] mi pomohla!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Před tím, než jsem objevila [program Habitica] jsem se zasekla s diplomkou a byla jsem nespokojena se svou disciplínou ohledně domácích prací a věcí, jako učením se slovíček. Ukázalo se, že když si tyhle cíle rozdělím na menší, je mnohem snazší se motivovat a neustále pracovat.", "landingadminlink": "administrační balíčky", "landingend": "Stále nejsi přesvědčen?", @@ -182,5 +182,11 @@ "tweet": "Tweet", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/cs/generic.json b/common/locales/cs/generic.json index 058209f640..b2ff371d09 100644 --- a/common/locales/cs/generic.json +++ b/common/locales/cs/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Posílám Ti tisíce díků.", "thankyou3": "Jsem velmi vděčný - děkuji!", "thankyouCardAchievementTitle": "Velmi vděčný", - "thankyouCardAchievementText": "Díky za vděčnost! Poslal nebo odeslal <%= cards %> děkovných přání." + "thankyouCardAchievementText": "Díky za vděčnost! Poslal nebo odeslal <%= cards %> děkovných přání.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/cs/pets.json b/common/locales/cs/pets.json index 663b07257e..f70032750e 100644 --- a/common/locales/cs/pets.json +++ b/common/locales/cs/pets.json @@ -58,8 +58,16 @@ "firstDrop": "Odemknuto nalézání předmětů! Od teď máš malou šanci nalézt předmět při dokončení úkolů, včetně vajec, lektvarů a jídla! Právě nalezeno vejce zvířátka <%= eggText %>! <%= eggNotes %>", "useGems": "Pokud ti padlo oko na zvířátko a nemůžeš se dočkat až ti padne, použij Drahokamy v Inventář > Trh a kup si ho!", "hatchAPot": "<%= potion %> <%= egg %>, jsi si jistý?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Myslíš, že <%= name %> si pochutná na něčem takovém jako je <%= article %><%= text %> ?", "useSaddle": "Koho osedláme? Bude to <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Klíč ke kotcům", diff --git a/common/locales/cs/quests.json b/common/locales/cs/quests.json index 29eec4caf2..1b82fa4068 100644 --- a/common/locales/cs/quests.json +++ b/common/locales/cs/quests.json @@ -76,5 +76,7 @@ "startAQuest": "VYDEJ SE NA VÝPRAVU", "startQuest": "Začít Výpravu", "whichQuestStart": "Na kterou výpravu se chceš vydat?", - "getMoreQuests": "Získej více výprav" + "getMoreQuests": "Získej více výprav", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/cs/questscontent.json b/common/locales/cs/questscontent.json index 284c2d1b1a..d9c3126204 100644 --- a/common/locales/cs/questscontent.json +++ b/common/locales/cs/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "Poražený žabák se vrátí zpět do bažiny. Spolu s ním se z cesty stáhne i modrý sliz a cesta vpřed je volná.

Uprostřed cesty sedí tři dokonale čistá vejce. \"Jé, dokonce jsou v něm vidět pulci!\" říká @Breadstrings. \"Na, vezmi si je.\"", "questFrogBoss": "Nepořádný žabák", "questFrogDropFrogEgg": "Žabák (vejce)", - "questFrogUnlockText": "Odemyká vejce žabáka na Trhu" + "questFrogUnlockText": "Odemyká vejce žabáka na Trhu", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/cs/settings.json b/common/locales/cs/settings.json index 4daa9d2f2b..ac8a11e98b 100644 --- a/common/locales/cs/settings.json +++ b/common/locales/cs/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Pokud je tato volba nastavena, seznam štítků bude skryt, když poprvé otevřeš úkol pro úpravu.", "startAdvCollapsed": "Pokročilé možnosti se v úkolu zobrazí zabalené.", "startAdvCollapsedPop": "Pokud je tato volba nastavena, pokročilé možnosti budou skryté, když poprvé otevřeš úkol pro úpravu.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Zobrazit průvodce", "restartTour": "Restartovat instruktážního průvodce od bodu, kdy jsi se do země Habitica vydal.", "showBailey": "Zobraz Baileyho", @@ -81,7 +86,6 @@ "emailChange1": "Ke změně emailu, prosím, pošli email na", "emailChange2": "admin@habitica.com", "emailChange3": "spolu s tvým starým a novým emailem a tvým uživatelským ID.", - "username": "Přihlašovací jméno", "usernameOrEmail": "Přihlašovací jméno nebo email", "email": "Email", "registeredWithFb": "Registrovaný přes Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "Uživatel -> Profil", "loginNameDescription3": "aby sis změnil jméno, které se objevuje u tvého avataru a zpráv v chatu.", "emailNotifications": "Emailová upozornění", - "wonChallenge": "Vyhrál jsi Výzvu", + "wonChallenge": "You won a Challenge!", "newPM": "Obdržena soukromá zpráva", "giftedGems": "Darované drahokamy", "giftedGemsInfo": "<%= amount %> Drahokamů - od <%= name %>", diff --git a/common/locales/da/challenge.json b/common/locales/da/challenge.json index 6714369c16..144a039d99 100644 --- a/common/locales/da/challenge.json +++ b/common/locales/da/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "Du har ikke rettigheder til at ændre denne udfordring", "noPermissionDeleteChallenge": "Du har ikke rettigheder til at slette denne udfordring", "noPermissionCloseChallenge": "Du har ikke rettigheder til at afslutte denne udfordring", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "no owner", "noChallengeOwnerPopover": "This challenge does not have an owner because the person who created the challenge deleted their account." } \ No newline at end of file diff --git a/common/locales/da/character.json b/common/locales/da/character.json index 65e4e28531..ac38ebfc3e 100644 --- a/common/locales/da/character.json +++ b/common/locales/da/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Har opgraderet til det maksimale våben- og rustningssæt for de følgende klasser:", "level": "Niveau", "levelUp": "Niveau op!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "HP", "mp": "MP", diff --git a/common/locales/da/content.json b/common/locales/da/content.json index 3da18e13ac..ac0de91c5c 100644 --- a/common/locales/da/content.json +++ b/common/locales/da/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Frog", "questEggFrogMountText": "Frog", "questEggFrogAdjective": "a princely", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Find en udrugningseliksir til at hælde på dit æg, og det vil udklække <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Almindelig", "hatchingPotionWhite": "Hvid", diff --git a/common/locales/da/front.json b/common/locales/da/front.json index 139222518f..be59bc0e86 100644 --- a/common/locales/da/front.json +++ b/common/locales/da/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] har virkelig hjulpet mig med at indføre struktur i min studietid på universitetet.", "invalidEmail": "Det kræver en valid emailadresse for at få nulstillet dit kodeord.", "irishfeet123Quote": "Jeg havde en forfærdelig vane med ikke at rydde ud efter jeg havde spist. Jeg efterlod tallerkener og glas alle vegne. Den dårlige vane har [Habitica] hjulpet mig med af med!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Inden jeg opdagede [Habitica] var jeg gået i stå i min afhandling. Jeg var også utilfreds med min manglende disciplin omkring huslige pligter og ting som at udvide mit ordforråd eller dykke ned i skak-teori. Det viste sig, at det holder mig motiveret at bryde disse opgaver ned i mindre Tjeklister, der er mere overskuelige.", "landingadminlink": "administrative pakker", "landingend": "Ikke overbevist endnu?", @@ -182,5 +182,11 @@ "tweet": "Tweet", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/da/generic.json b/common/locales/da/generic.json index 61f74931b1..a0f43e18f1 100644 --- a/common/locales/da/generic.json +++ b/common/locales/da/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Tusind tak!", "thankyou3": "Jeg er virkelig taknemmelig - tak!", "thankyouCardAchievementTitle": "Temmelig Taknemmelig", - "thankyouCardAchievementText": "Tak for at være taknemmelig! Har sendt eller modtaget <%= cards %> Takkekort." + "thankyouCardAchievementText": "Tak for at være taknemmelig! Har sendt eller modtaget <%= cards %> Takkekort.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/da/pets.json b/common/locales/da/pets.json index 99b3937e1b..78bd44534d 100644 --- a/common/locales/da/pets.json +++ b/common/locales/da/pets.json @@ -58,8 +58,16 @@ "firstDrop": "Du har nu adgang til dropsystemet! Når du nu fuldender opgaver, har du en lille chance for at finde en ting, bl.a. æg, eliksirer og mad. Du har lige fundet et <%= eggText %>-æg! <%= eggNotes %>", "useGems": "Hvis du gerne vil have et bestemt kæledyr, men ikke vil vente på at du finder det, så brug ædelsten i Inventar > Marked til at købe det!", "hatchAPot": "Vil du udruge et <%= potion %> <%= egg %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Giv <%= text %> til <%= name %>?", "useSaddle": "Giv <%= pet %> sadel på?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Nøglen til Kennelen", diff --git a/common/locales/da/quests.json b/common/locales/da/quests.json index 8ef7cab218..5557b5c2d0 100644 --- a/common/locales/da/quests.json +++ b/common/locales/da/quests.json @@ -76,5 +76,7 @@ "startAQuest": "START EN QUEST", "startQuest": "Start Quest", "whichQuestStart": "Hvilken quest vil du starte?", - "getMoreQuests": "Få flere quests" + "getMoreQuests": "Få flere quests", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/da/questscontent.json b/common/locales/da/questscontent.json index 00f016a18f..1bcc27f969 100644 --- a/common/locales/da/questscontent.json +++ b/common/locales/da/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/da/settings.json b/common/locales/da/settings.json index 7c360c3b5c..8ac210d534 100644 --- a/common/locales/da/settings.json +++ b/common/locales/da/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Hvis valgt vil listen af opgavetags være skjult når du åbner en opgave for at rette den.", "startAdvCollapsed": "Avancerede Indstillinger i opgaver starter lukket", "startAdvCollapsedPop": "Hvis valgt vil Avancerede Indstillinger være skjult når du åbner en opgave for at rette den.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Vis Rundvisning", "restartTour": "Genstart rundvisningen fra da du blev medlem af Habitica.", "showBailey": "Vis Bailey", @@ -81,7 +86,6 @@ "emailChange1": "For at ændre din email-adresse bedes du sende en email til", "emailChange2": "admin@habitica.com", "emailChange3": "hvor du inkluderer både din gamle og nye email-adresse, samt tid BrugerID", - "username": "Loginnavn", "usernameOrEmail": "Loginnavn eller Email", "email": "Email", "registeredWithFb": "Registreret via Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "Bruger->Profil", "loginNameDescription3": "for at ændre det navn, der vises på din avatar og i dine chatbeskeder.", "emailNotifications": "Mail-notifikationer", - "wonChallenge": "Du vandt en Udfordring", + "wonChallenge": "You won a Challenge!", "newPM": "Modtaget Privatbesked", "giftedGems": "Ædelstensgave", "giftedGemsInfo": "<%= amount %> Ædelsten - af <%= name %>", diff --git a/common/locales/de/backgrounds.json b/common/locales/de/backgrounds.json index f6336b7598..357eeb8b3f 100644 --- a/common/locales/de/backgrounds.json +++ b/common/locales/de/backgrounds.json @@ -116,14 +116,14 @@ "backgroundHarvestMoonText": "Erntemond", "backgroundHarvestMoonNotes": "Kichern unter der Harvest Moon.", "backgroundSlimySwampText": "Schleimiger Sumpf", - "backgroundSlimySwampNotes": "Prügle dich durch einen Schleimigen Sumpf. ", + "backgroundSlimySwampNotes": "Wate durch einen Schleimigen Sumpf. ", "backgroundSwarmingDarknessText": "Wimmelnde Dunkelheit", "backgroundSwarmingDarknessNotes": "Zittre in der Wimmelnden Dunkelheit.", - "backgrounds112015": "SET 18: Released November 2015", - "backgroundFloatingIslandsText": "Floating Islands", - "backgroundFloatingIslandsNotes": "Hop across the Floating Islands.", - "backgroundNightDunesText": "Night Dunes", - "backgroundNightDunesNotes": "Walk peacefully through the Night Dunes.", - "backgroundSunsetOasisText": "Sunset Oasis", - "backgroundSunsetOasisNotes": "Bask in the Sunset Oasis." + "backgrounds112015": "Set 18: Veröffentlicht im November 2015", + "backgroundFloatingIslandsText": "Schwebende Inseln", + "backgroundFloatingIslandsNotes": "Hüpfe über die Schwebenden Inseln.", + "backgroundNightDunesText": "Nachtdünen", + "backgroundNightDunesNotes": "Spaziere friedlich durch die Nachtdünen.", + "backgroundSunsetOasisText": "Oase im Abendrot", + "backgroundSunsetOasisNotes": "Sonne in der Oase im Abendrot." } \ No newline at end of file diff --git a/common/locales/de/challenge.json b/common/locales/de/challenge.json index 62ead3b921..1d1478d29f 100644 --- a/common/locales/de/challenge.json +++ b/common/locales/de/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "Du hast keine Berechtigung, um diesen Wettbewerb zu ändern.", "noPermissionDeleteChallenge": "Du hast keine Berechtigung, um diesen Wettbewerb zu löschen.", "noPermissionCloseChallenge": "Du hast keine Berechtigung, um diesen Wettbewerb zu schließen.", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "Kein Besitzer", "noChallengeOwnerPopover": "Dieser Wettbewerb hat keinen Besitzer, da der Spieler, der den Wettbewerb erstellt hat, sein Benutzerkonto gelöscht hat." } \ No newline at end of file diff --git a/common/locales/de/character.json b/common/locales/de/character.json index 7ccb086804..49b0bf97b1 100644 --- a/common/locales/de/character.json +++ b/common/locales/de/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Hat auf die besten Waffen und Rüstung der folgenden Klassen aufgerüstet:", "level": "Level", "levelUp": "Aufgestiegen!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "LP", "mp": "MP", diff --git a/common/locales/de/content.json b/common/locales/de/content.json index 48ab3944e2..83a93c0682 100644 --- a/common/locales/de/content.json +++ b/common/locales/de/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Frosch", "questEggFrogMountText": "Frosch", "questEggFrogAdjective": "ein fürstlicher", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Finde einen Schlüpftrank, den du über dieses Ei gießen kannst, damit ein <%= eggAdjective(locale) %> <%= eggText(locale) %> schlüpfen kann.", "hatchingPotionBase": "Normaler", "hatchingPotionWhite": "Weißer", diff --git a/common/locales/de/faq.json b/common/locales/de/faq.json index 73146f4f46..74932ffc90 100644 --- a/common/locales/de/faq.json +++ b/common/locales/de/faq.json @@ -30,7 +30,7 @@ "faqQuestion9": "Wie bekämpfe ich Monster und gehe auf Quests?", "iosFaqAnswer9": "First, you need to join or start a Party (see above). Although you can battle monsters alone, we recommend playing in a group, because this will make Quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n\n Next, you need a Quest Scroll, which are stored under Menu > Items. There are three ways to get a scroll:\n\n - At level 15, you get a Quest-line, aka three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively. \n - When you invite people to your Party, you'll be rewarded with the Basi-List Scroll!\n - You can buy Quests from the Quests Page on the [website](https://habitica.com/#/options/inventory/quests) for Gold and Gems. (We will add this feature to the app in a future update.)\n\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading by pulling down on the screen may be required to see the Boss's health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your Party at the same time that you damage the Boss. \n\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", "webFaqAnswer9": "Zuerst musst du eine Gruppe gründen oder einer Gruppe beitreten (unter Soziales > Gruppe). Obwohl du Monster auch alleine bekämpfen kannst, empfehlen wir in einer Gruppe mit anderen Mitspielern zu spielen, da dies die Quests viel einfacher macht. Zusätzlich ist es sehr motivierend einen Freund zu haben, der einen anspornt seine Aufgaben zu erledigen.\n

\nAls nächstes benötigst du eine Questrolle, welche unter Inventar > Quests gespeichert sind. Es gibt drei Möglichkeiten an Rollen zu kommen:\n

\n* Wenn du Mitspieler zu deiner Gruppe einlädst, erhälst du die Basi-List-Rolle.\n* Bei Erreichen von Level 15 erhälst du eine Questreihe, d.h. drei zusammenhängende Quests. Weitere Questreihen werden bei den Leveln 30, 40 und 60 freigeschaltet.\n* Du kanst Quests auf der Quest-Seite (Inventar > Quests) für Gold und Edelsteine kaufen.\n

\nUm den Boss zu bekämpfen oder Gegenstände bei einer Sammelquest zu sammeln, musst du einfach deine Aufgaben normal erledigen und sie werden über Nacht in Schaden umgerechnet. (Möglicherweise ist es erforderlich die Seite neu zu laden, um den Effekt auf den Lebensbalken des Bosses zu sehen.) Wenn du einen Boss bekämpfst und tägliche Aufgaben nicht erledigst, wird der Boss eurer Gruppe zur gleichen Zeit Schaden zufügen wie ihr dem Boss.\n

\nAb Level 11 erhalten Magier und Krieger Fäghigkeiten, welche dem Boss zusätzlichen Schaden zufügen, also sind dies ausgezeichnete Klassen, welche du ab Level 10 wählen sollte, wenn du viel Bossen viel Schaden zufügen möchtest.", - "faqQuestion10": "What are Gems, and how do I get them?", + "faqQuestion10": "Was sind Edelsteine und wie erhalte ich welche?", "iosFaqAnswer10": "Gems are purchased with real money by tapping on the gem icon in the header. When people buy gems, they are helping us to keep the site running. We're very grateful for their support!\n\n In addition to buying gems directly, there are three other ways players can gain gems:\n\n * Win a Challenge on the [website](https://habitica.com) that has been set up by another player under Social > Challenges. (We will be adding Challenges to the app in a future update!)\n * Subscribe on the [website](https://habitica.com/#/options/settings/subscription) and unlock the ability to buy a certain number of gems per month.\n * Contribute your skills to the Habitica project. See this wiki page for more details: [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica).\n\n Keep in mind that items purchased with gems do not offer any statistical advantages, so players can still make use of the app without them!", "webFaqAnswer10": "Edelsteine werden [mit realem Geld gekauft](https://habitica.com/#/options/settings/subscription), jedoch können [Abonnenten](https://habitica.com/#/options/settings/subscription) sie mit Gold kaufen. Wenn Menschen abonnieren oder Edelsteine kaufen, helfen sie uns die Seite zu betreiben. Wir sind sehr dankbar für ihre Unterstützung!\n

\nZusätzlich zum Kaufen von Edelsteinen oder Abonnieren gibt es zwei andere Möglichkeiten für einen Spieler an Edelsteine zu kommen.\n

\n* Gewinne einen Wettbewerb eines anderen Spielers unter Soziales > Wettbewerbe.\n* Trage mit deinen Fähigkeiten zum Habitica Projekt bei. Für mehr Details, sieh im Wiki nach: [An Habitica mitarbeiten](http://habitica.wikia.com/wiki/Contributing_to_Habitica)\n

\nBeachte, dass Gegenstände, die mit Edelsteinen gekauft werden keine statistischen Vorteile bringen, sodass Spieler die Seite auch ohne sie benutzen können!", "faqQuestion11": "Wie melde ich einen Fehler oder schlage ein Feature vor?", diff --git a/common/locales/de/front.json b/common/locales/de/front.json index 48d1e44336..2b7161c6cd 100644 --- a/common/locales/de/front.json +++ b/common/locales/de/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] hat mir geholfen Struktur in mein Leben an der Universität zu bringen.", "invalidEmail": "Um das Passwort zurückzusetzen, ist eine gültige Email-Adresse notwendig.", "irishfeet123Quote": "Ich hatte die schrecklichen Angewohnheiten, nach Mahlzeiten nicht aufzuräumen und Tassen in der ganzen Wohnung stehen zu lassen. [Habitica] hat mich davon geheilt!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Vor [Habitica] kam ich mit meiner Dissertation nicht weiter und war unzufrieden mit meiner Selbstdisziplin bei Hausarbeiten, Vokabellernen und dem Studium der Go-Theorie. Es hat sich herausgestellt, dass das Aufteilen der Aufgaben in kleinere, machbare Checklisten etwas ist, das mich motiviert und zum konstanten Arbeiten anregt.", "landingadminlink": "Verwaltungspakete", "landingend": "Noch nicht überzeugt?", @@ -181,6 +181,12 @@ "marketingInquiries": "Marketing-/Soziale Netzwerke Anfragen", "tweet": "Tweet", "apps": "Apps", - "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "notifyAndroidApp": "Möchtest du, dass wir dir mitteilen, wenn die Android app fertig ist? Trage dich in unsere E-Mail-Liste ein!", + "checkOutIOSApp": "Schau dir unsere neue iOS App an!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/de/gear.json b/common/locales/de/gear.json index 25fd2c332d..1fb4c63916 100644 --- a/common/locales/de/gear.json +++ b/common/locales/de/gear.json @@ -129,7 +129,7 @@ "weaponSpecialFall2015RogueText": "Bat-tle Ax", "weaponSpecialFall2015RogueNotes": "Furchterregende tägliche Aufgaben ducken sich unter den Schlägen dieser Axt. Erhöht Stärke um <&=str %>. Limited Edition 2015 Herbst-Ausrüstung. ", "weaponSpecialFall2015WarriorText": "Holzplanke", - "weaponSpecialFall2015WarriorNotes": "Great for elevating things in cornfields and/or smacking tasks. Increases Strength by <%= str %>. Limited Edition 2015 Autumn Gear.", + "weaponSpecialFall2015WarriorNotes": "Super um Dinge in Kornfeldern hochzuheben und/oder Aufgaben zu verprügeln. Erhöht die Stärke um <%=str%>. Begrenzte Auflage 2015 Herbst Ausrüstung", "weaponSpecialFall2015MageText": "Verzauberter Faden", "weaponSpecialFall2015MageNotes": "A powerful Stitch Witch can control this enchanted thread without even touching it! Increases Intelligence by <%= int %> and Perception by <%= per %>. Limited Edition 2015 Autumn Gear.", "weaponSpecialFall2015HealerText": "Sumpfschleimtrank", @@ -156,8 +156,8 @@ "weaponArmoireGoldWingStaffNotes": "Die Flügel dieses Stabes flattern und drehen sich ständig. Erhöht alle Attribute um <%= attrs %>. Verzauberter Schrank: Unabhängiger Gegenstand.", "weaponArmoireBatWandText": "Fledermaus Zauberstab", "weaponArmoireBatWandNotes": "Dieser Zauberstab kann jede Aufgabe in eine Fledermaus verwandeln. Schwinge ihn und schau zu wie sie davon fliegen. Erhöht Intelligenz um <%= int %> und Wahrnehmung um <%= per %>. Verzauberter Schrank: Unabhängiger Gegenstand. ", - "weaponArmoireShepherdsCrookText": "Shepherd's Crook", - "weaponArmoireShepherdsCrookNotes": "Useful for herding gryphons. Increases Constitution by <%= con %>. Enchanted Armoire: Shepherd Set (Item 1 of 3).", + "weaponArmoireShepherdsCrookText": "Hirtenstab", + "weaponArmoireShepherdsCrookNotes": "Nützlich um Greife zu hüten. Erhöht Ausdauer um <%= con %>. Verzauberte Rüstung: Hirten-Set (Gegenstand 1 von 3)", "armor": "Rüstung", "armorBase0Text": "Schlichte Kleidung", "armorBase0Notes": "Gewöhnliches Kleidungsstück. Gewährt keinen Bonus zu Attributen.", @@ -271,12 +271,12 @@ "armorSpecialSummer2015MageNotes": "Versteckte Macht liegt in diesen Puffärmeln. Erhöht Intelligenz um <%= int %>. Limited Edition 2015 Sommer-Ausrüstung.", "armorSpecialSummer2015HealerText": "Matrosenrüstung", "armorSpecialSummer2015HealerNotes": "Mit dieser Rüstung weiß jeder, dass du ein ehrlicher Handelsseemann bist, der niemals davon träumen würde sich wie ein Taugenichts zu benehmen. Erhöht Ausdauer um <%= con %>. Limited Edition 2015 Sommer-Ausrüstung.", - "armorSpecialFall2015RogueText": "Bat-tle Armor", + "armorSpecialFall2015RogueText": "Kampfrüstung", "armorSpecialFall2015RogueNotes": "Fly into bat-tle! Increases Perception by <%= per %>. Limited Edition 2015 Autumn Gear.", "armorSpecialFall2015WarriorText": "Vogelscheuchenrüstung", "armorSpecialFall2015WarriorNotes": "Despite being stuffed with straw, this armor is extremely hefty! Increases Constitution by <%= con %>. Limited Edition 2015 Autumn Gear.", "armorSpecialFall2015MageText": "Genähte Roben", - "armorSpecialFall2015MageNotes": "Every stitch in this armor shimmers with enchantment. Increases Intelligence by <%= int %>. Limited Edition 2015 Autumn Gear.", + "armorSpecialFall2015MageNotes": "Jede Masche dieser Rüstung schimmert mit Zauberei. Erhöht Intelligenz um <%= int %>. Limited Edition 2015 Herbst Ausrüstung.", "armorSpecialFall2015HealerText": "Roben des Tränkebrauers", "armorSpecialFall2015HealerNotes": "What? Of course that was a potion of constitution. No, you are definitely not turning into a frog! Don't be ribbiticulous. Increases Constitution by <%= con %>. Limited Edition 2015 Autumn Gear.", "armorMystery201402Text": "Robe des Nachrichtenbringers", @@ -323,9 +323,9 @@ "armorArmoireHornedIronArmorNotes": "Diese mit Leidenschaft aus Eisen gehämmerte, gehörnte Rüstung ist fast unzerbrechlich. Erhöht Ausdauer um <%= con %> und Wahrnehmung um <%= per %>. Verzauberter Schrank: Gehörntes Eisenset (Gegenstand 2 von 3)", "armorArmoirePlagueDoctorOvercoatText": "Pestarzt Umhang", "armorArmoirePlagueDoctorOvercoatNotes": "Ein authentischer Umhang wie ihn Ärzte tragen, die die Pest der Prokrastination bekämpfen! Steigert die Intelligenz um <%= int %>, Stärke um <%= str %>, und Ausdauer um <%= con %>. Verzauberter Schrank: Pestdoktor Set (Gegenstand 3 von 3).", - "armorArmoireShepherdRobesText": "Shepherd Robes", + "armorArmoireShepherdRobesText": "Hirtengewand", "armorArmoireShepherdRobesNotes": "The fabric is cool and breathable, perfect for a hot day herding gryphons in the desert. Increases Strength and Perception by <%= attrs %> each. Enchanted Armoire: Shepherd Set (Item 2 of 3).", - "armorArmoireRoyalRobesText": "Royal Robes", + "armorArmoireRoyalRobesText": "Königliche Gewänder", "armorArmoireRoyalRobesNotes": "Wonderful ruler, rule all day long! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 3 of 3).", "headgear": "Kopfschutz", "headBase0Text": "Kein Helm.", @@ -444,7 +444,7 @@ "headSpecialFall2015WarriorNotes": "Everyone would want this hat--if they only had a brain. Increases Strength by <%= str %>. Limited Edition 2015 Autumn Gear.", "headSpecialFall2015MageText": "Genähter Hut", "headSpecialFall2015MageNotes": "Dieser Hut wurde mit jedem Nadelstich stärker. Erhöht Wahrnehmung um <%= per %> Punkte. Limited Edition 2015 Herbst-Ausrüstung.", - "headSpecialFall2015HealerText": "Hat of Frog", + "headSpecialFall2015HealerText": "Froschhut", "headSpecialFall2015HealerNotes": "This is an extremely serious hat that is worthy of only the most advanced potioners. Increases Intelligence by <%= int %>. Limited Edition 2015 Autumn Gear.", "headSpecialGaymerxText": "Regenbogenkriegerhelm", "headSpecialGaymerxNotes": "Dieser besondere Helm ist zur Feier der Pride-Zeit und GaymerX mit einem strahlenden, bunten Regenbogen verziert! GaymerX ist eine Game Convention, die LGBTQ und Gaming feiert und an der jeder teilnehmen kann. Sie findet im InterContinental in der Stadtmitte von SanFrancisco vom 11.-13. Juli statt. Kein Attributbonus.", @@ -504,7 +504,7 @@ "headArmoireOrangeCatNotes": "Dieser orangene Hut ... schnurrt. Und sein Schwanz zuckt. Und er atmet? Okay, du hast einfach bloß eine schlafende Katze auf dem Kopf. Erhöht Intelligenz und Wahrnehmung um jeweils <%= attrs %>. Verzauberter Schrank: Unabhängiger Gegenstand.", "headArmoireBlueFloppyHatText": "Blue Floppy Hat", "headArmoireBlueFloppyHatNotes": "Many spells have been sewn into this simple hat, giving it a brilliant blue color. Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Independent Item.", - "headArmoireShepherdHeaddressText": "Shepherd Headdress", + "headArmoireShepherdHeaddressText": "Kopfschmuck des Hirten", "headArmoireShepherdHeaddressNotes": "Sometimes the gryphons that you herd like to chew on this headdress, but it makes you seem more intelligent nonetheless. Increases Intelligence by <%= int %>. Enchanted Armoire: Shepherd Set (Item 3 of 3).", "offhand": "Schildhand-Gegenstand", "shieldBase0Text": "Keine Schildhand-Ausrüstung", @@ -581,7 +581,7 @@ "shieldSpecialFall2015RogueNotes": "Furchterregende tägliche Aufgaben ducken sich unter den Schlägen dieser Axt. Erhöht Stärke um <&=str %>. Limited Edition 2015 Herbst-Ausrüstung. ", "shieldSpecialFall2015WarriorText": "Vogelfutterbeutel", "shieldSpecialFall2015WarriorNotes": "It's true that you're supposed to be SCARING the crows, but there's nothing wrong with making friends! Increases Constitution by <%= con %>. Limited Edition 2015 Autumn Gear.", - "shieldSpecialFall2015HealerText": "Stirring Stick", + "shieldSpecialFall2015HealerText": "Rührstab", "shieldSpecialFall2015HealerNotes": "This stick can stir anything without melting, dissolving, or bursting into flame! It can also be used to fiercely poke enemy tasks. Increases Constitution by <%= con %>. Limited Edition 2015 Autumn Gear.", "shieldMystery301405Text": "Uhrenschild", "shieldMystery301405Notes": "Die Zeit ist auf deiner Seite mit diesem gewaltigen Uhrenschild! Juni 3015 Abonennten-Gegenstand. Kein Attributbonus.", @@ -589,7 +589,7 @@ "shieldArmoireGladiatorShieldNotes": "Um ein Gladiator zu sein, musst du ... naja, egal, schlag sie einfach mit deinem Schild. Erhöht Ausdauer um <%= con %> und Stärke um <%= str %>. Verzauberter Schrank: Gladiatorset (Gegenstand 3 von 3).", "shieldArmoireMidnightShieldText": "Mitternachtsschild", "shieldArmoireMidnightShieldNotes": "This shield is most powerful at the stroke of midnight! Increases Constitution by <%= con %> and Strength by <%= str %>. Enchanted Armoire: Independent Item.", - "shieldArmoireRoyalCaneText": "Royal Cane", + "shieldArmoireRoyalCaneText": "Königlicher Stock", "shieldArmoireRoyalCaneNotes": "Hooray for the ruler, worthy of song! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 2 of 3).", "back": "Rückenschmuck", "backBase0Text": "Kein Rückenschmuck", @@ -604,7 +604,7 @@ "backMystery201504Notes": "Summ summ summ! Schwirre von Aufgabe zu Aufgabe. Verleiht keine Attributboni. April 2015 Abonnentengegenstand.", "backMystery201507Text": "Cooles Surfboard", "backMystery201507Notes": "Brande vor den Fleißigen Docks und reite die Wellen der Unvollständigkeitsbucht! gewährt keinen Attributbonus. Abonnentengegenstand Juli 2015", - "backMystery201510Text": "Goblin Tail", + "backMystery201510Text": "Koboldschwanz", "backMystery201510Notes": "Prehensile and powerful! Confers no benefit. October 2015 Subscriber Item.", "backSpecialWonderconRedText": "Mächtiger Umhang", "backSpecialWonderconRedNotes": "Strotzt vor Stärke und Schönheit. Kein Attributbonus. Special Edition Convention-Gegenstand.", @@ -676,8 +676,8 @@ "headAccessoryMystery201409Notes": "Dieses mächtige Geweih passt sich in seiner Farbe den Blättern an. Kein Attributbonus. September 2014 Abonnenten-Gegenstand.", "headAccessoryMystery201502Text": "Flügel der Gedanken", "headAccessoryMystery201502Notes": "Verleihe deiner Vorstellung Flügel! Gewährt keinen Attributbonus. Februar 2015 Abonnentengegenstand.", - "headAccessoryMystery201510Text": "Goblin Horns", - "headAccessoryMystery201510Notes": "These fearsome horns are slightly slimy. Confers no benefit. October 2015 Subscriber Item.", + "headAccessoryMystery201510Text": "Koboldhörner", + "headAccessoryMystery201510Notes": "Diese schreckenerregenden Hörner sind ein wenig schleimig. Gibt keine Verbesserung. Oktober 2015 Abonnementen Gegenstand.", "headAccessoryMystery301405Text": "Kopf-Brille", "headAccessoryMystery301405Notes": "\"Brillen sind für die Augen,\" haben sie gesagt. \"Niemand will Brillen, die man nur auf dem Kopf tragen kann,\" haben sie gesagt. Ha! Da hast du es ihnen aber ordentlich gezeigt! August 3015 Abonnenten-Gegenstand. Kein Attributbonus.", "eyewear": "Brillen", diff --git a/common/locales/de/generic.json b/common/locales/de/generic.json index 05ca3d2454..b97bfcd9b6 100644 --- a/common/locales/de/generic.json +++ b/common/locales/de/generic.json @@ -28,7 +28,7 @@ "market": "Marktplatz", "subscriberItem": "Überraschungsgegenstand", "newSubscriberItem": "Neuer Überraschungsgegenstand", - "subscriberItemText": "Each month, subscribers will receive a mystery item. This is usually released about one week before the end of the month. See the wiki's 'Mystery Item' page for more information.", + "subscriberItemText": "Abonnenten bekommen jeden Monat einen Überraschungsgegenstand. Dieser wird üblicherweise ungefähr eine Woche vor Monatsende herausgegeben. Schaue auf der 'Überraschungsgegenstand'-Seite des Wikis für mehr Informationen nach.", "all": "Alle", "none": "Keine", "or": "Oder", @@ -79,7 +79,7 @@ "errorUpCase": "FEHLER:", "newPassSent": "Neues Passwort wurde gesendet.", "serverUnreach": "Der Server ist momentan nicht erreichbar.", - "requestError": "Yikes, an error occurred! Please reload the page, your last action may not have been saved correctly.", + "requestError": "Ojeh, ein Fehler ist aufgetreten! Bitte lade die Seite neu, deine letzte Aktion wurde vielleicht nicht korrekt gespeichert.", "seeConsole": "Tritt der Fehler weiterhin auf, bitte berichte ihn bei Hilfe > Berichte einen Bug. Falls du weißt, wie du die Konsole deines Internetbrowsers einsehen kannst, füge die entsprechenden Fehlernachrichten bei.", "error": "Fehler", "menu": "Menü", @@ -134,5 +134,17 @@ "thankyou2": "Ich danke dir tausend mal.", "thankyou3": "Im bin sehr dankbar - danke!", "thankyouCardAchievementTitle": "Danke vielmals.", - "thankyouCardAchievementText": "Danke für deine Dankbarkeit! Hat <%= cards %> Dankeskarten verschickt. " + "thankyouCardAchievementText": "Danke für deine Dankbarkeit! Hat <%= cards %> Dankeskarten verschickt. ", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/de/groups.json b/common/locales/de/groups.json index 30ba7cb80f..c6cc9dd64c 100644 --- a/common/locales/de/groups.json +++ b/common/locales/de/groups.json @@ -147,5 +147,5 @@ "partyChatEmpty": "Dein Gruppenchat ist leer. Tippe eine Nachricht in der Box und beginne mit dem Chat.", "guildChatEmpty": "Dieser Gildenchat ist leer. Gib eine Nachricht ein und beginne mit dem Chat.", "possessiveParty": "<%= name %>s Gruppe", - "requestAcceptGuidelines": "If you would like to post messages in the Tavern or any party or guild chat, please first read our <%= linkStart %>Communit Guidelines<%= linkEnd %> and then click the button below to indicate that you accept them." + "requestAcceptGuidelines": "Wenn du gerne Nachrichten im Gasthaus oder einem Gruppen- oder Gildenchat posten möchtest, lies vorher bitte unsere <%= linkStart %>Community-Richtlinien<%= linkEnd %> und klicke auf den Button darunter, um zu anzugeben, dass du sie akzeptierst." } \ No newline at end of file diff --git a/common/locales/de/limited.json b/common/locales/de/limited.json index 25b1e48b70..ba74e31dcf 100644 --- a/common/locales/de/limited.json +++ b/common/locales/de/limited.json @@ -30,7 +30,7 @@ "seasonalShopText": "Willkommen zum Jahreszeitenmarkt!! Momentan haben wir Frühlingsgegenstände auf Lager. Alles hier wird während des Frühlingsevents, das jedes Jahr stattfindet, verfügbar sein. Allerdings nur bis zum 30. April, also stocke jetzt auf, ansonsten musst du bis nächstes Jahr warten.", "seasonalShopSummerText": "Willkommen zum Jahreszeitenmarkt!! Momentan haben wir jahreszeitlich wechselnde Gegenstände auf Lager. Alles hier wird während des Sommerevents, das jedes Jahr stattfindet, verfügbar sein. Allerdings nur bis zum 31. Juli, also stocke jetzt auf, ansonsten musst du bis nächstes Jahr warten.", "seasonalShopFallText": "Willkommen zum saisonalen Shop!! Momentan haben wir Herbstgegenstände auf Lager. Alles hier wird während des Herbstevents, das jedes Jahr stattfindet, verfügbar sein. Allerdings nur bis zum 31. October, also stocke jetzt deine Vorräte auf, ansonsten musst du bis nächstes Jahr warten.", - "seasonalShopFallTextBroken": "Oh.... Welcome to the Seasonal Shop... We're stocking autumn Seasonal Edition goodies, or something... Everything here will be available to purchase during the Fall Festival event each year, but we're only open until October 31... I guess you should to stock up now, or you'll have to wait... and wait... and wait... *sigh*", + "seasonalShopFallTextBroken": "Willkommen zum saisonalen Shop!! Momentan haben wir herbst Gegenstände auf Lager. Alles hier wird während des Herbstevents, das jedes Jahr stattfindet, verfügbar sein. Allerdings nur bis zum 31. October, also stocke jetzt deine Vorräte auf, ansonsten musst du bis nächstes Jahr warten...*hach*", "seasonalShopRebirth": "Wenn du die Sphäre der Wiedergeburt benutzt hast, kannst du diesen Ausrüstungsgegenstand in der Belohnungsspalte erneut kaufen. Anfangs wirst du nur Gegenstände für deine momentane Klasse (Krieger) kaufen können, aber keine Sorge, die anderen klassenspezifischen Gegenstände werden verfügbar, sobald du zu der jeweiligen Klasse wechselst. ", "candycaneSet": "Zuckerstange (Magier)", "skiSet": "Ski-Attentäter (Schurke)", diff --git a/common/locales/de/messages.json b/common/locales/de/messages.json index d611eb56c7..8da8eef691 100644 --- a/common/locales/de/messages.json +++ b/common/locales/de/messages.json @@ -44,12 +44,12 @@ "messageGroupOnlyLeaderCanUpdate": "Nur der Gruppenleiter kann die Gruppe aktualisieren!", "messageGroupRequiresInvite": "Du kannst keiner Gruppe beitreten, zu der du nicht eingeladen wurdest.", "messageGroupCannotRemoveSelf": "Du kannst dich nicht selbst entfernen!", - "messageGroupChatBlankMessage": "You cannot send a blank message", - "messageGroupChatLikeOwnMessage": "Can't like your own message. Don't be that person.", - "messageGroupChatFlagOwnMessage": "Can't report your own message.", - "messageGroupChatFlagAlreadyReported": "You have already reported this message", - "messageGroupChatNotFound": "Message not found!", - "messageGroupChatAdminClearFlagCount": "Only an admin can clear the flag count!", + "messageGroupChatBlankMessage": "Du kannst keine leere Nachricht versenden", + "messageGroupChatLikeOwnMessage": "\"Gefällt mir\" funktioniert nicht bei eigenen Nachrichten. Sei nicht so einer.", + "messageGroupChatFlagOwnMessage": "Du kannst deine eigene Nachricht nicht melden.", + "messageGroupChatFlagAlreadyReported": "Du hast diese Nachricht bereits gemeldet.", + "messageGroupChatNotFound": "Nachricht wurde nicht gefunden!", + "messageGroupChatAdminClearFlagCount": "Nur Admins können den Zählmarker zurücksetzen!", "messageUserOperationProtected": "Pfad `<%= operation %>` nicht gespeichert, da dieser geschützt ist.", "messageUserOperationNotFound": "<%= operation %> Operation nicht gefunden" } \ No newline at end of file diff --git a/common/locales/de/npc.json b/common/locales/de/npc.json index 4319caa0b0..12c7d7b869 100644 --- a/common/locales/de/npc.json +++ b/common/locales/de/npc.json @@ -7,19 +7,19 @@ "daniel": "Daniel", "danielText": "Willkommen im Gasthaus! Setz dich und triff die Einheimischen. Willst du dich ausruhen (Urlaub? Krankheit?), dann besorge ich dir ein schönes Zimmer. Solange du dort eingecheckt bist, werden deine täglichen Aufgaben dir am Ende des Tages keinen Schaden zufügen, du kannst sie trotzdem noch abhaken.", "danielText2": "Sei gewarnt: Falls Du an einer Boss-Quest teilnimmst, wird Dir der Boss immer noch Schaden für die nicht abgehakten Aufgaben Deiner Gruppenmitglieder zufügen! Außerdem wird der Schaden, den Du dem Boss zufügst (sowie gefundene Gegenstände) erst angerechnet, wenn Du das Gasthaus verlässt.", - "danielTextBroken": "Welcome to the Tavern... I guess... If you need to rest, I'll set you up at the Inn... While checked-in, your Dailies won't hurt you at the day's end, but you can still check them off... if you have the energy...", - "danielText2Broken": "Oh... If you are participating in a boss quest, the boss will still damage you for your party mates' missed Dailies... Also, your own damage to the Boss (or items collected) will not be applied until you check out of the Inn...", + "danielTextBroken": "Willkommen im Gasthaus... Willst du dich ausruhen, dann besorge ich dir ein schönes Zimmer... Solange du dort eingecheckt bist, werden deine täglichen Aufgaben dir am Ende des Tages keinen Schaden zufügen, du kannst sie trotzdem noch abhaken... wenn du die Kraft dazu hast...", + "danielText2Broken": "Oh... Falls Du an einer Boss-Quest teilnimmst, wird Dir der Boss immer noch Schaden für die nicht abgehakten Aufgaben Deiner Gruppenmitglieder zufügen... Außerdem wird der Schaden, den Du dem Boss zufügst (sowie gefundene Gegenstände) erst angerechnet, wenn Du das Gasthaus verlässt...", "alexander": "Alexander der Händler", "welcomeMarket": "Willkommen auf dem Marktplatz! Kaufe schwer zu findende Eier und Tränke! Verkaufe Überflüssiges! Gib' wichtige Dienste in Auftrag! Komm' und schau', was wir anzubieten haben.", - "displayItemForGold": "Do you want to sell a <%= itemType %>?", - "displayEggForGold": "Do you want to sell a <%= itemType %> Egg?", - "displayPotionForGold": "Do you want to sell a <%= itemType %> Potion?", - "sellForGold": "Sell it for <%= gold %> Gold", + "displayItemForGold": "Möchtest du ein <%= itemType %> verkaufen?", + "displayEggForGold": "Möchtest du ein <%= itemType %> Ei verkaufen?", + "displayPotionForGold": "Möchtest du einen <%= itemType %> Trank verkaufen?", + "sellForGold": "Verkauf es für <%= gold %> Gold", "buyGems": "Kaufe Edelsteine", "justin": "Justin", "ian": "Jan", "ianText": "Willkommen beim Quest Shop! Hier kannst du Questschriftrollen besorgen, um mit deinen Freunden Monster zu bekämpfen. Durchstöbere unsere große Anzahl an Schriftrollen und investiere in die Richtige!", - "ianBrokenText": "Welcome to the Quest Shop... Here you can use Quest Scrolls to battle monsters with your friends... Be sure to check out our fine array of Quest Scrolls for purchase on the right...", + "ianBrokenText": "Willkommen beim Quest Shop... Hier kannst du Questschriftrollen besorgen, um mit deinen Freunden Monster zu bekämpfen... Durchstöbere unsere große Anzahl an Schriftrollen und investiere in die Richtige...", "USD": "USD ($)", "newStuff": "Neuigkeiten", "cool": "Erzähl es mir später", diff --git a/common/locales/de/pets.json b/common/locales/de/pets.json index 6fadd84c25..90dfe94e8d 100644 --- a/common/locales/de/pets.json +++ b/common/locales/de/pets.json @@ -58,8 +58,16 @@ "firstDrop": "Du hast das Beutesystem freigeschaltet! Ab jetzt hast du jedes mal wenn Du eine Aufgabe abhakst eine kleine Chance einen Gegenstand zu finden, wie zum Beispiel Eier, Schlüpftränke und Futter! Du hast eben ein <%= eggText %> Ei gefunden! <%= eggNotes %>", "useGems": "Du willst ein bestimmtes Haustier haben, möchtest aber nicht länger warten, bis Du die richtigen Gegenstände gefunden hast? Mit Edelsteinen kannst du im Inventar > Marktplatz die entsprechenden Gegenstände kaufen!", "hatchAPot": "Willst du ein <%= potion %> <%= egg %> ausbrüten?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "'Verfüttere <%= article %> <%= text %> an <%= name %>?", "useSaddle": "Einen magischen Sattel auf <%= pet %> anwenden?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Schlüssel zu den Zwingern.", diff --git a/common/locales/de/quests.json b/common/locales/de/quests.json index 959e6fb6d1..1e65eceb7e 100644 --- a/common/locales/de/quests.json +++ b/common/locales/de/quests.json @@ -13,7 +13,7 @@ "youReceived": "Du hast folgendes erhalten:", "dropQuestCongrats": "Gratulation zum Erwerb dieser Questschriftrolle! Du kannst nun deine Gruppe dazu einladen die Quest zu starten oder du kommst irgendwann darauf zurück unter Inventar > Quests.", "questSend": "Ein Klick auf \"Einladen\" sendet eine Einladung an Deine Gruppenmitglieder. Sobald alle Mitglieder diese angenommen oder abgelehnt haben, beginnt die Quest. Der Status ist unter Optionen > Soziales > Gruppe einsehbar.", - "questSendBroken": "Clicking \"Invite\" will send an invitation to your party members... When all members have accepted or denied, the quest begins... See status under Social > Party...", + "questSendBroken": "Ein Klick auf \"Einladen\" sendet eine Einladung an Deine Gruppenmitglieder. Sobald alle Mitglieder diese angenommen oder abgelehnt haben, beginnt die Quest ... Der Status ist unter Optionen > Soziales > Gruppe einsehbar.", "inviteParty": "Lade Gruppe zur Quest ein", "questInvitation": "Quest Einladung:", "questInvitationTitle": "Quest-Einladung", @@ -37,12 +37,12 @@ "bossDmg1": "Jede erledigte tägliche Aufgabe und Aufgabe und jede positive Gewohnheit fügt dem Boss Schaden zu. Mit röteren Aufgaben, Gewaltschlag oder Flammenstoß kannst du ihm noch stärkeren Schaden zufügen. Für jede tägliche Aufgabe, die du nicht erledigt hast, wird der Boss jedem Teilnehmer der Quest Schaden zufügen (multipliziert mit der Stärke des Bosses), der zu deinem normalen Schaden noch dazukommt. Deshalb sorge dafür, dass deine Gruppe gesund bleibt, indem du deine täglichen Aufgaben erledigst! Jeder Schaden, der dem Boss zugefügt wird und den er zufügt, wird zu Cron berechnet (dein individueller Tagesbeginn).", "bossDmg2": "Nur Teilnehmer kämpfen gegen den Boss und bekommen ihren Anteil an der Beute.", "bossDmg1Broken": "Each completed Daily and To-Do and each positive Habit hurts the boss... Hurt it more with redder tasks or Brutal Smash and Burst of Flames... The boss will deal damage to every quest participant for every Daily you've missed (multiplied by the boss's Strength) in addition to your regular damage, so keep your party healthy by completing your Dailies... All damage to and from a boss is tallied on cron (your day roll-over)...", - "bossDmg2Broken": "Only participants will fight the boss and share in the quest loot...", + "bossDmg2Broken": "Nur Teilnehmer kämpfen gegen den Boss und erhalten ihren Anteil an der Beute.", "tavernBossInfo": "Complete Dailies and To-Dos and score positive Habits to damage the World Boss! Incomplete Dailies fill the Exhaust Strike Bar. When the Exhaust Strike bar is full, the World Boss will attack an NPC. A World Boss will never damage individual players or accounts in any way. Only active accounts not resting in the Inn will have their tasks tallied.", "tavernBossInfoBroken": "Complete Dailies and To-Dos and score positive Habits to damage the World Boss... Incomplete Dailies fill the Exhaust Strike Bar... When the Exhaust Strike bar is full, the World Boss will attack an NPC... A World Boss will never damage individual players or accounts in any way... Only active accounts not resting in the Inn will have their tasks tallied...", "bossColl1": "Um Gegenstände zu sammeln musst Du Deine Aufgaben erfüllen. Quest Gegenstände sind genauso wie normale Gegenstände zu finden, aber Du kannst das Ergebnis erst zum Tageswechsel sehen. Dann wird alles, was jeder Teilnehmer gefunden hat zusammengerechnet und dem Quest zugerechnet.", "bossColl2": "Nur Teilnehmer können Gegenstände sammeln und erhalten ihren Anteil an der Beute.", - "bossColl1Broken": "To collect items, do your positive tasks... Quest items drop just like normal items; however, you won't see the drops until the next day, then everything you've found will be tallied up and contributed to the pile...", + "bossColl1Broken": "Im Gegenstände zu sammeln müssen positive Aufgaben abgeschlossen werden... Quest Gegenstände erhält man genau wie normale Gegenstände; Egal welche du kannst sie nicht vor dem nächsten Tag sehen.\nthen everything you've found will be tallied up and contributed to the pile...", "bossColl2Broken": "Nur Mitglieder können Gegenstände sammeln und sich die Quest-Beute teilen ...", "abort": "Abbrechen", "leaveQuest": "Quest verlassen", @@ -70,11 +70,13 @@ "sureAbort": "Bist du sicher, dass du diese Mission abbrechen willst? Das wird sie für alle in deiner Gruppe abbrechen und jeder Fortschritt wird verloren gehen. Die Questrolle wird dem Quest-Besitzer zurückgegeben.", "doubleSureAbort": "Bist Du wirklich wirklich sicher? Sei' ganz sicher, dass sie Dich nicht für immer hassen werden!", "questWarning": "Wenn neue Mitglieder der Gruppe beitreten, bevor das Quest anfängt, werden auch sie eine Einladung bekommen. Aber sobald das Quest angefangen hat, können neue Gruppenmitglieder dem Quest nicht mehr beitreten.", - "questWarningBroken": "If new players join the party before the quest starts, they will also receive an invitation... However once the quest has started, no new party members can join the quest...", + "questWarningBroken": "Wenn neue Mitglieder der Gruppe beitreten, bevor die Quest beginnt, werden auch sie eine Einladung erhalten ... Aber sobald die Quest angefangen hat, können der Quest keine neuen Gruppenmitglieder mehr beitreten ...", "bossRageTitle": "Zorn", "bossRageDescription": "Wenn sich dieser Balken füllt, wird der Boss eine Spezialattacke ausführen", "startAQuest": "STARTE EINE QUEST", "startQuest": "Quest starten", "whichQuestStart": "Welche Quest willst Du starten?", - "getMoreQuests": "Erhalte mehr Quests" + "getMoreQuests": "Erhalte mehr Quests", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/de/questscontent.json b/common/locales/de/questscontent.json index a7b4ae0a21..ad9a2f46be 100644 --- a/common/locales/de/questscontent.json +++ b/common/locales/de/questscontent.json @@ -18,7 +18,7 @@ "questGryphonUnlockText": "Ermöglicht den Kauf von Greifeneiern auf dem Marktplatz.", "questHedgehogText": "Das Igelmonster", "questHedgehogNotes": "Igel gehören einer kuriosen Gruppe von Tieren an. Zwar sind sie die liebevollsten Haustiere, die sich ein Habiteer wünschen kann, aber es gibt ein Gerücht wonach sie, wenn man sie nach Mitternacht mit Milch füttert, ein wenig gereizt werden. Und fünfzig mal größer. Und inventrix hat genau das gemacht - Hoppla.", - "questHedgehogCompletion": "Eure Gruppe hat das Igel Weibchen beruhigt! Es hoppelt zurück zu seinen Eiern, nachdem es auf seine normale Größe geschrumpft ist. Quietschend kehrt es mit einigen Eiern zurück und stupst sie vorsichtig in eure Richtung. Hoffentlich mögen Igel Milch!", + "questHedgehogCompletion": "Eure Gruppe hat das Igelweibchen beruhigt! Es hoppelt zurück zu seinen Eiern, nachdem es auf seine normale Größe geschrumpft ist. Quietschend kehrt es mit einigen Eiern zurück und stupst sie vorsichtig in eure Richtung. Hoffentlich mögen Igel Milch!", "questHedgehogBoss": "Igelmonster", "questHedgehogDropHedgehogEgg": "Igel (Ei)", "questHedgehogUnlockText": "Ermöglicht den Kauf von Igeleiern auf dem Marktplatz.", @@ -53,7 +53,7 @@ "questRoosterDropRoosterEgg": "Hahn (Ei)", "questRoosterUnlockText": "Ermöglicht den Kauf von Hahneiern auf dem Marktplatz.", "questSpiderText": "Die eisige Arachnoide", - "questSpiderNotes": "Das Wetter kühlt sich ab und leichter Frost beginnt auf den Fensterscheiben der Einwohner von Habitika in Form von filigranen Netzen zu erscheinen... außer bei @Arcosine, dessen Fenster komplett zugefroren sind und bei dem sich die Frostspinne eingenistet hat. Oh je!", + "questSpiderNotes": "Das Wetter kühlt sich ab und leichter Frost beginnt auf den Fensterscheiben der Einwohner von Habitica in Form von filigranen Netzen zu erscheinen ... außer bei @Arcosine, dessen Fenster komplett zugefroren sind und bei dem sich die Frostspinne eingenistet hat. Oh je!", "questSpiderCompletion": "Die Frostspinne bricht zusammen. Von ihr bleibt nur ein kleiner Haufen Frost und ein paar ihrer verzauberten Eiersäcke. @Arcosine bietet sie dir recht hastig als Belohnung an--vielleicht könntest du ein paar ungefährliche Spinnen als deine Haustiere aufziehen?", "questSpiderBoss": "Spinne", "questSpiderDropSpiderEgg": "Spinne (Ei)", @@ -142,13 +142,13 @@ "questAtom3Boss": "Der Wäschebeschwörer", "questAtom3DropPotion": "Standard Schlüpftrank", "questOwlText": "Die Nachteule", - "questOwlNotes": "Das Gasthauslicht brennt bis zum in die Morgenstunden
Doch eine Nacht ist das Leuchten verschwunden!
Wo sollen denn jetzt alle Nachtschwärmern hin?
@Twitching ruft, \"Wir müssen in den Kampfe ziehn!\"
Siehst du diese Nachteule, den gefiederten Feind?
Kämpfe schnell, kämpfe gut, mach sie klein!
Wir werden ihren Schatten schnell verscheuchen,
und die Nacht wieder hell erleuchten!\"", + "questOwlNotes": "Das Gasthauslicht brennt bis in die Morgenstunden
doch eines Nachts ist das Leuchten verschwunden!
Wo sollen denn jetzt alle Nachtschwärmer hin?
@Twitching ruft, \"Wir müssen in den Kampfe ziehn!\"
Siehst du diese Nachteule, den gefiederten Feind?
Kämpfe schnell, kämpfe gut, mach sie klein!
Wir werden ihren Schatten schnell verscheuchen,
und die Nacht wieder hell erleuchten!\"", "questOwlCompletion": "Die Nachteul' verblasst, bevor die Nacht vergeht
Doch dennoch fühlst du, wie es in dir gähnt.
Vielleicht ist es Zeit, sich hinzulegen?
In deinem Bett siehst du ein Nestchen liegen!
Die Nachteul' weiß, es ist sehr schön
spät zu arbeiten und spät ins Bett zu gehn,
Aber deine neuen Haustiere werden leise krähen
und dir dann sagen, \"du sollst schlafen gehen\".", "questOwlBoss": "Die Nachteule", "questOwlDropOwlEgg": "Eule (Ei)", "questOwlUnlockText": "Ermöglicht den Kauf von Euleneiern auf dem Marktplatz.", "questPenguinText": "Der Federvieh-Frost", - "questPenguinNotes": "Obwohl es auf der Südspitze von Habitica ein heißer Sommertag ist, hat eine unnatürliche Kälte den Lively Lake befallen. Man hört das Heulen von starken, eisige Winden und das Ufer fängt an, zuzufrieren. Eisspitzen brechen aus dem Boden und verdrängen Gras und Dreck. @Melynnrose und @Breadstrings rennen zu dir hinüber.

\"Hilfe!\" sagt @Melynnrose. \"Wir haben einen riesigen Pinguin hergebracht, um den See zuzufrieren damit wir alle schlittschuhlaufen können, aber uns sind die Fische ausgegangen, mit denen wir ihn gefüttert haben!\"

\"Er wurde wütend und friert mit seinem Eis-Atem alles zu, was er sieht!\" sagt @Breadstrings. \"Bitte, du musst ihn überwältigen bevor wir alle von Eis bedeckt sind!\" Sieht aus, als ob du das Gemüt dieses Pinguins... etwas abkühlen musst.", + "questPenguinNotes": "Obwohl es auf der Südspitze von Habitica ein heißer Sommertag ist, hat eine unnatürliche Kälte den Lively Lake befallen. Man hört das Heulen von starken, eisigen Winden und das Ufer fängt an zuzufrieren. Eisspitzen brechen aus dem Boden und verdrängen Gras und Dreck. @Melynnrose und @Breadstrings rennen zu dir hinüber.

\"Hilfe!\" sagt @Melynnrose. \"Wir haben einen riesigen Pinguin hergebracht, um den See zuzufrieren damit wir alle schlittschuhlaufen können, aber uns sind die Fische ausgegangen, mit denen wir ihn gefüttert haben!\"

\"Er wurde wütend und friert mit seinem Eis-Atem alles zu, was er sieht!\" sagt @Breadstrings. \"Bitte, du musst ihn überwältigen bevor wir alle von Eis bedeckt sind!\" Sieht aus, als ob du das Gemüt dieses Pinguins... etwas abkühlen musst.", "questPenguinCompletion": "Mit der Niederlage des Pinguins beginnt das Eis zu schmelzen. Der riesige Pinguin setzt sich im Sonnenschein auf den Boden und schlürft einen Eimer Fische herunter. Er gleitet über den See und lässt dabei mit einem leichten Pusten nach unten glattes, glitzerndes Eis entstehen. Was für ein komischer Vogel! \"Es scheint so, als hätte er einige Eier hinterlassen,\" sagt @Painter de Cluster.

@Rattify lacht. \"Vielleicht werden diese Pinguine ein bisschen... gechillter sein?\"", "questPenguinBoss": "Frostpinguin", "questPenguinDropPenguinEgg": "Pinguin (Ei)", @@ -180,7 +180,7 @@ "questTRexDropTRexEgg": "Tyrannosaurus (Ei)", "questTRexUnlockText": "Schaltet die Option Tyrannosauruseier auf dem Marktplatz zu kaufen frei.", "questRockText": "Entkomme dem Höhlenungetüm", - "questRockNotes": "Beim Durchqueren des Habitica Mäandergebirges schlagen Deine Freunde und Du ein Lager in einer Höhle auf, welche mit funkelnden Kristallen übersät ist. Als Du jedoch am nächsten Morgen aufwachst ist der Eingang verschwunden und der Höhlenoden unter dir beginnt sich zu bewegen.

\"Der Berg lebt!\" schreit dein Kamerad @pfeffernusse. \"Das sind keine Kristalle - das sind Zähne!\"

@Painter de Cluster ergreift Deine Hand. \"Wir müssen einen anderen Weg nach draußen finden. Bleib bei mir und lasse Dich nicht ablenken, sonst sind wir vielleicht für immer hier drinnen gefangen!\"", + "questRockNotes": "Beim Durchqueren des Habitica Mäandergebirges schlagen Deine Freunde und Du ein Lager in einer Höhle auf, welche mit funkelnden Kristallen übersät ist. Als Du jedoch am nächsten Morgen aufwachst ist der Eingang verschwunden und der Höhlenboden unter dir beginnt sich zu bewegen.

\"Der Berg lebt!\" schreit dein Kamerad @pfeffernusse. \"Das sind keine Kristalle - das sind Zähne!\"

@Painter de Cluster ergreift Deine Hand. \"Wir müssen einen anderen Weg nach draußen finden. Bleib bei mir und lasse Dich nicht ablenken, sonst sind wir vielleicht für immer hier drinnen gefangen!\"", "questRockBoss": "Kristallkoloss", "questRockCompletion": "Dank Deiner harten Arbeit konntest Du zu guter Letzt einen sicheren Weg durch den lebenden Berg finden. \nNach der langen Dunkelheit genießt Du die wärmenden Sonnenstrahlen, als Dich Dein Freund @intune auf ein Funkeln am Boden nahe der Höhle aufmerksam macht.\nDas Funkeln kommt von einem kleinen Stein, der von einer Goldader durchzogen ist. \nWährend Du ihn aufhebst siehst Du, dass um ihn herum weitere merkwürdig geformte Steine liegen. Sind das... Eier?", "questRockDropRockEgg": "Fels (Ei)", @@ -188,7 +188,7 @@ "questBunnyText": "Das Killerkaninchen", "questBunnyNotes": "Nach vielen Tagen voller Schwierigkeiten erreichst Du den Gipfel des Berges des Aufschiebens und stehst vor den imposanten Toren der Festung der Verwahrlosung. Du liest die Inschrift im Stein. \"Hier lebt die Kreatur, die Deine größten Ängste verkörpert, der Grund für dein Nichtstun. Klopf an und stelle dich Deinem Dämon!\" Deine Hände beginnen zu zittern als Du Dir dieses Grauen vor Augen führst und Du spürst plötzlich den Drang zu fliehen, wie Du es schon so viele Male getan hast. @Draayder hält dich zurück. \"Bleib ruhig, mein Freund! Die Zeit ist endlich gekommen. Du musst dies tun!\"

Du klopfst und die Torflügel schwingen nach innen. Aus der Dunkelheit vor Dir hörst Du ein ohrenbetäubendes Brüllen und Du ziehst deine Waffe.", "questBunnyBoss": "Killerkaninchen", - "questBunnyCompletion": "Von einem letzten Schlag getroffen sinkt das Killerhäschen zu Boden. Funkelnde Nebelschwaden steigen aus dem riesigen Körper auf, während dieser schrumpft und sich in ein kleines Häschen verwandelt. Keine Spur mehr von dem furchteinflössenden Monster, dem Ihr euch wenige Momente zuvor stellen musstest. Das winzige Näschen zuckt zweimal in die Luft und schon hoppelt das Häschen davon. Dabei lässt es einige Eier zurück @Gully lacht: \"Jaja, der Berg des Aufschiebens hat so eine Art selbst die kleinsten Herausforderungen riesig groß erscheinen zu lassen... Lasst uns die Eier einsammeln und uns auf den Weg nach Hause machen\"", + "questBunnyCompletion": "Von einem letzten Schlag getroffen sinkt das Killerkaninchen zu Boden. Funkelnde Nebelschwaden steigen aus dem riesigen Körper auf, während dieser schrumpft und sich in ein kleines Häschen verwandelt. Keine Spur mehr von dem furchteinflössenden Monster, dem Du Dich wenige Momente zuvor stellen musstest. Das winzige Näschen zuckt zweimal in die Luft und schon hoppelt das Häschen davon. Dabei lässt es einige Eier zurück @Gully lacht: \"Jaja, der Berg des Aufschiebens hat so eine Art selbst die kleinsten Herausforderungen riesig groß erscheinen zu lassen ... Lasst uns die Eier einsammeln und uns auf den Weg nach Hause machen.\"", "questBunnyDropBunnyEgg": "Hase (Ei)", "questBunnyUnlockText": "Schaltet die Option Haseneier auf dem Marktplatz zu kaufen frei.", "questSlimeText": "Der Glibber König", @@ -212,7 +212,7 @@ "questWhaleText": "Jammern des Wals", "questWhaleNotes": "Du kommt am Diligent Hafen an und hoffst, dass du mit einem U-Boot zum Dilatory Derby fahren kannst. Plötzlich zwingt dich ein ohrenbetäubendes Grölen dazu anzuhalten und deine Ohren zuzuhalten. \"Wal in Sicht!\", schreit Kapitän @krazjega, während er auf einen riesigen, klagenden Wal deutet. \"Es ist nicht sicher U-Boote herauszuschicken während sie um sich schlägt!\"

\"Schnell\", ruft @UncommonCriminal. \"Hilf mir die arme Kreatur zu beruhigen, damit wir herausfinden können, wieso sie diesen ganzen Krach macht!\"", "questWhaleBoss": "Jammernder Wal", - "questWhaleCompletion": "Nach der ganzen harten Arbeit verstummt das donnernde Jammern des Wahles. \"Scheint als wäre sie in der Flut schlechter Angewohnheiten fast ertrunken\", erklärt @zoebeagle, \"Dank deiner ununterbrochenen Bemühungen konnten wir die Fluten abwenden!\" Als du in das U-Boot steigen willst fallen dir in der ruhigen See einige Eier auf.", + "questWhaleCompletion": "Nach der ganzen harten Arbeit verstummt das donnernde Jammern des Wales. \"Scheint als wäre sie in der Flut schlechter Angewohnheiten fast ertrunken\", erklärt @zoebeagle, \"Dank deiner ununterbrochenen Bemühungen konnten wir die Fluten abwenden!\" Als du in das U-Boot steigen willst fallen dir in der ruhigen See einige Eier auf.", "questWhaleDropWhaleEgg": "Wal (Ei)", "questWhaleUnlockText": "Ermöglicht den Kauf von Waleiern auf dem Marktplatz.", "questDilatoryDistress1Text": "Aufschiebendes Elend, Teil 1: Flaschenpost", @@ -225,16 +225,16 @@ "questDilatoryDistress2Notes": "Die Belagerung kann meilenweit entfernt gesehen werden: tausende körperlose Schädel drängen sich durch ein Portal zwischen den Wänden der Spalte und streben Dilatory entgegen.

Du triffst König Manta mit eingefallenen Augen und besorgtem Gesicht in seinem Kriegszimmer. \"Meine Tochter Adva verschwand in der dunklen Meeresspalte kurz bevor die Belagerung begann. Bitte finde sie und bringe sie sicher wieder zurück! Ich werde dir mein Feuerkorallendiadem leihen, um dir zu helfen. Wenn du erfolgreich bist, ist es deins.\"", "questDilatoryDistress2Completion": "Du bezwingst die albtraumhalfte Totenschädelhorde, aber du hast nicht das Gefühl näher dran zu sein Adva zu finden. Du fragst @Kiwibot, den königlichen Fährtensucher, ob sie irgendeine Idee hat. \"Die Fangschreckenkrebse, welche die Stadt verteidigen, sollten Advas Flucht gesehen haben\", antwortet @Kiwibot. \"Versuche ihnen in die dunkle Meeresspalte zu folgen.\"", "questDilatoryDistress2Boss": "Wasserschädel Schwarm", - "questDilatoryDistress2RageTitle": "Schwarm Auferstehung", - "questDilatoryDistress2RageDescription": "Schwarm Auferstehung: Diese Leiste füllt sich, wenn Du deine täglichen Aufgaben nicht erfüllst. Wenn sie voll ist, heilt sich der Wasserschädel Schwarm um 30% seiner übrigen Lebenspunkte!", - "questDilatoryDistress2RageEffect": "'Wasserschädelschwarm benutzt SCHWARM RESPAWN!'\n\nErmutigt durch ihre Siege, strömen weitere Schädel aus der Meeresspalte, um den Schwarm zu unterstützen!", + "questDilatoryDistress2RageTitle": "Schwarmnachwuchs", + "questDilatoryDistress2RageDescription": "Schwarmnachwuchs: Diese Leiste füllt sich, wenn Du deine täglichen Aufgaben nicht erfüllst. Wenn sie voll ist, heilt sich der Wasserschädel Schwarm um 30% seiner übrigen Lebenspunkte!", + "questDilatoryDistress2RageEffect": "'Wasserschädelschwarm benutzt SCHWARMNACHWUCHS!'\n\nErmutigt durch ihre Siege, strömen weitere Schädel aus der Meeresspalte, um den Schwarm zu unterstützen!", "questDilatoryDistress2DropSkeletonPotion": "Skelettierter Schlüpftrank", "questDilatoryDistress2DropCottonCandyBluePotion": "Zuckerwattenblauer Schlüpftrank", "questDilatoryDistress2DropHeadgear": "Feuerkorallendiadem (Kopfbedeckung)", "questDilatoryDistress3Text": "Säumiges Elend, Teil 3: Nicht nur ein Dienstmädchen", "questDilatoryDistress3Notes": "Du folgst den Fangschreckenkrebsen tief in die Meeresspalte und entdeckst eine Unterwasserfestung. Prinzessin Adva, von weiteren Wasserschädeln begleitet, erwartet dich in der Haupthalle. \"Mein Vater hat euch gesandt, oder? Berichtet ihm, dass ich es ablehne zurückzukehren. Ich bin damit zufrieden hier zu bleiben und Zauberei zu betreiben. Verschwinde jetzt oder du wirst den Zorn der neuen Meereskönigin spüren!\" Adva scheint unnachgiebig zu sein, aber während sie spricht bemerkst du einen seltsamen, bedrohlich glühenden Rubinanhänger an ihrem Hals... Vielleicht würden ihr Wahnvorstellungen aufhören, wenn du ihn zerbrichst?", "questDilatoryDistress3Completion": "Finally, you manage to pull the bewitched pendant from Adva's neck and throw it away. Adva clutches her head. \"Where am I? What happened here?\" After hearing your story, she frowns. \"This necklace was given to me by a strange ambassador - a lady called 'Tzina'. I don't remember anything after that!\"

Back at Dilatory, Manta is overjoyed by your success. \"Allow me to reward you with this trident and shield! I ordered them from @aiseant and @starsystemic as a gift for Adva, but... I'd rather not put weapons in her hands any time soon.\"", - "questDilatoryDistress3Boss": "Adva, die verdränge Meerjungfrau", + "questDilatoryDistress3Boss": "Adva, die putschende Meerjungfrau", "questDilatoryDistress3DropFish": "Fisch (Futter)", "questDilatoryDistress3DropWeapon": "Dreizack der zerschmetternden Gezeiten (Waffe)", "questDilatoryDistress3DropShield": "Mondperlenschild (Schildhand Item)", @@ -248,8 +248,8 @@ "questHorseNotes": "While relaxing in the Tavern with @beffymaroo and @JessicaChase, the talk turns to good-natured boasting about your adventuring accomplishments. Proud of your deeds, and perhaps getting a bit carried away, you brag that you can tame any task around. A nearby stranger turns toward you and smiles. One eye twinkles as he invites you to prove your claim by riding his horse.\nAs you all head for the stables, @UncommonCriminal whispers, \"You may have bitten off more than you can chew. That's no horse - that's a Night-Mare!\" Looking at its stamping hooves, you begin to regret your words...", "questHorseCompletion": "It takes all your skill, but finally the horse stamps a couple of hooves and nuzzles you in the shoulder before allowing you to mount. You ride briefly but proudly around the Tavern grounds while your friends cheer. The stranger breaks into a broad grin.\n\"I can see that was no idle boast! Your determination is truly impressive. Take these eggs to raise horses of your own, and perhaps we'll meet again one day.\" You take the eggs, the stranger tips his hat... and vanishes.", "questHorseBoss": "Alptraum", - "questHorseDropHorseEgg": "Pferd (Ei)", - "questHorseUnlockText": "Schaltet die Option Pferdeeier auf dem Marktplatz zu kaufen frei.", + "questHorseDropHorseEgg": "Hengst (Ei)", + "questHorseUnlockText": "Schaltet die Option Hengsteier auf dem Marktplatz zu kaufen frei.", "questBurnoutText": "Burnout und die Geister der Erschöpfung", "questBurnoutNotes": "Es ist weit nach Mitternacht, still und erstickend heiß als Redphoenix und Späheranführer Kiwibot plötzlich durch die Stadttore platzen. \"Wir müssen sämtliche Holzgebäude evakuieren!\", schreit Redphoenix. \"Beeilung!\"

Kiwibot stützt sich an die Wand als sie Luft holt. \"Es erschöpft die Menschen und verwandelt sie in Erschöpfungsgeister! Deshalb hat sich alles verzögert. Das ist, wo die Vermissten hin verschwunden sind. Es stiehlt ihre Energie!\"

\"Es?\", fragt Lemoness.

Und dann nimmt die Hitze Gestalt an.

Es steigt von der Erde empor, als wogende, wirbelnde Masse und die Luft wird erfüllt von einem Gestank nach Rauch und Schwefel. Flammen lecken über den geschmolzenen Boden und verkrümmen sich zu Gliedmaßen und winden sich in entsetzliche Höhen. Glimmende Augen öffnen sich und die Kreatur stößt ein tiefes und knackendes Lachen aus.

Kiwibot flüstert ein einzelnes Wort.

\"Burnout.\"", "questBurnoutCompletion": "Burnout is DEFEATED!

With a great, soft sigh, Burnout slowly releases the ardent energy that was fueling its fire. As the monster curls quietly into ashes, its stolen energy shimmers through the air, rejuvenating the Exhaust Spirits and returning them to their true forms.

Ian, Daniel, and the Seasonal Sorceress cheer as Habiticans rush to greet them, and all the missing citizens of the Flourishing Fields embrace their friends and families. The final Exhaust Spirit transforms into the Joyful Reaper herself!

\"Look!\" whispers @Baconsaur, as the ashes begin to glitter. Slowly, they resolve into hundreds of shining phoenixes!

One of the glowing birds alights on the Joyful Reaper's skeletal arm, and she grins at it. \"It has been a long time since I've had the exquisite privilege to behold a phoenix in the Flourishing Fields,\" she says. \"Although given recent occurrences, I must say, this is highly thematically appropriate!\"

Her tone sobers, although (naturally) her grin remains. \"We're known for being hard-working here, but we are also known for our feasts and festivities. Rather ironic, I suppose, that as we strove to plan a spectacular party, we refused to permit ourselves any time for fun. We certainly won't make the same mistake twice!\"

She claps her hands. \"Now - let's celebrate!\"", @@ -262,10 +262,16 @@ "questBurnoutBossRageQuests": "`Burnout uses EXHAUST STRIKE!`\n\nOh no! Despite our best efforts, we've let some Dailies get away from us, and now Burnout is inflamed with energy! With a crackling snarl, it engulfs Ian the Quest Master in a surge of spectral fire. As fallen quest scrolls smolder, the smoke clears, and you see that Ian has been drained of energy and turned into a drifting Exhaust Spirit!\n\nOnly defeating Burnout can break the spell and restore our beloved Quest Master. Let's keep our Dailies in check and defeat this monster before it attacks again!", "questBurnoutBossRageSeasonalShop": "`Burnout uses EXHAUST STRIKE!`\n\nAhh!!! Our incomplete Dailies have fed the flames of Burnout, and now it has enough energy to strike again! It lets loose a gout of spectral flame that sears the Seasonal Shop. You're horrified to see that the cheery Seasonal Sorceress has been transformed into a drooping Exhaust Spirit.\n\nWe have to rescue our NPCs! Hurry, Habiticans, complete your tasks and defeat Burnout before it strikes for a third time!", "questBurnoutBossRageTavern": "`Burnout uses EXHAUST STRIKE!`\n\nMany Habiticans have been hiding from Burnout in the Tavern, but no longer! With a screeching howl, Burnout rakes the Tavern with its white-hot hands. As the Tavern patrons flee, Daniel is caught in Burnout's grip, and transforms into an Exhaust Spirit right in front of you!\n\nThis hot-headed horror has gone on for too long. Don't give up... we're so close to vanquishing Burnout for once and for all!", - "questFrogText": "Swamp of the Clutter Frog", + "questFrogText": "Sumpf des Chaos-Froschs", "questFrogNotes": "As you and your friends are slogging through the Swamps of Stagnation, @starsystemic points at a large sign. \"Stay on the path -- if you can.\"

\"Surely that isn't hard!\" @RosemonkeyCT says. \"It's broad and clear.\"

But as you continue, you notice that path is gradually overtaken by the muck of the swamp, laced with bits of strange blue debris and clutter, until it's impossible to proceed.

As you look around, wondering how it got this messy, @Jon Arjinborn shouts, \"Look out!\" An angry frog leaps from the sludge, clad in dirty laundry and lit by blue fire. You will have to overcome this poisonous Clutter Frog to progress!", "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", - "questFrogBoss": "Clutter Frog", - "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogBoss": "Chaos-Frosch", + "questFrogDropFrogEgg": "Frosch (Ei)", + "questFrogUnlockText": "Ermöglicht den Kauf von Froscheiern auf dem Marktplatz", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/de/rebirth.json b/common/locales/de/rebirth.json index 0cc265cb7e..87daac4bb7 100644 --- a/common/locales/de/rebirth.json +++ b/common/locales/de/rebirth.json @@ -20,7 +20,7 @@ "rebirthBegan": "Hat ein neues Abenteuer begonnen", "rebirthText": "Hat <%= rebirths %> neue Abenteuer begonnen", "rebirthOrb": "Hat eine Sphäre der Wiedergeburt verwendet nachdem er folgendes Level erreicht hatte:", - "rebirthOrb100": "Used an Orb of Rebirth to start over after attaining Level 100 or higher", + "rebirthOrb100": "Hat eine Sphäre der Wiedergeburt verwendet um noch mal von vorne zu beginnen, nachdem Level 100 oder höher erreicht wurde", "rebirthPop": "Starte einen neuen Charakter mit Level 1, aber behalte Erfolge, Sammlungen und Aufgaben mit Verlauf bei.", "rebirthName": "Sphäre der Wiedergeburt", "reborn": "Wiedergeboren, max. Level <%= reLevel %>" diff --git a/common/locales/de/settings.json b/common/locales/de/settings.json index bf25acde77..b3333b16d7 100644 --- a/common/locales/de/settings.json +++ b/common/locales/de/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Mit dieser Option wird die Liste der Tags verdeckt, wenn Du eine Aufgabe das erste mal bearbeitest.", "startAdvCollapsed": "Erweiterte Optionen standartmäßig verdecken", "startAdvCollapsedPop": "Mit dieser Option werden die erweiterten Optionen verdeckt, wenn Du eine Aufgabe das erste mal bearbeitest.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Anleitung anzeigen", "restartTour": "Startet die Einleitungs Tour, die Du als erstes auf Habitica gesehen hast, neu.", "showBailey": "Bailey anzeigen", @@ -81,7 +86,6 @@ "emailChange1": "Um Deine Email-Adresse zu ändern, schicke bitte eine Email an", "emailChange2": "admin@habitica.com", "emailChange3": "Bitte gib sowohl Deine alte und neue Email-Adresse, als auch Deine Benutzer ID an.", - "username": "Login Name", "usernameOrEmail": "Login Name oder E-Mail-Adresse", "email": "E-Mail", "registeredWithFb": "Mit Facebook registriert", @@ -89,7 +93,7 @@ "loginNameDescription2": "Benutzer->Profil", "loginNameDescription3": "um den Namen, der bei Deinem Avatar und bei Deinen Chat Nachrichten steht zu ändern.", "emailNotifications": "Email Benachrichtigungen", - "wonChallenge": "Du hast einen Wettbewerb gewonnen", + "wonChallenge": "You won a Challenge!", "newPM": "Du hast eine private Nachricht erhalten", "giftedGems": "Verschenkte Edelsteine", "giftedGemsInfo": "<%= amount %> Edelsteine - von <%= name %>", @@ -119,25 +123,25 @@ "promoCodeApplied": "Promo Code aktiviert! Überprüfe dein Inventar", "promoPlaceholder": "Promo Code eingeben", "displayInviteToPartyWhenPartyIs1": "Zeige \"In Gruppe einladen\"-Schaltfläche an, wenn die Gruppe nur 1 Mitglied hat.", - "saveCustomDayStart": "Save Custom Day Start", - "registration": "Registration", - "addLocalAuth": "Add local authentication:", - "generateCodes": "Generate Codes", - "generate": "Generate", - "getCodes": "Get Codes", + "saveCustomDayStart": "Speichere den Tageswechsel", + "registration": "Registrierung", + "addLocalAuth": "Lokale Authentifizierung hinzufügen:", + "generateCodes": "Erstelle Codes", + "generate": "Erstelle", + "getCodes": "Codes erhalten!", "webhooks": "Webhooks", - "enabled": "Enabled", + "enabled": "Aktivieren", "webhookURL": "Webhook URL", - "add": "Add", + "add": "Hinzufügen", "buyGemsGoldCap": "Cap raised to <%= amount %>", - "mysticHourglass": "<%= amount %> Mystic Hourglass", - "mysticHourglassText": "Mystic Hourglasses allow purchasing a previous month's Mystery Item set.", + "mysticHourglass": "<%= amount %> mystische Sanduhr", + "mysticHourglassText": "Mystische Sanduhren erlauben dir ein Überraschungsgegenstandsset früherer Monate zu kaufen.", "purchasedPlanId": "Recurring $<%= price %> each <%= months %> Month(s) (<%= plan %>)", "purchasedPlanExtraMonths": "You have <%= months %> months of subscription credit.", - "consecutiveSubscription": "Consecutive Subscription", - "consecutiveMonths": "Consecutive Months:", + "consecutiveSubscription": "Fortlaufendes Abonnement", + "consecutiveMonths": "Aufeinanderfolgende Monate:", "gemCapExtra": "Gem Cap Extra:", - "mysticHourglasses": "Mystic Hourglasses:", + "mysticHourglasses": "Mystische Stundengläser", "paypal": "PayPal", "amazonPayments": "Amazon Payments" } \ No newline at end of file diff --git a/common/locales/de/subscriber.json b/common/locales/de/subscriber.json index 191396d183..20256f9703 100644 --- a/common/locales/de/subscriber.json +++ b/common/locales/de/subscriber.json @@ -59,8 +59,8 @@ "timeTravelers": "Mysteriöse Zeitreisende", "timeTravelersTitleNoSub": "<%= linkStartTyler %>Tyler<%= linkEnd %> und <%= linkStartVicky %>Vicky<%= linkEnd %>", "timeTravelersTitle": "Mysteriöse Zeitreisende", - "timeTravelersPopoverNoSub": "You'll need a Mystic Hourglass to summon the mysterious Time Travelers! <%= linkStart %>Subscribers<%= linkEnd %> earn one Mystic Hourglass for every three months of consecutive subscribing. Come back when you have a Mystic Hourglass, and the Time Travelers will fetch you a rare pet, mount, or Subscriber Item Set from the past... or maybe even the future.", - "timeTravelersPopover": "We see you have a Mystic Hourglass, so we will happily travel back in time for you! Please choose the pet, mount, or Mystery Item Set you would like. You can see a list of the past item sets here! If those don't satisfy you, perhaps you'd be interested in one of our fashionably futuristic Steampunk Item Sets?", + "timeTravelersPopoverNoSub": "Du brauchst eine mystische Sanduhr um die mysteriösen Zeitreisenden herbeizurufen! <%= linkStart %>Abbonnementen<%= linkEnd %> verdienen eine mystische Sanduhr für je drei Monate durchgehendes abonnieren. Komm zurück, wenn du eine mystischer Sanduhr hast und die Zeitreisenden werden Dir ein seltenes Haustier, Reittier oder Abonnementen Gegenstandsset aus der Vergangenheit holen... oder vielleicht sogar aus der Zukunft.", + "timeTravelersPopover": "Wir sehen du hast eine mystische Sanduhr, deshalb werden wir gerne für dich zurück durch die Zeit reisen! Bitte wähle das Haustier, Reittier oder mystische Gegenstandsset, dass Du haben möchtest. Die Liste aller vergangenen Gegenstandssets kannst du hier finden! Wenn diese Dich nicht zufrieden stellen können wir dich vielleicht für eines unserer futuristischen Steampunk Gegenstandssets interessieren?", "timeTravelersAlreadyOwned": "Herzlichen Glückwunsch! Du besitzt bereits alles, was die Zeitreisenden gerade anbieten können. Danke, dass du die Seite unterstützt!", "mysticHourglassPopover": "Eine Mystische Sanduhr erlaubt dir für eine begrenzte Zeit spezifische alte Gegenstand, so wie Geheimnis Abonnenten-Sets und Belohnungen von Welt-Bosse, zu kaufen.", "subUpdateCard": "Aktualisiere deine Karte", diff --git a/common/locales/en/front.json b/common/locales/en/front.json index 5caba021eb..5738e14df2 100644 --- a/common/locales/en/front.json +++ b/common/locales/en/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] has really helped me impart structure to my life in graduate school.", "invalidEmail": "A valid email address is required in order to perform a password reset.", "irishfeet123Quote": "I've had horrible habits with clearing my place completely after meals and leaving cups all over the place. [Habitica] has cured that!", - "joinOthers": "Join 900,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Before [Habitica], I was stuck with my thesis, as well as dissatisfied with my personal discipline regarding housework and things like learning vocabulary and studying Go theory. It turns out breaking down these tasks into smaller manageable checklists is quite the thing to keep me motivated and constantly working.", "landingadminlink": "administrative packages", "landingend": "Not convinced yet?", @@ -186,7 +186,7 @@ "imagine1": "Imagine if improving your life were as fun as playing a game.", "landingCopy1": "Advance in the game by completing your real-life tasks.", "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", - "landingCopy3": "Join over 900,000 people having fun as they improve their lives.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", "alreadyHaveAccount": "I already have an account!", "getStartedNow": "Get Started Now!" } diff --git a/common/locales/en@pirate/challenge.json b/common/locales/en@pirate/challenge.json index 7f0afea865..28d12939fd 100644 --- a/common/locales/en@pirate/challenge.json +++ b/common/locales/en@pirate/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "You don't have permissions to edit this challenge", "noPermissionDeleteChallenge": "You don't have permissions to delete this challenge", "noPermissionCloseChallenge": "You don't have permissions to close this challenge", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "no owner", "noChallengeOwnerPopover": "This challenge does not have an owner because the person who created the challenge deleted their account." } \ No newline at end of file diff --git a/common/locales/en@pirate/character.json b/common/locales/en@pirate/character.json index 1a7150a82d..232d2697ad 100644 --- a/common/locales/en@pirate/character.json +++ b/common/locales/en@pirate/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Has upgraded to th' maximum weapon 'n armor set for yee followin' classes", "level": "Level", "levelUp": "Level Up!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "HP", "mp": "MP", diff --git a/common/locales/en@pirate/content.json b/common/locales/en@pirate/content.json index 4d9a5f102a..42294ea9ee 100644 --- a/common/locales/en@pirate/content.json +++ b/common/locales/en@pirate/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Frog", "questEggFrogMountText": "Frog", "questEggFrogAdjective": "a princely", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Base", "hatchingPotionWhite": "White", diff --git a/common/locales/en@pirate/contrib.json b/common/locales/en@pirate/contrib.json index 87b64fc4ff..038ed83b21 100644 --- a/common/locales/en@pirate/contrib.json +++ b/common/locales/en@pirate/contrib.json @@ -1,15 +1,15 @@ { "friend": "Bucko", "friendFirst": "When yer first set o' submissions be deployed, ye will receive th' Habitica Contributor's badge. Yer name in Tavern chat will proudly display that ye be a contributor. As a bounty for yer work, ye will also receive 3 Sapphires.", - "friendSecond": "When ye fourth set 'o submissions be deployed, th' Crystal Sword gunna be available fer purchase in th' Rewards shop. As a bounty fer ye continued work, ye gunna also receive 3 Sapphires.", + "friendSecond": "When ye second set 'o submissions be deployed, th' Crystal Armor gunna be available fer purchase in th' Rewards shop. As a bounty fer ye continued work, ye gunna also receive 3 Sapphires.", "elite": "Boatswain", - "eliteThird": "When ye fifth set 'o submissions be deployed, th' Crystal Shield gunna be available fer purchase in th' Rewards shop. As a bounty fer ye continued work, ye gunna also receive 3 Sapphires.", - "eliteFourth": "When ye fifth set 'o submissions be deployed, th' Crystal Shield gunna be available fer purchase in th' Rewards shop. As a bounty fer ye continued work, ye gunna also receive 4 Sapphires.", + "eliteThird": "When ye third set 'o submissions be deployed, th' Crystal Helmet gunna be available fer purchase in th' Rewards shop. As a bounty fer ye continued work, ye gunna also receive 3 Sapphires.", + "eliteFourth": "When ye fourth set 'o submissions be deployed, th' Crystal Sword gunna be available fer purchase in th' Rewards shop. As a bounty fer ye continued work, ye gunna also receive 4 Sapphires.", "champion": "Quartermaster", - "championFifth": "When ye fourth set 'o submissions be deployed, th' Crystal Sword gunna be available fer purchase in th' Rewards shop. As a bounty fer ye continued work, ye gunna also receive 4 Sapphires.", - "championSixth": "When yer fifth set 'o submissions be deployed, th' Crystal Shield gunna be available fer purchase in th' Rewards shop. As a bounty fer ye continued work, ye gunna also receive 4 Sapphires.", + "championFifth": "When ye fifth set 'o submissions be deployed, th' Crystal Shield gunna be available fer purchase in th' Rewards shop. As a bounty fer ye continued work, ye gunna also receive 4 Sapphires.", + "championSixth": "When yer sixth set 'o submissions be deployed, ye gunna receive a Hydra Pet. Ye gunna also receive 4 Sapphires.", "legendary": "Captain", - "legSeventh": "When yer seventh set o' submissions be deployed, you will receive 4 Sapphiresan' become a member o' t' honored Contributor's Guild an' be privy t' th' behind-the-scenes details o' Habitica! Further contributions do not increase your tier, but you may continue t' earn Sapphire bounties and titles.", + "legSeventh": "When yer seventh set o' submissions be deployed, ye gunna receive 4 Sapphiresan' become a member o' t' honored Contributor's Guild an' be privy t' th' behind-the-scenes details o' Habitica! Further contributions do not increase yer tier, but ye may continue t' earn Sapphire bounties and titles.", "moderator": "Seadog", "guardian": "Flibustier", "guardianText": "There be also a couple 'a Moderators assistin' the staff members. They be wise fellows, so respect and heed 'em or else!", diff --git a/common/locales/en@pirate/front.json b/common/locales/en@pirate/front.json index e6a6d2deb4..582f68f9df 100644 --- a/common/locales/en@pirate/front.json +++ b/common/locales/en@pirate/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] has really helped me impart structure to my life in graduate school.", "invalidEmail": "Arr, we need yer email before we can reset yer password, matey!", "irishfeet123Quote": "I've had horrible habits with clearing my place completely after meals and leaving cups all over the place. [Habitica] has cured that!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Before [Habitica], I was stuck with my thesis, as well as dissatisfied with my personal discipline regarding housework and things like learning vocabulary and studying Go theory. It turns out breaking down these tasks into smaller manageable checklists is quite the thing to keep me motivated and constantly working.", "landingadminlink": "administrative packages", "landingend": "Haven't reeled ye in yet?", @@ -182,5 +182,11 @@ "tweet": "Tweet", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/en@pirate/generic.json b/common/locales/en@pirate/generic.json index 81f0c0ff69..4072d983ec 100644 --- a/common/locales/en@pirate/generic.json +++ b/common/locales/en@pirate/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Sending ye a thousand thanks.", "thankyou3": "I be  very grateful - thank ye!", "thankyouCardAchievementTitle": "Greatly Grateful", - "thankyouCardAchievementText": "Thanks fer bein' thankful! Sent or received <%= cards %> Thank-Ye cards." + "thankyouCardAchievementText": "Thanks fer bein' thankful! Sent or received <%= cards %> Thank-Ye cards.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/en@pirate/pets.json b/common/locales/en@pirate/pets.json index c1c47b2bc7..906aca2f7c 100644 --- a/common/locales/en@pirate/pets.json +++ b/common/locales/en@pirate/pets.json @@ -58,8 +58,16 @@ "firstDrop": "Ye've unlocked th' Drop System! Now when ye complete tasks, ye have a small chance o' findin' an item, includin' eggs, potions, an' food! Ye just found a <%= eggText %> Egg! <%= eggNotes %>", "useGems": "If ye've got yer eye on a pet, but can't wait any longer fer it t' drop, use Sapphires in Inventory > Market t' buy one!", "hatchAPot": "Hatch a <%= potion %> <%= egg %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Feed <%= article %><%= text %> t' yer <%= name %>?", "useSaddle": "Saddle <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Key t' th' Kennels", diff --git a/common/locales/en@pirate/quests.json b/common/locales/en@pirate/quests.json index 592be10aba..464cbb6e14 100644 --- a/common/locales/en@pirate/quests.json +++ b/common/locales/en@pirate/quests.json @@ -76,5 +76,7 @@ "startAQuest": "START AN ADVENTURE", "startQuest": "Start Adventure", "whichQuestStart": "Which adventure do ye want t' start?", - "getMoreQuests": "Get more adventures" + "getMoreQuests": "Get more adventures", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/en@pirate/questscontent.json b/common/locales/en@pirate/questscontent.json index b1ebab7f8c..9cb4dc2fdb 100644 --- a/common/locales/en@pirate/questscontent.json +++ b/common/locales/en@pirate/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/en@pirate/settings.json b/common/locales/en@pirate/settings.json index 27f61001fd..1c1d05826b 100644 --- a/common/locales/en@pirate/settings.json +++ b/common/locales/en@pirate/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "With this option set, th' list o' task tags will be hidden when ye first open a task fer editing.", "startAdvCollapsed": "Advanced Options in tasks start collapsed", "startAdvCollapsedPop": "With this option set, Advanced Options will be hidden when ye first open a task fer editing.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Show Tour", "restartTour": "Restart th' introductory tour from when ye first joined Habitica.", "showBailey": "Show Bailey", @@ -81,7 +86,6 @@ "emailChange1": "T' change yer email address, please send an email t'", "emailChange2": "admin@habitica.com", "emailChange3": "including both yer old an' new email address as well as yer User ID.", - "username": "Login Name", "usernameOrEmail": "Login Name or Email", "email": "Email", "registeredWithFb": "Registered with Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "User->Profile", "loginNameDescription3": "t' change th' name that appears in yer avatar an' chat messages.", "emailNotifications": "Email Notifications", - "wonChallenge": "Ye Won a Challenge", + "wonChallenge": "You won a Challenge!", "newPM": "Received Private Message", "giftedGems": "Gifted Sapphires", "giftedGemsInfo": "<%= amount %> Sapphires - by <%= name %>", diff --git a/common/locales/en_GB/challenge.json b/common/locales/en_GB/challenge.json index 404613170d..3b0ee8f47f 100644 --- a/common/locales/en_GB/challenge.json +++ b/common/locales/en_GB/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "You don't have permissions to edit this challenge", "noPermissionDeleteChallenge": "You don't have permissions to delete this challenge", "noPermissionCloseChallenge": "You don't have permissions to close this challenge", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "no owner", "noChallengeOwnerPopover": "This challenge does not have an owner because the person who created the challenge deleted their account." } \ No newline at end of file diff --git a/common/locales/en_GB/character.json b/common/locales/en_GB/character.json index 69cfadf7bd..f0c7cc46d7 100644 --- a/common/locales/en_GB/character.json +++ b/common/locales/en_GB/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Has upgraded to the maximum weapon and armour set for the following classes:", "level": "Level", "levelUp": "Level Up!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "HP", "mp": "MP", diff --git a/common/locales/en_GB/content.json b/common/locales/en_GB/content.json index cf17bd1ed0..0477c48046 100644 --- a/common/locales/en_GB/content.json +++ b/common/locales/en_GB/content.json @@ -43,7 +43,7 @@ "questEggDeerAdjective": "an elegant", "questEggEggText": "Egg", "questEggEggMountText": "Egg Basket", - "questEggEggAdjective": "a colorful", + "questEggEggAdjective": "a colourful", "questEggRatText": "Rat", "questEggRatMountText": "Rat", "questEggRatAdjective": "a dirty", @@ -98,6 +98,9 @@ "questEggFrogText": "Frog", "questEggFrogMountText": "Frog", "questEggFrogAdjective": "a princely", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Base", "hatchingPotionWhite": "White", diff --git a/common/locales/en_GB/front.json b/common/locales/en_GB/front.json index a74634350f..6f3d143fa4 100644 --- a/common/locales/en_GB/front.json +++ b/common/locales/en_GB/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] has really helped me impart structure to my life in graduate school.", "invalidEmail": "A valid email address is required in order to perform a password reset.", "irishfeet123Quote": "I've had horrible habits with clearing my place completely after meals and leaving cups all over the place. [Habitica] has cured that!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Before [Habitica], I was stuck with my thesis, as well as dissatisfied with my personal discipline regarding housework and things like learning vocabulary and studying Go theory. It turns out breaking down these tasks into smaller manageable checklists is quite the thing to keep me motivated and constantly working.", "landingadminlink": "administrative packages", "landingend": "Not convinced yet?", @@ -182,5 +182,11 @@ "tweet": "Tweet", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/en_GB/generic.json b/common/locales/en_GB/generic.json index 4f3d6333a1..77e679d413 100644 --- a/common/locales/en_GB/generic.json +++ b/common/locales/en_GB/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Sending you a thousand thanks.", "thankyou3": "I'm very grateful—thank you!", "thankyouCardAchievementTitle": "Greatly Grateful", - "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank You cards." + "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank You cards.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/en_GB/pets.json b/common/locales/en_GB/pets.json index 2a672b16ef..7c49cba987 100644 --- a/common/locales/en_GB/pets.json +++ b/common/locales/en_GB/pets.json @@ -58,8 +58,16 @@ "firstDrop": "You've unlocked the Drop System! Now, when you complete tasks you have a small chance of finding an item, including eggs, potions, and food! You just found a <%= eggText %> Egg! <%= eggNotes %>", "useGems": "If you've got your eye on a pet, but can't wait any longer for it to drop, use Gems in Inventory > Market to buy one!", "hatchAPot": "Hatch a <%= potion %> <%= egg %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Feed <%= article %><%= text %> to your <%= name %>?", "useSaddle": "Saddle <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Key to the Kennels", diff --git a/common/locales/en_GB/quests.json b/common/locales/en_GB/quests.json index dc5ca1d09f..85695d3000 100644 --- a/common/locales/en_GB/quests.json +++ b/common/locales/en_GB/quests.json @@ -76,5 +76,7 @@ "startAQuest": "START A QUEST", "startQuest": "Start Quest", "whichQuestStart": "Which quest do you want to start?", - "getMoreQuests": "Get more quests" + "getMoreQuests": "Get more quests", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/en_GB/questscontent.json b/common/locales/en_GB/questscontent.json index b9de92cc06..808ebe1f52 100644 --- a/common/locales/en_GB/questscontent.json +++ b/common/locales/en_GB/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/en_GB/settings.json b/common/locales/en_GB/settings.json index e3c3a51c07..e0b3e1ec7a 100644 --- a/common/locales/en_GB/settings.json +++ b/common/locales/en_GB/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "With this option set, the list of task tags will be hidden when you first open a task for editing.", "startAdvCollapsed": "Advanced Options in tasks start collapsed", "startAdvCollapsedPop": "With this option set, Advanced Options will be hidden when you first open a task for editing.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Show Tour", "restartTour": "Restart the introductory tour from when you first joined Habitica.", "showBailey": "Show Bailey", @@ -81,7 +86,6 @@ "emailChange1": "To change your email address, please send an email to", "emailChange2": "admin@habitica.com", "emailChange3": "including both your old and new email address as well as your User ID.", - "username": "Login Name", "usernameOrEmail": "Login Name or Email", "email": "Email", "registeredWithFb": "Registered with Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "User->Profile", "loginNameDescription3": "to change the name that appears in your avatar and chat messages.", "emailNotifications": "Email Notifications", - "wonChallenge": "You Won a Challenge", + "wonChallenge": "You won a Challenge!", "newPM": "Received Private Message", "giftedGems": "Gifted Gems", "giftedGemsInfo": "<%= amount %> Gems - by <%= name %>", diff --git a/common/locales/es/challenge.json b/common/locales/es/challenge.json index 2f763d2d0a..d7280b0c3e 100644 --- a/common/locales/es/challenge.json +++ b/common/locales/es/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "No tienes permiso para editar este desafío", "noPermissionDeleteChallenge": "No tienes permiso para eliminar este desafío", "noPermissionCloseChallenge": "No tienes permiso para cerrar este desafío", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "no owner", "noChallengeOwnerPopover": "This challenge does not have an owner because the person who created the challenge deleted their account." } \ No newline at end of file diff --git a/common/locales/es/character.json b/common/locales/es/character.json index 562fb5b216..28add8a231 100644 --- a/common/locales/es/character.json +++ b/common/locales/es/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Has conseguido el conjunto de armas y armadura de mayor nivel en las siguientes clases:", "level": "Nivel", "levelUp": "¡Subiste de Nivel!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Maná", "hp": "PV", "mp": "PM", diff --git a/common/locales/es/content.json b/common/locales/es/content.json index b6f4d468ec..a329e89dda 100644 --- a/common/locales/es/content.json +++ b/common/locales/es/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Frog", "questEggFrogMountText": "Frog", "questEggFrogAdjective": "a princely", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Base", "hatchingPotionWhite": "Blanco", diff --git a/common/locales/es/faq.json b/common/locales/es/faq.json index 48d2413aeb..026f278de1 100644 --- a/common/locales/es/faq.json +++ b/common/locales/es/faq.json @@ -10,8 +10,8 @@ "iosFaqAnswer2": "Esta wiki tiene cuatro listas de tareas de muestras para usar como inspiración.\n

\n* [", "webFaqAnswer2": "Esta wiki tiene cuatro listas de tareas de muestras para usar como inspiración.\n* [Hábitos de muestras](http://habitica.wikia.com/wiki/Sample_Habits)\n* [Diarias de muestras](http://habitica.wikia.com/wiki/Sample_Dailies)\n* [Tareas pendientes de muestras](http://habitica.wikia.com/wiki/Sample_To-Dos)\n* [Recompensas personales de muestras](http://habitica.wikia.com/wiki/Sample_Custom_Rewards)", "faqQuestion3": "¿Por qué las tareas cambian de color?", - "iosFaqAnswer3": "Your tasks change color based on how well you are currently accomplishing them! Each new task starts out as a neutral yellow. Perform Dailies or positive Habits more frequently and they move toward blue. Miss a Daily or give in to a bad Habit and the task moves toward red. The redder a task, the more rewards it will give you, but if it's a Daily or bad Habit, the more it will hurt you! This helps motivate you to complete the tasks that are giving you trouble.", - "webFaqAnswer3": "Your tasks change color based on how well you are currently accomplishing them! Each new task starts out as a neutral yellow. Perform Dailies or positive Habits more frequently and they move toward blue. Miss a Daily or give in to a bad Habit and the task moves toward red. The redder a task, the more rewards it will give you, but if it’s a Daily or bad Habit, the more it will hurt you! This helps motivate you to complete the tasks that are giving you trouble.", + "iosFaqAnswer3": "Tus tareas cambian de color según que tan bien las cumplas! Cada tarea nueva empieza neutralmente con el color amarillo. Realiza tareas Diarias o Hábitos positivos consecutivamente y se volverán azules. Descuida una tarea Diaria o realiza un Habito negativo y se volverán rojos. Entre mas roja sea una tarea, más recompensas recibirás, pero si son tareas Diarias o Hábitos negativos, te harán mas daño! Esto ayuda a motivarte a realizar las tareas que te están dando problemas.", + "webFaqAnswer3": "Tus tareas cambian de color según que tan bien las cumplas! Cada tarea nueva empieza neutralmente con el color amarillo. Realiza tareas Diarias o Hábitos positivos consecutivamente y se volverán azules. Descuida una tarea Diaria o realiza un Habito negativo y se volverán rojos. Entre mas roja sea una tarea, más recompensas recibirás, pero si son tareas Diarias o Hábitos negativos, te harán mas daño! Esto ayuda a motivarte a realizar las tareas que te están dando problemas.", "faqQuestion4": "¿Por qué mi avatar pierde salud y cómo puedo recuperarla?", "iosFaqAnswer4": "There are several things that can cause you to take damage. First, if you left Dailies incomplete overnight, they will damage you. Second, if you tap a bad Habit, it will damage you. Finally, if you are in a Boss Battle with your Party and one of your Party mates did not complete all their Dailies, the Boss will attack you.\n\n The main way to heal is to gain a level, which restores all your health. You can also buy a Health Potion with gold from the Rewards column. Plus, at level 10 or above, you can choose to become a Healer, and then you will learn healing skills. If you are in a Party with a Healer, they can heal you as well.", "webFaqAnswer4": "There are several things that can cause you to take damage. First, if you left Dailies incomplete overnight, they will damage you. Second, if you click a bad Habit, it will damage you. Finally, if you are in a Boss Battle with your party and one of your party mates did not complete all their Dailies, the Boss will attack you.\n

\n The main way to heal is to gain a level, which restores all your Health. You can also buy a Health Potion with Gold from the Rewards column. Plus, at level 10 or above, you can choose to become a Healer, and then you will learn healing skills. If you are in a party (under Social > Party) with a Healer, they can heal you as well.", @@ -30,15 +30,15 @@ "faqQuestion9": "¿Cómo peleo con los monstruos y hago misiones?", "iosFaqAnswer9": "First, you need to join or start a Party (see above). Although you can battle monsters alone, we recommend playing in a group, because this will make Quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n\n Next, you need a Quest Scroll, which are stored under Menu > Items. There are three ways to get a scroll:\n\n - At level 15, you get a Quest-line, aka three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively. \n - When you invite people to your Party, you'll be rewarded with the Basi-List Scroll!\n - You can buy Quests from the Quests Page on the [website](https://habitica.com/#/options/inventory/quests) for Gold and Gems. (We will add this feature to the app in a future update.)\n\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading by pulling down on the screen may be required to see the Boss's health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your Party at the same time that you damage the Boss. \n\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", "webFaqAnswer9": "First, you need to join or start a party (under Social > Party). Although you can battle monsters alone, we recommend playing in a group, because this will make quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n

\n Next, you need a Quest Scroll, which are stored under Inventory > Quests. There are three ways to get a scroll:\n

\n * When you invite people to your party, you’ll be rewarded with the Basi-List Scroll!\n * At level 15, you get a Quest-line, i.e., three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively.\n * You can buy Quests from the Quests Page (Inventory > Quests) for Gold and Gems.\n

\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading may be required to see the Boss's Health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your party at the same time that you damage the Boss.\n

\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", - "faqQuestion10": "What are Gems, and how do I get them?", + "faqQuestion10": "¿Que son gemas, y como puedo obtener ellas?", "iosFaqAnswer10": "Gems are purchased with real money by tapping on the gem icon in the header. When people buy gems, they are helping us to keep the site running. We're very grateful for their support!\n\n In addition to buying gems directly, there are three other ways players can gain gems:\n\n * Win a Challenge on the [website](https://habitica.com) that has been set up by another player under Social > Challenges. (We will be adding Challenges to the app in a future update!)\n * Subscribe on the [website](https://habitica.com/#/options/settings/subscription) and unlock the ability to buy a certain number of gems per month.\n * Contribute your skills to the Habitica project. See this wiki page for more details: [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica).\n\n Keep in mind that items purchased with gems do not offer any statistical advantages, so players can still make use of the app without them!", "webFaqAnswer10": "Gems are [purchased with real money](https://habitica.com/#/options/settings/subscription), although [subscribers](https://habitica.com/#/options/settings/subscription) can purchase them with Gold. When people subscribe or buy Gems, they are helping us to keep the site running. We're very grateful for their support!\n

\n In addition to buying Gems directly or becoming a subscriber, there are two other ways players can gain Gems:\n

\n * Win a Challenge that has been set up by another player under Social > Challenges.\n * Contribute your skills to the Habitica project. See this wiki page for more details: [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica)\n

\n Keep in mind that items purchased with Gems do not offer any statistical advantages, so players can still make use of the site without them!", "faqQuestion11": "Como reportó un bug o solicitó una característica ", "iosFaqAnswer11": "Puedes reportar un bug, solicitar una característica, o ", "webFaqAnswer11": "Bug reports are collected on GitHub. Go to [Help > Report a Bug](https://github.com/HabitRPG/habitrpg/issues/2760) and follow the instructions. Don't worry, we'll get you fixed up soon!\n

\n Feature requests are collected on Trello. Go to [Help > Request a Feature](https://trello.com/c/odmhIqyW/440-read-first-table-of-contents) and follow the instructions. Ta-da!", - "faqQuestion12": "How do I battle a World Boss?", + "faqQuestion12": "¿Cómo puedo combatir un jefe de mundo?", "iosFaqAnswer12": "World Bosses are special monsters that appear in the Tavern. All active users are automatically battling the Boss, and their tasks and skills will damage the Boss as usual.\n\n You can also be in a normal Quest at the same time. Your tasks and skills will count towards both the World Boss and the Boss/Collection Quest in your party.\n\n A World Boss will never hurt you or your account in any way. Instead, it has a Rage Bar that fills when users skip Dailies. If its Rage bar fills, it will attack one of the Non-Player Characters around the site and their image will change.\n\n You can read more about [past World Bosses](http://habitica.wikia.com/wiki/World_Bosses) on the wiki.", "webFaqAnswer12": "World Bosses are special monsters that appear in the Tavern. All active users are automatically battling the Boss, and their tasks and skills will damage the Boss as usual.\n

\n You can also be in a normal Quest at the same time. Your tasks and skills will count towards both the World Boss and the Boss/Collection Quest in your party.\n

\n A World Boss will never hurt you or your account in any way. Instead, it has a Rage Bar that fills when users skip Dailies. If its Rage bar fills, it will attack one of the Non-Player Characters around the site and their image will change.\n

\n You can read more about [past World Bosses](http://habitica.wikia.com/wiki/World_Bosses) on the wiki.", "iosFaqStillNeedHelp": "Si tienes una pregunta que no est´å en esta lista, ¡ven a preguntar en la Taberna debajo de Menú > Taberna! Estamos felices a ayudar.", - "webFaqStillNeedHelp": "If you have a question that isn't on this list, come ask in the [Newbies Guild](https://habitica.com/#/options/groups/guilds/5481ccf3-5d2d-48a9-a871-70a7380cee5a)! We're happy to help." + "webFaqStillNeedHelp": "Si tienes alguna pregunta que no esté en esta lista, ven a preguntar al Gremio [The Newbies] (https://habitica.com/#/options/groups/guilds/5481ccf3-5d2d-48a9-a871-70a7380cee5a)! Estaremos felices de ayudar." } \ No newline at end of file diff --git a/common/locales/es/front.json b/common/locales/es/front.json index 6dbf473a51..93f7eec4c3 100644 --- a/common/locales/es/front.json +++ b/common/locales/es/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] realmente me ha ayudado a estructurar mi vida universitaria", "invalidEmail": "Se requiere una dirección de correo electrónico válida para resetear la contraseña.", "irishfeet123Quote": "He tenido terribles hábitos limpiando mi casa completamente tras las comidas y dejándome tazas por todas partes. ¡[Habitica] ha curado eso!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Antes de [Habitica], estaba atascado con mi tesis, así como insatisfecho con mi disciplina personal en cuanto a tareas domésticas y cosas como aprender vocabulario y estudiar teoría de Go. Resulta que romper estas tareas en pequeñas y manejables listas es exactamente lo que me mantiene motivado y constantemente trabajando.", "landingadminlink": "paquetes administrativos", "landingend": "¿Todavía no estás convencido?", @@ -182,5 +182,11 @@ "tweet": "Tuitear", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/es/generic.json b/common/locales/es/generic.json index 29a94b3566..681695781b 100644 --- a/common/locales/es/generic.json +++ b/common/locales/es/generic.json @@ -134,5 +134,17 @@ "thankyou2": "¡Un millón de gracias!", "thankyou3": "Estoy muy agradecido - ¡gracias!", "thankyouCardAchievementTitle": "Agradablemente Agradecido", - "thankyouCardAchievementText": "¡Gracias por las gracias! Envió o recibió <%= cards %> tarjetas de agradecimiento." + "thankyouCardAchievementText": "¡Gracias por las gracias! Envió o recibió <%= cards %> tarjetas de agradecimiento.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/es/messages.json b/common/locales/es/messages.json index 5bb61d4385..6141b279b0 100644 --- a/common/locales/es/messages.json +++ b/common/locales/es/messages.json @@ -31,12 +31,12 @@ "armoireEquipment": "<%= image %> Has encontrado un objeto de equipamiento raro en el armario: <%= dropText %>! ¡Genial!", "armoireFood": "<%= image %> Hurgas en el Ropero y encuentras <%= dropArticle %><%= dropText %>. ¿Qué hace eso aquí?", "armoireExp": "Luchas con el Ropero y ganas Experiencia. ¡Toma eso!", - "messageInsufficientGems": "Not enough gems!", + "messageInsufficientGems": "No hay suficientes gemas!", "messageAuthPasswordMustMatch": ":password and :confirmPassword don't match", "messageAuthCredentialsRequired": ":username, :email, :password, :confirmPassword required", - "messageAuthUsernameTaken": "Username already taken", - "messageAuthEmailTaken": "Email already taken", - "messageAuthNoUserFound": "No user found.", + "messageAuthUsernameTaken": "El nombre de usuario ya está en uso", + "messageAuthEmailTaken": "El correo electrónico ya está en uso", + "messageAuthNoUserFound": "No se encontró el usuario.", "messageAuthMustBeLoggedIn": "You must be logged in.", "messageAuthMustIncludeTokens": "You must include a token and uid (user id) in your request", "messageGroupNotFound": "Group not found or you don't have access.", diff --git a/common/locales/es/pets.json b/common/locales/es/pets.json index fbc3265345..15eaacb8a4 100644 --- a/common/locales/es/pets.json +++ b/common/locales/es/pets.json @@ -58,8 +58,16 @@ "firstDrop": "¡Has desbloqueado el sistema de botines! Ahora, al completar tareas, es posible que encuentres algún articulo, como huevos, pociones y alimentos. ¡Acabas de encontrar un <%= eggText %>huevo! <%= eggNotes %>", "useGems": "Si tienes el ojo puesto en una mascota, pero no quieres seguir esperando a que te toque, usa tus gemas en Inventario > Mercado para comprarla.", "hatchAPot": "¿Eclosionar un <%= egg %> <%= potion %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "¿Dar de comer <%= article %><%= text %>a su <%= name %>?", "useSaddle": "¿Ensillar <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= egg %> <%= potion %>", "mountName": "<%= mount %> <%= potion %>", "petKeyName": "Llave de la perrera", diff --git a/common/locales/es/quests.json b/common/locales/es/quests.json index bad60e0e22..6b80a2f4d5 100644 --- a/common/locales/es/quests.json +++ b/common/locales/es/quests.json @@ -76,5 +76,7 @@ "startAQuest": "EMPRENDER UNA MISIÓN", "startQuest": "Emprender misión", "whichQuestStart": "¿Qué misión quieres emprender?", - "getMoreQuests": "Conseguir más misiones" + "getMoreQuests": "Conseguir más misiones", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/es/questscontent.json b/common/locales/es/questscontent.json index 098888e48c..a3b455db98 100644 --- a/common/locales/es/questscontent.json +++ b/common/locales/es/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/es/settings.json b/common/locales/es/settings.json index 4f7ebe6fe2..431be93719 100644 --- a/common/locales/es/settings.json +++ b/common/locales/es/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Con esta opción marcada, la lista de etiquetas estará escondida al abrir la tarea para editarla.", "startAdvCollapsed": "Las opciones avanzadas de las tareas no se abren automáticamente", "startAdvCollapsedPop": "Con esta opción marcada, las opciones avanzadas estarán escondidas al abrir la tarea para editarla.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Empezar el Rour", "restartTour": "Reiniciar la introducción a Habitica que se muestra al registrarse.", "showBailey": "Mostrar a Bailey", @@ -81,7 +86,6 @@ "emailChange1": "Para cambiar tu correo electrónico, por favor, envía un email a", "emailChange2": "admin@habitica.com", "emailChange3": "incluyendo tu nueva y tu antigua dirección de correo electrónico, así como tu ID de Usuario.", - "username": "Nombre de Usuario", "usernameOrEmail": "Introduce tu Nombre o Correo electrónico.", "email": "Correo Electrónico", "registeredWithFb": "Registrado con Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "Usuario->Perfil", "loginNameDescription3": "para cambiar el nombre que aparece en tu avatar y en los mensajes del chat.", "emailNotifications": "Notificaciones por Correo Electrónico", - "wonChallenge": "Has ganado un Desafío", + "wonChallenge": "You won a Challenge!", "newPM": "Mensaje Privado Recibido", "giftedGems": "Gemas Regaladas", "giftedGemsInfo": "<%= amount %> Gemas - por <%= name %>", diff --git a/common/locales/es/spells.json b/common/locales/es/spells.json index 0fc2d6d573..dfa3d033ec 100644 --- a/common/locales/es/spells.json +++ b/common/locales/es/spells.json @@ -16,9 +16,9 @@ "spellWarriorIntimidateText": "Mirada Intimidante.", "spellWarriorIntimidateNotes": "Tu mirada provoca el temor de tus enemigos. Aumenta por hoy el atributo de constitución de todo tu grupo. (Proporcional a la constitución antes de aplicarlo).", "spellRoguePickPocketText": "Hurtar", - "spellRoguePickPocketNotes": "Te robas una tarea cercana. Ganas oro! Clickea en la tarea a lanzar. (Basado en: Percepción)", + "spellRoguePickPocketNotes": "Le robas a una tarea cercana. Ganas oro! Clickea en la tarea a lanzar. (Basado en: Percepción)", "spellRogueBackStabText": "Puñalada", - "spellRogueBackStabNotes": "Delatas a una tarea ridícula. ¡Ganas oro y puntos de experiencia! Haz clic en una tarea para lanzarlo. (Proporcional a la fuerza).", + "spellRogueBackStabNotes": "Delatas a una tarea necia. ¡Ganas oro y puntos de experiencia! Haz clic en una tarea para lanzarlo. (Proporcional a la fuerza).", "spellRogueToolsOfTradeText": "Herramientas del Oficio", "spellRogueToolsOfTradeNotes": "Compartes el talento que tienes con tus amigos. Aumenta por hoy la percepción de todo el grupo. (Proporcional a la percepción antes de aplicarlo).", "spellRogueStealthText": "Sigilo", diff --git a/common/locales/es_419/backgrounds.json b/common/locales/es_419/backgrounds.json index 18ec91cbec..a81ee93326 100644 --- a/common/locales/es_419/backgrounds.json +++ b/common/locales/es_419/backgrounds.json @@ -119,11 +119,11 @@ "backgroundSlimySwampNotes": "Atrafaga a través del pantano legamoso.", "backgroundSwarmingDarknessText": "Enjambre de oscuridad", "backgroundSwarmingDarknessNotes": "Tiembla en el enjambre de oscuridad.", - "backgrounds112015": "SET 18: Released November 2015", - "backgroundFloatingIslandsText": "Floating Islands", - "backgroundFloatingIslandsNotes": "Hop across the Floating Islands.", - "backgroundNightDunesText": "Night Dunes", - "backgroundNightDunesNotes": "Walk peacefully through the Night Dunes.", - "backgroundSunsetOasisText": "Sunset Oasis", - "backgroundSunsetOasisNotes": "Bask in the Sunset Oasis." + "backgrounds112015": "CONJUNTO 18: Lanzado en noviembre de 2015", + "backgroundFloatingIslandsText": "Islas Flotantes", + "backgroundFloatingIslandsNotes": "Salta a través de las Islas Flotantes.", + "backgroundNightDunesText": "Dunas Nocturnas", + "backgroundNightDunesNotes": "Camina pacíficamente atravesando las Dunas Nocturnas.", + "backgroundSunsetOasisText": "Oasis en el Ocaso", + "backgroundSunsetOasisNotes": "Disfruta de un Oasis en el Ocaso." } \ No newline at end of file diff --git a/common/locales/es_419/challenge.json b/common/locales/es_419/challenge.json index 914f8b1719..80c712d779 100644 --- a/common/locales/es_419/challenge.json +++ b/common/locales/es_419/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "No tienes permiso de editar este desafío", "noPermissionDeleteChallenge": "No tienes permiso de eliminar este desafío", "noPermissionCloseChallenge": "No tienes permiso de cerrar este desafío", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "Sin dueño", "noChallengeOwnerPopover": "Este desafío no tiene un dueño porque la persona que lo creó eliminó su cuenta." } \ No newline at end of file diff --git a/common/locales/es_419/character.json b/common/locales/es_419/character.json index dfd9d6fba2..6ceee5498d 100644 --- a/common/locales/es_419/character.json +++ b/common/locales/es_419/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Ha llegado al máximo conjunto de arma y armadura para las siguientes clases:", "level": "Nivel", "levelUp": "¡Subiste de nivel!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Maná", "hp": "PV", "mp": "PM", diff --git a/common/locales/es_419/content.json b/common/locales/es_419/content.json index 45705948c3..fb39eab869 100644 --- a/common/locales/es_419/content.json +++ b/common/locales/es_419/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Rana", "questEggFrogMountText": "Rana", "questEggFrogAdjective": "Una principesca", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Encuentra una poción de eclosión para verter sobre este huevo y eclosionará en un <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Básico", "hatchingPotionWhite": "Blanco", diff --git a/common/locales/es_419/front.json b/common/locales/es_419/front.json index 702f1e070b..7a76635de1 100644 --- a/common/locales/es_419/front.json +++ b/common/locales/es_419/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] realmente me ha ayudado a estructurar mi vida en la universidad.", "invalidEmail": "Se requiere una dirección válida de correo electrónico para poder restablecer una contraseña.", "irishfeet123Quote": "He tenido horribles hábitos respecto a limpiar mi puesto completamente despues de comer y dejar todos pos platos sobre la mesa. [Habitica] curó eso!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Antes de [Habitica], estaba estancado con mi tesis, del mismo modo decepcionado con mi disciplina personal respecto al aseo del hogar, cosas como aprender vocabulario y estudiar teoría del Go. El romper todas esas tareas en listas pequeñas y manejables es prácticamente lo que me mantiene motivado y trabajando constantemente.", "landingadminlink": "paquetes administrativos", "landingend": "¿Todavía no estás convencido?", @@ -180,7 +180,13 @@ "merchandiseInquiries": "Preguntas sobre márketing y merchandising", "marketingInquiries": "Preguntas sobre márketing y redes sociales", "tweet": "Tweetear", - "apps": "Apps", - "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "apps": "Aplicaciones", + "notifyAndroidApp": "¿Quieres que te avisemos cuando la aplicación para Android esté lista? ¡Regístrate en esta lista de envío!", + "checkOutIOSApp": "¡Chequea nuestra nueva aplicación para iOS!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/es_419/gear.json b/common/locales/es_419/gear.json index 93f4576b5c..5cc9e5a8c8 100644 --- a/common/locales/es_419/gear.json +++ b/common/locales/es_419/gear.json @@ -128,11 +128,11 @@ "weaponSpecialSummer2015HealerNotes": "Cures seasickness and sea sickness! Increases Intelligence by <%= int %>. Limited Edition 2015 Summer Gear.", "weaponSpecialFall2015RogueText": "Bati-Batalla Ax", "weaponSpecialFall2015RogueNotes": "Fearsome To-Dos cower before the flapping of this ax. Increases Strength by <%= str %>. Limited Edition 2015 Autumn Gear.", - "weaponSpecialFall2015WarriorText": "Wooden Plank", + "weaponSpecialFall2015WarriorText": "Tablón de madera", "weaponSpecialFall2015WarriorNotes": "Great for elevating things in cornfields and/or smacking tasks. Increases Strength by <%= str %>. Limited Edition 2015 Autumn Gear.", - "weaponSpecialFall2015MageText": "Enchanted Thread", + "weaponSpecialFall2015MageText": "Hilo encantado", "weaponSpecialFall2015MageNotes": "A powerful Stitch Witch can control this enchanted thread without even touching it! Increases Intelligence by <%= int %> and Perception by <%= per %>. Limited Edition 2015 Autumn Gear.", - "weaponSpecialFall2015HealerText": "Swamp-Slime Potion", + "weaponSpecialFall2015HealerText": "Poción de Pantano-Slime", "weaponSpecialFall2015HealerNotes": "Brewed to perfection! Now you just have to convince yourself to drink it. Increases Intelligence by <%= int %>. Limited Edition 2015 Autumn Gear.", "weaponMystery201411Text": "Horca de banquete", "weaponMystery201411Notes": "Apuñalar a tus enemigos o tu comida favorita - ¡esta horca versátil lo hace todo! No otorga ningún beneficio. Articulo de suscriptor de noviembre 2014.", @@ -156,7 +156,7 @@ "weaponArmoireGoldWingStaffNotes": "The wings on this staff constantly flutter and twist. Increases all attributes by <%= attrs %> each. Enchanted Armoire: Independent Item.", "weaponArmoireBatWandText": "Varita de Murciélago", "weaponArmoireBatWandNotes": "This wand can turn any task into a bat! Wave it about and watch them fly away. Increases Intelligence by <%= int %> and Perception by <%= per %>. Enchanted Armoire: Independent Item.", - "weaponArmoireShepherdsCrookText": "Shepherd's Crook", + "weaponArmoireShepherdsCrookText": "Cayado de Pastor", "weaponArmoireShepherdsCrookNotes": "Useful for herding gryphons. Increases Constitution by <%= con %>. Enchanted Armoire: Shepherd Set (Item 1 of 3).", "armor": "armadura", "armorBase0Text": "Ropa simple", @@ -271,13 +271,13 @@ "armorSpecialSummer2015MageNotes": "Hidden power resides in the puffs of these sleeves. Increases Intelligence by <%= int %>. Limited Edition 2015 Summer Gear.", "armorSpecialSummer2015HealerText": "Armadura de Marinero", "armorSpecialSummer2015HealerNotes": "This armor lets everyone know that you are an honest merchant sailor who would never dream of behaving like a scalawag. Increases Constitution by <%= con %>. Limited Edition 2015 Summer Gear.", - "armorSpecialFall2015RogueText": "Bat-tle Armor", + "armorSpecialFall2015RogueText": "Armadura de Murcie-lago", "armorSpecialFall2015RogueNotes": "Fly into bat-tle! Increases Perception by <%= per %>. Limited Edition 2015 Autumn Gear.", - "armorSpecialFall2015WarriorText": "Scarecrow Armor", + "armorSpecialFall2015WarriorText": "Armadura de Espantapájaros", "armorSpecialFall2015WarriorNotes": "Despite being stuffed with straw, this armor is extremely hefty! Increases Constitution by <%= con %>. Limited Edition 2015 Autumn Gear.", - "armorSpecialFall2015MageText": "Stitched Robes", + "armorSpecialFall2015MageText": "Túnica Cocida", "armorSpecialFall2015MageNotes": "Every stitch in this armor shimmers with enchantment. Increases Intelligence by <%= int %>. Limited Edition 2015 Autumn Gear.", - "armorSpecialFall2015HealerText": "Potioner Robes", + "armorSpecialFall2015HealerText": "Túnica de Potero", "armorSpecialFall2015HealerNotes": "What? Of course that was a potion of constitution. No, you are definitely not turning into a frog! Don't be ribbiticulous. Increases Constitution by <%= con %>. Limited Edition 2015 Autumn Gear.", "armorMystery201402Text": "Túnica de mensajero", "armorMystery201402Notes": "Reluciente y fuerte, esta túnica tiene muchos bolsillos para llevar cartas. No otorga ningún beneficio. Artículo de suscriptor de febrero 2014.", @@ -307,8 +307,8 @@ "armorMystery201506Notes": "Snorkel through a coral reef in this brightly-colored swim suit! Confers no benefit. June 2015 Subscriber Item.", "armorMystery201508Text": "Disfraz de Cheetah", "armorMystery201508Notes": "Run fast as a flash in the fluffy Cheetah Costume! Confers no benefit. August 2015 Subscriber Item.", - "armorMystery201509Text": "Werewolf Costume", - "armorMystery201509Notes": "This IS a costume, right? Confers no benefit. September 2015 Subscriber Item.", + "armorMystery201509Text": "Disfraz de Hombre Lobo", + "armorMystery201509Notes": "Este es un disfraz, vale? No otorga ningún beneficio. Artículo de suscriptor Septiembre de 2015.", "armorMystery301404Text": "Traje steampunk", "armorMystery301404Notes": "¡Sofisticado y elegante, oh no! No otorga ningún beneficio. Artículo de suscriptor de febrero 3015.", "armorArmoireLunarArmorText": "Armadura Lunar Tranquilizadora", @@ -323,9 +323,9 @@ "armorArmoireHornedIronArmorNotes": "Fiercely hammered from iron, this horned armor is nearly impossible to break. Increases Constitution by <%= con %> and Perception by <%= per %>. Enchanted Armoire: Horned Iron Set (Item 2 of 3).", "armorArmoirePlagueDoctorOvercoatText": "Abrigo de Doctor Plaga", "armorArmoirePlagueDoctorOvercoatNotes": "An authentic overcoat worn by the doctors who battle the Plague of Procrastination! Increases Intelligence by <%= int %>, Strength by <%= str %>, and Constitution by <%= con %>. Enchanted Armoire: Plague Doctor Set (Item 3 of 3).", - "armorArmoireShepherdRobesText": "Shepherd Robes", + "armorArmoireShepherdRobesText": "Túnica de Pastor", "armorArmoireShepherdRobesNotes": "The fabric is cool and breathable, perfect for a hot day herding gryphons in the desert. Increases Strength and Perception by <%= attrs %> each. Enchanted Armoire: Shepherd Set (Item 2 of 3).", - "armorArmoireRoyalRobesText": "Royal Robes", + "armorArmoireRoyalRobesText": "Túnica Real", "armorArmoireRoyalRobesNotes": "Wonderful ruler, rule all day long! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 3 of 3).", "headgear": "protector de cabeza", "headBase0Text": "Sin yelmo", @@ -440,9 +440,9 @@ "headSpecialSummer2015HealerNotes": "Lazo de Cabello Rojo", "headSpecialFall2015RogueText": "Alas Bati-Batalla", "headSpecialFall2015RogueNotes": "Echolocate your enemies with this powerful helm! Increases Perception by <%= per %>. Limited Edition 2015 Autumn Gear.", - "headSpecialFall2015WarriorText": "Scarecrow Hat", + "headSpecialFall2015WarriorText": "Sombrero de Espantapájaros", "headSpecialFall2015WarriorNotes": "Everyone would want this hat--if they only had a brain. Increases Strength by <%= str %>. Limited Edition 2015 Autumn Gear.", - "headSpecialFall2015MageText": "Stitched Hat", + "headSpecialFall2015MageText": "Sombrero Cocido", "headSpecialFall2015MageNotes": "Every stitch in this hat augments its power. Increases Perception by <%= per %>. Limited Edition 2015 Autumn Gear.", "headSpecialFall2015HealerText": "Sombrero de Sapo", "headSpecialFall2015HealerNotes": "This is an extremely serious hat that is worthy of only the most advanced potioners. Increases Intelligence by <%= int %>. Limited Edition 2015 Autumn Gear.", @@ -464,12 +464,12 @@ "headMystery201412Notes": "¿Quien es un pingüino? No otorga ningún beneficio. Artículo de suscriptor de diciembre 2014.", "headMystery201501Text": "Yelmo estrellado", "headMystery201501Notes": "Las constelaciones parpadean y se arremolinan en este yelmo, enfocando los pensamientos del usuario. No otorga ningún beneficio. Artículo de suscriptor de enero 2015.", - "headMystery201505Text": "Casco del caballero verde", + "headMystery201505Text": "Casco del Caballero Verde", "headMystery201505Notes": "La pluma verde de este casco hierroso ondea orgullosamente. Artículo de Suscriptor de Mayo de 2015. No confiere ningún beneficio.", "headMystery201508Text": "Sombrero Cheetah", "headMystery201508Notes": "This cozy cheetah hat is very fuzzy! Confers no benefit. August 2015 Subscriber Item.", - "headMystery201509Text": "Werewolf Mask", - "headMystery201509Notes": "This IS a mask, right? Confers no benefit. September 2015 Subscriber Item.", + "headMystery201509Text": "Máscara de Hombre Lobo", + "headMystery201509Notes": "Esta es una mascara, vale? No otorga ningún beneficio. Artículo de suscriptor Septiembre de 2015.", "headMystery301404Text": "Galera elegante", "headMystery301404Notes": "¡Una galera elegante para los señores más sofisticados! Artículo de Suscriptor de Enero de 3015. No confiere ningún beneficio.", "headMystery301405Text": "Galera básica", @@ -492,7 +492,7 @@ "headArmoireGoldenLaurelsNotes": "These golden laurels reward those who have conquered bad habits. Increases Perception and Constitution by <%= attrs %> each. Enchanted Armoire: Golden Toga Set (Item 2 of 3).", "headArmoireHornedIronHelmText": "Casco de Hierro con Cuernos", "headArmoireHornedIronHelmNotes": "Fiercely hammered from iron, this horned helmet is nearly impossible to break. Increases Constitution by <%= con %> and Strength by <%= str %>. Enchanted Armoire: Horned Iron Set (Item 1 of 3).", - "headArmoireYellowHairbowText": "Lazo para el pelo amarillo", + "headArmoireYellowHairbowText": "Lazo de Cabello Amarillo", "headArmoireYellowHairbowNotes": "Become perceptive, strong, and smart while wearing this beautiful Yellow Hairbow! Increases Perception, Strength, and Intelligence by <%= attrs %> each. Enchanted Armoire: Independent Item.", "headArmoireRedFloppyHatText": "Sombrero Flexible Rojo", "headArmoireRedFloppyHatNotes": "Many spells have been sewn into this simple hat, giving it a radiant red color. Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Independent Item.", @@ -502,9 +502,9 @@ "headArmoireBlackCatNotes": "This black hat is... purring. And twitching its tail. And breathing? Yeah, you just have a sleeping cat on your head. Increases Intelligence and Perception by <%= attrs %> each. Enchanted Armoire: Independent Item.", "headArmoireOrangeCatText": "Sombrero de Gato Naranja", "headArmoireOrangeCatNotes": "This orange hat is... purring. And twitching its tail. And breathing? Yeah, you just have a sleeping cat on your head. Increases Strength and Constitution by <%= attrs %> each. Enchanted Armoire: Independent Item.", - "headArmoireBlueFloppyHatText": "Blue Floppy Hat", + "headArmoireBlueFloppyHatText": "Sombrero Escurrido Azul", "headArmoireBlueFloppyHatNotes": "Many spells have been sewn into this simple hat, giving it a brilliant blue color. Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Independent Item.", - "headArmoireShepherdHeaddressText": "Shepherd Headdress", + "headArmoireShepherdHeaddressText": "Tocado de Pastor", "headArmoireShepherdHeaddressNotes": "Sometimes the gryphons that you herd like to chew on this headdress, but it makes you seem more intelligent nonetheless. Increases Intelligence by <%= int %>. Enchanted Armoire: Shepherd Set (Item 3 of 3).", "offhand": "artículo adicional", "shieldBase0Text": "Sin equipamiento addicional", @@ -589,7 +589,7 @@ "shieldArmoireGladiatorShieldNotes": "To be a gladiator you must.... eh, whatever, just bash them with your shield. Increases Constitution by <%= con %> and Strength by <%= str %>. Enchanted Armoire: Gladiator Set (Item 3 of 3).", "shieldArmoireMidnightShieldText": "Escudo de Medianoche", "shieldArmoireMidnightShieldNotes": "This shield is most powerful at the stroke of midnight! Increases Constitution by <%= con %> and Strength by <%= str %>. Enchanted Armoire: Independent Item.", - "shieldArmoireRoyalCaneText": "Royal Cane", + "shieldArmoireRoyalCaneText": "Bastón Real", "shieldArmoireRoyalCaneNotes": "Hooray for the ruler, worthy of song! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 2 of 3).", "back": "Accesorio en Espalda", "backBase0Text": "Sin accesorio de la espalda", @@ -632,8 +632,8 @@ "bodySpecialSummer2015HealerText": "Pañuelo de Marinero", "bodySpecialSummer2015HealerNotes": "Yo jo jo? No, no, no! No otorga ningún beneficio. Edición Limitada Equipamiento Verano 2015.", "headAccessory": "Accesorio para cabeza", - "accessories": "accesorios", - "animalEars": "Orejas de animal", + "accessories": "Accesorios", + "animalEars": "Orejas de Animal", "headAccessoryBase0Text": "Sin accesorio de la cabeza", "headAccessoryBase0Notes": "Sin accesorio de la cabeza.", "headAccessorySpecialSpringRogueText": "Orejas de gato moradas", @@ -652,21 +652,21 @@ "headAccessorySpecialSpring2015MageNotes": "Estas orejas escuchan atentamente, en caso de que algún mago esté revelando secretos. No confieren ningún beneficio. Equipamiento de edición limitada de primavera 2015.", "headAccessorySpecialSpring2015HealerText": "Orejas de gatito verdes", "headAccessorySpecialSpring2015HealerNotes": "Estas adorables orejas de gatito pondrán a los demás verdes de envidia. No confieren ningún beneficio. Equipamiento de edición limitada de primavera 2015.", - "headAccessoryBearEarsText": "Orejas de un oso", + "headAccessoryBearEarsText": "Orejas de Oso", "headAccessoryBearEarsNotes": "Estas orejas te hacen parecer como un osito. No confieren ningún beneficio", - "headAccessoryCactusEarsText": "Orejas de nopal", + "headAccessoryCactusEarsText": "Orejas de Nopal", "headAccessoryCactusEarsNotes": "Estas orejas te hacen paracer como un nopal espinoso. No otorgan ningún beneficio.", - "headAccessoryFoxEarsText": "Orejas de zorro", + "headAccessoryFoxEarsText": "Orejas de Zorro", "headAccessoryFoxEarsNotes": "Estas orejas te hacen paracer como un zorro tramposo. No otorgan ningún beneficio.", - "headAccessoryLionEarsText": "Orejas de leon", + "headAccessoryLionEarsText": "Orejas de León", "headAccessoryLionEarsNotes": "Estas orejas te hacen paracer como un leon real. No otorgan ningún beneficio.", - "headAccessoryPandaEarsText": "Orejas de una Panda", + "headAccessoryPandaEarsText": "Orejas de Panda", "headAccessoryPandaEarsNotes": "Estas orejas te hacen paracer como un panda gentil. on otorgan ningun beneficio", - "headAccessoryPigEarsText": "Orejas de cerdo", + "headAccessoryPigEarsText": "Orejas de Cerdo", "headAccessoryPigEarsNotes": "Estas orejas te hacen paracer como un cerdo excéntrico. No otorgan ningún beneficio.", "headAccessoryTigerEarsText": "Orejas de Tigre", "headAccessoryTigerEarsNotes": "Estas orejas te hacen paracer como un tigre feroz. No otorgan ningún beneficio.", - "headAccessoryWolfEarsText": "orejas de lobo.", + "headAccessoryWolfEarsText": "Orejas de Lobo", "headAccessoryWolfEarsNotes": "estas orejas te hacen paracer como un lobo leal. No otorgan ningún beneficio.", "headAccessoryMystery201403Text": "Astas de paseante del bosque", "headAccessoryMystery201403Notes": "Estas astas brillan con musgo y líquenes. No otorgan ningún beneficio. Artículo de suscriptor de marzo 2014.", diff --git a/common/locales/es_419/generic.json b/common/locales/es_419/generic.json index 9facdaa911..7f07471aae 100644 --- a/common/locales/es_419/generic.json +++ b/common/locales/es_419/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Te mando mil gracias.", "thankyou3": "Estoy muy agradecido - ¡gracias!", "thankyouCardAchievementTitle": "Muy agradecido", - "thankyouCardAchievementText": "Gracias por ser agradecido! Enviadas o recibidas <%= cards %> Cartas de agradecimiento." + "thankyouCardAchievementText": "Gracias por ser agradecido! Enviadas o recibidas <%= cards %> Cartas de agradecimiento.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/es_419/limited.json b/common/locales/es_419/limited.json index 347dfbbdcf..f126fba212 100644 --- a/common/locales/es_419/limited.json +++ b/common/locales/es_419/limited.json @@ -18,7 +18,7 @@ "valentine2": "\"Roses are red\n\nThis poem style is old\n\nI hope that you like this\n\n'Cause it cost ten Gold.\"", "valentine3": "\"Roses are red\n\nIce Drakes are blue\n\nNo treasure is better\n\nThan time spent with you!\"", "valentineCardAchievementTitle": "Amigos cariñosos", - "valentineCardAchievementText": "Aww, you and your friend must really care about each other! Sent or received <%= cards %> Valentine's Day cards.", + "valentineCardAchievementText": "Aww, tú y tu amigo se deben querer mucho mutuamente! <%= cards %> Cartas de San Valentín enviadas o recibidas.", "polarBear": "Oso polar", "turkey": "Pavo", "polarBearPup": "Cachorro de oso polar", @@ -38,7 +38,7 @@ "yetiSet": "Domadora de yetis (Guerrero)", "toAndFromCard": "Para: <%= toName %>, De: <%= fromName %>", "nyeCard": "Tarjeta del Año Nuevo", - "nyeCardExplanation": "For celebrating the new year together, you both receive the \"Auld Acquaintance\" badge!", + "nyeCardExplanation": "Para celebrar el año nuevo juntos, ambos reciben la placa \"Viejas Amistades\"!", "nyeCardNotes": "Envía una carta de Feliz Año Nuevo a un compañero de equipo.", "seasonalItems": "Artículos estacionales", "nyeCardAchievementTitle": "Antiguo conocido", @@ -54,12 +54,12 @@ "lovingPupSet": "Cachorro cariñoso (Curador)", "stealthyKittySet": "Gatito sigiloso (Granuja)", "daringSwashbucklerSet": "Espadachín Atrevido (Guerrero)", - "emeraldMermageSet": "Emerald Mermage (Mage)", + "emeraldMermageSet": "Sireno Esmeralda (Mago)", "reefSeahealerSet": "Reef Seahealer (Healer)", "roguishPirateSet": "Pirata Travieso (Granuja)", "monsterOfScienceSet": "Monstruo de Ciencia (Guerrero)", "witchyWizardSet": "Hechicero Embrujado (Mago)", "mummyMedicSet": "Momia Médica (Curador)", - "vampireSmiterSet": "Vampire Smiter (Rogue)", + "vampireSmiterSet": "Golpeador Vampiro (Rogue)", "fallEventAvailability": "Disponible hasta el 31 de Octubre" } \ No newline at end of file diff --git a/common/locales/es_419/messages.json b/common/locales/es_419/messages.json index 52a438af7b..e9e969f1be 100644 --- a/common/locales/es_419/messages.json +++ b/common/locales/es_419/messages.json @@ -30,14 +30,14 @@ "messageAlreadyOwnGear": "Ya posees este item. Equípalo yendo a la página de equipamiento.", "armoireEquipment": "<%= image %> Hallaste una pieza de Equipamiento raro en el Armario: <%= dropText %> ¡Genial!", "armoireFood": "<%= image %> You rummage in the Armoire and find <%= dropArticle %><%= dropText %>. What's that doing in here?", - "armoireExp": "You wrestle with the Armoire and gain Experience. Take that!", + "armoireExp": "Luchas con el Armario y ganas Experiencia. Tómala!", "messageInsufficientGems": "No tienes suficientes gemas!", "messageAuthPasswordMustMatch": ":password y :confirmPassword no coinciden", - "messageAuthCredentialsRequired": ":username, :email, :password, :confirmPassword required", - "messageAuthUsernameTaken": "El nombre de usuario no está disponible", - "messageAuthEmailTaken": "Esta dirección de correo electrónico ya esta siendo usada", + "messageAuthCredentialsRequired": "Se necesitan :username, :email, :password, y :confirmPassword", + "messageAuthUsernameTaken": "Este nombre de usuario ya está siendo usado", + "messageAuthEmailTaken": "Esta dirección de correo electrónico ya está siendo usada", "messageAuthNoUserFound": "Usuario no encontrado.", - "messageAuthMustBeLoggedIn": "Debes iniciar sesión.", + "messageAuthMustBeLoggedIn": "Tienes que iniciar sesíon.", "messageAuthMustIncludeTokens": "Debes incluir un token o un uid (ID de usuario) en tu petición.", "messageGroupNotFound": "Grupo no encontrado o tu no tienes acceso.", "messageGroupAlreadyInParty": "Ya estás en un equipo, intenta actualizar.", @@ -51,5 +51,5 @@ "messageGroupChatNotFound": "Mensaje no encontrado!", "messageGroupChatAdminClearFlagCount": "Only an admin can clear the flag count!", "messageUserOperationProtected": "path `<%= operation %>` was not saved, as it's a protected path.", - "messageUserOperationNotFound": "<%= operation %> operation not found" + "messageUserOperationNotFound": "<%= operation %> operación no encontrada" } \ No newline at end of file diff --git a/common/locales/es_419/npc.json b/common/locales/es_419/npc.json index 0f89073b15..cac885f64f 100644 --- a/common/locales/es_419/npc.json +++ b/common/locales/es_419/npc.json @@ -7,19 +7,19 @@ "daniel": "Daniel", "danielText": "¡Bienvenido a la Taberna! Quédate un rato y conoce a los locales. Si necesitas descansar (¿vacaciones, enfermedad?) te alojaré en la Posada. Mientras estés registrado tus Diarias no te lastimarán al final del día, pero todavía las puedes marcar.", "danielText2": "Aviso: Si estás participando en una misión contra un jefe, ¡el jefe todavía te hará daño si los de tu equipo no completan sus Diarias! Además, el daño que acumules contra el (o los objetos que hayas recolectado) no se aplicarán sino hasta que salgas de la Posada.", - "danielTextBroken": "Welcome to the Tavern... I guess... If you need to rest, I'll set you up at the Inn... While checked-in, your Dailies won't hurt you at the day's end, but you can still check them off... if you have the energy...", - "danielText2Broken": "Oh... If you are participating in a boss quest, the boss will still damage you for your party mates' missed Dailies... Also, your own damage to the Boss (or items collected) will not be applied until you check out of the Inn...", + "danielTextBroken": "Bienvenido a la Taberna... Supongo... Si necesitas descansar, te instalaré en la Posada... Mientras estés registrado, tus Diarias no te harán daño al final del día, pero aún así puedes tildarlas... Si tienes la energía...", + "danielText2Broken": "Oh... Si estás participando en una misión de jefe, el jefe seguirá dañándote por las Diarias que tus compañeros de equipo no completen... Ademas, el daño que tú le causes al Jefe (o los ítems recolectados) no será aplicado hasta que salgas de la Posada...", "alexander": "Alexander el Comerciante", "welcomeMarket": "¡Bienvenidos al Mercado! ¡Compra huevos difíciles de encontrar y pociones! ¡Vende tus extras! ¡Encarga servicios útiles! Ven a ver lo que tenemos para ofrecer.", - "displayItemForGold": "Do you want to sell a <%= itemType %>?", - "displayEggForGold": "Do you want to sell a <%= itemType %> Egg?", - "displayPotionForGold": "Do you want to sell a <%= itemType %> Potion?", - "sellForGold": "Sell it for <%= gold %> Gold", + "displayItemForGold": "¿Quieres vender un/a <%= itemType %>?", + "displayEggForGold": "¿Quieres vender un Huevo de <%= itemType %>?", + "displayPotionForGold": "¿Quieres vender una Poción <%= itemType %>?", + "sellForGold": "Véndelo/a por <%= gold %> Oro", "buyGems": "Comprar Gemas", "justin": "Justin", "ian": "Ian", "ianText": "Bienvenido a la Tienda de Misiones! Aquí puedes usar Pergaminos de Misiones para luchar contra monstruos con tus amigos. Asegúrate de haber mirado todos los Pergaminos de Misiones para comprar el correcto!", - "ianBrokenText": "Welcome to the Quest Shop... Here you can use Quest Scrolls to battle monsters with your friends... Be sure to check out our fine array of Quest Scrolls for purchase on the right...", + "ianBrokenText": "Bienvenido a la Tienda de Misiones... Aquí puedes utilizar Pergaminos de Misión para luchar contra monstruos con tus amigos... Asegúrate de chequear nuestra fina selección de Pergaminos de Misión a la derecha...", "USD": "USD", "newStuff": "Cosas nuevas", "cool": "Dímelo más tarde", diff --git a/common/locales/es_419/pets.json b/common/locales/es_419/pets.json index 21c510b0cd..60c80ac2b0 100644 --- a/common/locales/es_419/pets.json +++ b/common/locales/es_419/pets.json @@ -58,8 +58,16 @@ "firstDrop": "¡Has desbloqueado el Sistema de botín! Ahora, cuando realizas tareas, tendrás una probabilidad pequeña de encontrar un objeto ¡incluyendo huevos, pociones y comida!. Has encontrado un <%= eggText %> Huevo! <%= eggNotes %>", "useGems": "Si deseas una mascota pero no puedes esperar más para el botín, ¡usa Gemas en Inventario > Mercardo para comprar una!", "hatchAPot": "¿Eclosionar un <%= egg %> <%= potion %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "¿Dar de comer <%= article %><%= text %> a tu <%= name %>?", "useSaddle": "¿Ensillar <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= egg %> <%= potion %>", "mountName": "<%= mount %> <%= potion %>", "petKeyName": "Llave de la caseta", diff --git a/common/locales/es_419/quests.json b/common/locales/es_419/quests.json index 9c8d580081..78014c5517 100644 --- a/common/locales/es_419/quests.json +++ b/common/locales/es_419/quests.json @@ -37,13 +37,13 @@ "bossDmg1": "Cada tarea diaria o tarea pendiente completada y cada hábito positivo lastima al Jefe. Dañalo aun mas con las tareas mas rojas o aplástalos brutalmente y hazlos estallar en llamas. El Jefe hará daño a cada participante de la misión por cada tarea diaria que dejes pasar (multiplicado por la fuerza del jefe) en adición al daño regular, ¡así que mantén a tu grupo saludable completando tus tareas diarias! Todo daño hacia y desde el jefe se anota en tu cron (el día de cambio) ", "bossDmg2": "Sólo los participantes lucharán contra el Jefe y se repartirán el botín.", "bossDmg1Broken": "Each completed Daily and To-Do and each positive Habit hurts the boss... Hurt it more with redder tasks or Brutal Smash and Burst of Flames... The boss will deal damage to every quest participant for every Daily you've missed (multiplied by the boss's Strength) in addition to your regular damage, so keep your party healthy by completing your Dailies... All damage to and from a boss is tallied on cron (your day roll-over)...", - "bossDmg2Broken": "Only participants will fight the boss and share in the quest loot...", + "bossDmg2Broken": "Solo los participantes pelearán contra el Jefe y compartirán el botín de la misión...", "tavernBossInfo": "Complete Dailies and To-Dos and score positive Habits to damage the World Boss! Incomplete Dailies fill the Exhaust Strike Bar. When the Exhaust Strike bar is full, the World Boss will attack an NPC. A World Boss will never damage individual players or accounts in any way. Only active accounts not resting in the Inn will have their tasks tallied.", "tavernBossInfoBroken": "Complete Dailies and To-Dos and score positive Habits to damage the World Boss... Incomplete Dailies fill the Exhaust Strike Bar... When the Exhaust Strike bar is full, the World Boss will attack an NPC... A World Boss will never damage individual players or accounts in any way... Only active accounts not resting in the Inn will have their tasks tallied...", "bossColl1": "Para coleccionar artículos, haga tus tareas positivas. Objetos de misiones se ganan como objetos normales; sin embargo, no verá estos artículos hasta el próximo día cuando todo que encontró estará sumado y contribuido al total.", "bossColl2": "Solo los participantes pueden coleccionar artículos y compartir del botín de la misión.", "bossColl1Broken": "To collect items, do your positive tasks... Quest items drop just like normal items; however, you won't see the drops until the next day, then everything you've found will be tallied up and contributed to the pile...", - "bossColl2Broken": "Only participants can collect items and share in the quest loot...", + "bossColl2Broken": "Solo los participantes pueden recolectar items y compartir el botín de la misión...", "abort": "Abortar", "leaveQuest": "Abandonar misión", "sureLeave": "¿Estás seguro que quieres salir de la misión activa? Todo tu progreso en la misión se perderá.", @@ -70,11 +70,13 @@ "sureAbort": "¿Estás seguro de querer abortar la misión? Esto hará que todo tu equipo aborte la misión y todo el progreso se perderá. El pergamino de misión será regresado al organizador de la misión.", "doubleSureAbort": "¿Verdaderamente estas seguro? ¡Asegúrate que no te oidarán eternamente!", "questWarning": "Si nuevos miembros se unen al equipo antes de que comience la misión, también recibirán una invitación. Sin embargo, una vez que la misión ha comenzado, nuevos miembros no se pueden unir a la misión.", - "questWarningBroken": "If new players join the party before the quest starts, they will also receive an invitation... However once the quest has started, no new party members can join the quest...", + "questWarningBroken": "Si nuevos jugadores ingresan al grupo antes de que la misión empiece, ellos recibirán una invitación también... De todos modos una vez la misión empiece, no pueden ingresar nuevos miembros de grupo a la misión...", "bossRageTitle": "Ira", "bossRageDescription": "Cuando esta barra se llene, el jefe desencadenará un ataque especial!", "startAQuest": "INICIAR UNA MISIÓN", "startQuest": "Iniciar Misión", "whichQuestStart": "¿Cuál misión quieres empezar?", - "getMoreQuests": "Obtén más misiones" + "getMoreQuests": "Obtén más misiones", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/es_419/questscontent.json b/common/locales/es_419/questscontent.json index 416c32b343..a6e94fba18 100644 --- a/common/locales/es_419/questscontent.json +++ b/common/locales/es_419/questscontent.json @@ -200,7 +200,7 @@ "questSheepText": "El carnero del trueno", "questSheepNotes": "Mientras deambulas por las campiñas de Taskan con tus amigos, tomando un \"rápido descanso\" de tus obligaciones, encuentras una acogedora tienda de estambre. Estás tan sumergido en tu procrastinación que apenas y te das cuenta de las siniestras nubes que cubren el cielo. \"Tengo un ma-a-al presentimiento de este clima\", balbucea @Misceo mientras miras hacia arriba. Las tempestuosas nubes se arremolinan y se parecen mucho a... \"¡No tenemos tiempo para mirar nubes!\" grita @starsystemic. \"¡Está atacando!\" ¡El carnero del trueno se abalanza, lanzando relámpagos y truenos hacia ti!", "questSheepBoss": "Carnero del trueno", - "questSheepCompletion": "Impressed by your diligence, the Thunder Ram is drained of its fury. It launches three huge hailstones in your direction, and then fades away with a low rumble. Upon closer inspection, you discover that the hailstones are actually three fluffy eggs. You gather them up, and then stroll home under a blue sky.", + "questSheepCompletion": "La furia del Carnero del Trueno merma cuando éste queda Impresionado por tu diligencia. La criatura lanza granizo en tu dirección, y luego se desvanece con un retumbo grave. Al inspeccionar más de cerca, descubres que las piedras de granizo son en realidad tres huevos suaves y esponjosos. Los recoges, y luego caminas tranquilamente a casa debajo de un cielo azul.", "questSheepDropSheepEgg": "Oveja (Huevo)", "questSheepUnlockText": "Desbloquea huevos de oveja adquiribles en el Mercado", "questKrakenText": "El Kraken de Inkompleta", @@ -210,9 +210,9 @@ "questKrakenDropCuttlefishEgg": "Sepia (Huevo)", "questKrakenUnlockText": "Desbloquea huevos de sepia adquiribles en el Mercado", "questWhaleText": "El lamento de la ballena", - "questWhaleNotes": "You arrive at the Diligent Docks, hoping to take a submarine to watch the Dilatory Derby. Suddenly, a deafening bellow forces you to stop and cover your ears. \"Thar she blows!\" cries Captain @krazjega, pointing to a huge, wailing whale. \"It's not safe to send out the submarines while she's thrashing around!\"

\"Quick,\" calls @UncommonCriminal. \"Help me calm the poor creature so we can figure out why she's making all this noise!\"", + "questWhaleNotes": "Llegas a los Muelles Diligentes, esperando abordar un submarino para ver el Derby de Dilatoria. De pronto, un bramido ensordecedor te obliga a detenerte y tapar tus oídos. \"¡Por allí resopla!\" grita el Capitán @krazjega, señalando a una enorme ballena que se lamentaba. \"¡No es seguro enviar a los submarinos mientras ella está dando vueltas!\"

\"Rápido,\" dice @UncommonCriminal. \"¡Ayúdenme a calmar a esta pobre criatura así podemos averiguar por qué está haciendo todo este ruido!\"", "questWhaleBoss": "Ballena lamentosa ", - "questWhaleCompletion": "After much hard work, the whale finally ceases her thunderous cry. \"Looks like she was drowning in waves of negative habits,\" @zoebeagle explains. \"Thanks to your consistent effort, we were able to turn the tides!\" As you step into the submarine, several whale eggs bob towards you, and you scoop them up.", + "questWhaleCompletion": "Luego de un arduo trabajo, la ballena finalmente cesa su llanto estruendoso. \"Parece que estaba ahogándose en olas de hábitos negativos,\" explica @zoebeagle. \"¡Gracias a tu consistente esfuerzo hemos podido cambiar el curso de la situación!\" Mientras entras al submarino, varios huevos de ballena flotan hacia ti, y tú los recoges.", "questWhaleDropWhaleEgg": "Ballena (Huevo)", "questWhaleUnlockText": "Desbloquea huevos de ballena adquiribles en el Mercado", "questDilatoryDistress1Text": "Peligro en Dilatoria, Parte 1: Mensaje en una Botella", @@ -239,15 +239,15 @@ "questDilatoryDistress3DropWeapon": "Tridente de Mareas Estruendosas (Arma)", "questDilatoryDistress3DropShield": "Escudo Luna perlada (Objeto Escudo-Mano)", "questCheetahText": "Como un Guepardo", - "questCheetahNotes": "As you hike across the Sloensteadi Savannah with your friends @PainterProphet, @tivaquinn, @Unruly Hyena, and @Crawford, you're startled to see a Cheetah screeching past with a new Habitican clamped in its jaws. Under the Cheetah's scorching paws, tasks burn away as though complete -- before anyone has the chance to actually finish them! The Habitican sees you and yells, \"Please help me! This Cheetah is making me level too quickly, but I'm not getting anything done. I want to slow down and enjoy the game. Make it stop!\" You fondly remember your own fledgling days, and know that you have to help the newbie by stopping the Cheetah!", - "questCheetahCompletion": "The new Habitican is breathing heavily after the wild ride, but thanks you and your friends for your help. \"I'm glad that Cheetah won't be able to grab anyone else. It did leave some Cheetah eggs for us, so maybe we can raise them into more trustworthy pets!\"", + "questCheetahNotes": "Mientras realizas una caminata a través de la Sabana Sloensteadi con tus amigos @PainterProphet, @tivaquinn, @Unruly Hyena, y @Crawford, te sobresaltas al ver a un Guepardo pasar corriendo con un nuevo Habiticano atrapado entre sus mandíbulas. Bajo las patas abrasadoras del Guepardo, las tareas son consumidas por el fuego como si estuvieran completas -- ¡antes de que alguien tenga la chance de realmente terminarlas! El Habiticano te ve y grita, \"¡Por favor, ayúdenme! Este Guepardo me está haciendo aumentar de nivel demasiado rápido, pero no estoy logrando hacer nada. Quiero disminuir la velocidad y disfrutar el juego. ¡Hagan que se detenga!\" Tú recuerdas cariñosamente tus propios días como novato, ¡y estás seguro de que tienes que ayudar al principiante deteniendo al Guepardo!", + "questCheetahCompletion": "El nuevo Habiticano está respirando con dificultad luego del recorrido desenfrenado, pero te agradece a ti y a tus amigos por su ayuda. \"Me alegra que el Guepardo no vaya a poder atrapar a nadie más. Pero sí dejó algunos huevos de Guepardo para nosotros, ¡así que quizás podemos criarlos y convertirlos en mascotas más confiables!\"", "questCheetahBoss": "Guepardo", "questCheetahDropCheetahEgg": "Guepardo (Huevo)", "questCheetahUnlockText": "Desbloquea huevos de Guepardo adquiribles en el Mercado", - "questHorseText": "Ride the Night-Mare", - "questHorseNotes": "While relaxing in the Tavern with @beffymaroo and @JessicaChase, the talk turns to good-natured boasting about your adventuring accomplishments. Proud of your deeds, and perhaps getting a bit carried away, you brag that you can tame any task around. A nearby stranger turns toward you and smiles. One eye twinkles as he invites you to prove your claim by riding his horse.\nAs you all head for the stables, @UncommonCriminal whispers, \"You may have bitten off more than you can chew. That's no horse - that's a Night-Mare!\" Looking at its stamping hooves, you begin to regret your words...", - "questHorseCompletion": "It takes all your skill, but finally the horse stamps a couple of hooves and nuzzles you in the shoulder before allowing you to mount. You ride briefly but proudly around the Tavern grounds while your friends cheer. The stranger breaks into a broad grin.\n\"I can see that was no idle boast! Your determination is truly impressive. Take these eggs to raise horses of your own, and perhaps we'll meet again one day.\" You take the eggs, the stranger tips his hat... and vanishes.", - "questHorseBoss": "Night-Mare", + "questHorseText": "Monta a la Pesadi-Yegua", + "questHorseNotes": "Mientras te relajas en la Taberna con @beffymaroo y @JessicaChase, la charla se transforma en un amistoso alarde sobre tus logros en tus aventuras. Orgulloso de tus hazañas, y quizás dejándote llevar un poco, fanfarroneas sobre cómo puedes domar a cualquier tarea que encuentras. Un desconocido próximo a ti se da vuelta a mirarte y sonríe. Uno de sus ojos brilla cuando te invita a probar lo que dices montando a su caballo.\nMientras todos se dirigen hacia los establos, @UncommonCriminal murmura, \"El que mucho abarca poco aprieta. Eso no es un caballo - ¡es una Pesadi-Yegua!\" Viendo cómo todas sus pezuñas dan pisotones, comienzas a arrepentirte de tus palabras...", + "questHorseCompletion": "Requiere de todas tus habilidades, pero finalmente el caballo pisotea con algunas de sus pezuñas y te acaricia el hombro con el hocico antes de dejarte montarlo. Tú cabalgas brevemente pero de forma orgullosa alrededor del terreno de la Taberna mientras tus amigos te aclaman. El desconocido muestra una gran sonrisa.\n\"¡Veo que no era un alarde vacío! Tu determinación es realmente impresionante. Toma estos huevos para criar tus propios caballos, y quizás algún día nos encontremos de nuevo.\" Tú agarras los huevos, el extraño inclina su sombrero... y desaparece.", + "questHorseBoss": "Pesadi-Yegua", "questHorseDropHorseEgg": "Caballo (Huevo)", "questHorseUnlockText": "Desbloquea huevos de Caballo adquiribles en el Mercado", "questBurnoutText": "Burnout y los Espíritus Consumidos", @@ -267,5 +267,11 @@ "questFrogCompletion": "La rana se hunde en el lodo, derrotada. Mientras se escabulle, el cieno azul se disipa, despejando el camino.

Posados en el medio del sendero se encuentran tres huevos inmaculados. \"¡Se pueden ver incluso los pequeños renacuajos a través de la cubierta transparente!\" dice @Breadstrings. \"Tengan, deberían quedárselos.\"", "questFrogBoss": "Rana Desastrosa", "questFrogDropFrogEgg": "Rana (Huevo)", - "questFrogUnlockText": "Desbloquea huevos de Rana adquiribles en el Mercado" + "questFrogUnlockText": "Desbloquea huevos de Rana adquiribles en el Mercado", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/es_419/rebirth.json b/common/locales/es_419/rebirth.json index ad359824cc..9fbb90f3fd 100644 --- a/common/locales/es_419/rebirth.json +++ b/common/locales/es_419/rebirth.json @@ -16,11 +16,11 @@ "rebirthEarnAchievement": "¡También recibirás un Logro por haber empezado una nueva aventura!", "beReborn": "Ser renacido", "rebirthAchievement": "¡Has comenzado una nueva aventura! Este es tu <%= number %> Renacimiento, y el Nivel más alto que has logrado es <%= level %>. Para apilar este Logro, ¡empieza tu aventura siguiente después de haber conseguido un nivel aún más alto!", - "rebirthAchievement100": "You've begun a new adventure! This is Rebirth <%= number %> for you, and the highest Level you've attained is 100 or higher. To stack this Achievement, begin your next new adventure when you've reached at least 100!", + "rebirthAchievement100": "¡Haz comenzado una nueva aventura! Este es el Renacimiento <%= number %> para ti, y el Nivel más alto que has adquirido es 100 o más alto. Para acumular este Logro, ¡empieza tu nueva aventura cuando hayas alcanzado como mínimo el nivel 100!", "rebirthBegan": "Comienzo una aventura nueva", "rebirthText": "Comenzó <%= rebirths %> aventuras nuevas", "rebirthOrb": "Uso una Esfera derenacimiento para comenzar de nuevo después de conseguir Nivel", - "rebirthOrb100": "Used an Orb of Rebirth to start over after attaining Level 100 or higher", + "rebirthOrb100": "Utilizó una Esfera de Renacimiento para comenzar de nuevo luego de adquirir el Nivel 100 or más alto", "rebirthPop": "Comenzar con un personaje nuevo a Nivel 1, mientras manteniendo logros, lo coleccionable, y tareas con historial.", "rebirthName": "Esfera de renacimiento", "reborn": "Renacido, nivel máximo <%= reLevel %>" diff --git a/common/locales/es_419/settings.json b/common/locales/es_419/settings.json index 7b9ef57ec8..ff7e65087b 100644 --- a/common/locales/es_419/settings.json +++ b/common/locales/es_419/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Con esta opción marcada, la lista de etiquetas estará escondida al abrir la tarea para editarla.", "startAdvCollapsed": "Las opciones avanzadas de las tareas no se abren automáticamente", "startAdvCollapsedPop": "Con esta opción marcada, las opciones avanzadas estarán escondidas al abrir la tarea para editarla.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Mostrar el tour", "restartTour": "Reiniciar el tour de introducción a Habitica", "showBailey": "Mostrar a Bailey", @@ -81,7 +86,6 @@ "emailChange1": "Para cambiar tu dirección de correo electrónico, por favor envía un correo a", "emailChange2": "admin@habitica.com", "emailChange3": "incluyendo tanto tu viejo y tu nuevo correo electronico acompañados de tu ID de usuario.", - "username": "Nombre de usuario", "usernameOrEmail": "Nombre de usuario o E-mail", "email": "Email", "registeredWithFb": "Registrado con Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "Usuario->Perfil", "loginNameDescription3": "para cambiar el nombre que aparece en tu avatar y mensajes de chat", "emailNotifications": "Notificaciones vía email", - "wonChallenge": "Ganaste un desafío", + "wonChallenge": "You won a Challenge!", "newPM": "Mensaje privado recibido", "giftedGems": "Gemas regaladas", "giftedGemsInfo": "<%= amount %> Gemas - por <%= name %>", @@ -119,25 +123,25 @@ "promoCodeApplied": "¡Tu código promocional fue aceptado! Revisa tu inventario.", "promoPlaceholder": "Ingresa tu código promocional", "displayInviteToPartyWhenPartyIs1": "Mostrar el botón de \"Invitar a grupo\" cuando el grupo tiene 1 miembro.", - "saveCustomDayStart": "Save Custom Day Start", - "registration": "Registration", - "addLocalAuth": "Add local authentication:", - "generateCodes": "Generate Codes", - "generate": "Generate", - "getCodes": "Get Codes", + "saveCustomDayStart": "Guarda el Inicio de Día Personalizado", + "registration": "Registro", + "addLocalAuth": "Agrega autenticación local:", + "generateCodes": "Genera Códigos", + "generate": "Generar", + "getCodes": "Obtén Códigos", "webhooks": "Webhooks", - "enabled": "Enabled", - "webhookURL": "Webhook URL", - "add": "Add", - "buyGemsGoldCap": "Cap raised to <%= amount %>", - "mysticHourglass": "<%= amount %> Mystic Hourglass", - "mysticHourglassText": "Mystic Hourglasses allow purchasing a previous month's Mystery Item set.", + "enabled": "Habilitado", + "webhookURL": "URL del Webhook", + "add": "Agregar", + "buyGemsGoldCap": "Tope aumentado a <%= amount %>", + "mysticHourglass": "<%= amount %> Reloj de arena mística", + "mysticHourglassText": "Los Relojes de Arena Mística permiten comprar un anterior Conjunto Misterioso de items del mes.", "purchasedPlanId": "Recurring $<%= price %> each <%= months %> Month(s) (<%= plan %>)", - "purchasedPlanExtraMonths": "You have <%= months %> months of subscription credit.", - "consecutiveSubscription": "Consecutive Subscription", - "consecutiveMonths": "Consecutive Months:", - "gemCapExtra": "Gem Cap Extra:", - "mysticHourglasses": "Mystic Hourglasses:", + "purchasedPlanExtraMonths": "Tu tienes <%=months %> meses de suscripción crédito. ", + "consecutiveSubscription": "Consecutivo Suscripción ", + "consecutiveMonths": "Consecutivo Meses:", + "gemCapExtra": "Gema tapa extra:", + "mysticHourglasses": "Reloj de arenas místicas:", "paypal": "PayPal", "amazonPayments": "Amazon Payments" } \ No newline at end of file diff --git a/common/locales/es_419/spells.json b/common/locales/es_419/spells.json index da001f13f0..1277889333 100644 --- a/common/locales/es_419/spells.json +++ b/common/locales/es_419/spells.json @@ -10,27 +10,27 @@ "spellWarriorSmashText": "Golpe brutal", "spellWarriorSmashNotes": "Golpeas salvajemente a una tarea con toda tu fuerza. ¡La tarea se vuelve más azul/menos roja y haces daño adicional a los Jefes! Haz lick sobre una tarea para invocar el conjuro. (Basado en FRZ).", "spellWarriorDefensiveStanceText": "Postura defensiva", - "spellWarriorDefensiveStanceNotes": "Te preparas para la dificultad de tus tareas. ¡Tu constitución se ve potenciada! (Basado en: CON no potenciada)", + "spellWarriorDefensiveStanceNotes": "Te preparas para arrasar con tus tareas. ¡Tu constitución se ve potenciada! (Basado en: CON no potenciada)", "spellWarriorValorousPresenceText": "Presencia valerosa", "spellWarriorValorousPresenceNotes": "Tu presencia anima tu equipo. ¡La fuerza de tu equipo se ve potenciada! (Basado en: STR no potenciada)", "spellWarriorIntimidateText": "Mirada intimidante", "spellWarriorIntimidateNotes": "Tu mirada hace que tus enemigos temblen de miedo. ¡La constitución de tu equipo se ve potenciada! (Basado en: CON no potenciada)", "spellRoguePickPocketText": "Carterista", - "spellRoguePickPocketNotes": "Robas una tarea cerca. ¡Ganas oro! Haz click sobre una tarea para envocar el conjuro. (Basado en: PER)", + "spellRoguePickPocketNotes": "Robas a una tarea cercana. ¡Ganas oro! Haz click sobre una tarea para invocar el conjuro. (Basado en: PER)", "spellRogueBackStabText": "Puñalada", - "spellRogueBackStabNotes": "Traicionas una tarea tonta. ¡Ganas EXP y oro! Haz click sobre una tarea para invocar el conjuro. (Basado en: STR)", + "spellRogueBackStabNotes": "Traicionas una tarea necia. ¡Ganas EXP y oro! Haz click sobre una tarea para invocar el conjuro. (Basado en: STR)", "spellRogueToolsOfTradeText": "Herramientas del oficio", - "spellRogueToolsOfTradeNotes": "Compartes tus talentos con tus amigos. ¡La percepción de tu equipo se ve potenciada! (Basado en: PER no potenciada) ", + "spellRogueToolsOfTradeNotes": "Compartes tus talentos con tus amigos. ¡La percepción de tu equipo se ve potenciada! (Basado en: PER no potenciada)", "spellRogueStealthText": "Sigilo", - "spellRogueStealthNotes": "Eres tan furtivo que no te pueden ver. Algunos de tus Tareas Diarias no causarán daño hoy, y sus correos desnudos y colores no cambiarán. (Puede invocar el conjuro varias veces para afectar mas Tareas Diarias)", - "spellHealerHealText": "Luz de curación ", - "spellHealerHealNotes": "Tu cuerpo cubra con luz, sanando tus heridos. ¡Recuperas salud! (Basado en: CON e INT)", + "spellRogueStealthNotes": "Eres tan furtivo que no te pueden ver. Algunas de tus Tareas Diarias no hechas no causarán daño, y sus rachas/color no cambiarán. (Puedes invocar el conjuro varias veces para afectar multiples Tareas Diarias)", + "spellHealerHealText": "Luz de curación", + "spellHealerHealNotes": "Una luz cubre tu cuerpo sanando tus heridas. ¡Recuperas salud! (Basado en: CON e INT)", "spellHealerBrightnessText": "Claridad abrasadora", - "spellHealerBrightnessNotes": "Una ráfaga de luz deslumbra a tus tareas. ¡Cambian menos rojo y más azul! (Basado en: INT)", + "spellHealerBrightnessNotes": "Una ráfaga de luz deslumbra a tus tareas. ¡Se vuelven menos rojas y más azules! (Basado en: INT)", "spellHealerProtectAuraText": "Aura protectora", "spellHealerProtectAuraNotes": "Escudas tu equipo de daño. ¡La constitución de tu equipo se ve potenciada! (Basado en: CON no potenciada)", "spellHealerHealAllText": "Bendición", - "spellHealerHealAllNotes": "Una aura relajante les rodea. ¡Los de tu equipo recuperan salud! (Basado en: CON e INT)", + "spellHealerHealAllNotes": "Una aura relajante los rodea. ¡Todos los de tu equipo recuperan salud! (Basado en: CON e INT)", "spellSpecialSnowballAuraText": "Bola de nieve", "spellSpecialSnowballAuraNotes": "¡Lanza una bola de nieve a un miembro del grupo! ¿Qué podría salir mal? Dura hasta el nuevo día del compañero.", "spellSpecialSaltText": "Sal", @@ -47,4 +47,4 @@ "spellSpecialSeafoamNotes": "¡Convierte a un amigo en una criatura marina!", "spellSpecialSandText": "Arena", "spellSpecialSandNotes": "Cancela los efectos de la espuma de mar." -} +} \ No newline at end of file diff --git a/common/locales/fr/backgrounds.json b/common/locales/fr/backgrounds.json index 0c7e15d22d..f904a6dc16 100644 --- a/common/locales/fr/backgrounds.json +++ b/common/locales/fr/backgrounds.json @@ -119,11 +119,11 @@ "backgroundSlimySwampNotes": "Échinez-vous à traverser un Marais Visqueux", "backgroundSwarmingDarknessText": "Ténèbres Grouillantes", "backgroundSwarmingDarknessNotes": "Frissonnez dans les Ténèbres Grouillantes", - "backgrounds112015": "SET 18: Released November 2015", - "backgroundFloatingIslandsText": "Floating Islands", - "backgroundFloatingIslandsNotes": "Hop across the Floating Islands.", - "backgroundNightDunesText": "Night Dunes", - "backgroundNightDunesNotes": "Walk peacefully through the Night Dunes.", - "backgroundSunsetOasisText": "Sunset Oasis", - "backgroundSunsetOasisNotes": "Bask in the Sunset Oasis." + "backgrounds112015": "Ensemble 18: Sortie en novembre 2015", + "backgroundFloatingIslandsText": "Les Îles Flottantes", + "backgroundFloatingIslandsNotes": "Parcourez les Îles Flottantes.", + "backgroundNightDunesText": "Les Dunes Nocturnes", + "backgroundNightDunesNotes": "Promenez-vous tranquillement dans les Dunes Nocturnes.", + "backgroundSunsetOasisText": "L'Oasis du Coucher de Soleil", + "backgroundSunsetOasisNotes": "Prélassez-vous à l'Oasis du Coucher de Soleil." } \ No newline at end of file diff --git a/common/locales/fr/challenge.json b/common/locales/fr/challenge.json index c6c9d85dd1..73020422fc 100644 --- a/common/locales/fr/challenge.json +++ b/common/locales/fr/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "Vous n'avez pas le droit d'éditer ce défi.", "noPermissionDeleteChallenge": "Vous n'avez pas le droit de supprimer ce défi.", "noPermissionCloseChallenge": "Vous n'avez pas le droit de fermer ce défi.", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "Sans propriétaire", "noChallengeOwnerPopover": "Ce défi n'a pas de propriétaire, parce que la personne qui a créé le défi a supprimé son compte." } \ No newline at end of file diff --git a/common/locales/fr/character.json b/common/locales/fr/character.json index b53b4f7388..962271a97b 100644 --- a/common/locales/fr/character.json +++ b/common/locales/fr/character.json @@ -65,6 +65,10 @@ "ultimGearText": "S'est équipé avec les meilleurs armes et les meilleures armures pour les classes suivantes :", "level": "Niveau", "levelUp": "Montée de niveau !", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "Vie", "mp": "PM", diff --git a/common/locales/fr/content.json b/common/locales/fr/content.json index 54c7b8aade..a7bdbaa6f7 100644 --- a/common/locales/fr/content.json +++ b/common/locales/fr/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Grenouille", "questEggFrogMountText": "Grenouille", "questEggFrogAdjective": "un princier", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Trouvez une potion d’éclosion à verser sur cet œuf et il en sortira <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "de Base", "hatchingPotionWhite": "Blanc", diff --git a/common/locales/fr/faq.json b/common/locales/fr/faq.json index 5016c008e5..0cff1b8c61 100644 --- a/common/locales/fr/faq.json +++ b/common/locales/fr/faq.json @@ -16,7 +16,7 @@ "iosFaqAnswer4": "Il y a plusieurs choses qui peuvent vous causer des dégâts. D'abord, si vous laissez de tâches Quotidiennes incomplètes pendant la nuit, elles vous causeront des dégâts. Ensuite, si vous réalisez une mauvaise Habitude, elle vous causera des dégâts. Enfin, si vous et votre Équipe affrontez un Boss, et qu'un de vos compagnons n'a pas réalisé toutes ses tâches Quotidiennes, Le Boss vous attaquera.\n\nLa meilleure façon de guérir est de gagner un niveau, qui vous rendra toute votre santé. Vous pouvez aussi acheter une Potion de Santé avec de l'or à partir de la colonne Récompenses. En plus, au delà du niveau 10, vous pouvez choisir de devenir un Guérisseur, et vous pourrez apprendre les compétences de guérison. Si vous êtes en Équipe avec un Guérisseur, il peut aussi vous guérir.", "webFaqAnswer4": "Il y a plusieurs choses qui peuvent vous causer des dégâts. D'abord, si vous laissez de tâches Quotidiennes incomplètes pendant la nuit, elles vous causeront des dégâts. Ensuite, si vous réalisez une mauvaise Habitude, elle vous causera des dégâts. Enfin, si vous et votre Équipe affrontez un Boss, et qu'un de vos compagnons n'a pas réalisé toutes ses tâches quotidiennes, Le Boss vous attaquera.\n

\nLa meilleure façon de guérir est de gagner un niveau, qui vous rendra toute votre santé. Vous pouvez aussi acheter une Potion de Santé avec de l'or à partir de la colonne Récompenses. En plus, au delà du niveau 10, vous pouvez choisir de devenir un Guérisseur, et vous pourrez apprendre les compétences de guérison. Si vous êtes en Équipe (dans Social > Équipe) avec un Guérisseur, il peut aussi vous guérir.", "faqQuestion5": "Comment jouer à Habitica avec mes amis ?", - "iosFaqAnswer5": "The best way is to invite them to a Party with you! Parties can go on quests, battle monsters, and cast skills to support each other. Go to Menu > Party and click \"Create New Party\" if you don't already have a Party. Then tap on the Members list, and tap Invite in the upper right-hand corner to invite your friends by entering their User ID (a string of numbers and letters that they can find under Settings > Account Details on the app, and Settings > API on the website). On the website, you can also invite friends via email, which we will add to the app in a future update.\n\nOn the website, you and your friends can also join Guilds, which are public chat rooms. Guilds will be added to the app in a future update!", + "iosFaqAnswer5": "Le meilleur moyen est de les inviter dans une Équipe avec vous. Les Équipes peuvent partir en quêtes, combattre des monstres, et utiliser leurs compétences pour s’entraider. Si vous n'avez pas encore d'Équipe, allez dans Menu > Équipe et cliquez sur « Créer une nouvelle Équipe », puis cliquez sur la liste de membres et finalement cliquez sur Inviter dans le coin supérieur droit pour inviter vos amis en inscrivant leur ID d'utilisateur (une chaîne de nombres et de lettres que vous pouvez trouver sous Paramètres > Détails du compte, dans l'application, ou sous Paramètres > API sur le site Web). Sur le site Web, vous pouvez également inviter des amis par courriel. Cette option sera rajouté à l'application à une mise à mise ultérieure.\n\nSur le site Web, vous et vos amis pouvez aussi rejoindre des Guildes, qui sont des salons de discussion publics. Les Guildes seront ajoutés à cette application dans une mise à jour ultérieure !", "webFaqAnswer5": "Le meilleur moyen est de les inviter dans une Équipe avec vous, en passant par Social > Équipe ! Les Équipes peuvent partir en quêtes, combattre des monstres, et utiliser leurs compétences pour s'entraider. Vous et vos amis pouvez aussi rejoindre des Guildes (Social > Guildes), qui sont des salons de discussion sur un intérêt partagé ou à la poursuite d'un même but, et peuvent être publiques ou privées. Vous pouvez joindre autant de guildes que vous voulez, mais seulement une équipe.\n

\nPour des informations plus précises, lisez sur le wiki les pages à propos des [Équipes](http://habitrpg.wikia.com/wiki/Party) et des [Guildes](http://habitrpg.wikia.com/wiki/Guilds).", "faqQuestion6": "Comment obtenir des Familiers ou des Montures ?", "iosFaqAnswer6": "A partir du niveau 3, vous débloquerez le Système de Butin. Chaque fois que vous réaliserez une tâche, vous aurez une chance aléatoire de recevoir un œuf, une potion d'éclosion, ou un morceau de nourriture. Ils seront stockés dans Menu > Objets.\n\nPour faire éclore un Familier, vous aurez besoin d'un œuf et d'une potion d'éclosion. Sélectionnez l’œuf pour déterminer l'espèce que vous voulez faire éclore, et choisissez \"Faire éclore l'Œuf.\" Puis choisissez la potion d'éclosion pour déterminer sa couleur ! Allez dans Menu > Familiers pour équiper votre nouveau Familier en cliquant dessus.\n\nVous pouvez aussi faire grandir vos Familiers en Montures en les nourrissant dans Menu > Familiers, et en sélectionnant \"Nourrir le Familier\" ! Vous devrez nourrir un familier plusieurs fois avant qu'il ne devienne une Monture, mais si vous devinez sa nourriture préférée, il grandira plus vite. Faites des essais, ou [lisez les spoilers ici](http://habitica.wikia.com/wiki/Food#Food_Preferences). Une fois que vous avez obtenu une monture, allez dans Menu > Montures et sélectionnez la pour l'équiper.\n\nVous pouvez aussi gagner des œufs pour les Quêtes de Familiers en accomplissant certaines Quêtes. (Voir ci-dessous pour en apprendre plus sur les Quêtes.)", @@ -28,9 +28,9 @@ "iosFaqAnswer8": "Cette barre bleue qui apparaît lorsque vous atteignez le niveau 10 et choisissez une Classe est votre barre de Mana. En gagnant des niveaux supplémentaires, vous débloquerez des Compétences spéciales qui coûtent du Mana. Chaque Classe a des Compétences différentes, qui apparaissent après le niveau 11 dans Menu > Utiliser les Compétences. Contrairement à votre barre de vie, votre barre de Mana ne se réinitialise pas quand vous gagnez un niveau. A la place, du Mana est récupéré lorsque vous réalisez une Bonne Habitude, une Quotidienne ou une tâche À Faire, et du Mana est perdu quand vous succombez à une Mauvaise Habitude. Vous regagnerez aussi du Mana pendant la nuit -- Plus vous aurez complété de Quotidiennes, plus vous en regagnerez.", "webFaqAnswer8": "Cette barre bleue qui apparaît lorsque vous atteignez le niveau 10 et choisissez une Classe est votre barre de Mana. En gagnant des niveaux supplémentaires, vous débloquerez des Compétences spéciales qui coûtent du Mana. Chaque Classe a des Compétences différentes, qui apparaissent après le niveau 11 dans la colonne Récompenses. Contrairement à votre barre de vie, votre barre de Mana ne se réinitialise pas quand vous gagnez un niveau. A la place, du Mana est récupéré lorsque vous réalisez une Bonne Habitude, une Quotidienne ou une tâche À Faire, et du Mana est perdu quand vous succombez à une Mauvaise Habitude. Vous regagnerez aussi du Mana pendant la nuit -- Plus vous aurez complété de Quotidiennes, plus vous en regagnerez.", "faqQuestion9": "Comment combattre des monstres et partir en Quête ?", - "iosFaqAnswer9": "First, you need to join or start a Party (see above). Although you can battle monsters alone, we recommend playing in a group, because this will make Quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n\n Next, you need a Quest Scroll, which are stored under Menu > Items. There are three ways to get a scroll:\n\n - At level 15, you get a Quest-line, aka three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively. \n - When you invite people to your Party, you'll be rewarded with the Basi-List Scroll!\n - You can buy Quests from the Quests Page on the [website](https://habitica.com/#/options/inventory/quests) for Gold and Gems. (We will add this feature to the app in a future update.)\n\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading by pulling down on the screen may be required to see the Boss's health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your Party at the same time that you damage the Boss. \n\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", + "iosFaqAnswer9": "Il vous faudra tout d'abord rejoindre une Équipe (Social > Équipe). Bien que vous puissiez combattre des monstres en solo, nous vous recommandons de jouer en groupe ; vos Quêtes n'en seront que plus faciles. Il est aussi très motivant d'avoir des amis à vos côtés pour vous encourager à finir toutes vos tâches !

Vous aurez ensuite besoin d'un Parchemin de Quête, que vous retrouverez dans Inventaire > Quêtes. Il y a trois façons d'obtenir un parchemin :

- Au niveau 15, vous recevrez une série de Quêtes, c'est-à-dire trois quêtes liées. D'autres séries seront débloquées aux niveau 30, 40 et 60.
- Quand vous invitez des membres à rejoindre votre équipe, vous serez récompensé(e) avec le parchemin du Basi-list !
- Vous pouvez acheter des Quêtes depuis la page Quêtes de votre inventaire [Inventaire > Quêtes](https://habitica.com/#/options/inventory/quests) pour de l'Or et des Gemmes.

Pour combattre un Boss ou réunir des objets lors d'une quête de collection, complétez simplement vos tâches comme vous le faites d'habitude, et elles seront automatiquement converties en dégâts pendant la nuit. (Il vous faudra peut-être recharger la page pour voir descendre la barre de vie du Boss). Si vous combattez un Boss et ratez une de vos tâches Quotidiennes, le Boss infligera des dégâts à votre équipe au moment où vous l'attaquerez.

Après le niveau 11, les Mages et les Guerriers gagnent des compétences leur permettant d'infliger des dégâts additionnels au Boss. Ce sont donc les deux classes à privilégier au niveau 10 si vous souhaitez gagner en force de frappe.", "webFaqAnswer9": "D'abord, vous devez rejoindre une Équipe (dans Social > Équipe). Bien que vous puissiez combattre des monstres seul, nous recommandons de jouer dans un groupe car cela rendra vos Quêtes plus facile. En plus, avoir des amis qui vous encouragent à accomplir vos tâches est très motivant !\n

\nEnsuite, vous avez besoin d'un Parchemin de Quête, qui sont stockés dans Inventaire > Quêtes. Il y a trois façons d'obtenir un parchemin :\n

\n* Quand vous invitez des membres dans votre équipe, vous serez récompensés avec le parchemin du Basi-list !\n* Au niveau 15, vous recevrez une série de Quêtes, c'est à dire trois quêtes liées. D'autres séries seront débloquées aux niveau 30, 40 et 60.\n* Vous pouvez acheter des Quêtes depuis la page Quêtes (Inventaire > Quêtes) pour de l'Or et des Gemmes.\n

\nPour combattre un Boss ou réunir des objets pour une quête de collection, réalisez simplement vos tâches normalement, et elle seront transformées en dégâts pendant la nuit. (Recharger peut être nécessaire pour voir la barre de vie du Boss descendre). Si vous combattez un Boss et ratez une de vos tâches Quotidiennes, le Boss infligera des dégâts à votre équipe au moment où vous lui infligerez des dégâts.\n

\nAprès le niveau 11, les Mages et les Guerriers gagneront des compétences qui leurs permettent d'infliger des dégâts additionnels au Boss, en faisant ainsi d'excellentes classes après le niveau 10 si vous souhaitez taper dur.", - "faqQuestion10": "What are Gems, and how do I get them?", + "faqQuestion10": "Que sont les Gemmes, et comment puis-je en obtenir ?", "iosFaqAnswer10": "Les Gemmes sont achetées avec de l'argent en sélectionnant l'icône de gemme dans l'en-tête. Lorsque des gens achètent des gemmes, ils nous aident à maintenir le site. Nous les remercions pour leur soutien ! En plus d'acheter des gemmes directement, il y a trois façons pour les joueurs de gagner des gemmes : * Gagnez un Défi sur le [site](https://habitica.com) qui a été ouvert par un autre joueur dans Social > Défis. (Nous ajouterons cette fonctionnalité dans l'application dans une mise à jour ultérieure !) * Abonnez-vous sur le [site](https://habitica.com/#/options/settings/subscription) et débloquez la capacité d'acheter un certain nombre de gemmes par mois. * Contribuez au projet Habitica avec vos compétences. Lisez cette page du Wiki pour plus de détails : [Contribuer à Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica). Gardez à l'esprit que les objets achetés avec des gemmes n'offrent aucun avantage statistique, donc les joueurs peuvent très bien utiliser l'application sans elles !", "webFaqAnswer10": "Les Gemmes sont [achetées avec de l'argent](https://habitica.com/#/options/settings/subscription) bien que les [abonnés](https://habitica.com/#/options/settings/subscription) puissent en acheter avec de l'Or. Lorsque des gens achètent des gemmes, il nous aident à maintenir le site. Nous les remercions pour leur soutient !\n

\nEn plus d'acheter des gemmes directement, il y a deux façons pour les joueurs de gagner des gemmes :\n

\n* Gagnez un Défi qui a été ouvert par un autre joueur dans Social > Défis.\n* Contribuez au projet Habitica avec vos compétences. Lisez cette page du Wiki pour plus de détail : [Contribuer à Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica).\n

\nGardez à l'esprit que les objets achetés avec des gemmes n'offrent aucun avantage statistiques, donc les joueurs peuvent très bien utiliser l'application sans elles !", "faqQuestion11": "Comment signaler un bug ou demander une fonctionnalité ?", diff --git a/common/locales/fr/front.json b/common/locales/fr/front.json index 890397dffd..1e509f50f3 100644 --- a/common/locales/fr/front.json +++ b/common/locales/fr/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] m'a vraiment aidé à définir une structure à mon quotidien à l'université.", "invalidEmail": "Une adresse mail valide est nécessaire pour lancer une réinitialisation du mot de passe.", "irishfeet123Quote": "J'ai de terribles habitudes avec le nettoyage de ma place à table après le repas, et je laissais mes tasses partout. [Habitica] a réglé ça !", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Avant [Habitica], j'étais coincé sur ma thèse, et insatisfait avec ma discipline personnelle à propos des tâches ménagère, et des choses comme apprendre le vocabulaire ou étudier la théorie de Go. Il s'avère que découper toutes ces tâches en petites listes de vérification gérables m'a permis de rester motivé et continuellement actif.", "landingadminlink": "solutions administratives", "landingend": "Pas encore convaincu·e ?", @@ -180,7 +180,13 @@ "merchandiseInquiries": "Demandes commerciales", "marketingInquiries": "Demandes pour le marketing/les réseaux sociaux", "tweet": "Tweet", - "apps": "Apps", - "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "apps": "Applications", + "notifyAndroidApp": "Vous voulez savoir quand l'application Android sera prête ? Inscrivez-vous à la mailing list !", + "checkOutIOSApp": "Découvrez notre nouvelle application iOS !", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/fr/gear.json b/common/locales/fr/gear.json index 54137a40f8..9db185bdfb 100644 --- a/common/locales/fr/gear.json +++ b/common/locales/fr/gear.json @@ -156,8 +156,8 @@ "weaponArmoireGoldWingStaffNotes": "Les ailes de ce bâton s'agitent et se tordent en permanence. Augmente tous les attributs de <%= attrs %> chacun. Armoire Enchantée : Objet indépendant.", "weaponArmoireBatWandText": "Baguette Chauve-souris", "weaponArmoireBatWandNotes": "Cette baguette peut transformer n'importe quelle tâche en chauve-souris! Agitez-la dans tous les sens et regardez-les s'envoler. Augmente l'Intelligence de <%= int %> points et la Perception de <%= per %> points. Armoire Enchantée: Objet indépendant.", - "weaponArmoireShepherdsCrookText": "Shepherd's Crook", - "weaponArmoireShepherdsCrookNotes": "Useful for herding gryphons. Increases Constitution by <%= con %>. Enchanted Armoire: Shepherd Set (Item 1 of 3).", + "weaponArmoireShepherdsCrookText": "Houlette de Berger", + "weaponArmoireShepherdsCrookNotes": "Utile pour rassembler les griffons. Augmente la Constitution de <%= con %>. Armoire Enchantée : Ensemble du Berger (Objet 1 sur 3).", "armor": "armure", "armorBase0Text": "Habit simple", "armorBase0Notes": "Un vêtement ordinaire. N'apporte aucun avantage.", @@ -323,10 +323,10 @@ "armorArmoireHornedIronArmorNotes": "Férocement forgée dans le fer, cette armure cornue est presque impossible à briser. Augmente la Constitution de <%= con %> et la Perception de <%= per %>. Armoire Enchantée : Ensemble des Cornes de Fer (Objet 2 sur 3).", "armorArmoirePlagueDoctorOvercoatText": "Pardessus de Médecin de la Peste", "armorArmoirePlagueDoctorOvercoatNotes": "Un authentique pardessus porté par les médecins qui ont combattu la Peste de Procrastination ! Augmente l'Intelligence de <%= int %>, la Force de <%= str %>, et la Constitution de <%= con %>. Armoire Enchantée, Ensemble de Médecin de la Peste (Objet 3 sur 3).", - "armorArmoireShepherdRobesText": "Shepherd Robes", - "armorArmoireShepherdRobesNotes": "The fabric is cool and breathable, perfect for a hot day herding gryphons in the desert. Increases Strength and Perception by <%= attrs %> each. Enchanted Armoire: Shepherd Set (Item 2 of 3).", - "armorArmoireRoyalRobesText": "Royal Robes", - "armorArmoireRoyalRobesNotes": "Wonderful ruler, rule all day long! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 3 of 3).", + "armorArmoireShepherdRobesText": "Tunique de Berger", + "armorArmoireShepherdRobesNotes": "Le tissu est léger et aéré, parfait pour une chaude journée passée à rassembler des griffons dans le désert. Augmente la Force et la Perception <%= attrs %> de chacune. Armoire Enchantée : Ensemble du Berger (Objet 2 sur 3)", + "armorArmoireRoyalRobesText": "Robe Royale", + "armorArmoireRoyalRobesNotes": "Merveilleux souverain, règne du matin au soir ! Augmente la Constitution, l'Intelligence et la Perception de <%= attrs %> chacun. Armoire Enchantée : Ensemble Royal ( Objet 3 sur 3)", "headgear": "coiffe", "headBase0Text": "Pas de casque", "headBase0Notes": "Pas de couvre-chef.", @@ -487,7 +487,7 @@ "headArmoireBlueHairbowText": "Nœud Bleu", "headArmoireBlueHairbowNotes": "Devenez perspicace, tenace et brillant en portant ce magnifique Nœud Bleu ! Augmente la Perception de <%= per %> points, la Constitution de <%= con %> points et l'Intelligence de <%= int %> points. Armoire Enchantée : Objet Indépendant.", "headArmoireRoyalCrownText": "Couronne Royale", - "headArmoireRoyalCrownNotes": "Hooray for the ruler, mighty and strong! Increases Strength by <%= str %>. Enchanted Armoire: Royal Set (Item 1 of 3).", + "headArmoireRoyalCrownNotes": "Hourra pour le souverain, puissant et fort ! Augmente la Force de <%= str %>. Armoire Enchantée : Ensemble Royal (Objet 1 sur 3).", "headArmoireGoldenLaurelsText": "Lauriers Dorés", "headArmoireGoldenLaurelsNotes": "Ces lauriers dorés récompensent ceux qui ont conquis les mauvaises habitudes. Augmente la Perception et la Constitution de <%= attrs %> chacun. Armoire Enchantée : Ensemble de la Toge Dorée (Objet 2 sur 3).", "headArmoireHornedIronHelmText": "Casque de Fer Cornu", @@ -502,10 +502,10 @@ "headArmoireBlackCatNotes": "Ce chapeau noir... ronronne. Et remue la queue. Et respire aussi? Bon, vous avez simplement un chat endormi sur la tête. Augmente l'Intelligence et la Perception de <%= attrs %> points chacune. Armoire Enchantée: Objet indépendant.", "headArmoireOrangeCatText": "Chapeau Chat Orange", "headArmoireOrangeCatNotes": "Ce chapeau orange... ronronne. Et remue la queue. Et respire aussi? Bon, vous avez simplement un chat endormi sur la tête. Augmente la Force et la Constitution de <%= attrs %> points chacune. Armoire Enchantée: Objet indépendant.", - "headArmoireBlueFloppyHatText": "Blue Floppy Hat", - "headArmoireBlueFloppyHatNotes": "Many spells have been sewn into this simple hat, giving it a brilliant blue color. Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Independent Item.", - "headArmoireShepherdHeaddressText": "Shepherd Headdress", - "headArmoireShepherdHeaddressNotes": "Sometimes the gryphons that you herd like to chew on this headdress, but it makes you seem more intelligent nonetheless. Increases Intelligence by <%= int %>. Enchanted Armoire: Shepherd Set (Item 3 of 3).", + "headArmoireBlueFloppyHatText": "Chapeau Négligé Bleu", + "headArmoireBlueFloppyHatNotes": "De nombreux sorts ont été cousus dans ce chapeau simple, lui conférant une couleur bleue brillante. Augmente la Constitution, l'Intelligence et la Perception de <%= attrs %> chacun. Armoire Enchantée : Objet indépendant.", + "headArmoireShepherdHeaddressText": "Capuche de Berger", + "headArmoireShepherdHeaddressNotes": "Parfois, les griffons que vous gardez s'amusent à mâchonner cette capuche, mais elle vous donne tout de même l'air plus intelligent. Augmente l'Intelligence de <%= int %>. Armoire Enchantée : Ensemble du Berger (Objet 3 sur 3).", "offhand": "objet de main de bouclier", "shieldBase0Text": "Pas d'Équipement de Main de Bouclier", "shieldBase0Notes": "Pas de bouclier ni de deuxième arme.", @@ -589,8 +589,8 @@ "shieldArmoireGladiatorShieldNotes": "Pour être un gladiateur, vous devez ... euh, peu importe, cognez-les simplement avec votre bouclier. Augmente la Constitution de <%= con %> points et la Force de <%= str %> points. Armoire Enchantée : Ensemble de Gladiateur (Objet 3 sur 3).", "shieldArmoireMidnightShieldText": "Bouclier de Minuit", "shieldArmoireMidnightShieldNotes": "Ce bouclier est le plus puissant aux douze coups de minuit! Augmente la Constitution de <%= con %> points et la Force de <%= str %> points. Armoire Enchantée : Objet Indépendant.", - "shieldArmoireRoyalCaneText": "Royal Cane", - "shieldArmoireRoyalCaneNotes": "Hooray for the ruler, worthy of song! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 2 of 3).", + "shieldArmoireRoyalCaneText": "Canne Royale", + "shieldArmoireRoyalCaneNotes": "Hourra pour le souverain, dont on chante les louanges dans le royaume ! Augmente la Constitution, l'Intelligence et la Perception de <%= attrs %> chacun. Armoire Enchantée : Ensemble Royal ( Objet 2 sur 3).", "back": "Accessoire de Dos", "backBase0Text": "Pas d’accessoire dorsal", "backBase0Notes": "Pas d’accessoire dorsal.", diff --git a/common/locales/fr/generic.json b/common/locales/fr/generic.json index 80c0567577..ab35d27f62 100644 --- a/common/locales/fr/generic.json +++ b/common/locales/fr/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Je t'envoie mille mercis.", "thankyou3": "Je suis très reconnaissant - merci !", "thankyouCardAchievementTitle": "Grandement Reconnaissant", - "thankyouCardAchievementText": "Merci d'être reconnaissant ! A envoyé ou reçu <%= cards %> cartes de remerciements." + "thankyouCardAchievementText": "Merci d'être reconnaissant ! A envoyé ou reçu <%= cards %> cartes de remerciements.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/fr/pets.json b/common/locales/fr/pets.json index 395bf58dd2..8f53006985 100644 --- a/common/locales/fr/pets.json +++ b/common/locales/fr/pets.json @@ -58,8 +58,16 @@ "firstDrop": "Vous avez débloqué le système d'objets ! À présent lorsque vous complétez des tâches, vous avez une petite chance de trouver un objet. Vous venez de trouver un <%= eggText %> Œuf ! <%= eggNotes %>", "useGems": "Si vous voulez un Familier et que vous n'en pouvez plus d'attendre de le trouver, utilisez des Gemmes dans Inventaire > Marchépour l'acheter !", "hatchAPot": "Faire éclore un <%= egg %> <%= potion %> ?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Donner <%= article %><%= text %> à <%= name %> ?", "useSaddle": "Seller <%= pet %> ?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= egg %> <%= potion %>", "mountName": "<%= mount %> <%= potion %>", "petKeyName": "Clé du Chenil", diff --git a/common/locales/fr/quests.json b/common/locales/fr/quests.json index 7fbbcbd057..3afa17d79c 100644 --- a/common/locales/fr/quests.json +++ b/common/locales/fr/quests.json @@ -13,7 +13,7 @@ "youReceived": "Vous remportez", "dropQuestCongrats": "Félicitations d'avoir gagné ce parchemin de quête ! Vous pouvez inviter votre équipe à commencer la quête maintenant, ou y revenir à n'importe quel moment dans votre Inventaire > Quêtes.", "questSend": "En cliquant sur \"Inviter\", vous enverrez une invitation aux membres de votre équipe. Lorsque tous les membres auront accepté ou refusé, la quête commencera. Vous pouvez suivre le statut de l'invitation sous Social > Équipe.", - "questSendBroken": "En cliquant sur \"Inviter\", vous enverrez une invitation aux membres de votre équipe. Lorsque tous les membres auront accepté ou refusé, la quête commencera. Vous pouvez suivre le statut de l'invitation sous Social > Équipe.", + "questSendBroken": "En cliquant sur « Inviter », vous enverrez une invitation aux membres de votre équipe. Lorsque tous les membres auront accepté ou refusé, la quête commencera. Vous pouvez suivre le statut de l'invitation sous Social > Équipe.", "inviteParty": "Inviter l’Equipe dans une Quête", "questInvitation": "Invitation à une Quête :", "questInvitationTitle": "Invitation à une Quête", @@ -76,5 +76,7 @@ "startAQuest": "COMMENCER UNE QUÊTE", "startQuest": "Commencer la Quête", "whichQuestStart": "Quelle quête voulez-vous démarrer ?", - "getMoreQuests": "Obtenez plus de quêtes" + "getMoreQuests": "Obtenez plus de quêtes", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/fr/questscontent.json b/common/locales/fr/questscontent.json index 8490e5d91e..3fa6d9b496 100644 --- a/common/locales/fr/questscontent.json +++ b/common/locales/fr/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "La grenouille se replie dans la vase, vaincue. Tandis qu'elle s'éloigne en titubant, la vase bleue disparaît, laissant la voie libre.

Au beau milieu du chemin se trouvent trois oeufs immaculés. \"L'enveloppe est tellement claire qu'on peut même voir les têtards au travers!\" dit @Breadstrings. \"Tiens, tu devrais les prendre.\"", "questFrogBoss": "La Grenouille du Désordre", "questFrogDropFrogEgg": "Grenouille (Œuf)", - "questFrogUnlockText": "Déverrouille l'achat d’œufs de grenouilles au Marché" + "questFrogUnlockText": "Déverrouille l'achat d’œufs de grenouilles au Marché", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/fr/rebirth.json b/common/locales/fr/rebirth.json index bc4c65b2ea..e2c6a0f1d7 100644 --- a/common/locales/fr/rebirth.json +++ b/common/locales/fr/rebirth.json @@ -16,11 +16,11 @@ "rebirthEarnAchievement": "Vous avez également obtenu un Succès pour avoir commencé une nouvelle aventure !", "beReborn": "Renaître", "rebirthAchievement": "Vous avez commencé une nouvelle aventure ! C'est votre Renaissance n°<%= number %> et le niveau le plus élevé que vous avez atteint est <%= level %>. Pour cumuler ce Succès, commencez votre nouvelle aventure une fois que vous aurez atteint un niveau encore plus élevé !", - "rebirthAchievement100": "Vous avez commencé une nouvelle aventure ! C'est votre Renaissance <%= number %>, et le plus haut niveau que vous ayez atteint est 100 ou plus. Pour empiler les succès, commencez votre prochaine nouvelle aventure lorsque vous aurez atteint au moins le niveau 100 !", + "rebirthAchievement100": "Vous avez commencé une nouvelle aventure ! C'est votre Renaissance <%= number %>, et le plus haut niveau que vous ayez atteint est 100 ou plus. Pour optimiser ce succès, commencez votre prochaine nouvelle aventure lorsque vous aurez atteint la prochaine centaine !", "rebirthBegan": "A commencé une Nouvelle Aventure", "rebirthText": "A débuté <%= rebirths %> Nouvelles Aventures", "rebirthOrb": "A utilisé un Orbe de Renaissance pour recommencer à zéro après avoir atteint le niveau", - "rebirthOrb100": "A utilisé une Orbe de Renaissance pour recommencer à zéro après avoir atteint le niveau 100 ou plus. ", + "rebirthOrb100": "A utilisé un Orbe de Renaissance pour recommencer à zéro après avoir atteint le niveau 100 ou plus", "rebirthPop": "Commencez un nouveau personnage au Niveau 1 en conservant les succès, les objets de collection et les tâches avec historique.", "rebirthName": "Orbe de Renaissance", "reborn": "Né de nouveau, niveau maximum <%= reLevel %>" diff --git a/common/locales/fr/settings.json b/common/locales/fr/settings.json index 8fd71f7342..1f06c60851 100644 --- a/common/locales/fr/settings.json +++ b/common/locales/fr/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Avec cette option cochée, la liste des étiquettes d'une tâche sera cachée à l'ouverture de la tâche pour modification.", "startAdvCollapsed": "Options Avancées des tâches réduites", "startAdvCollapsedPop": "Avec cette option cochée, les Options Avancées seront cachées quand vous modifierez une tâche pour la première fois.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Montrer la visite guidée", "restartTour": "Relance la visite guidée d'introduction vue lors de votre première visite sur Habitica.", "showBailey": "Montrer Bailey", @@ -81,7 +86,6 @@ "emailChange1": "Pour modifier votre adresse mail, merci d'envoyer un mail à", "emailChange2": "admin@habitica.com", "emailChange3": "incluant à la fois votre ancienne et votre nouvelle adresse mail et votre ID d'utilisateur·trice", - "username": "Nom d'utilisateur", "usernameOrEmail": "Nom d'utilisateur ou adresse courriel", "email": "Mail", "registeredWithFb": "Inscrit·e avec Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "Utilisateur -> Profil", "loginNameDescription3": "pour modifier le nom qui apparaît sur votre avatar et dans les messages.", "emailNotifications": "Notifications par Mail", - "wonChallenge": "Vous avez Remporté un Défi", + "wonChallenge": "You won a Challenge!", "newPM": "Message Privé Reçu", "giftedGems": "Gemmes Offertes", "giftedGemsInfo": "<%= amount %> Gemmes - de <%= name %>", diff --git a/common/locales/he/challenge.json b/common/locales/he/challenge.json index 99ba1935af..93468e8d49 100644 --- a/common/locales/he/challenge.json +++ b/common/locales/he/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "You don't have permissions to edit this challenge", "noPermissionDeleteChallenge": "You don't have permissions to delete this challenge", "noPermissionCloseChallenge": "You don't have permissions to close this challenge", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "no owner", "noChallengeOwnerPopover": "This challenge does not have an owner because the person who created the challenge deleted their account." } \ No newline at end of file diff --git a/common/locales/he/character.json b/common/locales/he/character.json index b98485d0e5..c368dc19e2 100644 --- a/common/locales/he/character.json +++ b/common/locales/he/character.json @@ -65,6 +65,10 @@ "ultimGearText": "שדרג את נשקיו ושריונו לדרגה הגבוהה ביותר במקצועות הבאים:", "level": "דרגה", "levelUp": "עלית דרגה!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "מאנה", "hp": "נק\"פ", "mp": "נק\"מ", diff --git a/common/locales/he/content.json b/common/locales/he/content.json index c0706a2cea..e2382b5c7c 100644 --- a/common/locales/he/content.json +++ b/common/locales/he/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Frog", "questEggFrogMountText": "Frog", "questEggFrogAdjective": "a princely", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "רגיל", "hatchingPotionWhite": "לבן", diff --git a/common/locales/he/front.json b/common/locales/he/front.json index ae4bdca895..210210e7e0 100644 --- a/common/locales/he/front.json +++ b/common/locales/he/front.json @@ -74,7 +74,7 @@ "infhQuote": "[הביטיקה] ממש עזרה לי להשליט ארגון בחיי במהלך תואר שני.", "invalidEmail": "כתובת דואר אלקטרוני תקפה הינה הכרחית על מנת לבצע איפוס סיסמא.", "irishfeet123Quote": "היו לי הרגלים ממש גרועים בנוגע להשארת כלים על השולחן ופיזור כוסות בכל הבית. [הביטיקה] ריפאה זאת!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "לפני [הביטיקה], הייתי תקוע עם התזה שלי, וגם מאוכזב מהמשמעת העצמית שלי בנוגע לעבודות הבית ודברים כמו לימוד אוצר מילים ותיאוריה מאחורי Go. מסתבר ששבירת המטרות האלו למשימות שניתנות לניהול וצ׳ק-ליסטים זה ה-דבר כדי להשאיר אותי לעבוד באופן קבוע עם מוטיבציה.", "landingadminlink": "החבילות הניהוליות שלנו,", "landingend": "עדיין לא השתכנעת?", @@ -182,5 +182,11 @@ "tweet": "Tweet", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/he/generic.json b/common/locales/he/generic.json index 047e5b4b4d..b4936f86e0 100644 --- a/common/locales/he/generic.json +++ b/common/locales/he/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Sending you a thousand thanks.", "thankyou3": "I'm very grateful - thank you!", "thankyouCardAchievementTitle": "Greatly Grateful", - "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards." + "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/he/pets.json b/common/locales/he/pets.json index a0f39f91c0..01c0796c6f 100644 --- a/common/locales/he/pets.json +++ b/common/locales/he/pets.json @@ -58,8 +58,16 @@ "firstDrop": "הרווחת את מערכת הביזה! מעתה, בכל פעם שתשלימ/י משימה, יהיה לך סיכוי קטן למצוא חפץ בעל ערך כולל ביצים, שיקויים ואוכל. הרגע מצאת <%= eggText %> ביצה! <%= eggNotes %>", "useGems": "אם חיית מחמד מסוימת תפסה את עיניך, אבל אינך יכול לחכות יותר לבזוז אותה, השתמש/י ביהלומים במלאי ציוד > שוק כדי לקנות אותה!", "hatchAPot": "להבקיע <%= egg %> <%= potion %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "להאכיל את ה<%= name %> שלך ב <%= text %>?", "useSaddle": "לשים אוכף על ה<%= pet %> שלך?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= egg %> <%= potion %>", "mountName": "<%= mount %> <%= potion %>", "petKeyName": "מפתח למכלאות", diff --git a/common/locales/he/quests.json b/common/locales/he/quests.json index a4ff0b30cc..4b41b17af9 100644 --- a/common/locales/he/quests.json +++ b/common/locales/he/quests.json @@ -76,5 +76,7 @@ "startAQuest": "START A QUEST", "startQuest": "Start Quest", "whichQuestStart": "Which quest do you want to start?", - "getMoreQuests": "Get more quests" + "getMoreQuests": "Get more quests", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/he/questscontent.json b/common/locales/he/questscontent.json index f201f1df4b..31bcb64540 100644 --- a/common/locales/he/questscontent.json +++ b/common/locales/he/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/he/settings.json b/common/locales/he/settings.json index 96d06be482..05f0b0c590 100644 --- a/common/locales/he/settings.json +++ b/common/locales/he/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "אם האפשרות הזו מסומנת, רשימת התגיות של המטלה תהיה מוסתרת כשתפתח/י את המטלה לעריכה", "startAdvCollapsed": "אפשרויות מתקדמות של מטלות מתחילות סגורות", "startAdvCollapsedPop": "אם אפשרות זו מסומנת, אפשרויות מתקדמות יהיו חבויות כאשר תפתח/י את המשימה לעריכה.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "הראה סיור", "restartTour": "מתחיל מחדש את סיור ההיכרות מהזמן בו הצטרפת לhabitRPG.", "showBailey": "הראה את באילי", @@ -81,7 +86,6 @@ "emailChange1": "כדי לשנות את כתובת הדוא\"ל שלך, בבקשה שלח מייל ל-", "emailChange2": "admin@habitica.com", "emailChange3": "וכלול את כתובות הדוא\"ל הישנה והחדשה שלך כמו גם את מספר זיהוי המשתמש שלך.", - "username": "שם כניסה", "usernameOrEmail": "שם משתמש או אימייל", "email": "כתובת דוא\"ל", "registeredWithFb": "רשום עם Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "משתמש->פרופיל", "loginNameDescription3": "כדי לשנות את השם שמופיע באוואטר שלך ובהודעות הצ'אט.", "emailNotifications": "הודעות", - "wonChallenge": "זכית באתגר", + "wonChallenge": "You won a Challenge!", "newPM": "קיבלת הודעה פרטית חדשה", "giftedGems": "אבני חן שזכית בהן", "giftedGemsInfo": "<%= amount %> אבני חן - מאת <%= name %>", diff --git a/common/locales/hu/challenge.json b/common/locales/hu/challenge.json index e6a74e45b3..4d6f023a56 100644 --- a/common/locales/hu/challenge.json +++ b/common/locales/hu/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "Nincs jogod szerkeszteni ezt a kihívást", "noPermissionDeleteChallenge": "Nincs jogod törölni ezt a kihívást", "noPermissionCloseChallenge": "Nincs jogod lezárni ezt a kihívást", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "nincs tulajdonosa", "noChallengeOwnerPopover": "Ennek a kihívásnak nincs tulajdonosa, mert a személy aki létrehozta törölte fiókját." } \ No newline at end of file diff --git a/common/locales/hu/character.json b/common/locales/hu/character.json index 362d1c41f8..46b049b87a 100644 --- a/common/locales/hu/character.json +++ b/common/locales/hu/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Maximálisra fejlesztette a fegyvert és páncélzatot a következő kasztoknak:", "level": "Szint", "levelUp": "Szintet léptél!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "ÉE", "mp": "VP", diff --git a/common/locales/hu/content.json b/common/locales/hu/content.json index afe6a10d62..df01861346 100644 --- a/common/locales/hu/content.json +++ b/common/locales/hu/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Frog", "questEggFrogMountText": "Frog", "questEggFrogAdjective": "a princely", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Alap", "hatchingPotionWhite": "Fehér", diff --git a/common/locales/hu/front.json b/common/locales/hu/front.json index 5c446ee6f0..788892b6c8 100644 --- a/common/locales/hu/front.json +++ b/common/locales/hu/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] has really helped me impart structure to my life in graduate school.", "invalidEmail": "A jelszó resethez érvényes email cím szükséges.", "irishfeet123Quote": "I've had horrible habits with clearing my place completely after meals and leaving cups all over the place. [Habitica] has cured that!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Before [Habitica], I was stuck with my thesis, as well as dissatisfied with my personal discipline regarding housework and things like learning vocabulary and studying Go theory. It turns out breaking down these tasks into smaller manageable checklists is quite the thing to keep me motivated and constantly working.", "landingadminlink": "adminisztratív csomagunkat", "landingend": "Nem győzött még meg?", @@ -182,5 +182,11 @@ "tweet": "Tweet", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/hu/generic.json b/common/locales/hu/generic.json index 9c797e401a..ea1b6a1eed 100644 --- a/common/locales/hu/generic.json +++ b/common/locales/hu/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Ezerhála neked.", "thankyou3": "Nagyon hálás vagyok, köszönöm!", "thankyouCardAchievementTitle": "Nagyon Hálás", - "thankyouCardAchievementText": "Köszönöm, hogy hálás vagy! Küldtél vagy kaptál <%= cards %> Köszönöm kártyát." + "thankyouCardAchievementText": "Köszönöm, hogy hálás vagy! Küldtél vagy kaptál <%= cards %> Köszönöm kártyát.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/hu/pets.json b/common/locales/hu/pets.json index 1f29f75736..cd0d89593f 100644 --- a/common/locales/hu/pets.json +++ b/common/locales/hu/pets.json @@ -58,8 +58,16 @@ "firstDrop": "You've unlocked the Drop System! Now when you complete tasks, you have a small chance of finding an item, including eggs, potions, and food! You just found a <%= eggText %> Egg! <%= eggNotes %>", "useGems": "Ha megtetszik egy háziállat, de nem tudsz tovább várni arra, hogy megtaláld, használj Drágaköveket itt: Tárgylista > Piac a vásárláshoz!", "hatchAPot": "Kelteted a(z) <%= egg %>-t a(z) <%= potion %> -al?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Megeteted a(z) <%= article %><%= text %>-t a <%= name %>-el?", "useSaddle": "Felnyergeled a(z) <%= pet %>-t?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Kulcs a ólakhoz", diff --git a/common/locales/hu/quests.json b/common/locales/hu/quests.json index f89a093ca0..b290446aa8 100644 --- a/common/locales/hu/quests.json +++ b/common/locales/hu/quests.json @@ -76,5 +76,7 @@ "startAQuest": "START A QUEST", "startQuest": "Start Quest", "whichQuestStart": "Which quest do you want to start?", - "getMoreQuests": "Get more quests" + "getMoreQuests": "Get more quests", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/hu/questscontent.json b/common/locales/hu/questscontent.json index eaf5157be7..18a7fd323b 100644 --- a/common/locales/hu/questscontent.json +++ b/common/locales/hu/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/hu/settings.json b/common/locales/hu/settings.json index ca7f2cffb5..5c33e43962 100644 --- a/common/locales/hu/settings.json +++ b/common/locales/hu/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Ha ez be van állítva, akkor a cimkelista el lesz rejtve, amikor megnyitsz egy feladatot szerkesztésre.", "startAdvCollapsed": "A Haladó Beállítások a feladatoknál összecsukva indulnak.", "startAdvCollapsedPop": "Ha ez be van állítva, akkor a Haladó Beállítások el lesznek rejtve, amikor először megnyitsz egy feladatot szerkesztésre.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Mutasd a bemutatót", "restartTour": "A bevezető újraindítása onnantól, hogy csatlakoztál a Habitica-hez.", "showBailey": "Mutasd Bailey-t", @@ -81,7 +86,6 @@ "emailChange1": "Az email címed megváltoztatásához kérjük küldj egy emailt a", "emailChange2": "admin@habitica.com-ra", "emailChange3": "a régi és az új email címeddel és a felhasználói azonosítóddal.", - "username": "Bejelentkezési név", "usernameOrEmail": "Login név vagy email cím", "email": "Email", "registeredWithFb": "Facebook-al regisztráltál", @@ -89,7 +93,7 @@ "loginNameDescription2": "Felhasználó->Profil", "loginNameDescription3": "oldalra hogy megváltoztasd a nevedet ami a avatarodnál és a chat üzeneteknél megjelenik.", "emailNotifications": "Email értesítések", - "wonChallenge": "Megnyertél egy Kihívást", + "wonChallenge": "You won a Challenge!", "newPM": "Kaptál egy Privát üzenetet", "giftedGems": "Ajándékoztál Drágaköveket", "giftedGemsInfo": "<%= amount %> Gems - by <%= name %>", diff --git a/common/locales/it/backgrounds.json b/common/locales/it/backgrounds.json index 7ac343759b..68a2a76b6f 100644 --- a/common/locales/it/backgrounds.json +++ b/common/locales/it/backgrounds.json @@ -113,17 +113,17 @@ "backgroundTavernText": "Taverna di Habitica", "backgroundTavernNotes": "Fai una visita alla Taverna.", "backgrounds102015": "SERIE 17: Ottobre 2015", - "backgroundHarvestMoonText": "Luna del Raccolto", - "backgroundHarvestMoonNotes": "Schiamazzare sotto la Luna del Raccolto", - "backgroundSlimySwampText": "Palude Melmosa", - "backgroundSlimySwampNotes": "Arrancare attraverso una Palude Melmosa.", + "backgroundHarvestMoonText": "Luna del Raccolto ", + "backgroundHarvestMoonNotes": "Canta al chiarore della Luna del Raccolto.", + "backgroundSlimySwampText": "Palude Melmosa ", + "backgroundSlimySwampNotes": "Arranca attraverso una palude melmosa.", "backgroundSwarmingDarknessText": "Oscurità Brulicante", - "backgroundSwarmingDarknessNotes": "Tremare nel Oscurità Brulicante.", - "backgrounds112015": "SET 18: Released November 2015", - "backgroundFloatingIslandsText": "Floating Islands", - "backgroundFloatingIslandsNotes": "Hop across the Floating Islands.", - "backgroundNightDunesText": "Night Dunes", - "backgroundNightDunesNotes": "Walk peacefully through the Night Dunes.", - "backgroundSunsetOasisText": "Sunset Oasis", - "backgroundSunsetOasisNotes": "Bask in the Sunset Oasis." + "backgroundSwarmingDarknessNotes": "Un'oscurità che mette i brividi.", + "backgrounds112015": "SERIE 18: Novembre 2015 ", + "backgroundFloatingIslandsText": "Isole Fluttuanti", + "backgroundFloatingIslandsNotes": "Saltella tra le isole fluttuanti.", + "backgroundNightDunesText": "Dune Notturne", + "backgroundNightDunesNotes": "Fai una passeggiata notturna tra le dune.", + "backgroundSunsetOasisText": "Oasi al tramonto", + "backgroundSunsetOasisNotes": "Goditi l'oasi durante il tramonto." } \ No newline at end of file diff --git a/common/locales/it/challenge.json b/common/locales/it/challenge.json index 3978f687c8..812623c046 100644 --- a/common/locales/it/challenge.json +++ b/common/locales/it/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "Non hai i permessi per modificare questa sfida", "noPermissionDeleteChallenge": "Non hai i permessi per eliminare questa sfida", "noPermissionCloseChallenge": "Non hai i permessi per concludere questa sfida", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "nessun proprietario", - "noChallengeOwnerPopover": "Questa sfida non ha un proprietario perché la persona che ha creato la sfida ha eliminato il suo account." + "noChallengeOwnerPopover": "Questa sfida non ha un proprietario perché la persona che ha creato la sfida ha eliminato il proprio account." } \ No newline at end of file diff --git a/common/locales/it/character.json b/common/locales/it/character.json index e230cc3e5e..f2ac6aaa28 100644 --- a/common/locales/it/character.json +++ b/common/locales/it/character.json @@ -52,7 +52,7 @@ "classEquipBonus": "Bonus classe", "battleGear": "Assetto di battaglia", "battleGearText": "Questo è l'equipaggiamento che indossi in battaglia, esso modifica alcuni valori quando interagisci con le tue attività.", - "autoEquipBattleGear": "Equipaggiare automatica nuova attrezzatura", + "autoEquipBattleGear": "Equipaggia automaticamente nuovi oggetti", "costume": "Costume", "costumeText": "Se preferisci il look di oggetti diversi da quelli equipaggiati, metti una spunta su \"Usa costume\" per visualizzare un costume anzichè l'equipaggiamento da battaglia (nonostante il cambio di aspetto, rimangono tutti i bonus delle armi e delle armature).", "useCostume": "Usa costume", @@ -65,6 +65,10 @@ "ultimGearText": "Ha potenziato al massimo armi e armatura per le seguenti classi:", "level": "Livello", "levelUp": "Livello aumentato!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "PV", "mp": "PM", diff --git a/common/locales/it/content.json b/common/locales/it/content.json index 4410ce2e9c..c5a7e44127 100644 --- a/common/locales/it/content.json +++ b/common/locales/it/content.json @@ -85,7 +85,7 @@ "questEggSheepAdjective": "una soffice", "questEggCuttlefishText": "Seppia", "questEggCuttlefishMountText": "Seppia", - "questEggCuttlefishAdjective": "un grazioso", + "questEggCuttlefishAdjective": "una graziosa", "questEggWhaleText": "Balena", "questEggWhaleMountText": "Balena", "questEggWhaleAdjective": "una zampillante", @@ -95,9 +95,12 @@ "questEggHorseText": "Cavallo", "questEggHorseMountText": "Cavallo", "questEggHorseAdjective": "un galoppante", - "questEggFrogText": "Frog", - "questEggFrogMountText": "Frog", - "questEggFrogAdjective": "a princely", + "questEggFrogText": "Rana", + "questEggFrogMountText": "Rana", + "questEggFrogAdjective": "una principesca", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Trova una pozione per far schiudere questo uovo, e nascerà <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Base", "hatchingPotionWhite": "Bianco", diff --git a/common/locales/it/faq.json b/common/locales/it/faq.json index f0b68baeca..046cde82f0 100644 --- a/common/locales/it/faq.json +++ b/common/locales/it/faq.json @@ -16,7 +16,7 @@ "iosFaqAnswer4": "Ci sono diverse ragioni per cui puoi venire ferito. Il motivo principale e' l'aver lasciato incompiute alcune tue Dailies durante la notte, queste mancanze ti danneggiano. In secondo luogo, se clicchi su di una Habit negativa, questa ti danneggera'. Ed in fine, se ti trovi a fronteggiare un Boss in una battaglia con la tua Squadra ed uno dei tuoi compagni non completa tutte le sue Dailies, il Boss vi attacchera'.\n\nLa via principale per riguadagnare i tuoi punti salute e' salire di livello, questo ti fara' recuperare completamente salute. Puoi inoltre comprare con dell'oro una Pozione Salute nella colonna delle Ricompense. Inoltre, dal livello 10 in poi, puoi scegliere di diventare un Guaritore ed imparerai cosi' degli incantesimi di guarigione. Se ti trovi in Squadra con un Guaritore, puoi beneficiare del suo aiuto.", "webFaqAnswer4": "Ci sono diverse ragioni per cui puoi venire ferito. Il motivo principale e' l'aver lasciato incompiute alcune tue Dailies durante la notte, queste mancanze ti danneggiano. In secondo luogo, se clicchi su di una Habit negativa, questa ti danneggera'. Ed in fine, se ti trovi a fronteggiare un Boss in una battaglia con la tua Squadra ed uno dei tuoi compagni non completa tutte le sue Dailies, il Boss vi attacchera'.\n

\nLa via principale per riguadagnare i tuoi punti salute e' salire di livello, questo ti fara' recuperare completamente salute. Puoi inoltre comprare con dell'oro una Pozione Salute nella colonna delle Ricompense. Inoltre, dal livello 10 in poi, puoi scegliere di diventare un Guaritore ed imparerai cosi' degli incantesimi di guarigione. Se ti trovi in Squadra (cerca in Social > Squadra) con un Guaritore, puoi beneficiare del suo aiuto.", "faqQuestion5": "Come faccio per giocare in Habitica con i miei amici?", - "iosFaqAnswer5": "The best way is to invite them to a Party with you! Parties can go on quests, battle monsters, and cast skills to support each other. Go to Menu > Party and click \"Create New Party\" if you don't already have a Party. Then tap on the Members list, and tap Invite in the upper right-hand corner to invite your friends by entering their User ID (a string of numbers and letters that they can find under Settings > Account Details on the app, and Settings > API on the website). On the website, you can also invite friends via email, which we will add to the app in a future update.\n\nOn the website, you and your friends can also join Guilds, which are public chat rooms. Guilds will be added to the app in a future update!", + "iosFaqAnswer5": "Il miglior modo é invitarli in un Gruppo con te! I Gruppi possono intraprendere missioni, sconfiggere mostri, e usare abilità per sopportarsi l'un l'altro. Vai su Menu > Gruppo e clicca \"Crea Nuovo Gruppo\" se non ne hai ancora uno. Dopodiché tocca la lista dei Membri, e tocca Invita nell'angolo in alto a destra per invitare i tuoi amici inserendo il loro ID Utente (una serie di numeri e lettere che possono trovare sotto Impostazioni > Dettagli Account sull'app, e sotto Impostazioni > API sul sito). Sul sito, puoi anche invitare i tuoi amici via email, che aggiungeremo all'applicazione in un aggiornamento futuro.\n\nSul sito, tu e i tuoi amici potete anche unirvi a una Gilda, che sono chat room pubbliche. Le Gilde saranno aggiunte all'app in un aggiornamento futuro!", "webFaqAnswer5": "Il modo migliore e' quello di invitarli a fare Squadra con te, dal menu' Social > Squadra! Le Squadre possono partecipare alle missioni, combattere i mostri e dividersi le abilita' per aiutarsi a vicenda. Insieme potete inoltre unirvi alle Gilde (Social > Gilde). Le Gilde sono delle chat rivolte ad un interesse condiviso o al raggiungimento di un obiettivo comune, possono essere pubbliche o private. Puoi unirti a tutte le Gilde che desideri ma ad un'unica Squadra.\n

\nPer informazioni piu' dettagliate, puoi guardare sulla pagina wiki [Parties](http://habitrpg.wikia.com/wiki/Party) and [Guilds](http://habitrpg.wikia.com/wiki/Guilds).", "faqQuestion6": "Come posso prendere un Animale o una Cavalcatura?", "iosFaqAnswer6": "Dopo il livello 3 sbloccherai il Sistema di Drop. Ogni volta che completi un'attività avrai una possibilità di vincere un Uovo, una Pozione di schiusura o del Cibo. Questi verranno archiviati in Menù > Inventario.\n\nPer far nascere un Animale avrai bisogno di un Uovo e di una Pozione di schiusura. Premi sull'uovo per scegliere la specie che vuoi far schiudere, e seleziona quindi la Pozione di Schiusura per determinare il colore! Torna su Menù > Animali per equipaggiare il tuo nuovo animale al tuo Avatar premendoci sopra.\n\nPuoi anche far evolvere i tuoi Animali in Cavalcature cibandoli in Menù > Animali. Clicca sul Cibo nel riquadro a destra \"Cibo e Selle\", quindi seleziona l'Animale. Dovrai alimentare l'Animale diverse volte prima di farlo diventare una Cavalcatura, ma se riesci a trovare il suo cibo preferito crescerà molto più in fretta. Fai diverse prove o [Spoiler qui](http://habitica.wikia.com/wiki/Food#Food_Preferences). Una volta che hai una Cavalcatura, vai in Menù > Cavalcature e selezionala per equipaggiarla al tuo avatar.\n\nPotrai inoltre ricevere Uova dalle Missioni Animali completandole.(Vedi sotto per saperne di più sulle Missioni)", @@ -26,13 +26,13 @@ "webFaqAnswer7": "Al livello 10, puoi scegliere di diventare un Guerriero, un Mago, un Assassino, o un Guaritore. (Tutti i giocatori iniziano come Guerrieri per impostazione predefinita.) Ogni classe ha diverse opzioni di equipaggiamento, diverse abilità che possono lanciare dopo il livello 11, e diversi vantaggi. I Guerrieri possono facilmente danneggiare i Boss, sopportare più danni dalle loro attività, e contribuire a rendere la loro squadra più forte. Anche i Maghi possono facilmente danneggiare i Boss, così come possono salire di livello velocemente e ripristinare mana per la loro squadra. Gli Assassini guadagnano più oro e trovano più item drop, e possono aiutare la loro squadra a fare lo stesso. Infine, i Guaritori possono curare loro stessi e i loro compagni di squadra.\n

\nSe non vuoi scegliere subito una Classe -- per esempio, se stai ancora lavorando per comprare tutto l'equipaggiamento della tua classe attuale -- puoi cliccare \"Rinuncia\" e riattivarla successivamente in Utente > Statistiche.", "faqQuestion8": "Cos'è la barra blu che appare nell'intestazione dopo il livello 10? ", "iosFaqAnswer8": "La barra blu che appare nell'intestazione quando raggiungi il livello 10 e scegli une Classe e la barra di Mana. Quando avanzi di livello, potrai scegliere delle Abilita' speciali che costano Mana ad ogni uso. Ogni Classe ha Abilita' diverse che appaiono dopo il livello 11, sotto Menu> Usare Abilita'. All'opposto della barra Salute, la barra Mana non si ripiena quando avanzi di livello, invece, si riempie ogni volta che completi buone Habit, Dailies e Da-Fare, e si svuota quando cedi ad una cattiva abitudine. Puoi anche guadagnare un po' di Mana durante la notte-- più Dailies hai completato, più Mana guadagni. ", - "webFaqAnswer8": "The blue bar that appeared when you hit level 10 and chose a Class is your Mana bar. As you continue to level up, you will unlock special Skills that cost Mana to use. Each Class has different Skills, which appear after level 11 in a special section in the Rewards Column. Unlike your Health bar, your Mana bar does not reset when you gain a level. Instead, Mana is gained when you complete Good Habits, Dailies, and To-Dos, and lost when you indulge bad Habits. You’ll also regain some Mana overnight -- the more Dailies you completed, the more you will gain.", + "webFaqAnswer8": "La barra blu che è apparsa nell'intestazione quando hai raggiunto il livello 10 e hai scelto une Classe è la barra del Mana. Quando avanzi di livello, sbloccherai delle Abilità speciali che costano Mana ad ogni uso. Ogni Classe ha Abilità diverse, che appaiono dopo il livello 11 in una sezione speciale della colonna delle Ricompense. A differenza della barra Salute, la barra Mana non si riempie quando avanzi di livello. Invece, il Mana si rigenera quando completi Habit positive, Dailies e To-do, e si svuota quando cedi ad una Habit negativa. Guadagni inoltre un po' di Mana durante la notte -- più Dailies hai completato, più Mana guadagni. ", "faqQuestion9": "Come faccio a combattere i mostri e andare in Missione?", "iosFaqAnswer9": "First, you need to join or start a Party (see above). Although you can battle monsters alone, we recommend playing in a group, because this will make Quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n\n Next, you need a Quest Scroll, which are stored under Menu > Items. There are three ways to get a scroll:\n\n - At level 15, you get a Quest-line, aka three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively. \n - When you invite people to your Party, you'll be rewarded with the Basi-List Scroll!\n - You can buy Quests from the Quests Page on the [website](https://habitica.com/#/options/inventory/quests) for Gold and Gems. (We will add this feature to the app in a future update.)\n\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading by pulling down on the screen may be required to see the Boss's health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your Party at the same time that you damage the Boss. \n\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", "webFaqAnswer9": "First, you need to join or start a party (under Social > Party). Although you can battle monsters alone, we recommend playing in a group, because this will make quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n

\n Next, you need a Quest Scroll, which are stored under Inventory > Quests. There are three ways to get a scroll:\n

\n * When you invite people to your party, you’ll be rewarded with the Basi-List Scroll!\n * At level 15, you get a Quest-line, i.e., three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively.\n * You can buy Quests from the Quests Page (Inventory > Quests) for Gold and Gems.\n

\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading may be required to see the Boss's Health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your party at the same time that you damage the Boss.\n

\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", - "faqQuestion10": "What are Gems, and how do I get them?", + "faqQuestion10": "Cosa sono le Gemme, e come le ottengo? ", "iosFaqAnswer10": "Gems are purchased with real money by tapping on the gem icon in the header. When people buy gems, they are helping us to keep the site running. We're very grateful for their support!\n\n In addition to buying gems directly, there are three other ways players can gain gems:\n\n * Win a Challenge on the [website](https://habitica.com) that has been set up by another player under Social > Challenges. (We will be adding Challenges to the app in a future update!)\n * Subscribe on the [website](https://habitica.com/#/options/settings/subscription) and unlock the ability to buy a certain number of gems per month.\n * Contribute your skills to the Habitica project. See this wiki page for more details: [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica).\n\n Keep in mind that items purchased with gems do not offer any statistical advantages, so players can still make use of the app without them!", - "webFaqAnswer10": "Gems are [purchased with real money](https://habitica.com/#/options/settings/subscription), although [subscribers](https://habitica.com/#/options/settings/subscription) can purchase them with Gold. When people subscribe or buy Gems, they are helping us to keep the site running. We're very grateful for their support!\n

\n In addition to buying Gems directly or becoming a subscriber, there are two other ways players can gain Gems:\n

\n * Win a Challenge that has been set up by another player under Social > Challenges.\n * Contribute your skills to the Habitica project. See this wiki page for more details: [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica)\n

\n Keep in mind that items purchased with Gems do not offer any statistical advantages, so players can still make use of the site without them!", + "webFaqAnswer10": "Le Gemme vengono [comprate con soldi reali](https://habitica.com/#/options/settings/subscription), anche se [gli abbonati](https://habitica.com/#/options/settings/subscription) possono comprare Gemme in cambio di Oro. Quando le persone si abbonano o comprano Gemme, ci aiutano a mantenre il sito attivo. Siamo molto grati per il loro sostegno!\n

\n Oltre a comprare le Gemme direttamente o abbonarsi, ci sono altri due modi in cui i gioctori possono ottenre Gemme:\n

\n * Vincendo una Sfida creata da una altro giocatore sotto Social > Sfide.\n * Contribuire con le tue abilità al progetto Habitica. Consulta questa pagina della wiki per maggiori informazioni: [Contribuire ad Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica)\n

\n Ricorda che gli oggetti comprati con le Gemme non offrono nessun vantaggio statistico, perciò i giocatori possono comunque utilizzare il sito anche senza di esse!", "faqQuestion11": "Come posso segnalare un bug o dare dei suggerimenti?", "iosFaqAnswer11": "Puoi segnalare un bug, richiedere una funzione, o inviare commenti in Menu > Segnala un Bug e Menu > Invia Commenti! Faremo tutto il possibile per aiutarti.", "webFaqAnswer11": "Errori vengono raggruppati su GitHub. Vai su [Aiuto> denuncia Errore] (https://github.com/HabitRPG/habitrpg/issues/2760) e segui le istruzioni. non ti preoccupare, ripareremo tutto presto.\n

\nRichieste per funzioni nuove vengono consegnate su Trello. Vai su [Aiuto> Richiesta funzione] (https://trello.com/c/odmhIqyW/440-read-first-table-of-contents) e segui le istruzioni. Ta-da!", diff --git a/common/locales/it/front.json b/common/locales/it/front.json index 42c660365c..6e9a36a42d 100644 --- a/common/locales/it/front.json +++ b/common/locales/it/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] mi ha davvero aiutato a dare una struttura alla mia vita universitaria.", "invalidEmail": "Per resettare la password è necessario un indirizzo email valido.", "irishfeet123Quote": "Avevo l'orribile abitudine di non ripulire completamente il mio posto dopo mangiato e lasciare tazze ovunque. [Habitica] si è rivelato essere la cura!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Prima di [Habitica] ero bloccata con la mia tesi, nonchè insoddisfatta della mia disciplina riguardo i lavori di casa e cose come imparare vocaboli e studiare la teoria del Go. A quanto pare separare queste attività in liste più piccole e maneggevoli è il modo giusto per mantenermi motivata e costantemente al lavoro.", "landingadminlink": "pacchetti amministrativi", "landingend": "Non sei ancora convinto?", @@ -180,7 +180,13 @@ "merchandiseInquiries": "Informazioni sui Prodotti", "marketingInquiries": "Informazioni su Marketing e Social Media", "tweet": "Tweet", - "apps": "Apps", - "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "apps": "Applicazioni", + "notifyAndroidApp": "Vuoi che ti notifichiamo quando l'app per Android é pronta? Iscriviti a questa mailing list!", + "checkOutIOSApp": "Dai un'occhiata alla nostra nuova App per iOS!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/it/gear.json b/common/locales/it/gear.json index 456628e7e8..29d5d3fffd 100644 --- a/common/locales/it/gear.json +++ b/common/locales/it/gear.json @@ -115,7 +115,7 @@ "weaponSpecialSpring2015WarriorText": "Clava Ossea", "weaponSpecialSpring2015WarriorNotes": "È una vera clava d'osso per veri cagnolini feroci! Certamente non è un giocattolo da masticare che la Maga Stagionale ti ha dato perchè chi è un bravo cagnolino? Chiiii è un bravo cagnolino?? Sei tu!!! Sei tu il bravo cagnolino!!! Aumenta la Forza di <%= str %>. Edizione limitata, primavera 2015.", "weaponSpecialSpring2015MageText": "Bacchetta da Prestigiatore", - "weaponSpecialSpring2015MageNotes": "Conjure up a carrot for yourself with this fancy wand. Increases Intelligence by <%= int %> and Perception by <%= per %>. Limited Edition 2015 Spring Gear.", + "weaponSpecialSpring2015MageNotes": "Evocati una carota con quest'elegante bacchetta. Aumenta l'intelligenza di <%=int %> e la Percezione di <%= per%>. Edizione Limitata Equipaggiamento Primaverile 2015.", "weaponSpecialSpring2015HealerText": "Sonaglio da Gatto", "weaponSpecialSpring2015HealerNotes": "Quando lo scuoti, produce un'affascinante tintinnio che intratterrebbe CHIUNQUE per ore. Aumenta l'Intelligenza di <%= int %>. Edizione limitata, primavera 2015.", "weaponSpecialSummer2015RogueText": "Corallo da Fuoco", @@ -129,11 +129,11 @@ "weaponSpecialFall2015RogueText": "Bat-tle Ax", "weaponSpecialFall2015RogueNotes": "Fearsome To-Dos cower before the flapping of this ax. Increases Strength by <%= str %>. Limited Edition 2015 Autumn Gear.", "weaponSpecialFall2015WarriorText": "Asse di Legno", - "weaponSpecialFall2015WarriorNotes": "Great for elevating things in cornfields and/or smacking tasks. Increases Strength by <%= str %>. Limited Edition 2015 Autumn Gear.", - "weaponSpecialFall2015MageText": "Enchanted Thread", + "weaponSpecialFall2015WarriorNotes": "Ottimo per sollevare cose nei cambi di grano e/o per picchiare le attività. Aumenta Forza di <%= str %>. Edizione Limitata, Equipaggiamento Autunnale 2015.", + "weaponSpecialFall2015MageText": "Filo Incantato", "weaponSpecialFall2015MageNotes": "A powerful Stitch Witch can control this enchanted thread without even touching it! Increases Intelligence by <%= int %> and Perception by <%= per %>. Limited Edition 2015 Autumn Gear.", - "weaponSpecialFall2015HealerText": "Swamp-Slime Potion", - "weaponSpecialFall2015HealerNotes": "Brewed to perfection! Now you just have to convince yourself to drink it. Increases Intelligence by <%= int %>. Limited Edition 2015 Autumn Gear.", + "weaponSpecialFall2015HealerText": "Pozione Melma di Palude", + "weaponSpecialFall2015HealerNotes": "Fermentata alla perfezione! Ora devi solo convincerti a berla. Aumenta l'Intelligenza di <%= int %>. Edizione Limitata Equipaggiamento Autunnale 2015.", "weaponMystery201411Text": "Forcone dei festeggiamenti", "weaponMystery201411Notes": "Infilza i tuoi nemici o inforca i tuoi cibi preferiti - questo versatile forcone può fare di tutto! Non conferisce alcun bonus. Oggetto per abbonati, novembre 2014.", "weaponMystery201502Text": "Scintillante Scettro Alato dell'Amore e anche della Verità", @@ -154,9 +154,9 @@ "weaponArmoireIronCrookNotes": "Fieramente forgiato dal ferro, questo uncino di ferro é ottimo per radunare pecore. Aumenta Percezione e Forza di <%= attrs %> ciascuna. Baule Incantato: Set del Ferro Uncinato (Oggetto 3 di 3)", "weaponArmoireGoldWingStaffText": "Bastone dell'Ala Dorata", "weaponArmoireGoldWingStaffNotes": "Le ali su questo bastone svolazzano e si intrecciano costantemente. Aumenta tutti gli attributi di <%= attrs %> ciascuna. Baule Incantato: Oggetto Indipendente.", - "weaponArmoireBatWandText": "Bat Wand", - "weaponArmoireBatWandNotes": "This wand can turn any task into a bat! Wave it about and watch them fly away. Increases Intelligence by <%= int %> and Perception by <%= per %>. Enchanted Armoire: Independent Item.", - "weaponArmoireShepherdsCrookText": "Shepherd's Crook", + "weaponArmoireBatWandText": "Bacchetta del Pipstrello", + "weaponArmoireBatWandNotes": "Questa bacchetta può trasformare qualunque attività in un pipistrello! Salutalo e guardalo volare via. Aumenta l'Intelligenza <%= int %> di e la Percezione di <%= per % . Baule Incantato: Oggetto Indipendente.", + "weaponArmoireShepherdsCrookText": "Uncino del Pastore", "weaponArmoireShepherdsCrookNotes": "Useful for herding gryphons. Increases Constitution by <%= con %>. Enchanted Armoire: Shepherd Set (Item 1 of 3).", "armor": "armatura", "armorBase0Text": "Vestiti semplici", @@ -323,10 +323,10 @@ "armorArmoireHornedIronArmorNotes": "Fieramente forgiata dal ferro, quest'armatura uncinato é praticamente indistruttibile. Aumenta la Costituzione di <%= con %> e la Percezione di <%= per %>. Baule Incantato: Set di ferro Uncinato (Oggetto 2 di 3).", "armorArmoirePlagueDoctorOvercoatText": "Soprabito da Dottore della Piaga", "armorArmoirePlagueDoctorOvercoatNotes": "Un autentico soprabito indossato dai dottori che combattono la Piaga della Procrastinazione! Aumenta l'Intelligenza di <%= int %>, la Forza di <%= str %>, e la Costituzione di <%= con %>. Baule Incantato: Set da Dottore della Piaga (Oggetto 3 di 3)", - "armorArmoireShepherdRobesText": "Shepherd Robes", - "armorArmoireShepherdRobesNotes": "The fabric is cool and breathable, perfect for a hot day herding gryphons in the desert. Increases Strength and Perception by <%= attrs %> each. Enchanted Armoire: Shepherd Set (Item 2 of 3).", - "armorArmoireRoyalRobesText": "Royal Robes", - "armorArmoireRoyalRobesNotes": "Wonderful ruler, rule all day long! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 3 of 3).", + "armorArmoireShepherdRobesText": "Vesti del Pastore", + "armorArmoireShepherdRobesNotes": "Il tessuto è fresco e traspirante, perfetto per una calda giornata di allevamento dei grifoni nel deserto. Aumenta la Forza e la Percezione di <%= attrs %> ciascuna. Baule Incantato: Set del Pastore (Oggetto 2 di 3).", + "armorArmoireRoyalRobesText": "Vesti Regali", + "armorArmoireRoyalRobesNotes": "Meraviglioso sovrano, governa tutto il giorno! Aumenta la Costituzione, l'Intelligenza, e la Percezione di <%= attrs %> ciascuna. Baule Incantato: Set Regale (Oggetto 3 di 3).", "headgear": "copricapo", "headBase0Text": "Nessun elmo", "headBase0Notes": "Non indossi nessun copricapo.", diff --git a/common/locales/it/generic.json b/common/locales/it/generic.json index 5ba667d099..9afe18a331 100644 --- a/common/locales/it/generic.json +++ b/common/locales/it/generic.json @@ -79,7 +79,7 @@ "errorUpCase": "ERRORE:", "newPassSent": "Nuova password inviata.", "serverUnreach": "Il server non è attualmente raggiungibile.", - "requestError": "Yikes, an error occurred! Please reload the page, your last action may not have been saved correctly.", + "requestError": "Oh no, c'é stato un errore! Per favore, ricarica la pagina, la tua ultima azione potrebbe non essere stata salvata correttamente.", "seeConsole": "Se l'errore persiste, per favore segnalalo in Aiuto > Segnala un bug. Se sai come utilizzare la console del tuo browser, per favore allega eventuali messaggi di errore.", "error": "Errore", "menu": "Menù", @@ -113,7 +113,7 @@ "achievementStressbeast": "Eroe di Stoïkalm", "achievementStressbeastText": "Ha contribuito alla sconfitta dell'Abominevole Mostro dello Stress durante l'evento Winter Wonderland 2014!", "achievementBurnout": "Eroe dei Campi Fiorenti", - "achievementBurnoutText": "Helped defeat Burnout and restore the Exhaust Spirits during the 2015 Fall Festival Event!", + "achievementBurnoutText": "Ha contribuito alla sconfitta degli Spiriti dell'Esaurimento durante l'evento Festival d'Autunno 2015!", "checkOutProgress": "Guarda i miei progressi su Habitica!", "cardReceived": "Hai ricevuto una cartolina!", "cardReceivedFrom": "<%= cardType %> da <%= userName %>", @@ -122,17 +122,29 @@ "greetingCardNotes": "Invia una cartolina di saluto a un membro della squadra.", "greeting0": "Ehilà!", "greeting1": "Volevo solo dirti ciao :)", - "greeting2": "`waves frantically`", + "greeting2": "'saluta agitatamente'", "greeting3": "Ehi!", "greetingCardAchievementTitle": "Cheery Chum", "greetingCardAchievementText": "Ehi! Hola! Ciao! Inviate o ricevute <%= cards %> cartoline di saluto.", "thankyouCard": "Cartolina-grazie", - "thankyouCardExplanation": "You both receive the Greatly Grateful achievement!", + "thankyouCardExplanation": "Entrambi ricevete il trofeto Grandemente Grato!", "thankyouCardNotes": "Invia una cartolina di ringraziamento a un compagno di squadra.", "thankyou0": "Grazie mille!", "thankyou1": "Grazie, grazie, grazie!", "thankyou2": "Ti mando un milione di grazie.", "thankyou3": "Hai tutta la mia gratitudine!", - "thankyouCardAchievementTitle": "Greatly Grateful", - "thankyouCardAchievementText": "Grazie per aver espresso la tua gratitudine! Inviate o ricevute <%= cards %> cartoline-grazie." + "thankyouCardAchievementTitle": "Grandemente Grato", + "thankyouCardAchievementText": "Grazie per aver espresso la tua gratitudine! Inviate o ricevute <%= cards %> cartoline-grazie.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/it/limited.json b/common/locales/it/limited.json index 27852a139c..7011616688 100644 --- a/common/locales/it/limited.json +++ b/common/locales/it/limited.json @@ -30,7 +30,7 @@ "seasonalShopText": "Benvenuto nel Negozio Stagionale! Abbiamo in vendita degli oggetti primaverili in Edizione Stagionale. Ogni cosa qui sarà acquistabile durante l'evento \"Spring Fling\" ogni anno, ma siamo aperti solo fino al 30 aprile! Quindi fai scorta adesso, sennò dovrai aspettare il prossimo anno per poter acquistare questi oggetti!", "seasonalShopSummerText": "Benvenuto nel Negozio Stagionale! Abbiamo in vendita degli oggetti estivi in Edizione Stagionale. Ogni cosa qui sarà acquistabile durante l'evento \"Summer Splash\" ogni anno, ma siamo aperti solo fino al 31 luglio! Quindi fai scorta adesso, sennò dovrai aspettare il prossimo anno per poter acquistare questi oggetti!", "seasonalShopFallText": "Benvenuto nel Negozio Stagionale! Abbiamo in vendita degli oggetti autunnali in Edizione Stagionale. Ogni cosa qui sarà acquistabile durante l'evento \"Fall Festival\" ogni anno, ma siamo aperti solo fino al 31 ottobre! Quindi fai scorta adesso, sennò dovrai aspettare il prossimo anno per poter acquistare questi oggetti!", - "seasonalShopFallTextBroken": "Oh.... Welcome to the Seasonal Shop... We're stocking autumn Seasonal Edition goodies, or something... Everything here will be available to purchase during the Fall Festival event each year, but we're only open until October 31... I guess you should to stock up now, or you'll have to wait... and wait... and wait... *sigh*", + "seasonalShopFallTextBroken": "Oh... Benvenuto al Negozio Stagionale... Abbiamo in vendita oggetti dell'Edizione Stagionale autunnale o qualcosa adel genere... Tutto quello che c'é qui sara disponibile per l'acquisto durante l'evento Festival d'Autunno di ogni anno, ma siamo aperti sono fino al 31 Ottobre... Penso che dovresti rifornirti ora altrimenti dovrai aspettare... e aspettare... e aspettare... *sigh*", "seasonalShopRebirth": "Se hai usato la Sfera della Rinascita, potrai riacquistare questo equipaggiamento dalla colonna delle Ricompense. All'inizio potrai comprare solo gli oggetti per la tua classe attuale (Guerriero, se non l'hai ancora scelta/cambiata), ma niente paura, gli altri oggetti specifici per le varie classi diventeranno disponibili se ti converti a quella classe.", "candycaneSet": "Caramello (Mago)", "skiSet": "Nevassassino (Assassino)", diff --git a/common/locales/it/messages.json b/common/locales/it/messages.json index 5b86364a46..c56288f321 100644 --- a/common/locales/it/messages.json +++ b/common/locales/it/messages.json @@ -41,7 +41,7 @@ "messageAuthMustIncludeTokens": "Devi includere un token e un UID (ID utente) nella tua richiesta.", "messageGroupNotFound": "Gruppo inesistente o a cui non puoi accedere.", "messageGroupAlreadyInParty": "Già in una squadra, prova a ricaricare la pagina", - "messageGroupOnlyLeaderCanUpdate": "Only the group leader can update the group!", + "messageGroupOnlyLeaderCanUpdate": "Solo il leader del gruppo può aggiornare il gruppo!", "messageGroupRequiresInvite": "Non puoi unirti ad un gruppo se non sei stato invitato.", "messageGroupCannotRemoveSelf": "Non puoi rimuovere te stesso!", "messageGroupChatBlankMessage": "Non puoi inviare un messaggio vuoto", @@ -49,7 +49,7 @@ "messageGroupChatFlagOwnMessage": "Non puoi segnalare un tuo messaggio.", "messageGroupChatFlagAlreadyReported": "Hai già segnalato questo messaggio.", "messageGroupChatNotFound": "Messaggio non trovato!", - "messageGroupChatAdminClearFlagCount": "Only an admin can clear the flag count!", + "messageGroupChatAdminClearFlagCount": "Solo un amministratore può azzerare il conteggio!", "messageUserOperationProtected": "Il percorso `<%= operation %>` non è stato salvato, perchè è un percorso protetto.", "messageUserOperationNotFound": "Operazione <%= operation %> non trovata" } \ No newline at end of file diff --git a/common/locales/it/npc.json b/common/locales/it/npc.json index e703660185..a76ffb3678 100644 --- a/common/locales/it/npc.json +++ b/common/locales/it/npc.json @@ -79,7 +79,7 @@ "welcome1": "Crea un semplice avatar.", "welcome1notes": "Questo avatar rappresenta te e i tuoi progressi nel gioco.", "welcome2": "Crea e personalizza le tue attività.", - "welcome2notes": "How well you do on your real-life tasks will control how well you do in the game!", + "welcome2notes": "La tua abilità nelle attività della vita reale determinerà la tua ", "welcome3": "Progredisci nella vita e nel gioco!", "welcome3notes": "Mentre migliori la tua vita, il tuo avatar salirà di livello e sbloccherà gli animali, le missioni, l'equipaggiamento, e molto altro ancora!", "welcome4": "Evita le cattive abitudini che ti fanno perdere Salute (HP), o il tuo avatar morirà!", diff --git a/common/locales/it/pets.json b/common/locales/it/pets.json index b76f9f3428..013cde3e61 100644 --- a/common/locales/it/pets.json +++ b/common/locales/it/pets.json @@ -58,8 +58,16 @@ "firstDrop": "Hai sbloccato il sistema di drop! Ora, quando completi un'attività, hai una piccola probabilità di trovare un oggetto, tra cui uova, pozioni e cibo! Hai appena trovato un Uovo di <%= eggText %>! <%= eggNotes %>", "useGems": "Se hai messo gli occhi su un animale, ma non vuoi più aspettare per averlo, usa le gemme in Inventario > Mercato per comparne uno!", "hatchAPot": "Far nascere <%= egg %> <%= potion %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Dare da mangiare <%= article %><%= text %> al tuo <%= name %>?", "useSaddle": "Mettere la sella a <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= egg %> <%= potion %>", "mountName": "<%= mount %> <%= potion %>", "petKeyName": "Chiave dell'Allevamento", diff --git a/common/locales/it/quests.json b/common/locales/it/quests.json index 4a1842c6a7..cc2bf9419a 100644 --- a/common/locales/it/quests.json +++ b/common/locales/it/quests.json @@ -25,25 +25,25 @@ "rejected": "Rifiutata", "pending": "In attesa", "questStart": "Una volta che ogni membro ha accettato o rifiutato, la missione inizia. Solo chi ha selezionato \"Accetta\" potrà partecipare e ricevere le ricompense. Se dei membri rimangono in attesa per troppo tempo (forse perché inattivi?) il Capomissione può iniziare la missione senza di loro selezionando \"Inizia\". Può anche annullare la missione e riottenere la Pergamena selezionando \"Annulla\".", - "questStartBroken": "Once all members have either accepted or rejected, the quest begins... Only those that clicked \"accept\" will be able to participate in the quest and receive the drops... If members are pending too long (inactive?), the quest owner can start the quest without them by clicking \"Begin\"... The quest owner can also cancel the quest and regain the quest scroll by clicking \"Cancel\"...", + "questStartBroken": "Una volta che ogni membro ha accettato o rifiutato, la missione inizia... Solo chi ha selezionato \"Accetta\" potrà partecipare e ricevere le ricompense... Se dei membri rimangono in attesa per troppo tempo (forse perché inattivi?) il Capomissione può iniziare la missione senza di loro selezionando \"Inizia\"... Può anche annullare la missione e riottenere la Pergamena selezionando \"Annulla\"...", "begin": "Inizia", "bossHP": "Salute del Boss", "bossStrength": "Forza del Boss", - "rage": "Rage", + "rage": "Furia", "collect": "Raccogli", "collected": "Collezionati", "collectionItems": "<%= number %> <%= items %>", "itemsToCollect": "Oggetti da raccogliere", "bossDmg1": "Ogni Daily e To-Do completata e ogni Habit positiva danneggiano il boss. Puoi infliggere danni maggiori con le attività più rosse, con Attacco Brutale e con Fiammata. I boss danneggeranno ogni partecipante per le Daily mancate (moltiplicate per la Forza del boss) oltre al loro normale danno, quindi tieni in forze la tua squadra completando le tue Daily! I danni inflitti e ricevuti dal boss sono calcolati al cambio di giorno (all'ora da te impostata).", "bossDmg2": "Solo i partecipanti potranno combattere il boss e condividere il bottino della missione.", - "bossDmg1Broken": "Each completed Daily and To-Do and each positive Habit hurts the boss... Hurt it more with redder tasks or Brutal Smash and Burst of Flames... The boss will deal damage to every quest participant for every Daily you've missed (multiplied by the boss's Strength) in addition to your regular damage, so keep your party healthy by completing your Dailies... All damage to and from a boss is tallied on cron (your day roll-over)...", - "bossDmg2Broken": "Only participants will fight the boss and share in the quest loot...", + "bossDmg1Broken": "Ogni Daily e To-Do completata e ogni Habit positiva danneggiano il boss... Puoi infliggere danni maggiori con le attività più rosse, con Attacco Brutale e con Fiammata... I boss danneggeranno ogni partecipante per le Daily mancate (moltiplicate per la Forza del boss) oltre al loro normale danno, quindi tieni in forze la tua squadra completando le tue Daily... I danni inflitti e ricevuti dal boss sono calcolati al cambio di giorno (all'ora da te impostata)...", + "bossDmg2Broken": "Solo i partecipanti combatteranno il boss e si divideranno il bottino della missione...", "tavernBossInfo": "Complete Dailies and To-Dos and score positive Habits to damage the World Boss! Incomplete Dailies fill the Exhaust Strike Bar. When the Exhaust Strike bar is full, the World Boss will attack an NPC. A World Boss will never damage individual players or accounts in any way. Only active accounts not resting in the Inn will have their tasks tallied.", "tavernBossInfoBroken": "Complete Dailies and To-Dos and score positive Habits to damage the World Boss... Incomplete Dailies fill the Exhaust Strike Bar... When the Exhaust Strike bar is full, the World Boss will attack an NPC... A World Boss will never damage individual players or accounts in any way... Only active accounts not resting in the Inn will have their tasks tallied...", "bossColl1": "Per ottenere gli oggetti, completa delle attività positive. Gli oggetti delle missioni compaiono come quelli normali; non li vedrai però fino al giorno dopo, quando tutto quello che hai trovato verrà raccolto e aggiunto agli oggetti già trovati.", "bossColl2": "Solo i partecipanti potranno collezionare gli oggetti e condividere il bottino della missione.", - "bossColl1Broken": "To collect items, do your positive tasks... Quest items drop just like normal items; however, you won't see the drops until the next day, then everything you've found will be tallied up and contributed to the pile...", - "bossColl2Broken": "Only participants can collect items and share in the quest loot...", + "bossColl1Broken": "Per raccogliere oggetti, completa le tue attività positive... Gli oggetti delle missioni compaiono come oggetti normali; tuttavia, non vedrai gli oggetti fino al giorno successivo, dopodiché tutto ciò che hai trovato verrà conteggiato e aggiunto ai tuoi oggetti.", + "bossColl2Broken": "Solo i partecipanti potranno collezionare gli oggetti e condividere il bottino della missione.", "abort": "Annulla", "leaveQuest": "Abbandona missione", "sureLeave": "Vuoi davvero abbandonare la missione attiva? Tutti i tuoi progressi nella missione andranno persi.", @@ -70,11 +70,13 @@ "sureAbort": "Vuoi davvero annullare questa missione? Questo causerà l'annullamento della missione anche per tutti i membri della tua squadra ed ogni progresso andrà perduto. La Pergamena verrà restituita al Capomissione.", "doubleSureAbort": "Sei veramente sicuro? Assicurati che non ti odieranno per sempre!", "questWarning": "Se altri giocatori si uniscono alla squadra prima che la missione abbia inizio, anche loro riceveranno un invito. Tuttavia, una volta che la missione sarà iniziata, nessun altro membro della squadra potrà unirsi ai partecipanti.", - "questWarningBroken": "If new players join the party before the quest starts, they will also receive an invitation... However once the quest has started, no new party members can join the quest...", + "questWarningBroken": "Se altri giocatori si uniscono alla squadra prima che la missione abbia inizio, anche loro riceveranno un invito. Tuttavia, una volta che la missione sarà iniziata, nessun altro membro della squadra potrà unirsi ai partecipanti.", "bossRageTitle": "Furia", "bossRageDescription": "Quando questa barra sarà completamente piena, il boss eseguirà un attacco speciale!", "startAQuest": "COMINCIA UNA MISSIONE", "startQuest": "Comincia missione", "whichQuestStart": "Che missione vuoi cominciare?", - "getMoreQuests": "Ottieni altre missioni" + "getMoreQuests": "Ottieni altre missioni", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/it/questscontent.json b/common/locales/it/questscontent.json index 0570e526cb..5259281cbe 100644 --- a/common/locales/it/questscontent.json +++ b/common/locales/it/questscontent.json @@ -128,15 +128,15 @@ "questSeahorseBoss": "Stallone Marino", "questSeahorseDropSeahorseEgg": "Cavalluccio Marino (Uovo)", "questSeahorseUnlockText": "Sblocca l'acquisto delle uova di cavalluccio marino nel Mercato", - "questAtom1Text": "Attack of the Mundane, Part 1: Dish Disaster!", + "questAtom1Text": "Attacco del Mondano, Parte 1: Disastro di Stoviglie!", "questAtom1Notes": "Hai raggiunto le rive del Lago Lavapiatti per un po' di relax... Ma il lago è infestato da piatti da lavare! Come sarà successo? Beh, non puoi permettere che il lago rimanga in questo stato. C'è soltanto una cosa da fare: lavare i piatti e salvare il vostro luogo di villeggiatura! Sarà meglio trovare un po' di sapone per pulire questa porcheria. Molto sapone...", "questAtom1CollectSoapBars": "Barrette di Sapone", "questAtom1Drop": "Il Mostro di SnackLess (Pergamena)", - "questAtom2Text": "Attack of the Mundane, Part 2: The SnackLess Monster", + "questAtom2Text": "Attacco del Mondano, Parte 2: Il Mostro Senza-Snack", "questAtom2Notes": "Phew, questo posto sembra molto più bello con tutti questi piatti puliti. Forse, adesso potrai finalmente rilassarti un po'. Oh - sembrerebbe un cartone della pizza quello che sta galleggiando nel lago. Beh, cosa sarà mai un'altra cosa da pulire in fondo? Ma, dannazione, non è un semplice cartone di pizza! Con uno scatto improvviso la scatola si solleva dall'acqua per rivelare la sua vera natura: è la testa di un mostro. Non può essere! Il leggendario Mostro di Snackless? Si dice che abbia vissuto nascosto sin dalla preistoria: una creatura generata dagli avanzi di cibo e dall'immondizia degli antichi abitanti di Habitica. Bleah!", "questAtom2Boss": "Il Mostro di SnackLess", "questAtom2Drop": "Il Bucatomante (Pergamena)", - "questAtom3Text": "Attack of the Mundane, Part 3: The Laundromancer", + "questAtom3Text": "Attacco del Mondano, Parte 3: Il Lavamante", "questAtom3Notes": "Con un urlo assordante, e cinque deliziosi tipi di formaggio che cadono dalla sua bocca, il Mostro di Snackless cade in pezzi. \"COME OSI!\" echeggia una voce da sotto la superficie dell'acqua. Una figura che indossa una tunica blu emerge dall'acqua, brandendo uno spazzolino da water magico. Dalla superficie del lago, inizia ad emergere biancheria sporchissima. \"Sono il Bucatomante!\" annuncia rabbioso. \"Sei davvero coraggioso - lavare i miei piatti deliziosamente sporchi, distruggere il mio servitore, ed entrare nel mio regno con abiti così puliti. Preparati a sentire la sozza furia della mia magia anti-bucato\"!", "questAtom3Completion": "Il pazzo Bucatomante è stato sconfitto! Bucato pulito si deposita a pile intorno a te. Le cose sembrano andare molto bene da queste parti. Mentre inizi a farti strada tra le armature stirate da poco, un bagliore di metallo attrae la tua attenzione, ed il tuo sguardo si posa su un elmo luccicante. Non sai chi possa aver indossato prima questo oggetto luminoso, ma mentre lo indossi, senti la calda presenza di uno spirito generoso. Un peccato che non ci abbiano cucito sopra un'etichetta col nome.", "questAtom3Boss": "Il Bucatomante", @@ -184,7 +184,7 @@ "questRockBoss": "Il Colosso di Cristallo", "questRockCompletion": "La tua diligenza ti ha permesso di trovare un sentiero sicuro tra le montagne viventi. In piedi al sole, il tuo amico @intune nota qualcosa di scintillante al suolo vicino all'uscita della caverna. Ti abbassi per raccoglierlo, e vedi che è una piccola roccia attraversata da una vena dorata. Al suo fianco ci sono svariate rocce dalla forma peculiare. Sembrano quasi... uova?", "questRockDropRockEgg": "Roccia (Uovo)", - "questRockUnlockText": "Sblocca l'cquisto delle uova di roccia nel Mercato", + "questRockUnlockText": "Sblocca l'acquisto delle uova di roccia nel Mercato", "questBunnyText": "La Coniglietta Assassina", "questBunnyNotes": "Dopo molti giorni difficili, raggiungi la cima del Monte Procrastinazione e ti trovi di fronte alle imponenti porte della Fortezza della Negligenza. Leggi l'inscrizione nella pietra. \"All'interno risiede la creatura che incarna le tue più grandi paure, la ragione dietro la tua mancanza di azione. Bussa e confronta il tuo demone!\" Tremi, immaginando l'orrore all'interno e senti l'istinto di scappare come hai fatto così tante volte in precedenza. @Draayder ti trattiene. \"Sta calmo, amico mio! È giunta l'ora. Devi affrontarlo!\"

Bussi e le porte si aprono verso l'interno. Dall'oscurità senti un ruggito assordante e sfoderi la tua arma.", "questBunnyBoss": "Coniglietta Assassina", @@ -203,7 +203,7 @@ "questSheepCompletion": "Colpita dalla tua diligenza, l'Ariete Tuonante è prosciugata della sua furia. Lancia tre enormi chicchi di grandine nella tua direzione, e poi scompare con un cupo rombo. Guardandoli meglio, scopri che i chicchi di grandine sono in realtà tre uova morbide e pelose. Le raccogli, e ti incammini verso casa sotto un cielo azzurro.", "questSheepDropSheepEgg": "Pecorella (Uovo)", "questSheepUnlockText": "Sblocca l'acquisto delle uova di pecorella nel Mercato", - "questKrakenText": "The Kraken of Inkomplete", + "questKrakenText": "Il Kraken dell'Inkompletezza", "questKrakenNotes": "It's a warm, sunny day as you sail across the Inkomplete Bay, but your thoughts are clouded with worries about everything that you still need to do. It seems that as soon as you finish one task, another crops up, and then another...

Suddenly, the boat gives a horrible jolt, and slimy tentacles burst out of the water on all sides! \"We're being attacked by the Kraken of Inkomplete!\" Wolvenhalo cries.

\"Quickly!\" Lemoness calls to you. \"Strike down as many tentacles and tasks as you can, before new ones can rise up to take their place!\"", "questKrakenBoss": "The Kraken of Inkomplete", "questKrakenCompletion": "As the Kraken flees, several eggs float to the surface of the water. Lemoness examines them, and her suspicion turns to delight. \"Cuttlefish eggs!\" she says. \"Here, take them as a reward for everything you've completed.\"", @@ -211,20 +211,20 @@ "questKrakenUnlockText": "Sblocca l'acquisto delle uova di seppia nel Mercato", "questWhaleText": "Il Lamento della Balena", "questWhaleNotes": "You arrive at the Diligent Docks, hoping to take a submarine to watch the Dilatory Derby. Suddenly, a deafening bellow forces you to stop and cover your ears. \"Thar she blows!\" cries Captain @krazjega, pointing to a huge, wailing whale. \"It's not safe to send out the submarines while she's thrashing around!\"

\"Quick,\" calls @UncommonCriminal. \"Help me calm the poor creature so we can figure out why she's making all this noise!\"", - "questWhaleBoss": "Wailing Whale", - "questWhaleCompletion": "After much hard work, the whale finally ceases her thunderous cry. \"Looks like she was drowning in waves of negative habits,\" @zoebeagle explains. \"Thanks to your consistent effort, we were able to turn the tides!\" As you step into the submarine, several whale eggs bob towards you, and you scoop them up.", + "questWhaleBoss": "Balena Lamentosa", + "questWhaleCompletion": "Dopo molto duro lavoro, la balena finalmente cessa il suo lamento portentoso. \"Sembra che stesse affogando nelle onde delle abitudini negative\", spiega @zoebeagle. \"Grazie al tuo impegno costate, siamo riusciti a cambiare la situazione!\" Mentre entri nel sottomarino, diverse uova di balena fluttuano verso di te, e tu le raccogli.", "questWhaleDropWhaleEgg": "Balena (Uovo)", "questWhaleUnlockText": "Sblocca l'acquisto delle uova di balena nel Mercato", "questDilatoryDistress1Text": "Dilatory Distress, Part 1: Message in a Bottle", - "questDilatoryDistress1Notes": "A message in a bottle arrived from the newly rebuilt city of Dilatory! It reads: \"Dear Habiticans, we need your help once again. Our princess has disappeared and the city is under siege by some unknown watery demons! The mantis shrimps are holding the attackers at bay. Please aid us!\" To make the long journey to the sunken city, one must be able to breathe water. Fortunately, the alchemists @Benga and @hazel can make it all possible! You only have to find the proper ingredients.", - "questDilatoryDistress1Completion": "You don the the finned armor and swim to Dilatory as quickly as you can. The merfolk and their mantis shrimp allies have managed to keep the monsters outside the city for the moment, but they are losing. No sooner are you within the castle walls than the horrifying siege descends!", + "questDilatoryDistress1Notes": "Un messaggio in una bottiglia é arrivato dalla nuovamente ricostruita città di Dilatoria! C'é scritto: \"Cari abitanti di Habitica, abbiamo bisogno del vostro aiuto un'altra volta. La nostra principessa é sparita e la città é tenuta sotto assedio da misteriosi demoni dell'acqua! Le Canocchie stanno trattenendo gli attaccanti. Per favore aiutateci!\" Per intraprendere il lungo viaggio verso la città sommersa, é necessario essere in grado di respirare sott'acqua. Fortunatamente gli alchimisti @Benga e @hazel possono renderlo possibile! Devi solo trovare gli ingredienti adatti. ", + "questDilatoryDistress1Completion": "Indossi l'armatura con le pinne e nuoti fino a Dilatoria più velocemente che puoi. La gente del mare e i loro alleati canocchie sono riusciti a tenere i mostri fuori dalla città per il momento, ma stanno perdendo. Non fai quasi in tempo ad arrivare all'interno delle mura del castello che l'orribile assedio comincia! ", "questDilatoryDistress1CollectFireCoral": "Corallo di Fuoco", "questDilatoryDistress1CollectBlueFins": "Pinne Azzurre", - "questDilatoryDistress1DropArmor": "Finned Oceanic Armor (Armor)", - "questDilatoryDistress2Text": "Dilatory Distress, Part 2: Creatures of the Crevasse", - "questDilatoryDistress2Notes": "The siege can be seen from miles away: thousands of disembodied skulls rushing through a portal in the crevasse walls and making their way towards Dilatory.

When you meet King Manta in his war room, his eyes seem sunken, and his face is worried. \"My daughter Adva disappeared into the Dark Crevasse just before this siege began. Please find her and bring her back home safely! I will lend you my Fire Coral Circlet to aid you. If you succeed, it is yours.\"", - "questDilatoryDistress2Completion": "You vanquish the nightmarish horde of skulls, but you feel no closer to finding Adva. You speak to @Kiwibot, the royal tracker, to see if she has any ideas. \"The mantis shrimps that defend the city must have seen Adva escape,\" @Kiwibot says. \"Try following them into the Dark Crevasse.\"", - "questDilatoryDistress2Boss": "Water Skull Swarm", + "questDilatoryDistress1DropArmor": "Armatura Oceanica con le Pinne (Armatura)", + "questDilatoryDistress2Text": "Dilatoria sotto Attacco, Parte 2: Le Creature del Crepaccio", + "questDilatoryDistress2Notes": "L'assedio può essere visto da miglia di distanza: migliaia di teschi senza corpo si affrettano attraverso un portale nelle pareti del crepaccio e vanno in direzione di Dilatoria.

Quando incontri Re Manta nella sua sala della guerra, i suoi occhi sembrano infossati, e la sua faccia é preoccupata. \"Mia figlia Adva é scomparsa dentro al Crepaccio Oscuro appena prima che l'assedio cominciasse. Per favore, trovala e portala a casa sana e salve! Ti presterò il mio Cerchietto del Corallo di Fuoco per aiutarti. Se avrai successo, sarà tuo.\"", + "questDilatoryDistress2Completion": "Sconfiggi l'infernale orda di teschi, ma non ti senti affatto più vicino a trovare Adva. Parli a @Kiwibot, l'investigatore reale, per sapere se lei ha qualche idea. \"Le canocchie che difendono la città devono aver visto Adva scappare,\" dice @Kiwibot. \"Prova a seguirle dentro al Crepaccio Oscuro.\"", + "questDilatoryDistress2Boss": "Sciame di Teschi dell'Acqua", "questDilatoryDistress2RageTitle": "Swarm Respawn", "questDilatoryDistress2RageDescription": "Swarm Respawn: This bar fills when you don't complete your Dailies. When it is full, the Water Skull Swarm will heal 30% of its remaining health!", "questDilatoryDistress2RageEffect": "`Water Skull Swarm uses SWARM RESPAWN!`\n\nEmboldened by their victories, more skulls pour forth from the crevasse, bolstering the swarm!", @@ -232,8 +232,8 @@ "questDilatoryDistress2DropCottonCandyBluePotion": "Pozione Blu Zucchero Filato", "questDilatoryDistress2DropHeadgear": "Tiara di Corallo di Fuoco (Copricapo)", "questDilatoryDistress3Text": "Dilatory Distress, Part 3: Not a Mere Maid", - "questDilatoryDistress3Notes": "You follow the mantis shrimps deep into the Crevasse, and discover an underwater fortress. Princess Adva, escorted by more watery skulls, awaits you inside the main hall. \"My father has sent you, has he not? Tell him I refuse to return. I am content to stay here and practice my sorcery. Leave now, or you shall feel the wrath of the ocean's new queen!\" Adva seems very adamant, but as she speaks you notice a strange, ruby pendant on her neck glowing ominously... Perhaps her delusions would cease should you break it?", - "questDilatoryDistress3Completion": "Finally, you manage to pull the bewitched pendant from Adva's neck and throw it away. Adva clutches her head. \"Where am I? What happened here?\" After hearing your story, she frowns. \"This necklace was given to me by a strange ambassador - a lady called 'Tzina'. I don't remember anything after that!\"

Back at Dilatory, Manta is overjoyed by your success. \"Allow me to reward you with this trident and shield! I ordered them from @aiseant and @starsystemic as a gift for Adva, but... I'd rather not put weapons in her hands any time soon.\"", + "questDilatoryDistress3Notes": "Segui le canocchie nelle profondità del Crepaccio, e scopri una fortezza subacquea. La Principessa Adva, scortata da altri teschi acquatici, ti aspetta nella sala principale. \"Mio padre ti ha mandato, vero? Digli che io rifiuto di tornare. Sono soddisfatta di rimanere qui ed esercitarmi nella mia stregoneria. Vattene ora, o scoprirai la furia della nuova regina dell'oceano!\" Ava sembra molto decisa, ma mentre parla, tu noti uno strano pendente di rubino sul suo collo brillare inquietantemente... Forse le sue illusioni cesserebbero se tu lo rompessi? ", + "questDilatoryDistress3Completion": "Finalmente riesci a strappare il pendente stregato dal collo di Adva e gettarlo via. Adva si stringe la testa. \"Dove sono? Cos'é successo qui?\" Dopo aver sentito la storia, si acciglia. \"Questa collana mi é stata data da uno strano ambasciatore - una donna chiama 'Tzina'. Non ricordo nulla dopo di ciò!\"

Tornato a Dilatoria, Manta é sopraffatto dalla gioia per il tuo successo. \"Permettimi di ricompensarti con questo tridente e scudo! Li ho ordinati da @aisean e @starsystemic come dono per Adva, ma... preferirei non mettere armi nelle sue mani nell'immediato futuro.\"", "questDilatoryDistress3Boss": "Adva, the Usurping Mermaid", "questDilatoryDistress3DropFish": "Pesce (Cibo)", "questDilatoryDistress3DropWeapon": "Trident of Crashing Tides (Weapon)", @@ -266,6 +266,12 @@ "questFrogNotes": "As you and your friends are slogging through the Swamps of Stagnation, @starsystemic points at a large sign. \"Stay on the path -- if you can.\"

\"Surely that isn't hard!\" @RosemonkeyCT says. \"It's broad and clear.\"

But as you continue, you notice that path is gradually overtaken by the muck of the swamp, laced with bits of strange blue debris and clutter, until it's impossible to proceed.

As you look around, wondering how it got this messy, @Jon Arjinborn shouts, \"Look out!\" An angry frog leaps from the sludge, clad in dirty laundry and lit by blue fire. You will have to overcome this poisonous Clutter Frog to progress!", "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", - "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogDropFrogEgg": "Rana (Uovo)", + "questFrogUnlockText": "Sblocca l'acquisto delle uova di rana nel Mercato", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/it/settings.json b/common/locales/it/settings.json index 44f1bb8510..c366ee6dfd 100644 --- a/common/locales/it/settings.json +++ b/common/locales/it/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Selezionando questa opzione, la lista dei tag dell'attività che stai modificando verrà inizialmente nascosta.", "startAdvCollapsed": "Comprimi opzioni avanzate", "startAdvCollapsedPop": "Selezionando questa opzione, la sezione delle opzioni avanzate verrà nascosta quando modifichi un'attività.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Mostra il tour introduttivo", "restartTour": "Resetta il tour introduttivo della prima volta che hai utilizzato Habitica.", "showBailey": "Mostra Bailey", @@ -81,7 +86,6 @@ "emailChange1": "Per cambiare il tuo indirizzo email, per favore manda un'email a", "emailChange2": "admin@habitica.com", "emailChange3": "inserendo sia il vecchio che il tuo nuovo indirizzo email assieme al tuo ID Utente", - "username": "Nome utente", "usernameOrEmail": "Nome di login o email", "email": "Email", "registeredWithFb": "Registrato tramite Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "Utente->Profilo", "loginNameDescription3": "per cambiare il nome che appare nel tuo avatar e nei messaggi della chat.", "emailNotifications": "Notifiche via email", - "wonChallenge": "Hai vinto una sfida", + "wonChallenge": "You won a Challenge!", "newPM": "Hai ricevuto un messaggio privato", "giftedGems": "Ti vengono regalate delle Gemme", "giftedGemsInfo": "<%= amount %> Gemme - da <%= name %>", @@ -119,25 +123,25 @@ "promoCodeApplied": "Codice promozionale applicato! Controlla il tuo inventario", "promoPlaceholder": "Inserisci codice promozionale", "displayInviteToPartyWhenPartyIs1": "Mostra il bottone di invito alla squadra quando la squadra ha solo 1 membro.", - "saveCustomDayStart": "Save Custom Day Start", - "registration": "Registration", - "addLocalAuth": "Add local authentication:", - "generateCodes": "Generate Codes", - "generate": "Generate", - "getCodes": "Get Codes", + "saveCustomDayStart": "Salva Inizio del Giorno Personalizzato", + "registration": "Registrazione", + "addLocalAuth": "Aggiungi autenticazione locale", + "generateCodes": "Genera Codici", + "generate": "Genera", + "getCodes": "Ottieni Codici", "webhooks": "Webhooks", - "enabled": "Enabled", + "enabled": "Abilitato", "webhookURL": "Webhook URL", - "add": "Add", - "buyGemsGoldCap": "Cap raised to <%= amount %>", + "add": "Aggiungi", + "buyGemsGoldCap": "Limite alzato a <%= amount %>", "mysticHourglass": "<%= amount %> Clessidra Mistica", - "mysticHourglassText": "Mystic Hourglasses allow purchasing a previous month's Mystery Item set.", + "mysticHourglassText": "Le Clessidre Mistiche ti permettono di acquistare i set di Oggetti Misteriosi del mese precedente.", "purchasedPlanId": "Recurring $<%= price %> each <%= months %> Month(s) (<%= plan %>)", - "purchasedPlanExtraMonths": "You have <%= months %> months of subscription credit.", - "consecutiveSubscription": "Consecutive Subscription", - "consecutiveMonths": "Consecutive Months:", - "gemCapExtra": "Gem Cap Extra:", - "mysticHourglasses": "Mystic Hourglasses:", + "purchasedPlanExtraMonths": "Ti rimangono <%= months %> mesi di credito di abbonamento.", + "consecutiveSubscription": "Abbonamento Consecutivo", + "consecutiveMonths": "Mesi Consecutivi:", + "gemCapExtra": "Limite Gemme Extra:", + "mysticHourglasses": "Clessidre Mistiche", "paypal": "PayPal", - "amazonPayments": "Amazon Payments" + "amazonPayments": "Pagamenti su Amazon" } \ No newline at end of file diff --git a/common/locales/it/tasks.json b/common/locales/it/tasks.json index 12d677e30c..df1aab09ff 100644 --- a/common/locales/it/tasks.json +++ b/common/locales/it/tasks.json @@ -99,12 +99,12 @@ "dailyHelp1": "Le Daily si ripetono <%= emphasisStart %>ogni giorno<%= emphasisEnd %> in cui sono attive. Clicca <%= pencilIcon %> per cambiare i giorni in cui sono attive.", "dailyHelp2": "Se non completi le Daily attive perdi Salute quando la giornata finisce.", "dailyHelp3": "Dailies turn <%= emphasisStart %>redder<%= emphasisEnd %> when you miss them, and <%= emphasisStart %>bluer<%= emphasisEnd %> when you complete them. The redder the Daily, the more it will reward you... or hurt you.", - "dailyHelp4": "To change when your day rolls over, go to <%= linkStart %> Settings > Site<%= linkEnd %> > Custom Day Start.", + "dailyHelp4": "Per cambiare quando il tuo giorno finisce, vai su <%= linkStart %> Impostazioni > Sito <%= linkEnd %> > Inizio Giorno Personalizzato.", "dailyHelp5": "Per cercare ispirazione, prova a guardare questi esempi di Daily! (in inglese)", "toDoHelp1": "Le To-Do appena create sono gialle, e più tempo ci metti a completarle più diventano rosse (aumentano di valore).", "toDoHelp2": "I To-Do non ti fanno del male! Ti premiamo solo con Oro ed Esperienza.", "toDoHelp3": "Suddividere una To-Do in una lista di attività più piccole (una checklist) la renderà meno spaventosa, a aumenterà i tuoi punti!", - "toDoHelp4": "For inspiration, check out these sample To-Dos!", + "toDoHelp4": "Per trovare inspirazione, dai un'occhiata a queste attività d'esempio!", "rewardHelp1": "L'equipaggiamento che compri per il tuo avatar viene messo in <%= linkStart %>Inventario > Equipaggiamento<%= linkEnd %>.", "rewardHelp2": "L'equipaggiamento condiziona le tue statistiche (<%= linkStart %>Utente > Statistiche<%= linkEnd %>).", "rewardHelp3": "Equipaggiamenti speciali compariranno qui durante gli Eventi Globali.", diff --git a/common/locales/ja/challenge.json b/common/locales/ja/challenge.json index 092b0f2202..4406f35d3d 100644 --- a/common/locales/ja/challenge.json +++ b/common/locales/ja/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "You don't have permissions to edit this challenge", "noPermissionDeleteChallenge": "You don't have permissions to delete this challenge", "noPermissionCloseChallenge": "You don't have permissions to close this challenge", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "no owner", "noChallengeOwnerPopover": "This challenge does not have an owner because the person who created the challenge deleted their account." } \ No newline at end of file diff --git a/common/locales/ja/character.json b/common/locales/ja/character.json index bc4f91d20f..d1a6da5b59 100644 --- a/common/locales/ja/character.json +++ b/common/locales/ja/character.json @@ -65,6 +65,10 @@ "ultimGearText": "以下のクラスの最高武器と防具セットを揃えた:", "level": "レベル", "levelUp": "レベルアップ!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "魔法", "hp": "再生", "mp": "魔法点", diff --git a/common/locales/ja/content.json b/common/locales/ja/content.json index c42026e183..cd7f6e9dd4 100644 --- a/common/locales/ja/content.json +++ b/common/locales/ja/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "カエル", "questEggFrogMountText": "カエル", "questEggFrogAdjective": "a princely", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "普通の", "hatchingPotionWhite": "白い", diff --git a/common/locales/ja/front.json b/common/locales/ja/front.json index ea3719f0f8..c49c2c81ea 100644 --- a/common/locales/ja/front.json +++ b/common/locales/ja/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica]は、学校に居たころ、私の学生生活にストラクチャーを加える大きな手助けだったわ。", "invalidEmail": "パスワードをリセットするために有効なメールアドレスが必要です。", "irishfeet123Quote": "僕は食後の食卓を片付けられないでコップをいろんなところに置きっぱなしの僕の最悪な癖があったんだ。それが治したのは[Habitica]だったよ!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Before [Habitica], I was stuck with my thesis, as well as dissatisfied with my personal discipline regarding housework and things like learning vocabulary and studying Go theory. It turns out breaking down these tasks into smaller manageable checklists is quite the thing to keep me motivated and constantly working.", "landingadminlink": "管理向けパッケージ", "landingend": "まだ納得していませんか?", @@ -182,5 +182,11 @@ "tweet": "ツイート", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/ja/generic.json b/common/locales/ja/generic.json index 4d510786f1..e8331f0b88 100644 --- a/common/locales/ja/generic.json +++ b/common/locales/ja/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Sending you a thousand thanks.", "thankyou3": "心よりありがとうございました。", "thankyouCardAchievementTitle": "Greatly Grateful", - "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards." + "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/ja/pets.json b/common/locales/ja/pets.json index 9ce2327f8f..be7416b1ac 100644 --- a/common/locales/ja/pets.json +++ b/common/locales/ja/pets.json @@ -58,8 +58,16 @@ "firstDrop": "ドロップシステムが解除されました!今後タスクを完了したとき、たまごやポーションやエサといったアイテムが見つかる可能性があります!あなたは今<%= eggText %>たまごを見つけました! <%= eggNotes %>", "useGems": "もしあなたがペットをじっと見守りつづけていて、これ以上ドロップを待てないのであれば、ジェムを使って所持品 > 市場 で買ってください!", "hatchAPot": "<%= potion %>の<%= egg %>を孵しますか?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "<%= name %>に<%= article %><%= text %>をやりますか?", "useSaddle": "<%= pet %>に鞍を置きますか?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= egg %>を孵しますか?", "petKeyName": "犬小屋への鍵", diff --git a/common/locales/ja/quests.json b/common/locales/ja/quests.json index 68c8ca9a42..6afa889e49 100644 --- a/common/locales/ja/quests.json +++ b/common/locales/ja/quests.json @@ -76,5 +76,7 @@ "startAQuest": "クエストを始める", "startQuest": "クエストを始めよう", "whichQuestStart": "どのクエストを始めますか?", - "getMoreQuests": "Get more quests" + "getMoreQuests": "Get more quests", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/ja/questscontent.json b/common/locales/ja/questscontent.json index 369c57a0cd..57d2448526 100644 --- a/common/locales/ja/questscontent.json +++ b/common/locales/ja/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/ja/settings.json b/common/locales/ja/settings.json index 1fdeed5943..998559baa3 100644 --- a/common/locales/ja/settings.json +++ b/common/locales/ja/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "このオプションを設定すると、編集のために最初にタスクを開いたときに、タスクのリストタグが非表示になります。", "startAdvCollapsed": "タスクの拡張オプションが崩れました", "startAdvCollapsedPop": "このオプションを設定すると、編集のために最初にタスクを開いたときに、拡張オプションが非表示になります。", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "ツアーを表示する。", "restartTour": "Habiticaを始めた時の紹介ツアーを見る。", "showBailey": "Baileyを表示する", @@ -81,7 +86,6 @@ "emailChange1": "あなたのメールアドレスを変更するには、", "emailChange2": "admin@habitica.com", "emailChange3": "へ、あなたの古いメールアドレスとユーザID、そして新しく使いたいユーザーIDを含め、Eメールを送信してください。", - "username": "ログイン名", "usernameOrEmail": "ログイン名またはメールアドレス", "email": "メール", "registeredWithFb": "Facebookで登録", @@ -89,7 +93,7 @@ "loginNameDescription2": "ユーザー->プロフィール", "loginNameDescription3": "で変更できます。", "emailNotifications": "メール通知", - "wonChallenge": "チャレンジが達成されました", + "wonChallenge": "You won a Challenge!", "newPM": "プライベートメッセージが届きました", "giftedGems": "贈られたジェム", "giftedGemsInfo": "<%= name %>から<%= amount %>ジェム", diff --git a/common/locales/nl/backgrounds.json b/common/locales/nl/backgrounds.json index 3d7671cae5..81541d6dc2 100644 --- a/common/locales/nl/backgrounds.json +++ b/common/locales/nl/backgrounds.json @@ -119,11 +119,11 @@ "backgroundSlimySwampNotes": "Ploeter door een slijmerig moeras", "backgroundSwarmingDarknessText": "Allesverhullende duisternis", "backgroundSwarmingDarknessNotes": "Bibber in de allesverhullende duisternis.", - "backgrounds112015": "SET 18: Released November 2015", - "backgroundFloatingIslandsText": "Floating Islands", - "backgroundFloatingIslandsNotes": "Hop across the Floating Islands.", - "backgroundNightDunesText": "Night Dunes", - "backgroundNightDunesNotes": "Walk peacefully through the Night Dunes.", - "backgroundSunsetOasisText": "Sunset Oasis", - "backgroundSunsetOasisNotes": "Bask in the Sunset Oasis." + "backgrounds112015": "SET 18: Uitgebracht in november 2015", + "backgroundFloatingIslandsText": "Drijvende eilanden", + "backgroundFloatingIslandsNotes": "Spring van één drijvend eiland naar de volgende.", + "backgroundNightDunesText": "Nachtduinen", + "backgroundNightDunesNotes": "Maak een vredige wandeling door de nachtduinen.", + "backgroundSunsetOasisText": "Oase bij zonsondergang", + "backgroundSunsetOasisNotes": "Baadt in de ondergaande oasezon." } \ No newline at end of file diff --git a/common/locales/nl/challenge.json b/common/locales/nl/challenge.json index a4a9309f85..1476654bce 100644 --- a/common/locales/nl/challenge.json +++ b/common/locales/nl/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "Je hebt geen toestemming om deze uitdaging te bewerken", "noPermissionDeleteChallenge": "Je hebt geen toestemming om deze uitdaging te verwijderen", "noPermissionCloseChallenge": "Je hebt geen toestemming om deze uitdaging te sluiten", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "geen eigenaar", - "noChallengeOwnerPopover": "Deze uitdaging heeft geen eigenaar, omdat de eigenaar zijn account heeft verwijdert." + "noChallengeOwnerPopover": "Deze uitdaging heeft geen eigenaar omdat de eigenaar zijn of haar account heeft verwijderd." } \ No newline at end of file diff --git a/common/locales/nl/character.json b/common/locales/nl/character.json index 4183942158..c7df02facf 100644 --- a/common/locales/nl/character.json +++ b/common/locales/nl/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Heeft de hoogst haalbare wapen- en uitrustingset voor de volgende klassen:", "level": "Niveau", "levelUp": "Niveau erbij!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "GP", "mp": "MP", diff --git a/common/locales/nl/communityguidelines.json b/common/locales/nl/communityguidelines.json index c162b60e06..3f36562605 100644 --- a/common/locales/nl/communityguidelines.json +++ b/common/locales/nl/communityguidelines.json @@ -52,7 +52,7 @@ "commGuideHeadingPublicGuilds": "Openbare gildes", "commGuidePara029": "Openbare gildes lijken op de herberg, behalve dat ze een eigen thema hebben en niet zo gericht zijn op algemene gesprekken. Openbare chat in de gildes moet dit thema in het oog houden. Leden van het Wordsmith-gilde vinden het waarschijnlijk niet leuk als het gesprek opeens over tuinieren gaat in plaats van over schrijven, en een Drakenfokkersgilde is misschien niet geïnteresseerd in het ontcijferen van oeroude runen. Sommige gilden zijn hier minder streng in dan anderen, maar over het algemeen geldt: houd je aan het onderwerp!", "commGuidePara031": "Sommige openbare gildes bespreken gevoelige onderwerpen zoals depressie, religie, politiek, enz. Dit is prima, zolang de gesprekken in het gilde de algemene voorwaarden of richtlijnen voor openbare ruimtes niet overtreden, en zolang ze over het onderwerp blijven gaan.", - "commGuidePara033": "Openbare gildes mogen geen volwassen (18+-)materiaal bevatten. Als ze van plan zijn om regelmatig gevoelig materiaal te bespreken, moeten ze dat aangeven in de titel van het gilde. Dit houdt Habitica voor iedereen veilig en comfortabel. Als het gilde over andere gevoelige onderwerpen gaat, is het goed om respect te tonen naar je mede-Habiticanen door een waarschuwing te plaatsen in je berichten (zoals \"Waarschuwing: verwijzing naar zelfverminking\"). Daarnaast moet het gevoelige materiaal wel te maken hebben met het onderwerp. Zelfverminking aanhalen in een gilde dat zich richt op het bestrijden van depressie is logisch, maar het is minder logisch in een muziekgilde. Als je merkt dat iemand deze richtlijn blijft overtreden, zelfs na regelmatig verzoek hiermee te stoppen, stuur dan een e-mail met screenshots naar leslie@habitica.com.", + "commGuidePara033": "Openbare gildes mogen geen volwassen (18+-)materiaal bevatten. Als ze van plan zijn om regelmatig gevoelig materiaal te bespreken, moeten ze dat aangeven in de titel van het gilde. Dit houdt Habitica voor iedereen veilig en comfortabel. Als het gilde over andere gevoelige onderwerpen gaat, is het goed om respect te tonen naar je mede-Habiticanen door een waarschuwing te plaatsen in je berichten (zoals \"Waarschuwing: verwijzing naar zelfverminking\"). Daarnaast moet het gevoelige materiaal wel te maken hebben met het onderwerp. Zelfverminking aanhalen in een gilde dat zich richt op het bestrijden van depressie kan logisch zijn, maar het past minder in een muziekgilde. Als je merkt dat iemand deze richtlijn blijft overtreden, zelfs na regelmatig verzoek hiermee te stoppen, stuur dan een e-mail met screenshots naar leslie@habitica.com.", "commGuidePara035": "Er mogen geen gildes, openbaar of besloten, gecreëerd worden met het doel om een persoon of groep aan te vallen. Zo'n gilde starten is reden voor een onmiddellijke royering. Vecht tegen je slechte gewoontes, niet tegen je mede-avonturiers!", "commGuidePara037": "Alle uitdagingen die door de herberg of door openbare gildes georganiseerd worden, moeten zich ook aan deze regels houden.", "commGuideHeadingBackCorner": "De Back Corner", diff --git a/common/locales/nl/content.json b/common/locales/nl/content.json index a361842f74..7a46f9a24b 100644 --- a/common/locales/nl/content.json +++ b/common/locales/nl/content.json @@ -16,10 +16,10 @@ "dropEggPandaCubAdjective": "zachtaardige", "dropEggLionCubText": "Leeuwenwelp", "dropEggLionCubMountText": "Leeuw", - "dropEggLionCubAdjective": "een vorstelijke", + "dropEggLionCubAdjective": "vorstelijke", "dropEggFoxText": "Vos", "dropEggFoxMountText": "Vos", - "dropEggFoxAdjective": "een sluwe", + "dropEggFoxAdjective": "sluwe", "dropEggFlyingPigText": "Vliegend Varken", "dropEggFlyingPigMountText": "Vliegend Varken", "dropEggFlyingPigAdjective": "wispelturige", @@ -37,67 +37,70 @@ "questEggGryphonAdjective": "trotse", "questEggHedgehogText": "Egel", "questEggHedgehogMountText": "Egel", - "questEggHedgehogAdjective": "een puntige", + "questEggHedgehogAdjective": "puntige", "questEggDeerText": "Hert", "questEggDeerMountText": "Hert", - "questEggDeerAdjective": "een elegant", + "questEggDeerAdjective": "elegant", "questEggEggText": "Ei", "questEggEggMountText": "Eiermand", - "questEggEggAdjective": "een kleurrijke", + "questEggEggAdjective": "kleurrijke", "questEggRatText": "Rat", "questEggRatMountText": "Rat", - "questEggRatAdjective": "een vieze", + "questEggRatAdjective": "vieze", "questEggOctopusText": "Octopus", "questEggOctopusMountText": "Octopus", "questEggOctopusAdjective": "een gladde", "questEggSeahorseText": "Zeepaardje", "questEggSeahorseMountText": "Zeepaard", - "questEggSeahorseAdjective": "een gevierd", + "questEggSeahorseAdjective": "eersteklas", "questEggParrotText": "Papegaai", "questEggParrotMountText": "Papegaai", - "questEggParrotAdjective": "een energieke", + "questEggParrotAdjective": "veelkleurige", "questEggRoosterText": "Haan", "questEggRoosterMountText": "Haan", - "questEggRoosterAdjective": "een paraderende", + "questEggRoosterAdjective": "paraderende", "questEggSpiderText": "Spin", "questEggSpiderMountText": "Spin", - "questEggSpiderAdjective": "een enge", + "questEggSpiderAdjective": "griezelige", "questEggOwlText": "Uil", "questEggOwlMountText": "Uil", - "questEggOwlAdjective": "een wijze", + "questEggOwlAdjective": "wijze", "questEggPenguinText": "Pinguïn", "questEggPenguinMountText": "Pinguïn", - "questEggPenguinAdjective": "een spitsvondige", + "questEggPenguinAdjective": "spitsvondige", "questEggTRexText": "Tyrannosaurus", "questEggTRexMountText": "Tyrannosaurus", - "questEggTRexAdjective": "een klein-armige", + "questEggTRexAdjective": "kortarmige", "questEggRockText": "Steen", "questEggRockMountText": "Steen", - "questEggRockAdjective": "een levendige", + "questEggRockAdjective": "levendige", "questEggBunnyText": "Konijn", "questEggBunnyMountText": "Konijn", - "questEggBunnyAdjective": "een knuffelig", + "questEggBunnyAdjective": "knuffelig", "questEggSlimeText": "Marshmallowslijm", "questEggSlimeMountText": "Marshmallowslijm", - "questEggSlimeAdjective": "een zoet", + "questEggSlimeAdjective": "zoete", "questEggSheepText": "Schaap", "questEggSheepMountText": "Schaap", - "questEggSheepAdjective": "een wollig", + "questEggSheepAdjective": "wollig", "questEggCuttlefishText": "Inktvis", "questEggCuttlefishMountText": "Zeekat", - "questEggCuttlefishAdjective": "een knuffelige", + "questEggCuttlefishAdjective": "knuffelige", "questEggWhaleText": "Walvis", "questEggWhaleMountText": "Walvis", - "questEggWhaleAdjective": "een spetterende", + "questEggWhaleAdjective": "spetterende", "questEggCheetahText": "Cheetah", "questEggCheetahMountText": "Cheetah", - "questEggCheetahAdjective": "een eerlijke", + "questEggCheetahAdjective": "eerlijke", "questEggHorseText": "Paard", "questEggHorseMountText": "Paard", - "questEggHorseAdjective": "een galopperend", + "questEggHorseAdjective": "galopperend", "questEggFrogText": "Kikker", "questEggFrogMountText": "Kikker", - "questEggFrogAdjective": "een prinselijke", + "questEggFrogAdjective": "prinselijke", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Vind een uitbroedtoverdrank om over dit ei te gieten en er zal een <%= eggAdjective(locale) %> <%= eggText(locale) %> uitkomen.", "hatchingPotionBase": "Normale", "hatchingPotionWhite": "Witte", diff --git a/common/locales/nl/faq.json b/common/locales/nl/faq.json index 6500118437..54b4111503 100644 --- a/common/locales/nl/faq.json +++ b/common/locales/nl/faq.json @@ -16,7 +16,7 @@ "iosFaqAnswer4": "Er zijn verschillende dingen die je kunnen schaden. Ten eerste: als je dagelijkse taken 's nachts incompleet zijn, doen ze schade. Ten tweede: als je een slechte gewoonte aanklikt, zal het je schade doen. Tenslotte: als je in een gevecht met een eindbaas bent met je groep en een van je groepsleden niet al zijn/haar taken gedaan heeft, dan zal de baas je aanvallen.\n\nDe belangrijkste manier om te genezen is om een level omhoog te gaan, dat herstelt al je levenspunten. Je kunt ook met goud een gezondheidsdrankje kopen in de beloningskolom. Daarbij, op level 10 en daarboven, kun je ervoor kiezen om een genezer te worden en dan kun je genezingsvaardigheden leren. Als je in een groep zit met een genezer, kan deze je ook genezen.", "webFaqAnswer4": "Er zijn verschillende dingen die je kunnen schaden. Ten eerste: als je dagelijkse taken 's nachts incompleet zijn, doen ze schade. Ten tweede: als je een slechte gewoonte aanklikt, zal het je schade doen. Tenslotte: als je in een gevecht met een eindbaas bent met je groep en een van je groepsleden niet al zijn/haar taken gedaan heeft, dan zal de baas je aanvallen.\n

\nDe belangrijkste manier om te genezen is om een level omhoog te gaan, dat herstelt al je levenspunten. Je kunt ook met goud een gezondheidsdrankje kopen in de beloningskolom. Daarbij, op level 10 en daarboven, kun je ervoor kiezen om een genezer te worden en dan kun je genezingsvaardigheden leren. Als je in een groep zit (onder Sociaal > Groep) met een genezer, kan deze je ook genezen.", "faqQuestion5": "Hoe speel ik Habitica samen met mijn vrienden?", - "iosFaqAnswer5": "The best way is to invite them to a Party with you! Parties can go on quests, battle monsters, and cast skills to support each other. Go to Menu > Party and click \"Create New Party\" if you don't already have a Party. Then tap on the Members list, and tap Invite in the upper right-hand corner to invite your friends by entering their User ID (a string of numbers and letters that they can find under Settings > Account Details on the app, and Settings > API on the website). On the website, you can also invite friends via email, which we will add to the app in a future update.\n\nOn the website, you and your friends can also join Guilds, which are public chat rooms. Guilds will be added to the app in a future update!", + "iosFaqAnswer5": "De beste manier is om ze uit te nodigen voor een groep met jou! Groepen kunnen queestes doen, monsters bevechten en vaardigheden uitspreken om elkaar te ondersteunen. Ga naar Menu > Groep en klik op \"Maak Nieuwe Groep\" als je er nog geen hebt. Druk dan op de ledenlijst en druk op Uitnodigen in de rechterbovenhoek om je vrienden uit te nodigen door hun Gebruikers-ID in te voeren (een serie nummers en letters die ze kunnen vinden onder Instellingen > Account in de app en Instellingen > API op de website). Op de website kun je ook vrienden uitnodigen via e-mail, hetgeen we in een latere update aan de app zullen toevoegen.\n\nOp de website kunnen jij en je vrienden je ook aansluiten bij Gildes, dat zijn publieke chatrooms. Gildes worden aan de app toegevoegd in een toekomstige update.", "webFaqAnswer5": "De beste manier is om ze uit te nodigen voor een groep met jou, via Sociaal > Groep! Groepen kunnen queestes doen, monsters bestrijden en vaardigheden uitspreken om elkaar te ondersteunen. Je kunt je ook samen aansluiten bij gildes (Sociaal > Gildes). Gildes zijn chatrooms die zicht richten op een gedeelde interesse of het nastreven van een zelfde doel en kunnen publiek of privé zijn. Je kunt je aansluiten bij zoveel gildes als je wilt, maar slechts bij één groep.\n

\nVoor meer gedetailleerde informatie, kun je kijken op de wiki-pagina's over [groepen](http://habitrpg.wikia.com/wiki/Party) en [gildes](http://habitrpg.wikia.com/wiki/Guilds).", "faqQuestion6": "Hoe kan ik een huisdier of een rijdier krijgen?", "iosFaqAnswer6": "Op level 3 speel je het vondstensysteem vrij. Iedere keer dat je een taak voltooid, zul je een willekeurige kans hebben een ei, een uitbroedtoverdrank of eten te ontvangen. Ze zullen opgeslagen worden in Menu > Boedel.\n\nOm een huisdier te laten uitkomen, heb je een ei en een uitbroedtoverdrank nodig. Druk op het ei om de soort te bepalen en selecteer 'Laat ei uitkomen'. Kies daarna een uitbroedtoverdrank om de kleur te bepalen! Ga naar Menu > Huisdieren en om je avatar uit te rusten met je nieuwe huisdier door erop te drukken.\n\nJe kunt je huisdieren ook laten opgroeien tot rijdieren door ze te voeren onder Menu > Huisdieren. Druk op het huisdier en selecteer dan 'Huisdier Voeren'. Je zult een huisdier vele malen moeten voeren voordat het verandert in een rijdier, maar als je zijn favoriete voedsel kan bepalen, zal hij sneller groeien. Probeer het met vallen en opstaan of [zie het het verklapt](http://habitica.wikia.com/wiki/Food#Food_Preferences). Als je eenmaal een rijdier hebt, kun je het toevoegen aan je avatar onder Menu > Rijdieren.\n\nJe kunt ook eieren van queeste-huisdieren krijgen door bepaalde queesten te voltooien. (Lees hieronder meer over queesten.) ", @@ -25,12 +25,12 @@ "iosFaqAnswer7": "Je kan pas kiezen om een krijger, magiër, dief of heler te worden als je niveau 10 bereikt hebt. (Alle spelers beginnen standaard als krijger.) Elke klasse heeft andere uitrusting, verschillende vaardigheden die ze kunnen uitspreken na niveau 11 en meer verschillende voordelen. Krijgers kunnen veel schade aanrichten bij eindbazen, schade weerstaan van taken en hun groep sterker maken. Magiërs kunnen ook makkelijk schade aanrichten bij eindbazen, evenals sneller niveaus behalen en extra mana geven aan de groep. Dieven verdienen het meeste geld en vinden sneller voorwerpen en kunnen hun groep hetzelfde laten doen. Tenslotte kunnen helers hunzelf, en mensen uit hun groep, helen.\n\nAls je nog niet direct een klasse wilt kiezen -- als je bijvoorbeeld nog al je uitrusting wilt kopen voor je huidige klasse -- kun je op \"later beslissen\" klikken en later kiezen bij menu > kies klasse.", "webFaqAnswer7": "Je kan pas kiezen om een krijger, magiër, dief of heler te worden als je niveau 10 bereikt hebt. (Alle spelers beginnen standaard als krijger.) Elke klasse heeft andere uitrusting, verschillende vaardigheden die ze kunnen uitspreken na niveau 11 en meer verschillende voordelen. Krijgers kunnen veel schade aanrichten bij eindbazen, schade weerstaan van taken en hun groep sterker maken. Magiërs kunnen ook makkelijk schade aanrichten bij eindbazen, evenals sneller niveaus behalen en extra mana geven aan de groep. Dieven verdienen het meeste geld en vinden sneller voorwerpen en kunnen hun groep hetzelfde laten doen. Tenslotte kunnen helers hunzelf, en mensen uit hun groep, helen.\n

\nAls je nog niet direct een klasse wilt kiezen -- als je bijvoorbeeld nog al je uitrusting wilt kopen voor je huidige klasse -- kun je op \"later beslissen\" klikken en later kiezen bij Gebruiker > Statistieken.", "faqQuestion8": "Wat is de blauwe statusbalk die in de bovenbalk verschijnt na level 10?", - "iosFaqAnswer8": "The blue bar that appeared when you hit level 10 and chose a Class is your Mana bar. As you continue to level up, you will unlock special Skills that cost Mana to use. Each Class has different Skills, which appear after level 11 under Menu > Use Skills. Unlike your health bar, your Mana bar does not reset when you gain a level. Instead, Mana is gained when you complete Good Habits, Dailies, and To-Dos, and lost when you indulge bad Habits. You'll also regain some Mana overnight -- the more Dailies you completed, the more you will gain.", + "iosFaqAnswer8": "The blauwe balk die verscheen toen je level 10 bereikte en een klasse koos, is je mana-balk. Als je een hoger level wordt, speel je speciale vaardigheden vrij die mana kostne om te gebruiken. Elke klasse heeft andere vaardigheden, die vanaf level 11 verschijnen onder Menu > Gebruik vaardigheden. Anders dan bij je gezondheidsbalk, reset je mana-balk niet als je een nieuw level bereikt. In plaats daarvan krijg je meer mana wanneer je goede gewoonten, dagelijkse taken en to-do's doet en verlies je het wanneer je hebt toegegeven aan slechte gewoonten. Je krijgt 'snachts ook wat mana terug -- hoe meer dagelijkse taken je voltooide, hoe meer je verdient.", "webFaqAnswer8": "The blue bar that appeared when you hit level 10 and chose a Class is your Mana bar. As you continue to level up, you will unlock special Skills that cost Mana to use. Each Class has different Skills, which appear after level 11 in a special section in the Rewards Column. Unlike your Health bar, your Mana bar does not reset when you gain a level. Instead, Mana is gained when you complete Good Habits, Dailies, and To-Dos, and lost when you indulge bad Habits. You’ll also regain some Mana overnight -- the more Dailies you completed, the more you will gain.", "faqQuestion9": "Hoe vecht ik tegen monsters en ga ik op queesten?", "iosFaqAnswer9": "First, you need to join or start a Party (see above). Although you can battle monsters alone, we recommend playing in a group, because this will make Quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n\n Next, you need a Quest Scroll, which are stored under Menu > Items. There are three ways to get a scroll:\n\n - At level 15, you get a Quest-line, aka three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively. \n - When you invite people to your Party, you'll be rewarded with the Basi-List Scroll!\n - You can buy Quests from the Quests Page on the [website](https://habitica.com/#/options/inventory/quests) for Gold and Gems. (We will add this feature to the app in a future update.)\n\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading by pulling down on the screen may be required to see the Boss's health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your Party at the same time that you damage the Boss. \n\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", "webFaqAnswer9": "First, you need to join or start a party (under Social > Party). Although you can battle monsters alone, we recommend playing in a group, because this will make quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n

\n Next, you need a Quest Scroll, which are stored under Inventory > Quests. There are three ways to get a scroll:\n

\n * When you invite people to your party, you’ll be rewarded with the Basi-List Scroll!\n * At level 15, you get a Quest-line, i.e., three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively.\n * You can buy Quests from the Quests Page (Inventory > Quests) for Gold and Gems.\n

\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading may be required to see the Boss's Health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your party at the same time that you damage the Boss.\n

\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", - "faqQuestion10": "What are Gems, and how do I get them?", + "faqQuestion10": "Wat zijn Edelstenen en hoe krijg ik ze?", "iosFaqAnswer10": "Gems are purchased with real money by tapping on the gem icon in the header. When people buy gems, they are helping us to keep the site running. We're very grateful for their support!\n\n In addition to buying gems directly, there are three other ways players can gain gems:\n\n * Win a Challenge on the [website](https://habitica.com) that has been set up by another player under Social > Challenges. (We will be adding Challenges to the app in a future update!)\n * Subscribe on the [website](https://habitica.com/#/options/settings/subscription) and unlock the ability to buy a certain number of gems per month.\n * Contribute your skills to the Habitica project. See this wiki page for more details: [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica).\n\n Keep in mind that items purchased with gems do not offer any statistical advantages, so players can still make use of the app without them!", "webFaqAnswer10": "Gems are [purchased with real money](https://habitica.com/#/options/settings/subscription), although [subscribers](https://habitica.com/#/options/settings/subscription) can purchase them with Gold. When people subscribe or buy Gems, they are helping us to keep the site running. We're very grateful for their support!\n

\n In addition to buying Gems directly or becoming a subscriber, there are two other ways players can gain Gems:\n

\n * Win a Challenge that has been set up by another player under Social > Challenges.\n * Contribute your skills to the Habitica project. See this wiki page for more details: [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica)\n

\n Keep in mind that items purchased with Gems do not offer any statistical advantages, so players can still make use of the site without them!", "faqQuestion11": "Hoe rapporteer ik een bug of vraag ik een feature aan?", diff --git a/common/locales/nl/front.json b/common/locales/nl/front.json index 84b28c7d6c..cacd37f776 100644 --- a/common/locales/nl/front.json +++ b/common/locales/nl/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] heeft me echt geholpen om structuur aan te brengen in mijn leven op de universiteit.", "invalidEmail": "Om het wachtwoord te resetten is een geldig e-mailadres vereist.", "irishfeet123Quote": "Ik had verschrikkelijke gewoontes wat betreft opruimen na het eten en liet overal kopjes slingeren. [Habitica] heeft me daarvan genezen!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Voor [Habitica] zat ik vast met mijn thesis en was ik ontevreden met mijn persoonlijke discipline op het gebied van het huishouden en dingen zoals vocabulaire leren en Go-theorie leren. Het blijkt dat deze taken opbreken in kleinere, behapbare checklijsten precies is wat nodig was om me gemotiveerd te houden.", "landingadminlink": "administratieve pakketten", "landingend": "Nog niet overtuigd?", @@ -101,7 +101,7 @@ "marketing1Lead3": "Maak kans om prijzen te vinden. Voor sommigen is het motiverend om op willekeurige momenten beloningen te krijgen (dit heet \"stochastische beloning\") . Habitica gebruikt alle typen motiveringstactieken: positief, negatief, voorspelbaar en willekeurig.", "marketing1Lead3Title": "Maak kans om prijzen te vinden", "marketing2Header": "Doe wedstrijden met vrienden, sluit je aan bij interessegroepen", - "marketing2Lead1": "Hoewel je Habitica solo kunt spelen, wordt het pas echt leuk als je gaat samenwerken en concurreren, en als je elkaar bij de les houdt. Het meest effectieve deel van een zelfverbeteringsprogramma is sociale verantwoordelijkheid, en welke omgeving is nou beter voor competitie en vertantwoording afleggen dan een computerspel?", + "marketing2Lead1": "Hoewel je Habitica solo kunt spelen, wordt het pas echt leuk als je gaat samenwerken en concurreren, en als je elkaar bij de les houdt. Het meest effectieve deel van een zelfverbeteringsprogramma is sociale verantwoordelijkheid, en welke omgeving is nou beter voor competitie en verantwoording afleggen dan een computerspel?", "marketing2Lead2": "Vecht tegen Eindbazen. Wat is een Rollenspel zonder battles? Vecht tegen eindbazen met je groep. Eindbazen houden je \"superverantwoordelijk\" - als jij een dag geen zin hebt om te sporten, raakt de baas iedereen.", "marketing2Lead2Title": "Eindbazen", "marketing2Lead3": "Uitdagingen laten je concurreren met vrienden en onbekenden. Wie het het beste heeft gedaan aan het einde van een uitdaging wint speciale prijzen.", @@ -181,6 +181,12 @@ "marketingInquiries": "Vragen over marketing/social media", "tweet": "Tweet", "apps": "Apps", - "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "notifyAndroidApp": "Wil je bericht van ons ontvangen als de Android app klaar is? Schrijf je in op deze mailinglijst!", + "checkOutIOSApp": "Probeer onze nieuwe iOS App uit!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/nl/gear.json b/common/locales/nl/gear.json index ceee4f620a..4c2c0080a7 100644 --- a/common/locales/nl/gear.json +++ b/common/locales/nl/gear.json @@ -156,8 +156,8 @@ "weaponArmoireGoldWingStaffNotes": "De vleugels op deze staf zijn altijd aan het trillen en draaien. Verhoogt elk attribuut met <%= attrs%>. Betoverd kabinet: losstaand voorwerp.", "weaponArmoireBatWandText": "Vleermuisstaf", "weaponArmoireBatWandNotes": "Deze staf kan iedere taak in een vleermuis veranderen! Zwaai hem in het rond en zie ze wegvliegen. verhoogt intelligentie met <%= int %> en perceptie met <%= per %>. Betoverd kabinet: Onafhankelijk voorwerp.", - "weaponArmoireShepherdsCrookText": "Shepherd's Crook", - "weaponArmoireShepherdsCrookNotes": "Useful for herding gryphons. Increases Constitution by <%= con %>. Enchanted Armoire: Shepherd Set (Item 1 of 3).", + "weaponArmoireShepherdsCrookText": "Herdersstaf", + "weaponArmoireShepherdsCrookNotes": "Handig voor het hoeden van Griffioenen. Verhoogt Lichaam met <%= con %>. Betoverd Kabinet: Herdersset (voorwerp 1 van 3).", "armor": "wapenrusting", "armorBase0Text": "Eenvoudige kleding", "armorBase0Notes": "Normale kleding. Verleent geen voordelen.", @@ -306,7 +306,7 @@ "armorMystery201506Text": "Snorkelpak", "armorMystery201506Notes": "Snorkel door het koraalrif in dit felgekleurde zwempak! Verleent geen voordelen. Abonnee-uitrusting juni 2015.", "armorMystery201508Text": "Cheetahkostuum", - "armorMystery201508Notes": "Ren snel als de bliksem in het pluizige cheeta kostuum! Verleent geen voordelen. Abonnee-uitrusting augustus 2015.", + "armorMystery201508Notes": "Ren zo snel als de bliksem in dit pluizige cheetahkostuum! Verleent geen voordelen. Abonnee-uitrusting augustus 2015.", "armorMystery201509Text": "Weerwolvenkostuum", "armorMystery201509Notes": "Dit IS een kostuum, toch? Verleent geen voordelen. Abonnee-uitrusting september 2015.", "armorMystery301404Text": "Steampunkpak", @@ -323,10 +323,10 @@ "armorArmoireHornedIronArmorNotes": "Dit gehoornde harnas is van heftig gehamerd ijzer waardoor het bijna onmogelijk is om het kapot te krijgen. Verhoogt Lichaam met <%= con %> en Perceptie met <%= per %> . Betoverd Kabinet: Gehoornde Yzerset (Onderdeel 2 van 3)", "armorArmoirePlagueDoctorOvercoatText": "Pestmeestersjas", "armorArmoirePlagueDoctorOvercoatNotes": "Een authentieke overjas die nog gedragen werd door dokters tijdens de procastinatiepest. Verhoogt Intelligentie met <%= int %>, Kracht met <%= str %> en Lichaam met <%= con %>. Betoverd kabinet: pestmeesterset (voorwerp 3 van 3).", - "armorArmoireShepherdRobesText": "Shepherd Robes", - "armorArmoireShepherdRobesNotes": "The fabric is cool and breathable, perfect for a hot day herding gryphons in the desert. Increases Strength and Perception by <%= attrs %> each. Enchanted Armoire: Shepherd Set (Item 2 of 3).", - "armorArmoireRoyalRobesText": "Royal Robes", - "armorArmoireRoyalRobesNotes": "Wonderful ruler, rule all day long! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 3 of 3).", + "armorArmoireShepherdRobesText": "Herdersgewaad", + "armorArmoireShepherdRobesNotes": "De stof is koel en ademend, perfect voor het hoeden van griffioenen op een hete dag in de woestijn. Verhoogt Kracht en Perceptie elk met <%= attrs %> . Betoverd Kabinet: Herderset (Onderdeel 2 van 3).", + "armorArmoireRoyalRobesText": "Koninklijke Mantel", + "armorArmoireRoyalRobesNotes": "Wonderbaarlijke heerser, heers de hele dag! Verhoogt Lichaam, Intelligentie en Perceptie elk met <%= attrs %> . Betoverd Kabinet: Koninklijke set (Onderdeel 3 van 3).", "headgear": "hoofdbescherming", "headBase0Text": "Geen helm", "headBase0Notes": "Geen hoofdbescherming.", @@ -467,7 +467,7 @@ "headMystery201505Text": "Lans van de Groene Ridder", "headMystery201505Notes": "De groene pluim op deze stalen helm wappert fier. Verleent geen voordelen. Abonnee-uitrusting mei 2015", "headMystery201508Text": "Cheetahhhoed", - "headMystery201508Notes": "Deze knusse cheeta hoed is erg pluizig! Verleent geen voordelen. Abonnee-uitrusting augustus 2015.", + "headMystery201508Notes": "Deze knusse cheetahhoed is erg pluizig! Verleent geen voordelen. Abonnee-uitrusting augustus 2015.", "headMystery201509Text": "Weerwolvenmasker", "headMystery201509Notes": "Dit IS een masker toch? Verleent geen voordelen. Abonnee-uitrusting september 2015.", "headMystery301404Text": "Chique hoge hoed", @@ -487,7 +487,7 @@ "headArmoireBlueHairbowText": "Blauwe strik", "headArmoireBlueHairbowNotes": "Word scherpzinnig, onverzettelijk en slim terwijl je deze prachtige blauwe strik draagt! Verhoogt Perceptie met <%= per %>, Lichaam met <%= con %> en Intelligentie met <%= int %>. Betoverd kabinet: losstaand voorwerp.", "headArmoireRoyalCrownText": "Koninklijke kroon", - "headArmoireRoyalCrownNotes": "Hooray for the ruler, mighty and strong! Increases Strength by <%= str %>. Enchanted Armoire: Royal Set (Item 1 of 3).", + "headArmoireRoyalCrownNotes": "Hoezee voor de vorst, machtig en sterk! Verhoogt Kracht met <%= str %>. Betoverd Kabinet: Koninklijke set (Onderdeel 1 van 3).", "headArmoireGoldenLaurelsText": "Gouden laurier", "headArmoireGoldenLaurelsNotes": "Deze gouden laurieren belonen hen die slechte gewoonten hebben overwonnen. Verhoogt Perceptie en Lichaam met elk <%= attrs %>. Betoverd kabinet: Gouden Togaset (Onderdeel 2 van 3).", "headArmoireHornedIronHelmText": "Gehoornde ijzeren helm", @@ -502,9 +502,9 @@ "headArmoireBlackCatNotes": "Deze zwarte hoed is... aan het spinnen. En zwaait met zijn staart. En ademt? Ja, je hebt gewoon een slapende kat op je hoofd. Verhoogt intelligentie en perceptie elk met <%= attrs %>. Betoverd kabinet: Onafhankelijk voorwerp.", "headArmoireOrangeCatText": "Oranje kattenhoed", "headArmoireOrangeCatNotes": "Deze oranje hoed is... aan het spinnen. En zwaait met zijn staart. En ademt? Ja, je hebt gewoon een slapende kat op je hoofd. Verhoogt kracht en lichaam elk met <%= attrs %>. Betoverd kabinet: Onafhankelijk voorwerp.", - "headArmoireBlueFloppyHatText": "Blue Floppy Hat", + "headArmoireBlueFloppyHatText": "Blauwe flaphoed", "headArmoireBlueFloppyHatNotes": "Many spells have been sewn into this simple hat, giving it a brilliant blue color. Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Independent Item.", - "headArmoireShepherdHeaddressText": "Shepherd Headdress", + "headArmoireShepherdHeaddressText": "Herders Hoofdtooi", "headArmoireShepherdHeaddressNotes": "Sometimes the gryphons that you herd like to chew on this headdress, but it makes you seem more intelligent nonetheless. Increases Intelligence by <%= int %>. Enchanted Armoire: Shepherd Set (Item 3 of 3).", "offhand": "artikel voor schildhand", "shieldBase0Text": "Geen uitrusting voor schildhand", @@ -589,8 +589,8 @@ "shieldArmoireGladiatorShieldNotes": "Om een gladiator te kunnen zijn moet je... eh, wat maakt het uit, mep ze gewoon met je schild. Verhoogt Lichaam met <%= con %> en Kracht met <%= str %>. Betoverd kabinet: gladiatorset (voorwerp 3 van 3).", "shieldArmoireMidnightShieldText": "Schild van Middernacht", "shieldArmoireMidnightShieldNotes": "Dit schild is klokslag middernacht het meest krachtig! Verhoogt lichaam met <%= con %> en kracht met <%= str %>. Betoverd kabinet: Onafhankelijk voorwerp.", - "shieldArmoireRoyalCaneText": "Royal Cane", - "shieldArmoireRoyalCaneNotes": "Hooray for the ruler, worthy of song! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 2 of 3).", + "shieldArmoireRoyalCaneText": "Koninklijke Wandelstok", + "shieldArmoireRoyalCaneNotes": "Hulde voor de leider, waard om bezongen te worden! Verhoogt lichaam, intelligentie en perceptie elk met <%= attrs %>. Betoverd Kabinet: Koninklijke set (voorwerp 2 van 3).", "back": "Lichaamsaccessoire", "backBase0Text": "Geen rugaccessoire", "backBase0Notes": "Geen rugaccessoire.", diff --git a/common/locales/nl/generic.json b/common/locales/nl/generic.json index 8cc9234f15..89a4f98044 100644 --- a/common/locales/nl/generic.json +++ b/common/locales/nl/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Ik stuur je duizendmaal dank.", "thankyou3": "Ik ben je heel dankbaar - dankjewel!", "thankyouCardAchievementTitle": "Duizendmaal Dank", - "thankyouCardAchievementText": "Bedankt voor het dankbaar zijn! Je hebt <%= cards %> bedankkaartjes verstuurd of ontvangen." + "thankyouCardAchievementText": "Bedankt voor het dankbaar zijn! Je hebt <%= cards %> bedankkaartjes verstuurd of ontvangen.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/nl/npc.json b/common/locales/nl/npc.json index 509bedd263..0ffebd6de3 100644 --- a/common/locales/nl/npc.json +++ b/common/locales/nl/npc.json @@ -14,7 +14,7 @@ "displayItemForGold": "Wil je een <%= itemType %> verkopen?", "displayEggForGold": "Wil je een <%= itemType %> Ei verkopen?", "displayPotionForGold": "Wil je een <%= itemType %> Toverdrank verkopen?", - "sellForGold": "Verkoop het voor <%= gold %> Goud", + "sellForGold": "Verkopen voor <%= gold %> Goud", "buyGems": "Koop edelstenen", "justin": "Justin", "ian": "Ian", diff --git a/common/locales/nl/pets.json b/common/locales/nl/pets.json index 95f2bc6655..4bae51010e 100644 --- a/common/locales/nl/pets.json +++ b/common/locales/nl/pets.json @@ -58,8 +58,16 @@ "firstDrop": "Je hebt het vondstensysteem vrijgespeeld! Als je nu een taak volbrengt, heb je een kleine kans om een voorwerp te vinden, zoals eieren, drankjes en voedsel! Je hebt net een <%= eggText %> ei gevonden! <%= eggNotes %>", "useGems": "Als je je oog hebt laten vallen op een huisdier, maar niet wilt wachten tot je het juiste ei of drankje vindt, gebruik dan edelstenen in Boedel > Markt om er één te kopen!", "hatchAPot": "<%= potion %> <%= egg %> uitbroeden?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "<%= text %> aan je <%= name %> voeren?", "useSaddle": "<%= pet %> zadelen?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Sleutel van de Hokken", diff --git a/common/locales/nl/quests.json b/common/locales/nl/quests.json index d8c59f8332..e480ebb990 100644 --- a/common/locales/nl/quests.json +++ b/common/locales/nl/quests.json @@ -76,5 +76,7 @@ "startAQuest": "START EEN QUEESTE", "startQuest": "Queeste starten", "whichQuestStart": "Welke queeste wil je beginnen?", - "getMoreQuests": "Verkrijg meer queesten" + "getMoreQuests": "Verkrijg meer queesten", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/nl/questscontent.json b/common/locales/nl/questscontent.json index 1d13ffa661..8b1d9708b7 100644 --- a/common/locales/nl/questscontent.json +++ b/common/locales/nl/questscontent.json @@ -179,7 +179,7 @@ "questTRexUndeadRageEffect": "'Skeletachtige Tyrannosaurus gebruikt Skeletgenezing!'\n\nHet monster slaakt een onaardse brul, en een paar van zijn beschadigde botten komen weer terug op de goede plaats.", "questTRexDropTRexEgg": "Tyrannosaurus (ei)", "questTRexUnlockText": "Maakt het kopen van tyrannosauruseieren in de markt mogelijk", - "questRockText": "Ontsnap van het Grottenmonster", + "questRockText": "Ontsnap aan het Grottenmonster", "questRockNotes": "Terwijl je door de Meanderende Bergen van Habitica aan het trekken bent met enkele vrienden, kampeer je op een avond in een prachtige grot doorspekt met glanzende mineralen. Maar als je de volgende ochtend wakker wordt, is de ingang verdwenen, en verschuift de vloer van de grot zich onder je.

\"De berg leeft!\" schreeuwt je reismakker @pfeffernusse. \"Dit zijn geen kristallen - het zijn tanden!\"

@Painter de Cluster grijpt je hand. \"We moeten een andere uitweg zien te vinden - blijf bij mij in de buurt en laat je niet afleiden, want anders zitten we hier misschien wel voor eeuwig gevangen!\"", "questRockBoss": "Kristallen Kolos", "questRockCompletion": "Door jullie ijverigheid is het gelukt een veilige route door de bergen te vinden. Je compagnon @intune, genietend van het zonlicht, ziet iets glitteren op de grond bij de uitgang van de grot. Je bukt om het op de rapen en ziet dat het een kleine rots is waar een goudader doorheen loopt. Ernaast liggen enkele vreemdgevormde rotsen. Het lijken wel... eieren?", @@ -238,7 +238,7 @@ "questDilatoryDistress3DropFish": "Vis (voedsel)", "questDilatoryDistress3DropWeapon": "Drietand van verpletterend getij (wapen)", "questDilatoryDistress3DropShield": "Maanparelschild (schild)", - "questCheetahText": "Wat een lui jachtluipaard", + "questCheetahText": "Wat een lui Jachtluipaard!", "questCheetahNotes": "Wanneer je door de Tragengestaagsavanne loopt met je vrienden @PainterProphet, @tivaquinn, @Unruly Hyena en @Crawford, schrik je ervan een cheetah langs te zien gieren met een nieuwe Habiticaan in zijn kaken. Onder de verzengende poten van de cheetah verbranden taken alsof ze voltooid zijn -- voordat iemand de kans heeft gehad ze te doen! De Habiticaan ziet je en roept: \"Help me alsjeblieft! Deze cheetah zorgt ervoor dat ik er te snel niveaus bij krijg, maar ik krijg niets gedaan. Ik wil afremmen en van het spel genieten. Hou hem tegen!\" Je herinnert je met plezier je eigen dagen als jonge hond en weet dat je het groentje moet helpen door de cheetah te stoppen!", "questCheetahCompletion": "De nieuwe Habiticaan ademt zwaar na de wilde rit, maar bedankt jou en je vrienden voor jullie hulp. \"Ik ben blij dat die cheetah niet meer iemand anders zal kunnen grijpen. Hij heeft enkele cheetah-eieren voor ons achtergelaten, dus misschien kunnen we die opvoeden tot betrouwbaardere huisdieren!\"", "questCheetahBoss": "Luie Cheetah", @@ -262,10 +262,16 @@ "questBurnoutBossRageQuests": "'Burnout gebruikt ONTLADINGSAANVAL!'\n\nO nee! Ondanks onze beste pogingen hebben we wat dagelijkse taken laten ontsnappen en nu is Burnout ontstoken met energie! Met een kakelende sneer overspoelt hij Ian de queestemeester met een golf van spookachtig vuur. De gevallen queesterollen smeulen en de rook lost op: je ziet dat de energie uit Ian gezogen is en dat hij veranderd is in een doelloze ontladingsgeest!\n\nAlleen het verslaan van Burnout kan de betovering doorbreken en onze geliefde queestemeester terugbrengen. Laten we onze dagelijkse taken in toom houden en dit monster verslaan voordat hij weer aanvalt!", "questBurnoutBossRageSeasonalShop": "'Burnout gebruikt ONTLADINGSAANVAL!'\n\nAh! Onze onafgemaakte dagelijkse taken hebben de vlammen van Burnout gevoed en nu heeft hij genoeg energie om opnieuw aan te vallen! Hij laat een pilaar van spookachtige vlammen los die de seizoenswinkel verschroeien. Vol afgrijzen zie je dat de vrolijke Seizoenstovenares veranderd is in een lijzige ontladingsgeest.\n\nWe moeten onze NPC's redden! Haast je, Habiticanen, voltooi je taken en versla Burnout voordat hij voor een derde keer toeslaat!", "questBurnoutBossRageTavern": "'Burnout gebruikt ONTLADINGSAANVAL!'\n\nVeel Habicitanen hebben zich voor Burnout verstopt in de herberg, maar niet langer! Met een schelle huil harkt Burnout de herberg omver met zijn withete handen. Terwijl de gasten van de herberg vluchten, wordt Daniel gevangen in de greep van Burnout en verandert hij voor je neus in een ontladingsgeest!\n\nDeze heethoofdige nachtmerrie heeft te lang geduurd. Geef niet op... we zijn er heel dichtbij Burnout voor eens en voor altijd te verslaan!", - "questFrogText": "Moeras van de belemmerende kikker", + "questFrogText": "Moeras van de Belemmerende Kikker", "questFrogNotes": "Terwijl jij en je vrienden door het Moeras van Stagnatie aan het ploeteren zijn, wijst @starsystemic naar een groot uithangbord. \"Blijf op het pad -- als je kan.\"

\"Dat is toch niet moeilijk!\" zegt @RosemonkeyCT. \"Het pad is breed en vrij.\"

Maar als je doorgaat, merk je dat het pad langzamerhand wordt ingenomen door drek uit het moeras, doorspekt met stukjes vreemde blauwe troep en rommel, totdat het is onmogelijk om verder te gaan.

Als je om je heen kijkt en je afvraagt hoe dit zo is gekomen roept @Jon Arjinborn: \"Kijk uit!\" Een boze kikker springt uit het slib, bekleed met vuile was en verlicht door blauw vuur. Je moet de giftige belemmerende kikker overwinnen om vooruitgang te boeken!", "questFrogCompletion": "De kikker krimpt ineen en verdwijnt in de drek, verslagen. Terwijl hij wegebt, verdwijnt ook het blauwe slijm en komt de weg vooruit vrij.

In het midden van het pad liggen drie onbevlekte eieren. \"Je kunt zelfs de kleine kikkervisjes zien door het heldere omhulsel heen!\" zegt @Breadstrings. \"Hier, neem jij ze maar.\"", - "questFrogBoss": "Belemmerende kikker", + "questFrogBoss": "Belemmerende Kikker", "questFrogDropFrogEgg": "Kikker (ei)", - "questFrogUnlockText": "Maakt het kopen van kikkereieren in de markt mogelijk" + "questFrogUnlockText": "Maakt het kopen van kikkereieren in de markt mogelijk", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/nl/settings.json b/common/locales/nl/settings.json index 8cee22b0d5..9217cbe077 100644 --- a/common/locales/nl/settings.json +++ b/common/locales/nl/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Deze optie verbergt aanvankelijk de lijst met labels als je een taak opent om hem te bewerken.", "startAdvCollapsed": "Geavanceerde opties in taken aanvankelijk ingeklapt laten zien", "startAdvCollapsedPop": "Deze optie verbergt de geavanceerde opties wanneer je voor het eerst een taak opent om hem te bewerken.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Rondleiding starten", "restartTour": "Herhaal de introductierondleiding van toen je net begon met Habitica.", "showBailey": "Bailey laten zien", @@ -81,7 +86,6 @@ "emailChange1": "Stuur om je e-mailadres te veranderen een e-mail naar", "emailChange2": "admin@habitica.com", "emailChange3": "met zowel je oude en nieuwe e-mailadres en je Gebruikers-ID.", - "username": "Inlognaam", "usernameOrEmail": "Loginnaam of e-mail", "email": "E-mail", "registeredWithFb": "Geregistreerd met Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "Gebruiker->Profiel", "loginNameDescription3": "om de naam die bij je avatar en chatberichten verschijnt aan te passen.", "emailNotifications": "E-mailberichten", - "wonChallenge": "Je hebt een uitdaging gewonnen!", + "wonChallenge": "You won a Challenge!", "newPM": "Privébericht ontvangen", "giftedGems": "Geschonken edelstenen", "giftedGemsInfo": "<%= amount %> edelstenen - van <%= name %>", @@ -100,7 +104,7 @@ "weeklyRecaps": "Samenvatting van je accountactiviteit in de afgelopen week", "questStarted": "Je queeste is begonnen", "invitedQuest": "Uitgenodigd voor queeste", - "kickedGroup": "Uit de groep gegooid", + "kickedGroup": "Uit de groep gezet", "remindersToLogin": "Herinneringsberichten om Habitica te checken", "unsubscribedSuccessfully": "Afmelden succesvol!", "unsubscribedTextUsers": "Je hebt je succesvol afgemeld van alle Habitica e-mail. Je kunt in de instellingen aangeven welke e-mail je wel wilt ontvangen. (Hier moet je voor ingelogd zijn.)", @@ -121,23 +125,23 @@ "displayInviteToPartyWhenPartyIs1": "Toon de 'Uitnodigen voor groep'-knop wanneer de groep 1 lid heeft.", "saveCustomDayStart": "Begin van de dag opslaan", "registration": "Registratie", - "addLocalAuth": "Voeg plaatselijke authenticatie toe:", - "generateCodes": "Genereer codes", - "generate": "Genereer", - "getCodes": "Verkrijg codes", + "addLocalAuth": "Plaatselijke authenticatie toevoegen:", + "generateCodes": "Codes genereren", + "generate": "Genereren", + "getCodes": "Codes verkrijgen", "webhooks": "Webhooks", "enabled": "Ingeschakeld", - "webhookURL": "Webhook URL", - "add": "Voeg toe", - "buyGemsGoldCap": "Capaciteit verheven naar <%= amount %>", - "mysticHourglass": "<%= amount %> mystieke zandloper", - "mysticHourglassText": "Mystieke zandlopers laat je de abonnee-uitrustingssets uit voorgaande maanden kopen.", - "purchasedPlanId": "Terugkerende $<%= price %> elke <%= months %> Maand(en) (<%= plan %>)", - "purchasedPlanExtraMonths": "Je hebt <%= months %> maanden abonnement krediet.", + "webhookURL": "Webhook-URL", + "add": "Toevoegen", + "buyGemsGoldCap": "Capaciteit verhoogd naar <%= amount %>", + "mysticHourglass": "<%= amount %> mystieke zandloper(s)", + "mysticHourglassText": "Met mystieke zandlopers kun je abonnee-uitrusting uit eerdere maanden kopen.", + "purchasedPlanId": "Terugkerend $<%= price %> elke <%= months %> maand(en) (<%= plan %>)", + "purchasedPlanExtraMonths": "Je hebt <%= months %> maanden abonnementkrediet.", "consecutiveSubscription": "Opeenvolgende abonnementen: ", "consecutiveMonths": "Opeenvolgende maanden:", - "gemCapExtra": "Edelsteen capaciteit extra:", + "gemCapExtra": "Extra edelsteencapaciteit:", "mysticHourglasses": "Mystieke zandlopers:", "paypal": "PayPal", - "amazonPayments": "Amazon betalingen" + "amazonPayments": "Amazon-betalingen" } \ No newline at end of file diff --git a/common/locales/pl/backgrounds.json b/common/locales/pl/backgrounds.json index 6c1e120b5a..ca9ac487ee 100644 --- a/common/locales/pl/backgrounds.json +++ b/common/locales/pl/backgrounds.json @@ -119,11 +119,11 @@ "backgroundSlimySwampNotes": "Przedzieraj się przez Grząskie Bagno", "backgroundSwarmingDarknessText": "Zarojona Ciemność", "backgroundSwarmingDarknessNotes": "Drżyj w Zarojonej Ciemności", - "backgrounds112015": "SET 18: Released November 2015", + "backgrounds112015": "ZESTAW 18: Opublikowany w listopadzie 2015", "backgroundFloatingIslandsText": "Floating Islands", "backgroundFloatingIslandsNotes": "Hop across the Floating Islands.", - "backgroundNightDunesText": "Night Dunes", + "backgroundNightDunesText": "Nocne wydmy", "backgroundNightDunesNotes": "Walk peacefully through the Night Dunes.", - "backgroundSunsetOasisText": "Sunset Oasis", - "backgroundSunsetOasisNotes": "Bask in the Sunset Oasis." + "backgroundSunsetOasisText": "Oaza o zachodzie słońca", + "backgroundSunsetOasisNotes": "Odpocznij w oazie o zachodzie słońca." } \ No newline at end of file diff --git a/common/locales/pl/challenge.json b/common/locales/pl/challenge.json index 5923003b91..ce0e4f83b4 100644 --- a/common/locales/pl/challenge.json +++ b/common/locales/pl/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "Nie posiadasz uprawnień, by edytować to wyzwanie", "noPermissionDeleteChallenge": "Nie posiadasz uprawnień, by usunąć to wyzwanie", "noPermissionCloseChallenge": "Nie posiadasz uprawnień, by zamknąć to wyzwanie", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "brak właściciela", "noChallengeOwnerPopover": "To wyzwanie nie posiada właściciela, ponieważ osoba zakładająca to wyzwanie usunęła swoje konto." } \ No newline at end of file diff --git a/common/locales/pl/character.json b/common/locales/pl/character.json index 113c0dc6ba..4b41f46da2 100644 --- a/common/locales/pl/character.json +++ b/common/locales/pl/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Zdobył najpotężniejsze uzbrojenie następujących klas:", "level": "Poziom", "levelUp": "Zyskujesz poziom!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "PZ", "mp": "PM", diff --git a/common/locales/pl/content.json b/common/locales/pl/content.json index 0dea37e75a..cbbc71e539 100644 --- a/common/locales/pl/content.json +++ b/common/locales/pl/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Żaba", "questEggFrogMountText": "Żaba", "questEggFrogAdjective": "książęca", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Znajdź eliksir wyklucia i wylej go na to jajo, a wykluje się z niego <%= eggAdjective(locale) %> <%= eggText(locale) %>. ", "hatchingPotionBase": "Zwyczajny", "hatchingPotionWhite": "Biały", diff --git a/common/locales/pl/faq.json b/common/locales/pl/faq.json index 3767cb8e51..b4e7056d06 100644 --- a/common/locales/pl/faq.json +++ b/common/locales/pl/faq.json @@ -16,7 +16,7 @@ "iosFaqAnswer4": "Jest kilka rzeczy, które mogą zadać ci obrażenia. Po pierwsze, jeśli nie wypełnisz Codziennego zadania do końca dnia. Po drugie, jeśli poddasz się złemu Nawykowi. Po trzecie, jeśli walczysz z bossem w swojej drużynie i jeden z jej członków nie wypełnił swojego Codziennego, wtedy boss cię zaatakuje.\n\nGłównym sposobem leczenia się jest zdobycie poziomu, co przywraca całe zdrowie. Możesz też zapłacić złotem za eliksir zdrowia z kolumny Nagrody. Poza tym, od poziomu 10. wzwyż, możesz stać się Uzdrowicielem, a wtedy nauczysz się leczenia. Jeśli masz w drużynie Uzdrowiciela, też może cię wyleczyć.", "webFaqAnswer4": "Jest kilka rzeczy, które mogą zadać ci obrażenia. Po pierwsze, jeśli nie wypełnisz Codziennego zadania do końca dnia. Po drugie, jeśli poddasz się złemu Nawykowi. Po trzecie, jeśli walczysz z bossem w swojej drużynie i jeden z jej członków nie wypełnił swojego Codziennego, wtedy boss cię zaatakuje.\n

\nGłównym sposobem leczenia się jest zdobycie poziomu, co przywraca całe zdrowie. Możesz też zapłacić złotem za eliksir zdrowia z kolumny Nagrody. Poza tym, od poziomu 10. wzwyż, możesz stać się Uzdrowicielem, a wtedy nauczysz się leczenia. Jeśli masz w drużynie (Społeczność > Drużyna) Uzdrowiciela, też może cię wyleczyć.", "faqQuestion5": "Jak grać w Habiticę z moimi przyjaciółmi?", - "iosFaqAnswer5": "The best way is to invite them to a Party with you! Parties can go on quests, battle monsters, and cast skills to support each other. Go to Menu > Party and click \"Create New Party\" if you don't already have a Party. Then tap on the Members list, and tap Invite in the upper right-hand corner to invite your friends by entering their User ID (a string of numbers and letters that they can find under Settings > Account Details on the app, and Settings > API on the website). On the website, you can also invite friends via email, which we will add to the app in a future update.\n\nOn the website, you and your friends can also join Guilds, which are public chat rooms. Guilds will be added to the app in a future update!", + "iosFaqAnswer5": "Najlepszy sposób to zaproszenie ich do twojej drużyny! W drużynie można wypełniać misje, walczyć z potworami i używać umiejętności, aby wzajemnie się wspierać. Wejdź w Menu > Drużyna i kliknij \"Załóż Drużynę\", jeśli jeszcze nie masz drużyny. Następnie kliknij w listę członków, a potem w Zaproś w prawym górnym rogu, aby zaprosić swoich przyjaciół, wpisując ich ID użytkownika (ciąg liczb i znaków, który mogą znaleźć w Ustawienia > Szczegóły konta w aplikacji lub Ustawienia > API na stronie). Na stronie możesz też zaprosić przyjaciół przez email, co dodamy do aplikacji w przyszłej aktualizacji.\n\nNa stronie ty i twoi przyjaciele możecie też dołączyć do gildii, czyli publicznych czatów. Gildie zostaną dodane w aplikacji w przyszłej aktualizacji!", "webFaqAnswer5": "Najlepszy sposób to zaproszenie ich do Twojej drużyny, przez Społeczność > Drużyna! W drużynie można wypełniać misje, walczyć z potworami i używać umiejętności aby wspierać się wzajemnie. Możecie również razem dołączyć do gildii (Społeczność > Gildie). Gildie są publicznymi czatami, poświęconymi wspólnym zainteresowaniom lub celom i mogą być publiczne lub prywatne. Możesz dołączyć do dowolnej liczby gildii, ale tylko do jednej drużyny. \n

\nAby uzyskac szczegółowe informacje, zajrzyj na strony wiki: [Drużyny](http://habitrpg.wikia.com/wiki/Party) i [Gildie](http://habitrpg.wikia.com/wiki/Guilds).", "faqQuestion6": "Jak zdobyć chowańca albo wierzchowca?", "iosFaqAnswer6": "Na poziomie 3. odblokujesz system zdobyczy. Za każdym razem, gdy ukończysz zadanie, dostaniesz szansę na zdobycie jaja, eliksiru wyklucia lub jedzenia. Znajdziesz je w Menu > Przedmioty.\n\nAby wykluć Chowańca, potrzebujesz jaja oraz eliksiru wyklucia. Kliknij na jajo aby wybrać gatunek, jaki chcesz wykluć, a potem na \"Wykluj Jajo\". Następnie wybierz eliksir wyklucia, aby wybrać jego kolor! Idź do Menu > Chowańce aby dodać swojego nowego Chowańca do swojego awatara, klikając na niego.\n\nMożesz też sprawić, że twój Chowaniec wyrośnie na Wierzchowca, karmiąc go w Menu > Chowańce. Kliknij na Chowańca, a potem na \"Nakarm Chowańca\"! Musisz nakarmić Chowańca dużo razy, zanim stanie się Wierzchowcem, ale jeśli odnajdziesz jego ulubione jedzenie, będzie szybciej rósł. Możesz to zrobić metodą prób i błędów albo [skorzystać z podpowiedzi](http://habitica.wikia.com/wiki/Food#Food_Preferences). Gdy już masz Wierzchowca, idź do Menu > Wierzchowce i kliknij na niego, aby twój awatar go dosiadł.\n\nMożesz też otrzymać jaja Chowańców z Misji, kończąc niektóre Misje. (Patrz niżej, aby dowiedzieć się więcej o Misjach).", @@ -30,7 +30,7 @@ "faqQuestion9": "Jak walczyć z bossami i wykonywać misje?", "iosFaqAnswer9": "First, you need to join or start a Party (see above). Although you can battle monsters alone, we recommend playing in a group, because this will make Quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n\n Next, you need a Quest Scroll, which are stored under Menu > Items. There are three ways to get a scroll:\n\n - At level 15, you get a Quest-line, aka three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively. \n - When you invite people to your Party, you'll be rewarded with the Basi-List Scroll!\n - You can buy Quests from the Quests Page on the [website](https://habitica.com/#/options/inventory/quests) for Gold and Gems. (We will add this feature to the app in a future update.)\n\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading by pulling down on the screen may be required to see the Boss's health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your Party at the same time that you damage the Boss. \n\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", "webFaqAnswer9": "First, you need to join or start a party (under Social > Party). Although you can battle monsters alone, we recommend playing in a group, because this will make quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n

\n Next, you need a Quest Scroll, which are stored under Inventory > Quests. There are three ways to get a scroll:\n

\n * When you invite people to your party, you’ll be rewarded with the Basi-List Scroll!\n * At level 15, you get a Quest-line, i.e., three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively.\n * You can buy Quests from the Quests Page (Inventory > Quests) for Gold and Gems.\n

\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading may be required to see the Boss's Health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your party at the same time that you damage the Boss.\n

\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", - "faqQuestion10": "What are Gems, and how do I get them?", + "faqQuestion10": "Czym są klejnoty i jak je zdobywać?", "iosFaqAnswer10": "Gems are purchased with real money by tapping on the gem icon in the header. When people buy gems, they are helping us to keep the site running. We're very grateful for their support!\n\n In addition to buying gems directly, there are three other ways players can gain gems:\n\n * Win a Challenge on the [website](https://habitica.com) that has been set up by another player under Social > Challenges. (We will be adding Challenges to the app in a future update!)\n * Subscribe on the [website](https://habitica.com/#/options/settings/subscription) and unlock the ability to buy a certain number of gems per month.\n * Contribute your skills to the Habitica project. See this wiki page for more details: [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica).\n\n Keep in mind that items purchased with gems do not offer any statistical advantages, so players can still make use of the app without them!", "webFaqAnswer10": "Gems are [purchased with real money](https://habitica.com/#/options/settings/subscription), although [subscribers](https://habitica.com/#/options/settings/subscription) can purchase them with Gold. When people subscribe or buy Gems, they are helping us to keep the site running. We're very grateful for their support!\n

\n In addition to buying Gems directly or becoming a subscriber, there are two other ways players can gain Gems:\n

\n * Win a Challenge that has been set up by another player under Social > Challenges.\n * Contribute your skills to the Habitica project. See this wiki page for more details: [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica)\n

\n Keep in mind that items purchased with Gems do not offer any statistical advantages, so players can still make use of the site without them!", "faqQuestion11": "Jak mogę zgłosić błąd lub zaproponować funkcjonalność?", diff --git a/common/locales/pl/front.json b/common/locales/pl/front.json index 0f70534cb4..40a63ff2b3 100644 --- a/common/locales/pl/front.json +++ b/common/locales/pl/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] naprawdę pomogła mi poukładać sobie życie na studiach.", "invalidEmail": "Do zresetowania hasła potrzebny jest ważny adres e-mail.", "irishfeet123Quote": "Miałam okropne nawyki związane z porządnym sprzątaniem po posiłkach i rozstawianiem wszędzie kubków. [Habitica] to wyleczyła!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Przed [Habitiką] utknęłam na swojej pracy dyplomowej, byłam też niezadowolona ze stanu swojej osobistej dyscypliny wykonywania prac domowych i prowadzenia spraw takich jak nauka słówek czy studiowanie teorii go. Okazało się, że rozbicie zadań na łatwiejsze do wykonania kroki jest wyjątkowo dobrym sposobem na podtrzymywanie motywacji i nieporzucanie pracy.", "landingadminlink": "pakietami dla administratorów", "landingend": "Wciąż nieprzekonany?", @@ -181,6 +181,12 @@ "marketingInquiries": "Zapytania marketingowe/społecznościowe", "tweet": "Tweetuj", "apps": "Apps", - "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "notifyAndroidApp": "Chcesz, żebyśmy cię powiadomili, kiedy aplikacja na Androida będzie gotowa? Zapisz się na naszą listę mailingową!", + "checkOutIOSApp": "Wypróbuj naszą nową aplikację na system iOS!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/pl/gear.json b/common/locales/pl/gear.json index 1dc932cd5b..cfe033d27d 100644 --- a/common/locales/pl/gear.json +++ b/common/locales/pl/gear.json @@ -212,11 +212,11 @@ "armorSpecialYetiText": "Szata poskramiacza yeti", "armorSpecialYetiNotes": "Puchaty i bezwzględny. Zwiększa Kondycję o <%= con %>. Edycja Limitowana Zima 2013-2014.", "armorSpecialSkiText": "Parka szusującego asasyna", - "armorSpecialSkiNotes": "Pełna ukrytych sztyletów i map tras narciarskich. Zwiększa percepcję o <%= per %>. Edycja Limitowana Zimowego Wyposażenia 2013-2014.", + "armorSpecialSkiNotes": "Pełna ukrytych sztyletów i map tras narciarskich. Zwiększa percepcję o <%= per %>. Edycja Limitowana Zima 2013-2014.", "armorSpecialCandycaneText": "Cukierkowa szata", - "armorSpecialCandycaneNotes": "Utkana z cukru i jedwabiu. Zwiększa inteligencję o <%= int %>. Edycja Limitowana Zimowego Wyposażenia 2013-2014.", + "armorSpecialCandycaneNotes": "Utkana z cukru i jedwabiu. Zwiększa inteligencję o <%= int %>. Edycja Limitowana Zima 2013-2014.", "armorSpecialSnowflakeText": "Szata śnieżynki", - "armorSpecialSnowflakeNotes": "Szata zapewni Ci ciepło nawet podczas zamieci. Podnosi kondycję o <%= con %>. Edycja Limitowana Zimowego Wyposażenia 2013-2014.", + "armorSpecialSnowflakeNotes": "Szata zapewni Ci ciepło nawet podczas zamieci. Podnosi kondycję o <%= con %>. Edycja Limitowana Zima 2013-2014.", "armorSpecialBirthdayText": "Absurdalne szaty imprezowe", "armorSpecialBirthdayNotes": "Wszystkiego najlepszego z okazji urodzin, Habitiko! Załóż Niedorzeczne Szaty Urodzinowe, aby świętować ten wspaniały dzień. Nie dają żadnych korzyści.", "armorSpecialBirthday2015Text": "Głupawe Szaty Urodzinowe", @@ -224,15 +224,15 @@ "armorSpecialGaymerxText": "Zbroja tęczowego wojownika", "armorSpecialGaymerxNotes": "Aby uczcić porę dumy i konwent GaymerX, ta specjalna zbroja jest przyozdobiona lśniącym, kolorowym wzorem tęczy! GaymerX to konwent poświęcony środowisku LGBTQ i grom komputerowym i jest otwarty dla wszystkich. Odbywa się w InterContinental w centrum San Francisco między 11 a 13 lipca! Nie zapewnia żadnych korzyści.", "armorSpecialSpringRogueText": "Lśniący kostium kota", - "armorSpecialSpringRogueNotes": "Nieskazitelnie zadbany. Dodaje <%= per %> punktów percepcji. Limitowana Edycja Wyposażenia, wiosna 2014.", + "armorSpecialSpringRogueNotes": "Nieskazitelnie zadbany. Dodaje <%= per %> punktów percepcji. Edycja Limitowana Wiosna 2014.", "armorSpecialSpringWarriorText": "Koniczystalowa zbroja", - "armorSpecialSpringWarriorNotes": "Miękka jak koniczyna, mocna jak stal!! Dodaje <%= con %> punktów kondycji. Limitowana Edycja Wyposażenia, wiosna 2014.", + "armorSpecialSpringWarriorNotes": "Miękka jak koniczyna, mocna jak stal!! Dodaje <%= con %> punktów kondycji. Edycja Limitowana Wiosna 2014.", "armorSpecialSpringMageText": "Szczurze szaty", - "armorSpecialSpringMageNotes": "Myszy się słyszy! Dodaje <%= int %> puntów inteligencji. Limitowana Edycja Wyposażenia, wiosna 2014.", + "armorSpecialSpringMageNotes": "Myszy się słyszy! Dodaje <%= int %> puntów inteligencji. Edycja Limitowana Wiosna 2014.", "armorSpecialSpringHealerText": "Szaty kudłatego szczeniaczka", - "armorSpecialSpringHealerNotes": "Ciepłe i przytulne, ale chronią właścicieli przed krzywdą. Dodaje <%= con %> punktów kondycji. Limitowana Edycja Wyposażenia, wiosna 2014.", + "armorSpecialSpringHealerNotes": "Ciepłe i przytulne, ale chronią właścicieli przed krzywdą. Dodaje <%= con %> punktów kondycji. Edycja Limitowana Wiosna 2014.", "armorSpecialSummerRogueText": "Szata pirata", - "armorSpecialSummerRogueNotes": "Do stu diabłów, przytulne te szaty! Dodają <%= str %> punktów percepcji. Limitowana Edycja Wyposażenia, wiosna 2014.", + "armorSpecialSummerRogueNotes": "Do stu diabłów, przytulne te szaty! Dodają <%= str %> punktów percepcji. Edycja Limitowana Wiosna 2014.", "armorSpecialSummerWarriorText": "Szaty zawadiaki", "armorSpecialSummerWarriorNotes": "Komplet z płaszczem, oraz ze szpadą. Zwiększa Kondycję o <%= con %>. Limitowana Edycja Wyposażenia Lato 2014.", "armorSpecialSummerMageText": "Szmaragdowy ogon", @@ -256,7 +256,7 @@ "armorSpecialWinter2015HealerText": "Strój Łyżwiarski", "armorSpecialWinter2015HealerNotes": "Łyżwiarstwo jest bardzo relaksujące, ale nie powinno się go próbować bez ochronnego wyposażenia na wypadek ataku soplowych smoków. Zwiększa kondycję o <%= con %>. Edycja Limitowana Zimowego Wyposażenia 2014-2015.", "armorSpecialSpring2015RogueText": "Piskliwa Szata", - "armorSpecialSpring2015RogueNotes": "Futrzasty, miękki oraz zdecydowanie niełatwopalny. Zwiększa percepcję o<%= per %>. Edycja Limitowana, wiosna 2015.", + "armorSpecialSpring2015RogueNotes": "Futrzana, miękka oraz zdecydowanie niełatwopalna. Zwiększa percepcję o<%= per %>. Edycja Limitowana, wiosna 2015.", "armorSpecialSpring2015WarriorText": "Zbroja \"Strzeż Się\"", "armorSpecialSpring2015WarriorNotes": "Tylko najwaleczniejsze psiaki mogą być tak puszyste. Zwiększa kondycję o <%= con %>. Limitowana Edycja Wiosennego Wyposażenia 2015.", "armorSpecialSpring2015MageText": "Króliczy strój iluzjonisty", @@ -274,11 +274,11 @@ "armorSpecialFall2015RogueText": "Nietoperza Zbroja", "armorSpecialFall2015RogueNotes": "Leć do walki! Zwiększa Percepcję o <%= per %>. Limitowana Edycja Wyposażenia, jesień 2015.", "armorSpecialFall2015WarriorText": "Zbroja Stracha na Wróble", - "armorSpecialFall2015WarriorNotes": "Chociaż wypchana słomą, ta zbroja jest niezwykle wytrzymała! Zwiększa Kondycję o <%= con %>. Limitowana Edycja Wyposażenia, jesień 2015.", + "armorSpecialFall2015WarriorNotes": "Chociaż wypchana słomą, ta zbroja jest niezwykle wytrzymała! Zwiększa Kondycję o <%= con %>. Edycja Limitowana Edycja Jesień 2015.", "armorSpecialFall2015MageText": "Szyta szata", - "armorSpecialFall2015MageNotes": "Każdy szew w tej zbroi lśni od zaklęć. Zwiększa Inteligencję o <%= int %>. Limitowana Edycja Wyposażenia, jesień 2015.", + "armorSpecialFall2015MageNotes": "Każdy szew w tej zbroi lśni od zaklęć. Zwiększa Inteligencję o <%= int %>. Edycja Limitowana Jesień 2015.", "armorSpecialFall2015HealerText": "Potioner Robes", - "armorSpecialFall2015HealerNotes": "Co? Oczywiście, że to był eliksir Kondycji. Nie, na pewno nie zmieniasz się w żabę. Nie kumkam, o co ci chodzi. Zwiększa Kondycję o <%= con %>. Limitowana Edycja Wyposażenia, jesień 2015.", + "armorSpecialFall2015HealerNotes": "Co? Oczywiście, że to był eliksir Kondycji. Nie, na pewno nie zmieniasz się w żabę. Nie kumkam, o co ci chodzi. Zwiększa Kondycję o <%= con %>. Edycja Limitowana Jesień 2015.", "armorMystery201402Text": "Szaty posłańca", "armorMystery201402Notes": "Połyskujące i wytrzymałe, te szaty mają wiele kieszeni na listy. Brak dodatkowych korzyści. Przedmiot Abonencki, luty 2014.", "armorMystery201403Text": "Zbroja przemierzania lasów", @@ -288,9 +288,9 @@ "armorMystery201406Text": "Szata ośmiornicy", "armorMystery201406Notes": "Noszenie tak elastycznej szata sprawia, że możesz prześlizgnąć się nawet przez najmniejszą szczelinę. Brak dodatkowych korzyści. Przedmiot Abonencki, czerwiec 2014.", "armorMystery201407Text": "Strój podmorskiego odkrywcy", - "armorMystery201407Notes": "Opisywany też jako \"pluskaty\", \"za gruby\" i \"szczerze, trochę kłopotliwy\", taki strój jest najlepszym przyjacielem nieustraszonych morskich odkrywców. Przedmiot dla Abonentów z lipca 2014. Nie ma na nic wpływu.", + "armorMystery201407Notes": "Opisywany też jako \"pluskaty\", \"za gruby\" i \"szczerze, trochę kłopotliwy\", taki strój jest najlepszym przyjacielem nieustraszonych morskich odkrywców. Brak dodatkowych korzyści. Przedmiot Abonencki, lipiec 2014.", "armorMystery201408Text": "Szaty Słońca", - "armorMystery201408Notes": "Te szaty są utkane z promieni słońca i złota. Żadnych dodatkowych korzyści. Sierpień 2014. Przedmiot abonencki", + "armorMystery201408Notes": "Te szaty są utkane z promieni słońca i złota. Brak dodatkowych korzyści. Przedmiot Abonencki, sierpień 2014. ", "armorMystery201409Text": "Kamizelka obieżyświata", "armorMystery201409Notes": "Kamizelka pokryta liśćmi zapewnia świetny kamuflaż. Brak dodatkowych korzyści. Przedmiot Abonencki, wrzesień 2014.", "armorMystery201410Text": "Goblińskie wyposażenie", @@ -300,7 +300,7 @@ "armorMystery201501Text": "Gwiaździsta Zbroja", "armorMystery201501Notes": "Galaktyki błyszczą w metalu takich zbrój, wzmacniając determinację walczących. Brak dodatkowych korzyści. Przedmiot Abonencki, styczeń 2015.", "armorMystery201503Text": "Akwamarynowa zbroja", - "armorMystery201503Notes": "Niebieski minerał symbolizuje szczęście, radość oraz wieczną produktywność. Nie daje żadnych korzyści. Marzec 2015 Przedmiot Abonenta.", + "armorMystery201503Notes": "Ten niebieski minerał symbolizuje szczęście, radość oraz wieczną produktywność. Nie daje żadnych korzyści. Przedmiot Abonencki, marzec 2015.", "armorMystery201504Text": "Szata Pracowitej Pszczółki", "armorMystery201504Notes": "W tej uroczej szacie dorównujesz produktywnością pracowitej pszczółce! Brak dodatkowych korzyści. Przedmiot Abonencki, kwiecień 2015.", "armorMystery201506Text": "Kombinezon do nurkowania", @@ -323,10 +323,10 @@ "armorArmoireHornedIronArmorNotes": "Ukształtowana zaciekłymi uderzeniami młota, ta żelazna Rogata Zbroja jest prawie niezniszczalna. Poprawia kondycję o <%= con %> i percepcję o <%= per %>. Zaczarowana szafa: Zestaw Rogate Żelazo (przedmiot 2 z 3.)", "armorArmoirePlagueDoctorOvercoatText": "Płaszcz Medyków", "armorArmoirePlagueDoctorOvercoatNotes": "Autentyczny płaszcz noszony przez medyków czasów Plagi Prokrastynacji! Podnosi inteligencję o <%= int %>, siłę o <%= str %> i kondycję o <%= con %>. Zaczarowana szafa: zestaw medyka (przedmiot 3 z 3).", - "armorArmoireShepherdRobesText": "Shepherd Robes", - "armorArmoireShepherdRobesNotes": "The fabric is cool and breathable, perfect for a hot day herding gryphons in the desert. Increases Strength and Perception by <%= attrs %> each. Enchanted Armoire: Shepherd Set (Item 2 of 3).", - "armorArmoireRoyalRobesText": "Royal Robes", - "armorArmoireRoyalRobesNotes": "Wonderful ruler, rule all day long! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 3 of 3).", + "armorArmoireShepherdRobesText": "Szata pasterza", + "armorArmoireShepherdRobesNotes": "Jest z chłodnej i przewiewnej tkaniny, świetna do pasania gryfów w gorące pustynne dni. Zwiększa Siłę i Percepcję o <%= attrs %>. Zaczarowana szafa: zestaw pasterza (przedmiot 2 z 3).", + "armorArmoireRoyalRobesText": "Królewskie szaty", + "armorArmoireRoyalRobesNotes": "Panuj nam jak najdłużej, od wiosny aż do zimy! Zwiększa kondycję, inteligencję i percepcję o <%= attrs %>. Zaczarowana Szafa: zestaw królewski (przedmiot 3 z 3).", "headgear": "nakrycie głowy", "headBase0Text": "Bez hełmu", "headBase0Notes": "Bez nakrycia głowy.", @@ -439,7 +439,7 @@ "headSpecialSummer2015HealerText": "Marynarska czapka", "headSpecialSummer2015HealerNotes": "Z tą marynarską czapką pewnie nasadzoną na głowę, możesz nawigować po najburzliwszych morzach! Zwiększa inteligencję o <%= int %>. Edycja Limitowana, lato 2015.", "headSpecialFall2015RogueText": "Nietoperze skrzydła", - "headSpecialFall2015RogueNotes": "Echolocate your enemies with this powerful helm! Increases Perception by <%= per %>. Limited Edition 2015 Autumn Gear.", + "headSpecialFall2015RogueNotes": "Wykorzystaj echolokację, by znaleźć swoich przeciwników! Zwiększa Percepcję o <%= per %>. Limitowana Edycja Wyposażenia, jesień 2015.", "headSpecialFall2015WarriorText": "Kapelusz Stracha na Wróble.", "headSpecialFall2015WarriorNotes": "Każdy by taki chciał - gyby tylko miał mózg. Zwiększa Siłę o <%= str %> Limitowana Edycja Jesiennego Wyposażenia 2015.", "headSpecialFall2015MageText": "Szyty kapelusz", @@ -487,7 +487,7 @@ "headArmoireBlueHairbowText": "Niebieska kokarda", "headArmoireBlueHairbowNotes": "Zwiększ swą spostrzegawczość, determinację i mądrość dzięki tej pięknej niebieskiej kokardzie! Podnosi percepcję o <%= per %>, kondycję o <%= con %> i inteligencję o <%= int %>. Zaczarowana szafa: przedmiot niezależny.", "headArmoireRoyalCrownText": "Królewska korona", - "headArmoireRoyalCrownNotes": "Hooray for the ruler, mighty and strong! Increases Strength by <%= str %>. Enchanted Armoire: Royal Set (Item 1 of 3).", + "headArmoireRoyalCrownNotes": "Panuj nam miłościwie, twą siłę i moc sławimy! Zwiększa siłę o <%= str %>. Zaczarowana Szafa: zestaw królewski (przedmiot 1 z 3).", "headArmoireGoldenLaurelsText": "Złoty laur", "headArmoireGoldenLaurelsNotes": "Złoty laur wieńczy czoła tych, co pokonali złe nawyki. Zwiększa percepcję i kondycję o <%= attrs %>. Zaczarowana szafa: zestaw Złota Toga (przedmiot 2 z 3).", "headArmoireHornedIronHelmText": "Żelazny Rogaty Hełm", @@ -589,8 +589,8 @@ "shieldArmoireGladiatorShieldNotes": "Do bycia gladiatorem nie wystarczy... a, zresztą, po prostu przygrzmoć im tarczą. Zwiększa kondycję o <%= con %> i siłę o <%= str %>. Zaczarowana szafa: zestaw gladiatora (przedmiot 3 z 3).", "shieldArmoireMidnightShieldText": "Tarcza Północy", "shieldArmoireMidnightShieldNotes": "Ta tarcza ma najwięcej mocy o północy! Zwięsza Kondycję o <%= con %> i Siłę o <%= str %>. Zaczarowana Szafa: przedmiot niezależny.", - "shieldArmoireRoyalCaneText": "Royal Cane", - "shieldArmoireRoyalCaneNotes": "Hooray for the ruler, worthy of song! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 2 of 3).", + "shieldArmoireRoyalCaneText": "Królewska laska", + "shieldArmoireRoyalCaneNotes": "Panuj nam miłościwie, o tobie pieśni nucimy! Zwiększa kondycję, inteligencję i percepcję o <%= attrs %>. Zaczarowana Szafa: zestaw królewski (przedmiot 2 z 3).", "back": "Osprzęt na plecy", "backBase0Text": "Nic na plecach", "backBase0Notes": "Nic na plecach.", diff --git a/common/locales/pl/generic.json b/common/locales/pl/generic.json index 5c6e941e0c..8e1d6ddf9b 100644 --- a/common/locales/pl/generic.json +++ b/common/locales/pl/generic.json @@ -28,7 +28,7 @@ "market": "Targ", "subscriberItem": "Tajemniczy przedmiot", "newSubscriberItem": "Nowy tajemniczy przedmiot", - "subscriberItemText": "Each month, subscribers will receive a mystery item. This is usually released about one week before the end of the month. See the wiki's 'Mystery Item' page for more information.", + "subscriberItemText": "W każdym miesiącu abonenci otrzymają tajemniczy przedmiot. Zazwyczaj jest on wydawany około tygodnia przed końcem miesiąca. Aby uzyskać więcej informacji, zobacz stronę \"Mystery Item\" w wiki.", "all": "Wszystkie", "none": "Żadne", "or": "Lub", @@ -134,5 +134,17 @@ "thankyou2": "Wysyłam Ci tysiąc podziękowań.", "thankyou3": "Jestem bardzo wdzięczny - dziękuję!", "thankyouCardAchievementTitle": "Ogromnie wdzięczny", - "thankyouCardAchievementText": "Dzięki za bycie wdzięcznym! Wysłał lub otrzymał <%= cards %> kartek z podziękowaniem." + "thankyouCardAchievementText": "Dzięki za bycie wdzięcznym! Wysłał lub otrzymał <%= cards %> kartek z podziękowaniem.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/pl/messages.json b/common/locales/pl/messages.json index 44cef9cfce..6a54357e52 100644 --- a/common/locales/pl/messages.json +++ b/common/locales/pl/messages.json @@ -32,7 +32,7 @@ "armoireFood": "<%= image %> Przeszukując Zaczarowaną Szafę znaleziono <%= dropArticle %><%= dropText %>. Co to tutaj robi?", "armoireExp": "Mocujesz się z Zaczarowaną Szafą i zyskujesz doświadczenie. Masz za swoje!", "messageInsufficientGems": "Masz za mało klejnotów!", - "messageAuthPasswordMustMatch": ":password and :confirmPassword don't match", + "messageAuthPasswordMustMatch": "Hasło i potwierdzenie hasła nie są identyczne", "messageAuthCredentialsRequired": ":username, :email, :password, :confirmPassword required", "messageAuthUsernameTaken": "Nazwa użytkownika już zajęta", "messageAuthEmailTaken": "Adres e-mail już zajęty.", diff --git a/common/locales/pl/pets.json b/common/locales/pl/pets.json index 3517225345..f59d37ddff 100644 --- a/common/locales/pl/pets.json +++ b/common/locales/pl/pets.json @@ -58,8 +58,16 @@ "firstDrop": "Odblokowałeś System Zdobyczy! Od teraz po ukończeniu zadań, masz niewielką szansę znalezienia przedmiotu, włączając w to jaja, eliksiry i jedzenie! Właśnie znalazłeś <%= eggText %> Jajo! <%= eggNotes %>", "useGems": "Jeśli masz na oku zwierzaka, ale nie możesz się doczekać jego zdobycia, użyj Klejnotów w Ekwipunek > Targ, by go kupić!", "hatchAPot": "Wykluć <%= potion %> <%= egg %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Nakarmić <%= text %> twojego <%= name %>?", "useSaddle": "Osiodłać <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Klucz do schroniska", diff --git a/common/locales/pl/quests.json b/common/locales/pl/quests.json index 50713dae66..d42b40b1a8 100644 --- a/common/locales/pl/quests.json +++ b/common/locales/pl/quests.json @@ -76,5 +76,7 @@ "startAQuest": "ROZPOCZNIJ MISJE", "startQuest": "Rozpocznij Misje", "whichQuestStart": "Którą misję chcesz rozpocząć?", - "getMoreQuests": "Zdobądź więcej misji" + "getMoreQuests": "Zdobądź więcej misji", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/pl/questscontent.json b/common/locales/pl/questscontent.json index c60ead375c..428cc51c5d 100644 --- a/common/locales/pl/questscontent.json +++ b/common/locales/pl/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Śmieciowa Żaba", "questFrogDropFrogEgg": "Żaba (jajo)", - "questFrogUnlockText": "Odblokowuje dostęp do kupna żabich jaj na Targu" + "questFrogUnlockText": "Odblokowuje dostęp do kupna żabich jaj na Targu", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/pl/settings.json b/common/locales/pl/settings.json index d5edd57828..faccbafad3 100644 --- a/common/locales/pl/settings.json +++ b/common/locales/pl/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Jeśli ta opcja jest włączona, lista tagów w zadaniach będzie ukryta, gdy po raz pierwszy otworzysz zadanie do edycji.", "startAdvCollapsed": "Zaawansowane Opcje w zadaniach startują zwinięte", "startAdvCollapsedPop": "Jeśli ta opcja jest włączona, Zaawansowane Opcje będą ukryte, gdy po raz pierwszy otworzysz zadanie do edycji.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Pokaż przewodnik", "restartTour": "Restartuje wprowadzający przewodnik, z czasu gdy dołączyłeś do Habitica", "showBailey": "Pokaż Bailey", @@ -81,7 +86,6 @@ "emailChange1": "Aby zmienić swój adres e-mail, wyślij wiadomość na", "emailChange2": "admin@habitica.com", "emailChange3": "w treści wpisując zarówno stary jak i nowy adres e-mail, a także swoje ID użytkownika.", - "username": "Nazwa użytkownika", "usernameOrEmail": "Login lub Email", "email": "E-mail", "registeredWithFb": "Logowanie / Rejestracja z użyciem Facebook'a", @@ -89,7 +93,7 @@ "loginNameDescription2": "Użytkownik → Profil", "loginNameDescription3": ", aby zmienić nazwę, która pojawia się na Twoim avatarze i przy wiadomościach na czacie.", "emailNotifications": "Powiadomienia e-mail", - "wonChallenge": "Wygrałeś wyzwanie", + "wonChallenge": "You won a Challenge!", "newPM": "Otrzymane wiadomości prywatne", "giftedGems": "Podarowane klejnoty", "giftedGemsInfo": "<%= amount %> klejnotów - przez <%= name %>", diff --git a/common/locales/pt/backgrounds.json b/common/locales/pt/backgrounds.json index a787e14084..021b3c9a71 100644 --- a/common/locales/pt/backgrounds.json +++ b/common/locales/pt/backgrounds.json @@ -120,10 +120,10 @@ "backgroundSwarmingDarknessText": "Escuridão Fervilhante", "backgroundSwarmingDarknessNotes": "Trema na Escuridão Fervilhante", "backgrounds112015": "SET 18: Released November 2015", - "backgroundFloatingIslandsText": "Floating Islands", + "backgroundFloatingIslandsText": "Ilhas Flutuantes", "backgroundFloatingIslandsNotes": "Hop across the Floating Islands.", - "backgroundNightDunesText": "Night Dunes", + "backgroundNightDunesText": "Dunas Noturnas", "backgroundNightDunesNotes": "Walk peacefully through the Night Dunes.", - "backgroundSunsetOasisText": "Sunset Oasis", + "backgroundSunsetOasisText": "Oasis do pôr do sol", "backgroundSunsetOasisNotes": "Bask in the Sunset Oasis." } \ No newline at end of file diff --git a/common/locales/pt/challenge.json b/common/locales/pt/challenge.json index 8c51084de9..b2aa7cccdd 100644 --- a/common/locales/pt/challenge.json +++ b/common/locales/pt/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "Você não têm permissões para editar esse desafio", "noPermissionDeleteChallenge": "Você não têm permissões para deletar esse desafio", "noPermissionCloseChallenge": "Você não têm permissões para fechar esse desafio", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "sem dono", "noChallengeOwnerPopover": "Esse desafio não possui um dono porque quem criou o desafio apagou sua conta." } \ No newline at end of file diff --git a/common/locales/pt/character.json b/common/locales/pt/character.json index 7bc2c219cb..76a88f2790 100644 --- a/common/locales/pt/character.json +++ b/common/locales/pt/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Atualizou para o conjunto de arma e armadura máxima para as seguintes classes:", "level": "Nível", "levelUp": "Subiu de Nível!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "PV", "mp": "PM", diff --git a/common/locales/pt/content.json b/common/locales/pt/content.json index d1463df07d..f971b43f49 100644 --- a/common/locales/pt/content.json +++ b/common/locales/pt/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Sapo", "questEggFrogMountText": "Sapo", "questEggFrogAdjective": "um principesco", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Ache uma poção de eclosão para usar nesse ovo e ele irá eclodir em um <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Básico", "hatchingPotionWhite": "Branco", diff --git a/common/locales/pt/faq.json b/common/locales/pt/faq.json index 32754c90ae..189fb071e1 100644 --- a/common/locales/pt/faq.json +++ b/common/locales/pt/faq.json @@ -31,8 +31,8 @@ "iosFaqAnswer9": "First, you need to join or start a Party (see above). Although you can battle monsters alone, we recommend playing in a group, because this will make Quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n\n Next, you need a Quest Scroll, which are stored under Menu > Items. There are three ways to get a scroll:\n\n - At level 15, you get a Quest-line, aka three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively. \n - When you invite people to your Party, you'll be rewarded with the Basi-List Scroll!\n - You can buy Quests from the Quests Page on the [website](https://habitica.com/#/options/inventory/quests) for Gold and Gems. (We will add this feature to the app in a future update.)\n\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading by pulling down on the screen may be required to see the Boss's health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your Party at the same time that you damage the Boss. \n\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", "webFaqAnswer9": "Primeiro, você precisa criar ou se juntar a uma Equipe (em Social > Equipe). Apesar de você poder enfrentar monstros sozinho, nós recomendamos jogar com um grupo, pois isso deixará as Missões muito mais fáceis. Além disso, ter um amigo para comemorar com você ao completar tarefas é bem mais motivante!\n

\nEm seguida, você precisará de um Pergaminho de Missão, que são guardados em Inventário > Missões. Existem três maneiras de conseguir um pergaminho:\n

\n*Quando você convida pessoas para sua Equipe, você sera recompensado com o Pergaminho da Basi-Lista!\n*No nível 15, você receberá uma série de Missões, que são três missões interligadas. Mais séries de Missões são desbloqueadas nos níveis 30, 40 e 60, respectivamente.\n*Você pode comprar Missões na página de Missões (Inventário > Missões) usando Ouro e Gemas.\n

\nPara enfrentar o Chefão ou coletar itens para uma Missão de coleção, simplesmente complete suas tarefas normalmente e elas serão convertidas em dano no fim do dia. (Recarregar a página pode ser necessário para ver a vida do Chefe diminuir.) Se você está lutando contra um Chefão e você perdeu alguma Diárias, o Chefe causará dano à Equipe ao mesmo tempo que você causará dano a ele.\n

\nApós o nível 11, Magos e Guerreiros ganham Habilidades que permitem causar dano adicional ao Chefe, então essas são classes execelentes para escolher após o nível 10 se você quiser ter um ataque poderoso.", "faqQuestion10": "What are Gems, and how do I get them?", - "iosFaqAnswer10": "Gemas são compradas com dinheiro real ao tocar no ícone no cabeçalho. Quando as pessoas compram gemas, elas estão nos ajudando a manter o site funcionando. Nós somos muito gratos pelo seu suporte!\n\nEm adição a comprar gemas diretamente, existem três outras maneiras que jogadores podem obter gemas:\n\n* Vença um Desafio no [site](https://habitica.com) que foi criado por outro jogador em Social > Desafios. (Nós iremos adicionar Desafios para o app numa futura atualização!)\n* Faça assinatura no [site](https://habitica.com/#/options/settings/subscription) and destrave a capacidade de comprar um certo número de gemas por mês.\n* Contribua com seus talentos para o projeto Habitica. Veja na página da wiki para mais detalhes: [Contribuindo com o Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica).\n\nTenha em mente que items comprados com gemas não oferecem nenhuma vantagem estatística, então os jogadores podem usar o app sem elas!", - "webFaqAnswer10": "Gemas são [compradas com dinheiro real](https://habitica.com/#/options/settings/subscription), apesar de que [assinantes](https://habitica.com/#/options/settings/subscription) podem compra-las usando Ouro. Quando alguém assina o site ou compra gemas, esta pessoa está nos ajudando a manter o site funcionando. Ficamos muito agradecidos com esse suporte!\n

\nAlém de comprar gemas diretamente, existem outras três maneiras de se conseguir gemas:\n

\n* Vença um Desafio feito por outro jogador em Social > Challenges.\n* Contribua com seus talentos para o projeto do Habitica. Veja essa pagina da wiki para mais detalhes: [Contribuindo com o Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica)\n

\nTenha em mente que itens comprados com gemas não oferecem nenhuma vantagem estatística, então todos podem utilizar o site sem elas!", + "iosFaqAnswer10": "Gemas são compradas com dinheiro real ao tocar no ícone no cabeçalho. Quando as pessoas compram jóias, elas estão nos ajudando a manter o site funcionando. Nós somos muito gratos pelo seu suporte!\n\nEm adição a comprar jóias diretamente, existem três outras maneiras que jogadores podem obter jóias:\n\n* Vença um Desafio no [site](https://habitica.com) que foi criado por outro jogador em Social > Desafios. (Nós iremos adicionar Desafios para o app numa futura atualização!)\n* Faça assinatura no [site](https://habitica.com/#/options/settings/subscription) and destrave a capacidade de comprar um certo número de jóias por mês.\n* Contribua com seus talentos para o projeto Habitica. Veja na página da wiki para mais detalhes: [Contribuindo com o Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica).\n\nTenha em mente que items comprados com jóias não oferecem nenhuma vantagem estatística, então os jogadores podem usar o app sem elas!", + "webFaqAnswer10": "Gemas são [compradas com dinheiro real](https://habitica.com/#/options/settings/subscription), apesar de que [assinantes](https://habitica.com/#/options/settings/subscription) podem compra-las usando Ouro. Quando alguém assina o site ou compra jóias, esta pessoa está nos ajudando a manter o site funcionando. Ficamos muito agradecidos com esse suporte!\n

\nAlém de comprar jóias diretamente, existem outras três maneiras de se conseguir jóias:\n

\n* Vença um Desafio feito por outro jogador em Social > Challenges.\n* Contribua com seus talentos para o projeto do Habitica. Veja essa pagina da wiki para mais detalhes: [Contribuindo com o Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica)\n

\nTenha em mente que itens comprados com jóias não oferecem nenhuma vantagem estatística, então todos podem utilizar o site sem elas!", "faqQuestion11": "Como eu relato um bug ou solicito uma funcionalidade?", "iosFaqAnswer11": "Você pode relatar um bug, solicitar uma funcionalidade ou enviar sua opinião através do menu Ajuda > Reportar um Problema e Ajuda > Fazer uma pergunta! Vamos fazer tudo que pudermos para ajudá-lo.", "webFaqAnswer11": "Relatos de bugs são armazenados no GitHub. Vá para [Ajuda > Relatar um Bug](https://github.com/HabitRPG/habitrpg/issues/2760) e siga as instruções. Não se preocupe, nós o consertaremos em breve!\n

\nSolicitações de funcionalidade são armazenadas no Trello. Vá para [Ajuda > Solicitar Funcionalidade] (https://trello.com/c/odmhIqyW/440-read-first-table-of-contents) e siga as instruções. Ta-dan!", diff --git a/common/locales/pt/front.json b/common/locales/pt/front.json index 191dc3f65e..f363fcc8c6 100644 --- a/common/locales/pt/front.json +++ b/common/locales/pt/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] me ajudou muito a atribuir estrutura à minha vida durante a graduação.", "invalidEmail": "Um endereço de e-mail válido é necessário para recuperar senha.", "irishfeet123Quote": "Eu tinha dificuldade em lavar a louça depois das refeições e hábitos horríveis de deixar copos por todo o lugar. [Habitica] resolveu isso!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Antes do [Habitica], eu estava empacado com minha tese, além de insatisfeito com minha disciplina nas atividades domésticas e coisas como aprendizado de vocabulário e estudo da teoria Go. No final das contas, dividir estas tarefas em pequenas listas foi a coisa certa para me manter motivado e constantemente trabalhando.", "landingadminlink": "pacotes administrativos", "landingend": "Ainda não está convencido?", @@ -182,5 +182,11 @@ "tweet": "Tweet", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/pt/generic.json b/common/locales/pt/generic.json index 4f0c1eae23..bf8598cbf9 100644 --- a/common/locales/pt/generic.json +++ b/common/locales/pt/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Agradecendo milhares de vezes.", "thankyou3": "Estou muito grato - obrigado!", "thankyouCardAchievementTitle": "Incrívelmente grato", - "thankyouCardAchievementText": "Agradeço por ser grato! Mandou ou recebeu <%= cards %> cartões de agradecimento." + "thankyouCardAchievementText": "Agradeço por ser grato! Mandou ou recebeu <%= cards %> cartões de agradecimento.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/pt/groups.json b/common/locales/pt/groups.json index 7c1c35fdc8..35212309ba 100644 --- a/common/locales/pt/groups.json +++ b/common/locales/pt/groups.json @@ -141,10 +141,10 @@ "partyExplanation2": "Lute contra monstros e crie Desafios!", "partyExplanation3": "Convide amigos agora para ganha um Pergaminho de Missão!", "wantToStartParty": "Você quer começar uma equipe?", - "exclusiveQuestScroll": "Convidar um amigo para a sua equipe lhe garantirá um exclusivo Pergaminho de Missão para lutar a Basi-Lista juntos!", + "exclusiveQuestScroll": "Convidar um amigo para a sua equipe lhe garantirá um exclusivo Pergaminho de Missão para que enfrentem a Basi-Lista juntos!", "nameYourParty": "Dê nome a sua nova equipe!", "partyEmpty": "Você é o único na sua equipe. Convide seus amigos!", - "partyChatEmpty": "Seu bate-papo da equipe está vazio! Digite uma mensagem na caixa abaixo para começar a conversar.", + "partyChatEmpty": "Seu bate-papo da equipe está vazio! Digite uma mensagem na caixa acima para começar a conversar.", "guildChatEmpty": "O bate-papo desta guilda está vazio! Digite uma mensagem na caixa abaixo para começar a conversar.", "possessiveParty": "Equipe de <%= name %>", "requestAcceptGuidelines": "Se você quiser publicar mensagens na Taverna, em qualquer equipe ou chat de guild, primeiro leia nossas <%= linkStart %>Diretrizes da Comunidade<%= linkEnd %> e depois clique no botão abaixo para indicar que você as aceita." diff --git a/common/locales/pt/pets.json b/common/locales/pt/pets.json index 7c1d3a6818..003d51feae 100644 --- a/common/locales/pt/pets.json +++ b/common/locales/pt/pets.json @@ -58,8 +58,16 @@ "firstDrop": "Você liberou o Sistema de Drops! Agora quando completar tarefas, você terá uma pequena chance de encontrar um item, incluindo ovos, poções e comida! Você acabou de encontrar um <%= eggText %>Ovo! <%= eggNotes %>", "useGems": "Se você está de olho em um mascote, mas não consegue esperar mais para encontrá-lo, use Gemas em Inventário > Mercado para comprar um!", "hatchAPot": "Chocar um <%= potion %> <%= egg %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Alimentar <%= article %><%= text %> para o seu <%= name %>?", "useSaddle": "Selar <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= egg %> <%= potion %>", "mountName": "<%= mount %> <%= potion %>", "petKeyName": "Chave dos Canis", diff --git a/common/locales/pt/quests.json b/common/locales/pt/quests.json index 84b19e46d4..fbd0349c5a 100644 --- a/common/locales/pt/quests.json +++ b/common/locales/pt/quests.json @@ -76,5 +76,7 @@ "startAQuest": "INICIAR UMA MISSÃO", "startQuest": "Iniciar missão", "whichQuestStart": "Que missão deseja iniciar?", - "getMoreQuests": "Conseguir mais missões" + "getMoreQuests": "Conseguir mais missões", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/pt/questscontent.json b/common/locales/pt/questscontent.json index 787adb3807..1ca8a7d923 100644 --- a/common/locales/pt/questscontent.json +++ b/common/locales/pt/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "O sapo se esconde de volta na sujeira, derrotado. Conforme ele escapule, o lodo azul desvanece, deixando o caminho a frente livre.

Parados no meio do caminho estão três ovos antigos. \"Você pode ver os pequenos girinos através da casca transparente!\" @Breadstrings diz. \"Aqui, você devia ficar com eles.\"", "questFrogBoss": "Sapo Bagunceiro", "questFrogDropFrogEgg": "Sapo (Ovo)", - "questFrogUnlockText": "Desbloqueia ovos de Sapo para compra no Mercado" + "questFrogUnlockText": "Desbloqueia ovos de Sapo para compra no Mercado", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/pt/settings.json b/common/locales/pt/settings.json index 14458cdd4d..bdfd40cebc 100644 --- a/common/locales/pt/settings.json +++ b/common/locales/pt/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Com essa opção ativada, a lista de etiquetas das tarefas será omitida quando você abrir uma tarefa para edição.", "startAdvCollapsed": "Opções Avançadas das tarefas começam omitidas", "startAdvCollapsedPop": "Com essa opção ativada, Opções Avançadas estarão omitidas quando você abrir uma tarefa para edição.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Mostrar Tour", "restartTour": "Reiniciar o tour de introdução de quando você se juntou ao Habitica.", "showBailey": "Mostrar Bailey", @@ -81,7 +86,6 @@ "emailChange1": "Para alterar seu endereço de e-mail, por favor envie um e-mail a", "emailChange2": "admin@habitica.com", "emailChange3": "incluindo ambos os seus e-mails antigo e novo, bem como seu ID de Usuário.", - "username": "Nome de login", "usernameOrEmail": "Nome de usuário ou E-mail", "email": "E-mail", "registeredWithFb": "Registrado com o Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "Usuário -> Perfil", "loginNameDescription3": "para alterar o nome que será apresentado em seu avatar e mensagens de chat.", "emailNotifications": "Notificações de E-mail", - "wonChallenge": "Você ganhou um Desafio", + "wonChallenge": "You won a Challenge!", "newPM": "Recebeu Mensagem Privada", "giftedGems": "Gemas Presenteadas", "giftedGemsInfo": "<%= amount %> Gemas - por <%= name %>", diff --git a/common/locales/ro/backgrounds.json b/common/locales/ro/backgrounds.json index 0cc1942224..274a5de2df 100644 --- a/common/locales/ro/backgrounds.json +++ b/common/locales/ro/backgrounds.json @@ -16,7 +16,7 @@ "backgroundSeafarerShipNotes": "Cutreieră apele la bordul Navei Navigatorului.", "backgrounds082014": "SET 3: Lansat în august 2014", "backgroundCloudsText": "Nori", - "backgroundCloudsNotes": "Zboară printre Nori", + "backgroundCloudsNotes": "Zboară printre nori", "backgroundDustyCanyonsText": "Canion prăfuit", "backgroundDustyCanyonsNotes": "Plimbă-te printr-un canion prăfuit.", "backgroundVolcanoText": "Vulcan", @@ -24,7 +24,7 @@ "backgrounds092014": "SET 4: Lansat în septembrie 2014", "backgroundThunderstormText": "Furtună", "backgroundThunderstormNotes": "Transmite fulgere într-o furtună.", - "backgroundAutumnForestText": "Pădure de toamnă", + "backgroundAutumnForestText": "Pădure tomnatică", "backgroundAutumnForestNotes": "Cutreieră o pădure tomnatică", "backgroundHarvestFieldsText": "Câmpuri de recoltă", "backgroundHarvestFieldsNotes": "Cultivă-ți câmpurile de recoltă.", @@ -114,16 +114,16 @@ "backgroundTavernNotes": "Vizitează Cârciuma Habitica.", "backgrounds102015": "SET 17: Lansat în Octombrie 2015", "backgroundHarvestMoonText": "Luna recoltei", - "backgroundHarvestMoonNotes": "Cackle under the Harvest Moon.", - "backgroundSlimySwampText": "Slimy Swamp", - "backgroundSlimySwampNotes": "Slog through a Slimy Swamp.", - "backgroundSwarmingDarknessText": "Swarming Darkness", - "backgroundSwarmingDarknessNotes": "Shiver in the Swarming Darkness.", - "backgrounds112015": "SET 18: Released November 2015", - "backgroundFloatingIslandsText": "Floating Islands", - "backgroundFloatingIslandsNotes": "Hop across the Floating Islands.", - "backgroundNightDunesText": "Night Dunes", - "backgroundNightDunesNotes": "Walk peacefully through the Night Dunes.", - "backgroundSunsetOasisText": "Sunset Oasis", - "backgroundSunsetOasisNotes": "Bask in the Sunset Oasis." + "backgroundHarvestMoonNotes": "Chicotește sub luna tomnatică", + "backgroundSlimySwampText": "Mlaștină noroioasă", + "backgroundSlimySwampNotes": "Târăște-te prin mlaștina noroioasă", + "backgroundSwarmingDarknessText": "Întunecime roitoare", + "backgroundSwarmingDarknessNotes": "Dârdâie-ți dinții prin întunecimea roitoare", + "backgrounds112015": "SET 18: Lansat în noiembrie 2015", + "backgroundFloatingIslandsText": "Insule plutitoare", + "backgroundFloatingIslandsNotes": "Țopăie printre insulele plutitoare", + "backgroundNightDunesText": "Dunele nopții", + "backgroundNightDunesNotes": "Mergi lejer printre dunele nopții", + "backgroundSunsetOasisText": "Oaza de la apus", + "backgroundSunsetOasisNotes": "Lenevește prin oaza de la apus" } \ No newline at end of file diff --git a/common/locales/ro/challenge.json b/common/locales/ro/challenge.json index 71f55c07dc..cc7158e0cc 100644 --- a/common/locales/ro/challenge.json +++ b/common/locales/ro/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "You don't have permissions to edit this challenge", "noPermissionDeleteChallenge": "You don't have permissions to delete this challenge", "noPermissionCloseChallenge": "You don't have permissions to close this challenge", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "no owner", "noChallengeOwnerPopover": "This challenge does not have an owner because the person who created the challenge deleted their account." } \ No newline at end of file diff --git a/common/locales/ro/character.json b/common/locales/ro/character.json index 8a9f71424e..1ea9c7fd67 100644 --- a/common/locales/ro/character.json +++ b/common/locales/ro/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Has upgraded to the maximum weapon and armor set for the following classes:", "level": "Nivel", "levelUp": "Creștere de nivel!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "PV", "mp": "PM", diff --git a/common/locales/ro/content.json b/common/locales/ro/content.json index 364f745481..b01fe7fbc1 100644 --- a/common/locales/ro/content.json +++ b/common/locales/ro/content.json @@ -1,25 +1,25 @@ { - "potionText": "Poțiune de sănătate", + "potionText": "Licoare de sănătate", "potionNotes": "Vindecă 15 puncte de sănătate (instantaneu)", - "armoireText": "Enchanted Armoire", - "armoireNotesFull": "Open the Armoire to randomly receive special Equipment, Experience, or food! Equipment pieces remaining:", - "armoireLastItem": "You've found the last piece of rare Equipment in the Enchanted Armoire.", - "armoireNotesEmpty": "The Armoire will have new Equipment in the first week of every month. Until then, keep clicking for Experience and Food!", + "armoireText": "Șifonier fermecat", + "armoireNotesFull": "Deschide șifonierul pentru a primi la întâmplare echipament, experiență sau mâncare! Piesele de echipament rămase:", + "armoireLastItem": "Ai găsit ultima piesă de echipament rar din șifonierul fermecat.", + "armoireNotesEmpty": "Șifonierul va avea noi echipamente în prima săptămână a fiecărei luni. Până atunci, continuă să faci clic pentru experiență și mâncare!", "dropEggWolfText": "Lup", "dropEggWolfMountText": "Lup", "dropEggWolfAdjective": "loial", "dropEggTigerCubText": "Pui de tigru", "dropEggTigerCubMountText": "Tigru", - "dropEggTigerCubAdjective": "a fierce", + "dropEggTigerCubAdjective": "feroce", "dropEggPandaCubText": "Pui de Panda", "dropEggPandaCubMountText": "Panda", - "dropEggPandaCubAdjective": "a gentle", + "dropEggPandaCubAdjective": "blând", "dropEggLionCubText": "Pui de leu", "dropEggLionCubMountText": "Leu", "dropEggLionCubAdjective": "regal", "dropEggFoxText": "Vulpoi", "dropEggFoxMountText": "Vulpoi", - "dropEggFoxAdjective": "a wily", + "dropEggFoxAdjective": "șiret", "dropEggFlyingPigText": "Porc zburător", "dropEggFlyingPigMountText": "Porc zburător", "dropEggFlyingPigAdjective": "năbădăios", @@ -28,90 +28,93 @@ "dropEggDragonAdjective": "măreţ", "dropEggCactusText": "Cactus", "dropEggCactusMountText": "Cactus", - "dropEggCactusAdjective": "a prickly", + "dropEggCactusAdjective": "spinos", "dropEggBearCubText": "Pui de urs", "dropEggBearCubMountText": "Urs", - "dropEggBearCubAdjective": "a cuddly", + "dropEggBearCubAdjective": "drăgălaș", "questEggGryphonText": "Grifon", "questEggGryphonMountText": "Grifon", - "questEggGryphonAdjective": "a proud", + "questEggGryphonAdjective": "mândru", "questEggHedgehogText": "Arici", - "questEggHedgehogMountText": "Hedgehog", - "questEggHedgehogAdjective": "a spiky", + "questEggHedgehogMountText": "Arici", + "questEggHedgehogAdjective": "țepos", "questEggDeerText": "Cerb", - "questEggDeerMountText": "Deer", - "questEggDeerAdjective": "an elegant", + "questEggDeerMountText": "Căprioară", + "questEggDeerAdjective": "elegantă", "questEggEggText": "Ou", "questEggEggMountText": "Egg Basket", - "questEggEggAdjective": "a colorful", + "questEggEggAdjective": "colorat", "questEggRatText": "Șobolan", - "questEggRatMountText": "Rat", - "questEggRatAdjective": "a dirty", - "questEggOctopusText": "Octopus", - "questEggOctopusMountText": "Octopus", - "questEggOctopusAdjective": "a slippery", + "questEggRatMountText": "Șobolan", + "questEggRatAdjective": "murdar", + "questEggOctopusText": "Caracatiță", + "questEggOctopusMountText": "Caracatiță", + "questEggOctopusAdjective": "alunecoasă", "questEggSeahorseText": "Căluț de mare", - "questEggSeahorseMountText": "Seahorse", - "questEggSeahorseAdjective": "a prize", + "questEggSeahorseMountText": "Căluț de mare", + "questEggSeahorseAdjective": "premiant", "questEggParrotText": "Papagal", - "questEggParrotMountText": "Parrot", - "questEggParrotAdjective": "a vibrant", + "questEggParrotMountText": "Papagal", + "questEggParrotAdjective": "vioi", "questEggRoosterText": "Cocoș", - "questEggRoosterMountText": "Rooster", - "questEggRoosterAdjective": "a strutting", + "questEggRoosterMountText": "Cocoș", + "questEggRoosterAdjective": "țanțoș", "questEggSpiderText": "Păianjen", - "questEggSpiderMountText": "Spider", - "questEggSpiderAdjective": "a creepy", - "questEggOwlText": "Owl", - "questEggOwlMountText": "Owl", - "questEggOwlAdjective": "a wise", + "questEggSpiderMountText": "Păianjen", + "questEggSpiderAdjective": "fioros", + "questEggOwlText": "Bufniță", + "questEggOwlMountText": "Bufniță", + "questEggOwlAdjective": "înțeleaptă", "questEggPenguinText": "Pinguin", - "questEggPenguinMountText": "Penguin", - "questEggPenguinAdjective": "a perspicacious", - "questEggTRexText": "Tyrannosaur", - "questEggTRexMountText": "Tyrannosaur", - "questEggTRexAdjective": "a tiny-armed", - "questEggRockText": "Rock", - "questEggRockMountText": "Rock", - "questEggRockAdjective": "a lively", - "questEggBunnyText": "Bunny", - "questEggBunnyMountText": "Bunny", - "questEggBunnyAdjective": "a snuggly", - "questEggSlimeText": "Marshmallow Slime", - "questEggSlimeMountText": "Marshmallow Slime", - "questEggSlimeAdjective": "a sweet", - "questEggSheepText": "Sheep", - "questEggSheepMountText": "Sheep", - "questEggSheepAdjective": "a woolly", - "questEggCuttlefishText": "Cuttlefish", - "questEggCuttlefishMountText": "Cuttlefish", - "questEggCuttlefishAdjective": "a cuddly", - "questEggWhaleText": "Whale", - "questEggWhaleMountText": "Whale", - "questEggWhaleAdjective": "a splashy", - "questEggCheetahText": "Cheetah", - "questEggCheetahMountText": "Cheetah", - "questEggCheetahAdjective": "an honest", - "questEggHorseText": "Horse", - "questEggHorseMountText": "Horse", - "questEggHorseAdjective": "a galloping", - "questEggFrogText": "Frog", - "questEggFrogMountText": "Frog", - "questEggFrogAdjective": "a princely", - "eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into <%= eggAdjective(locale) %> <%= eggText(locale) %>.", + "questEggPenguinMountText": "Pinguin", + "questEggPenguinAdjective": "perspicace", + "questEggTRexText": "Tiranozaur", + "questEggTRexMountText": "Tiranozaur", + "questEggTRexAdjective": "cu brațe minuscule", + "questEggRockText": "Piatră", + "questEggRockMountText": "Piatră", + "questEggRockAdjective": "vioaie", + "questEggBunnyText": "Iepuraș", + "questEggBunnyMountText": "Iepuraș", + "questEggBunnyAdjective": "drăgălaș", + "questEggSlimeText": "Bezele lipicioase", + "questEggSlimeMountText": "Bezele lipicioase", + "questEggSlimeAdjective": "o bomboană", + "questEggSheepText": "Oaie", + "questEggSheepMountText": "Oaie", + "questEggSheepAdjective": "lânoasă", + "questEggCuttlefishText": "Sepie", + "questEggCuttlefishMountText": "Sepie", + "questEggCuttlefishAdjective": "drăgălașă", + "questEggWhaleText": "Balenă", + "questEggWhaleMountText": "Balenă", + "questEggWhaleAdjective": "pleoscăindă", + "questEggCheetahText": "Ghepard", + "questEggCheetahMountText": "Ghepard", + "questEggCheetahAdjective": "onest", + "questEggHorseText": "Cal", + "questEggHorseMountText": "Cal", + "questEggHorseAdjective": "galopant", + "questEggFrogText": "Broască", + "questEggFrogMountText": "Broască", + "questEggFrogAdjective": "princiară", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", + "eggNotes": "Găsește o licoare de eclozat pentru a turna peste acest ou și va ecloza în <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "de bază", "hatchingPotionWhite": "Alb", - "hatchingPotionDesert": "de Deșert", + "hatchingPotionDesert": "Deșert", "hatchingPotionRed": "Roșu", - "hatchingPotionShade": "Fantomă", + "hatchingPotionShade": "Umbră", "hatchingPotionSkeleton": "Schelet", "hatchingPotionZombie": "Zombi", - "hatchingPotionCottonCandyPink": "roz bombon", - "hatchingPotionCottonCandyBlue": "bleo", + "hatchingPotionCottonCandyPink": "Roz bombon", + "hatchingPotionCottonCandyBlue": "Bleu", "hatchingPotionGolden": "Auriu", - "hatchingPotionSpooky": "Spooky", - "hatchingPotionNotes": "Pour this on an egg, and it will hatch as a <%= potText(locale) %> pet.", - "premiumPotionAddlNotes": "Not usable on quest pet eggs.", + "hatchingPotionSpooky": "Înfricoșător", + "hatchingPotionNotes": "Toarnă aceasta pe un ou și va ecloza ca un companion <%= potText(locale) %>.", + "premiumPotionAddlNotes": "Neutilizabil pe ouă de companioni obținute din expediții.", "foodMeat": "Carne", "foodMilk": "Lapte", "foodPotatoe": "Cartof", diff --git a/common/locales/ro/faq.json b/common/locales/ro/faq.json index 806c5fd29f..291c6f779d 100644 --- a/common/locales/ro/faq.json +++ b/common/locales/ro/faq.json @@ -6,9 +6,9 @@ "faqQuestion1": "Cum îmi setez sarcinile?", "iosFaqAnswer1": "Bunele obiceiuri (acelea marcate cu +) sunt sarcini pe care le poți efectua de mai multe ori pe zi, cum ar fi mâncatul legumelor. Proastele obiceiuri (cele marcate cu -) sunt sarcini pe care trebuie să le eviți, ca mâncatul unghiilor. Obiceiurile marcate cu + și - au asociate o alegere bună și o alegere proastă, cum ar fi mersul pe scări vs. mersul cu liftul. Bunele obiceiuri te răsplătesc cu experiență și aur. Proastele obiceiuri îți scad sănătatea.\n\nSarcinile zilnice sunt sarcini pe care le poți face în fiecare zi, cum ar fi spălatul pe dinți sau verificarea e-mailului. Poți ajusta zilele în care o sarcină trebuie efectuată printr-o apăsare pe aceasta pentru a o edita. Dacă sari peste o sarcină zilnică ce trebuie efectuată, avatarul va pierde sănătate peste noapte. Ai grijă să nu adaugi prea multe sarcini zilnice în același timp.\n\n„De făcut” este lista ta de sarcini de făcut. Prin completarea acestor sarcini câștigi aur și experiență. Nu pierzi niciodată sănătate prin nerealizarea acestor sarcini. Poți adăuga date limită pentru o sarcină „de făcut” prin atingerea acesteia pentru a o edita.", "webFaqAnswer1": "Obiceiurile bune (marcate cu ) sunt sarcini care pot fi realizate de mai multe ori pe zi, cum ar fi mâncatul legumelor. Obiceiurile proaste (marcate cu ) sunt sarcini pe care ar trebui să le eviți, cum ar fi mâncatul unghiilor. Obiceiurile marcate cu și au asociate o alegere bună și un a proastă, cum ar fi mersul pe scări vs. mersul cu liftul. Obiceiurile bune te răsplătesc cu experiență și aur iar obiceiurile proaste îți scad sănătatea.\n

\nSarcinile zilnice sunt sarcini pe care le poți face în fiecare zi, cum ar fi spălatul pe dinți sau verificarea e-mailului. Poți ajusta zilele în care trebuie realizată o sarcină zilnică printr-un clic pe iconița cu creion pentru a o edita. Dacă sari peste o sarcină zilnică ce trebuie realizată în acea zi, avatarul tău se va deteriora peste noapte. Ai grijă să nu adaugi prea multe sarcini zilnice în același timp.\n

\n „De făcut” sunt lista de sarcini de realizat. Prin completarea acestora câștigi aur și experiență. Nu pierzi niciodată sănătate prin nerealizarea acestor sarcini. Poți adăuga o dată limită pentru o sarcină „de făcut” printr-un clic pe iconița creion pentru a o edita.", - "faqQuestion2": "Care ar fi niște sarcini de încercat?", - "iosFaqAnswer2": "The wiki has four lists of sample tasks to use as inspiration:\n

\n * [Sample Habits](http://habitica.wikia.com/wiki/Sample_Habits)\n * [Sample Dailies](http://habitica.wikia.com/wiki/Sample_Dailies)\n * [Sample To-Dos](http://habitica.wikia.com/wiki/Sample_To-Dos)\n * [Sample Custom Rewards](http://habitica.wikia.com/wiki/Sample_Custom_Rewards)", - "webFaqAnswer2": "The wiki has four lists of sample tasks to use as inspiration:\n * [Sample Habits](http://habitica.wikia.com/wiki/Sample_Habits)\n * [Sample Dailies](http://habitica.wikia.com/wiki/Sample_Dailies)\n * [Sample To-Dos](http://habitica.wikia.com/wiki/Sample_To-Dos)\n * [Sample Custom Rewards](http://habitica.wikia.com/wiki/Sample_Custom_Rewards)", + "faqQuestion2": "Care ar fi niște sarcini exemplu?", + "iosFaqAnswer2": "Wiki-ul are patru liste de sarcini exemplu de folosit ca inspirație:\n

\n * [Exemple de obiceiuri](http://habitica.wikia.com/wiki/Sample_Habits)\n * [Exemple de sarcini zilnice](http://habitica.wikia.com/wiki/Sample_Dailies)\n * [Exemple de sarcini de făcut](http://habitica.wikia.com/wiki/Sample_To-Dos)\n * [Exemple de recompense particularizate](http://habitica.wikia.com/wiki/Sample_Custom_Rewards)", + "webFaqAnswer2": "Wiki-ul are patru liste de sarcini exemplu de folosit ca inspirație:\n * [Exemple de obiceiuri](http://habitica.wikia.com/wiki/Sample_Habits)\n * [Exemple de sarcini zilnice](http://habitica.wikia.com/wiki/Sample_Dailies)\n * [Exemple de sarcini de făcut](http://habitica.wikia.com/wiki/Sample_To-Dos)\n * [Exemple de recompense particularizate](http://habitica.wikia.com/wiki/Sample_Custom_Rewards)", "faqQuestion3": "De ce își schimbă culorile sarcinile mele?", "iosFaqAnswer3": "Sarcinile tale își schimbă culoarea pe baza a cât de bine le realizezi! Fiecare nouă sarcină începe c o culoare galben neutru. Întreprinde sarcini zilnice sau obiceiuri pozitive mai frecvent și culoarea se va schimba mai mult înspre albastru. Ratează o sarcină zilnică, sau cedează în fața tentației unui obicei prost și sarcina culoarea se va schimba înspre roșu. Cu cât e mai roșie o sarcină, cu atât te va recompensa mai mult, dar dacă este vorba de o sarcină zilnică sau obicei prost, cu atât mai mult te va răni! Aceasta te va motiva să completezi sarcinile care îți pun probleme.", "webFaqAnswer3": "Sarcinile tale își schimbă culoarea pe baza a cât de bine le completezi în acel moment! Fiecare sarcină nouă începe cu o culoare galben neutru. Întreprinde sarcini zilnice sau obiceiuri pozitive mai frecvent și culoarea se va schimba mai mult înspre albastru. Ratează o sarcină zilnică sau cedează în fața tentației unui obicei prost iar culoarea se va schimba înspre roșu. Cu cât e mai roșie o sarcină, cu atât te va recompensa mai mult, dar dacă este vorba de o sarcină zilnică sau un obicei prost, cu atât mai mult te va râni! Aceasta te va motiva să completezi sarcinile care îți pun probleme.", @@ -16,11 +16,11 @@ "iosFaqAnswer4": "Mai multe lucruri te pot răni. În primul rând, sarcinile zilnice necompletate te vor răni peste noapte. În al doilea rând, dacă întreprinzi un obicei prost, aceasta te va răni. În fine, dacă ești într-o bătălie cu un Super Monstru și unul din colegii de ceată nu își completează sarcinile zilnice, Super Monstrul te va ataca.\n\n Metoda principală de a te vindeca este câștigarea unui nivel, ceea ce reface complet sănătatea. Poți cumpăra și o licoare de sănătate cu aur din coloana de Răsplăți. În plus, la nivelul 10 sau mai sus, poți alege să devii Vrăciuitor (vindecător), iar apoi vei învăța abilități de vindecare. Dacă ești într-o ceată ce conține un vrăciuitor, aceștia te pot vindeca și pe tine.", "webFaqAnswer4": "Mai multe lucruri te pot răni. În primul rând, sarcinile zilnice necompletate te vor răni peste noapte. În al doilea rând, dacă întreprinzi un obicei prost, aceasta te va răni. În fine, dacă ești într-o bătălie cu un Super Monstru și unul din colegii de ceată nu își completează sarcinile zilnice, Super Monstrul te va ataca.\n

\n Metoda principală de a te vindeca este câștigarea unui nivel, ceea ce reface complet sănătatea. Poți cumpăra și o licoare de sănătate cu aur din coloana de Răsplăți. În plus, la nivelul 10 sau mai sus, poți alege să devii Vrăciuitor (vindecător), iar apoi vei învăța abilități de vindecare. Dacă ești într-o ceată ce conține un vrăciuitor, aceștia te pot vindeca și pe tine.", "faqQuestion5": "Cum joc Habitica cu prietenii mei?", - "iosFaqAnswer5": "The best way is to invite them to a Party with you! Parties can go on quests, battle monsters, and cast skills to support each other. Go to Menu > Party and click \"Create New Party\" if you don't already have a Party. Then tap on the Members list, and tap Invite in the upper right-hand corner to invite your friends by entering their User ID (a string of numbers and letters that they can find under Settings > Account Details on the app, and Settings > API on the website). On the website, you can also invite friends via email, which we will add to the app in a future update.\n\nOn the website, you and your friends can also join Guilds, which are public chat rooms. Guilds will be added to the app in a future update!", + "iosFaqAnswer5": "Cea mai bună metodă este să-i inviți într-o ceată cu tine! Cetele pot merge în expediții, lupta cu monștri și pot face vrăji pentru a se susține reciproc. Mergi la Meniu > Ceată și clic pe „Creează o nouă ceată” dacă nu ai deja o ceată activă. Apoi apasă pe lista de membri și apasă pe „Invită” în colțul din dreapta sus pentru a invita prieteni prin introducerea ID-urilor lor de utilizatori (un șir de numere și litere pe care le găsești în Setări > Detalii cont în aplicație și Setări > API pe site-ul web). Pe site poți invita prieteni și prin intermediul e-mailului, o funcție pe care o vom adăuga și aplicației într-o actualizare viitoare.\n\nPe site, tu și prietenii tăi vă puteți alătura și breslelor, care sunt camere de chat publice. Breslele vor fi adăugate aplicației într-o actualizare viitoare!", "webFaqAnswer5": "Cea mai bună metodă este să-i inviți într-o ceată cu tine în meniul Social > Ceată! Cetele pot merge în expediții, se pot lupta cu monștri și pot activa abilități pentru a se susține reciproc. Puteți să vă alăturați împreună și breslelor (Social > Bresle). Breslele sunt camere de chat axate pe interese comune și pot fi publice sau private. Poți să te alături oricâtor bresle vrei, dar unei singure cete la un moment dat.\n

\n Pentru informații mai detaliate, citește paginile de wiki despre [Cete](http://habitrpg.wikia.com/wiki/Party) și [Bresle](http://habitrpg.wikia.com/wiki/Guilds).", "faqQuestion6": "Cum pot obține un companion sau bidiviu (mount)?", "iosFaqAnswer6": "La nivelul 3 vei descuia sistemul de drop. De fiecare dată când completezi o sarcină ai o șansă să-ți pice un ou, o licoare de eclozat sau mâncare. Acestea sunt stocate în Meniu > Articole.\n\n Pentru a ecloza un companion, ai nevoie de un ou și o licoare de eclozat. Apasă pe ou pentru a stabili specia pe care vrei să o eclozezi și selectează „Eclozează oul”. Apoi alege licoarea de eclozat pentru a stabili culoarea acestuia. mergi la Meniu > Compaioni pentru a adăuga noul companion avatarului tău printr-un clic pe acesta.\n\n Poți să și crești companionii în bidivii (mounts) dacă îi hrănești - Meniu > Companioni, apoi selectează „Hrănește companion”! Va trebui să hrănești un companion de multe ori înainte ca acesta să devină bidiviu, dar dacă afli care e mâncarea sa preferată, acesta va crește mai repede. Poți afla prin încercarea repetată sau [poți vedea spoilerele aici](http://habitica.wikia.com/wiki/Food#Food_Preferences). Odată ce ai un bidiviu, mergi la Meniu > Bidivii și apasă pe acesta pentru a-l adăuga avatarului.\n\n Poți obține ouă pentru companioni de expediție prin completarea anumitor expediții. (Vezi mai jos pentru a afla mai multe despre expediții.)", - "webFaqAnswer6": "At level 3, you will unlock the Drop System. Every time you complete a task, you'll have a random chance at receiving an egg, a hatching potion, or a piece of food. They will be stored in Inventory > Market.\n

\n To hatch a Pet, you'll need an egg and a hatching potion. Click on the egg to determine the species you want to hatch, and then click on the hatching potion to determine its color! Go to Inventory > Pets to equip it to your avatar by clicking on it.\n

\n You can also grow your Pets into Mounts by feeding them under Inventory > Pets. Click on a Pet, and then click on a piece of food from the right-hand menu to feed it! You'll have to feed a pet many times before it becomes a Mount, but if you can figure out its favorite food, it will grow more quickly. Use trial and error, or [see the spoilers here](http://habitica.wikia.com/wiki/Food#Food_Preferences). Once you have a Mount, go to Inventory > Mounts and click on it to equip it to your avatar.\n

\n You can also get eggs for Quest Pets by completing certain Quests. (See below to learn more about Quests.)", + "webFaqAnswer6": "La nivelul 3 vei descuia sistemul de drop. De fiecare dată când completezi o sarcină ai o șansă să-ți pice un ou, o licoare de eclozat sau mâncare. Acestea sunt stocate în Meniu > Articole.\n

\n Pentru a ecloza un companion, ai nevoie de un ou și o licoare de eclozat. Apasă pe ou pentru a stabili specia pe care vrei să o eclozezi și selectează „Eclozează oul”. Apoi alege licoarea de eclozat pentru a stabili culoarea acestuia. mergi la Meniu > Compaioni pentru a adăuga noul companion avatarului tău printr-un clic pe acesta.\n

\n Poți să și crești companionii în bidivii (mounts) dacă îi hrănești - Meniu > Companioni, apoi selectează „Hrănește companion”! Va trebui să hrănești un companion de multe ori înainte ca acesta să devină bidiviu, dar dacă afli care e mâncarea sa preferată, acesta va crește mai repede. Poți afla prin încercarea repetată sau [poți vedea spoilerele aici](http://habitica.wikia.com/wiki/Food#Food_Preferences). Odată ce ai un bidiviu, mergi la Meniu > Bidivii și apasă pe acesta pentru a-l adăuga avatarului.\n

\n Poți obține ouă pentru companioni de expediție prin completarea anumitor expediții. (Vezi mai jos pentru a afla mai multe despre expediții.)", "faqQuestion7": "Cum pot deveni războinic, mag, bandit sau vrăciuitor?", "iosFaqAnswer7": "At level 10, you can choose to become a Warrior, Mage, Rogue, or Healer. (All players start as Warriors by default.) Each Class has different equipment options, different Skills that they can cast after level 11, and different advantages. Warriors can easily damage Bosses, withstand more damage from their tasks, and help make their Party tougher. Mages can also easily damage Bosses, as well as level up quickly and restore Mana for their party. Rogues earn the most gold and find the most item drops, and they can help their Party do the same. Finally, Healers can heal themselves and their Party members.\n\n If you don't want to choose a Class immediately -- for example, if you are still working to buy all the gear of your current class -- you can click “Decide Later” and choose later under Menu > Choose Class.", "webFaqAnswer7": "At level 10, you can choose to become a Warrior, Mage, Rogue, or Healer. (All players start as Warriors by default.) Each Class has different equipment options, different Skills that they can cast after level 11, and different advantages. Warriors can easily damage Bosses, withstand more damage from their tasks, and help make their party tougher. Mages can also easily damage Bosses, as well as level up quickly and restore Mana for their party. Rogues earn the most Gold and find the most item drops, and they can help their party do the same. Finally, Healers can heal themselves and their party members.\n

\n If you don't want to choose a Class immediately -- for example, if you are still working to buy all the gear of your current class -- you can click \"Opt Out\" and re-enable it later under User > Stats.", @@ -36,7 +36,7 @@ "faqQuestion11": "Cum raportez un defect sau cer o funcționalitate?", "iosFaqAnswer11": "Poți raporta un defect, solicita o funcționalitate sau poți trimite feedback în dreptul Meniu > Raportează un defect și Meniu > Trimite feedback! Vom face tot ce putem pentru a te ajuta.", "webFaqAnswer11": "Rapoartele de defecte sunt colectate pe GitHub. Mergi la [Ajutor > Raportează un defect](https://github.com/HabitRPG/habitrpg/issues/2760) și urmează instrucțiunile. Nu-ți fă griji, le vom repare în curând!\n

\nCererile de funcționalitate sunt colectate pe Trello. Mergi la [Ajutor > Solicită o funcționalitate](https://trello.com/c/odmhIqyW/440-read-first-table-of-contents) și urmează instrucțiunile. Ta-da!", - "faqQuestion12": "How do I battle a World Boss?", + "faqQuestion12": "Cum mă lupt cu un căpcăun șef?", "iosFaqAnswer12": "World Bosses are special monsters that appear in the Tavern. All active users are automatically battling the Boss, and their tasks and skills will damage the Boss as usual.\n\n You can also be in a normal Quest at the same time. Your tasks and skills will count towards both the World Boss and the Boss/Collection Quest in your party.\n\n A World Boss will never hurt you or your account in any way. Instead, it has a Rage Bar that fills when users skip Dailies. If its Rage bar fills, it will attack one of the Non-Player Characters around the site and their image will change.\n\n You can read more about [past World Bosses](http://habitica.wikia.com/wiki/World_Bosses) on the wiki.", "webFaqAnswer12": "World Bosses are special monsters that appear in the Tavern. All active users are automatically battling the Boss, and their tasks and skills will damage the Boss as usual.\n

\n You can also be in a normal Quest at the same time. Your tasks and skills will count towards both the World Boss and the Boss/Collection Quest in your party.\n

\n A World Boss will never hurt you or your account in any way. Instead, it has a Rage Bar that fills when users skip Dailies. If its Rage bar fills, it will attack one of the Non-Player Characters around the site and their image will change.\n

\n You can read more about [past World Bosses](http://habitica.wikia.com/wiki/World_Bosses) on the wiki.", "iosFaqStillNeedHelp": "Dacă ai o întrebare ce nu este pe listă, vino și întreabă în chat-ul de pe Cârciumă în dreptul Meniu > Cârciumă! Suntem bucuroși să fim de ajutor.", diff --git a/common/locales/ro/front.json b/common/locales/ro/front.json index 69557fa5b5..8e29a7978a 100644 --- a/common/locales/ro/front.json +++ b/common/locales/ro/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] has really helped me impart structure to my life in graduate school.", "invalidEmail": "Este necesară o adresă validă de email pentru a reseta parola.", "irishfeet123Quote": "I've had horrible habits with clearing my place completely after meals and leaving cups all over the place. [Habitica] has cured that!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Before [Habitica], I was stuck with my thesis, as well as dissatisfied with my personal discipline regarding housework and things like learning vocabulary and studying Go theory. It turns out breaking down these tasks into smaller manageable checklists is quite the thing to keep me motivated and constantly working.", "landingadminlink": "pachetele administrative", "landingend": "Încă nu te-ai convins?", @@ -182,5 +182,11 @@ "tweet": "Tweet", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/ro/generic.json b/common/locales/ro/generic.json index 2a3bb5847b..ad23abb7fb 100644 --- a/common/locales/ro/generic.json +++ b/common/locales/ro/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Sending you a thousand thanks.", "thankyou3": "I'm very grateful - thank you!", "thankyouCardAchievementTitle": "Greatly Grateful", - "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards." + "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/ro/messages.json b/common/locales/ro/messages.json index 421259751e..b1b1f57adf 100644 --- a/common/locales/ro/messages.json +++ b/common/locales/ro/messages.json @@ -1,11 +1,11 @@ { "messageLostItem": "Ți s-a stricat <%= itemText %>.", "messageTaskNotFound": "Țelul nu a fost găsit.", - "messageDuplicateTaskID": "A task with that ID already exists.", + "messageDuplicateTaskID": "Există deja o sarcină cu acel ID.", "messageTagNotFound": "Eticheta nu a fost găsită.", "messagePetNotFound": ":pet nu a fost găsit în user.items.pets", "messageFoodNotFound": ":food nu a fost găsit în user.items.food", - "messageNotAvailable": "This item is not currently available for purchase.", + "messageNotAvailable": "Acest articol nu poate fi cumpărat momentan.", "messageCannotFeedPet": "Nu poți hrăni acest companion.", "messageAlreadyMount": "Ai deja acest animal de călărit. Încearcă să hrănești alt companion.", "messageEvolve": "Ai îmblînzit <%= egg %>, hai să mergem la o plimbare!", @@ -15,7 +15,7 @@ "messageEquipped": "<%= itemText %> echipat.", "messageUnEquipped": "<%= itemText %> dezechipat.", "messageMissingEggPotion": "Îți lipsește ori oul ori poțiunea necesară", - "messageInvalidEggPotionCombo": "You can't hatch Quest Pet Eggs with Magic Hatching Potions! Try a different egg.", + "messageInvalidEggPotionCombo": "Nu poți ecloza ouă de companioni de expediție fără licori magice de eclozare! Încearcă un alt ou.", "messageAlreadyPet": "Deja ai acest companion. Încearcă o altă combinație pentru eclozare!", "messageHatched": "Oul tău a eclozat! Vizitează grajdul pentru a-ți lua noul companion.", "messageNotEnoughGold": "Nu ai destul aur", @@ -23,33 +23,33 @@ "messageDropFood": "Ai găsit <%= dropArticle %><%= dropText %>! <%= dropNotes %>", "messageDropEgg": "Ai găsit un Ou <%= dropText %>! <%= dropNotes %>", "messageDropPotion": "Ai găsit o poțiune de eclozare <%= dropText %>! <%= dropNotes %>", - "messageDropQuest": "You've found a quest!", - "messageDropMysteryItem": "You open the box and find <%= dropText %>!", + "messageDropQuest": "Ai găsit o expediție!", + "messageDropMysteryItem": "Deschizi cutia și găsești <%= dropText %>!", "messageFoundQuest": "Ai găsit aventura \"<%= questText %>\"!", - "messageAlreadyPurchasedGear": "You purchased this gear in the past, but do not currently own it. You can buy it again in the rewards column on the tasks page.", - "messageAlreadyOwnGear": "You already own this item. Equip it by going to the equipment page.", - "armoireEquipment": "<%= image %> You found a piece of rare Equipment in the Armoire: <%= dropText %>! Awesome!", - "armoireFood": "<%= image %> You rummage in the Armoire and find <%= dropArticle %><%= dropText %>. What's that doing in here?", - "armoireExp": "You wrestle with the Armoire and gain Experience. Take that!", - "messageInsufficientGems": "Not enough gems!", - "messageAuthPasswordMustMatch": ":password and :confirmPassword don't match", - "messageAuthCredentialsRequired": ":username, :email, :password, :confirmPassword required", - "messageAuthUsernameTaken": "Username already taken", - "messageAuthEmailTaken": "Email already taken", - "messageAuthNoUserFound": "No user found.", - "messageAuthMustBeLoggedIn": "You must be logged in.", - "messageAuthMustIncludeTokens": "You must include a token and uid (user id) in your request", - "messageGroupNotFound": "Group not found or you don't have access.", - "messageGroupAlreadyInParty": "Already in a party, try refreshing.", - "messageGroupOnlyLeaderCanUpdate": "Only the group leader can update the group!", - "messageGroupRequiresInvite": "Can't join a group you're not invited to.", - "messageGroupCannotRemoveSelf": "You cannot remove yourself!", - "messageGroupChatBlankMessage": "You cannot send a blank message", - "messageGroupChatLikeOwnMessage": "Can't like your own message. Don't be that person.", - "messageGroupChatFlagOwnMessage": "Can't report your own message.", - "messageGroupChatFlagAlreadyReported": "You have already reported this message", - "messageGroupChatNotFound": "Message not found!", - "messageGroupChatAdminClearFlagCount": "Only an admin can clear the flag count!", - "messageUserOperationProtected": "path `<%= operation %>` was not saved, as it's a protected path.", - "messageUserOperationNotFound": "<%= operation %> operation not found" + "messageAlreadyPurchasedGear": "Ai cumpărat acest echipament în trecut, dar momentan nu-l deții. Poți să-l cumperi din nou în coloana de răsplăți pe pagina cu sarcini.", + "messageAlreadyOwnGear": "Deja deții acest articol. Echipează-l la pagina de echipamente.", + "armoireEquipment": "<%= image %> Ai găsit o piesă rară de echipament în șifonier: <%= dropText %>! Grozav!", + "armoireFood": "<%= image %> Ai răscolit prin șifonier și ai găsit <%= dropArticle %><%= dropText %>. Ce caută asta aici?", + "armoireExp": "Te-ai luptat cu șifonierul și ai câștigat experiență. Na!", + "messageInsufficientGems": "Nu ai destule nestemate!", + "messageAuthPasswordMustMatch": ":password și :confirmPassword nu se potrivesc", + "messageAuthCredentialsRequired": "sunt necesare :username, :email, :password și :confirmPassword", + "messageAuthUsernameTaken": "Numele de utilizator este deja folosit", + "messageAuthEmailTaken": "E-mailul este deja folosit", + "messageAuthNoUserFound": "Niciun utilizator găsit", + "messageAuthMustBeLoggedIn": "Trebuie să fii autentificat.", + "messageAuthMustIncludeTokens": "Trebuie să incluzi un token și uid (ID utilizator) în cererea ta", + "messageGroupNotFound": "Grup negăsit sau nu ai acces.", + "messageGroupAlreadyInParty": "Ești deja într-o ceată, reîmprospătează pagina.", + "messageGroupOnlyLeaderCanUpdate": "Doar șeful de grup poate actualiza grupul!", + "messageGroupRequiresInvite": "Nu te poți alătura unui grup în care nu ești invitat.", + "messageGroupCannotRemoveSelf": "Nu te poți elimina singur!", + "messageGroupChatBlankMessage": "Nu poți trimite un mesaj gol", + "messageGroupChatLikeOwnMessage": "Nu-ți poți aprecia propriul mesaj. Nu fi acea persoană.", + "messageGroupChatFlagOwnMessage": "Nu-ți poți raporta propriul mesaj.", + "messageGroupChatFlagAlreadyReported": "Ai raportat deja acest mesaj.", + "messageGroupChatNotFound": "Mesajul nu a fost găsit!", + "messageGroupChatAdminClearFlagCount": "Doar un administrator poate curăța numărul de atenționări!", + "messageUserOperationProtected": "calea `<%= operation %>` nu a fost salvată pentru că este protejată", + "messageUserOperationNotFound": "nu a fost găsită operațiunea <%= operation %>" } \ No newline at end of file diff --git a/common/locales/ro/pets.json b/common/locales/ro/pets.json index f788bb2456..c7b2e3b966 100644 --- a/common/locales/ro/pets.json +++ b/common/locales/ro/pets.json @@ -58,8 +58,16 @@ "firstDrop": "You've unlocked the Drop System! Now when you complete tasks, you have a small chance of finding an item, including eggs, potions, and food! You just found a <%= eggText %> Egg! <%= eggNotes %>", "useGems": "If you've got your eye on a pet, but can't wait any longer for it to drop, use Gems in Inventory > Market to buy one!", "hatchAPot": "Eclozezi <%= potion %> <%= egg %> ?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Hrănești <%= name %> cu <%= article %><%= text %>?", "useSaddle": "Înșeuezi <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= egg %> <%= potion %>", "mountName": "<%= mount %> <%= potion %>", "petKeyName": "Cheia Adăposturilor", diff --git a/common/locales/ro/quests.json b/common/locales/ro/quests.json index 05728771a5..39f3f53867 100644 --- a/common/locales/ro/quests.json +++ b/common/locales/ro/quests.json @@ -76,5 +76,7 @@ "startAQuest": "START A QUEST", "startQuest": "Start Quest", "whichQuestStart": "Which quest do you want to start?", - "getMoreQuests": "Get more quests" + "getMoreQuests": "Get more quests", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/ro/questscontent.json b/common/locales/ro/questscontent.json index 04d55ed771..30f95d4d98 100644 --- a/common/locales/ro/questscontent.json +++ b/common/locales/ro/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/ro/settings.json b/common/locales/ro/settings.json index e3bb67530c..f485b45fc8 100644 --- a/common/locales/ro/settings.json +++ b/common/locales/ro/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Cu această opțiune activată, lista de etichete a unui țel va fi ascunsă atunci când deschizi o sarcină pentru modificare.", "startAdvCollapsed": "Opțiunile avansate ale țelurilor sunt ascunse", "startAdvCollapsedPop": "Cu această opțiune activată, Opțiunile Avansate vor fi ascunse atunci când deschizi pentru prima oară un țel pentru modificare.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Arată Tur de prezentare", "restartTour": "Repornește turul introductiv prezentat când ai intrat prima oară în Habitica.", "showBailey": "Arat-o pe Bailey", @@ -81,7 +86,6 @@ "emailChange1": "To change your email address, please send an email to", "emailChange2": "admin@habitica.com", "emailChange3": "including both your old and new email address as well as your User ID.", - "username": "Login Name", "usernameOrEmail": "Login Name or Email", "email": "Email", "registeredWithFb": "Registered with Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "User->Profile", "loginNameDescription3": "to change the name that appears in your avatar and chat messages.", "emailNotifications": "Email Notifications", - "wonChallenge": "You Won a Challenge", + "wonChallenge": "You won a Challenge!", "newPM": "Received Private Message", "giftedGems": "Gifted Gems", "giftedGemsInfo": "<%= amount %> Gems - by <%= name %>", diff --git a/common/locales/ro/subscriber.json b/common/locales/ro/subscriber.json index 71346e8eb3..bf1c8f0546 100644 --- a/common/locales/ro/subscriber.json +++ b/common/locales/ro/subscriber.json @@ -1,20 +1,20 @@ { "subscription": "Abonament", "subscriptions": "Abonamente", - "subDescription": "Buy gems with gold, get monthly mystery items, retain progress history, double daily drop-caps, support the devs. Click for more info.", + "subDescription": "Cumpără nestemate cu aur, obține articole misterioase în fiecare lună, păstrează istoricul progresului, dublează limitele zilnice de picări, sprijină dezvoltatorii. Clic pentru mai multe informații.", "buyGemsGold": "Cumpără Nestemate cu Aur", - "buyGemsGoldText": "Alexander the Merchant will sell you gems at a cost of <%= gemCost %> gold per gem. His monthly shipments are initially capped at <%= gemLimit %> gems per month, but this cap increases by 5 gems for every three months of consecutive subscription, up to a maximum of 50 gems per month!", + "buyGemsGoldText": "Alexandru Negustoru îți va vinde nestematele la un preț de <%= gemCost %> aur pe nestemată. Livrările sale lunare sunt limitate inițial la <%= gemLimit %> nestemate pe lună, dar această limită crește cu câte 5 nestemate la fiecare trei luni de abonament consecuriv, până la un maxim de 50 de nestemate pe lună!", "retainHistory": "Reține tot istoricul", "retainHistoryText": "Face tot istoricul disponibil în grafice sau pentru export. Istoricul celor care nu sunt abonați este arhivat pentru optimizarea bazei de date.", "doubleDrops": "Limita maximă de obiecte câștigate este dublată", "doubleDropsText": "Umpleți grajdul mai repede!", "mysteryItem": "Obiecte unice pentru abonați lunar", - "mysteryItemText": "Each month you will receive a unique cosmetic item for your avatar! Plus, for every three months of consecutive subscription, the Mysterious Time Travelers will grant you access to historic (and futuristic!) cosmetic items.", - "supportDevs": "Susțineți dezvoltatorii", - "supportDevsText": "Your subscription helps keep Habitica thriving and helps fund the development of new features. Thank you for your generosity!", + "mysteryItemText": "În fiecare lună vei primi un articol unic cu rol cosmetic pentru avatarul tău! În plus, odată la fiecare trei luni de abonament consecutiv, misterioșii călători în timp îți vor acorda acces la articole cosmetice istorice (și futuriste!).", + "supportDevs": "Susține dezvoltatorii", + "supportDevsText": "Abonamentul tău permite Habiticei să prospere și ajută la dezvoltarea noilor funcționalități. Mulțumim pentru generozitate!", "monthUSD": "USD / Lună", "organization": "Organizație", - "groupPlans": "Corporate Plans", + "groupPlans": "Planuri corporatiste", "indivPlan1": "Habitica este gratuit pentru persoane fizice. Chiar și pentru grupuri mici, gratuit (sau ieftin)", "indivPlan2": "poate fi folosit pentru a motiva participanții în modificarea comportamentului. De exemplu cercuri literare de creație, provocări artistice și altele.", "groupText1": "Dar unii lideri de grup vor dori mai mult control, confidențialitate, securitate și asistență. Exemple de astfel de grupuri sunt: familii, grupuri de îngrijirea sănătății, grupuri de angajați și altele. Aceste abonamente furnizează copii private Habitica pentru grupul sau organizația dumneavoastră, sigure și independente de", @@ -27,7 +27,7 @@ "subscribe": "Abonare", "subscribed": "Abonat", "manageSub": "Apasă ca să gestionezi abonamentul", - "cancelSub": "Anulare abonament", + "cancelSub": "Anulează abonamentul", "adminSub": "Abonamente de administrator", "morePlans": "Mai multe abonamente
În curând", "organizationSub": "Organizație privată", diff --git a/common/locales/ru/challenge.json b/common/locales/ru/challenge.json index a76f27da7b..65460c1e44 100644 --- a/common/locales/ru/challenge.json +++ b/common/locales/ru/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "У вас нет прав на редактирование этого испытания.", "noPermissionDeleteChallenge": "У вас нет прав на удаление этого испытания.", "noPermissionCloseChallenge": "У вас нет прав на закрытие этого испытания.", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "нет владельца", "noChallengeOwnerPopover": "Это испытание не имеет владельца, потому что игрок, который его создал, удалил свой аккаунт." } \ No newline at end of file diff --git a/common/locales/ru/character.json b/common/locales/ru/character.json index 712a2d36d7..3dff519666 100644 --- a/common/locales/ru/character.json +++ b/common/locales/ru/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Полностью усовершенствовал(а) оружие и комплект доспехов для следующих классов:", "level": "Уровень", "levelUp": "Новый уровень!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Мана", "hp": "здоровья", "mp": "М", diff --git a/common/locales/ru/content.json b/common/locales/ru/content.json index 92fe0babf0..b72d11fb35 100644 --- a/common/locales/ru/content.json +++ b/common/locales/ru/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Лягушонок", "questEggFrogMountText": "Лягушонок", "questEggFrogAdjective": "царственный", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Найдите инкубационный эликсир, чтобы полить им это яйцо, и из него вылупится <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Обыкновенный", "hatchingPotionWhite": "Белый", diff --git a/common/locales/ru/front.json b/common/locales/ru/front.json index 8c7f4920b6..692e18f084 100644 --- a/common/locales/ru/front.json +++ b/common/locales/ru/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] действительно помогла мне организовать структурный подход к своей жизни во время учёбы в аспирантуре.", "invalidEmail": "Для изменения пароля необходимо указать существующий адрес электронной почты.", "irishfeet123Quote": "У меня была ужасная привычка не мыть за собой посуду после еды и оставлять везде кружки. [Habitica] полностью меня исправила!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "До [Habitica] работа с моей диссертацией никак не продвигалась. Кроме того, вызывала недовольство моя недисциплинированность в отношении домашних дел и таких задач, как изучение новых слов и обучение игре Го. Оказывается, разбивка этих задач на списки из небольших подзаданий – как раз то, что мне нужно, чтобы сохранять мотивацию и постоянную работоспособность.", "landingadminlink": "административные пакеты,", "landingend": "Еще не уверены?", @@ -182,5 +182,11 @@ "tweet": "Твитнуть", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/ru/generic.json b/common/locales/ru/generic.json index e1a91a32ed..2a734db49b 100644 --- a/common/locales/ru/generic.json +++ b/common/locales/ru/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Тысяча благодарностей!", "thankyou3": "Я очень признателен. Спасибо тебе!", "thankyouCardAchievementTitle": "Благодарный", - "thankyouCardAchievementText": "Спасибо за спасибо! Отправлено или получено <%= cards %> Благодарственных писем." + "thankyouCardAchievementText": "Спасибо за спасибо! Отправлено или получено <%= cards %> Благодарственных писем.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/ru/pets.json b/common/locales/ru/pets.json index 97f8ab0bdb..0b0e6dd872 100644 --- a/common/locales/ru/pets.json +++ b/common/locales/ru/pets.json @@ -58,8 +58,16 @@ "firstDrop": "Вы открыли систему выпадения предметов! Теперь, когда вы выполняете задания, у вас есть маленький шанс найти предмет, включая яйца, эликсиры и еду! Вы только что нашли <%= eggText %> в яйце! <%= eggNotes %>", "useGems": "Если вы хотите питомца, но не можете больше ждать, когда он выпадет, купите его за самоцветы в меню Инвентарь > Рынок!", "hatchAPot": "Вылупится <%= potion %> <%= egg %>. Использовать эликсир?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Скормить <%= article %><%= text %> вашему питомцу: <%= name %>?", "useSaddle": "Оседлать <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Ключ от Вольеров", diff --git a/common/locales/ru/quests.json b/common/locales/ru/quests.json index eecd2ef4c7..4cc03b1f9b 100644 --- a/common/locales/ru/quests.json +++ b/common/locales/ru/quests.json @@ -76,5 +76,7 @@ "startAQuest": "НАЧАТЬ КВЕСТ", "startQuest": "Начать квест", "whichQuestStart": "Какой квест вы хотите начать?", - "getMoreQuests": "Получить больше квестов" + "getMoreQuests": "Получить больше квестов", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/ru/questscontent.json b/common/locales/ru/questscontent.json index 3931dfb41e..01cfe21a87 100644 --- a/common/locales/ru/questscontent.json +++ b/common/locales/ru/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Лягушонок (Яйцо)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/ru/settings.json b/common/locales/ru/settings.json index fea2f2709d..972f4c306e 100644 --- a/common/locales/ru/settings.json +++ b/common/locales/ru/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Когда этот параметр включен, при открытии задания для редактирования список тегов будет отображаться в свернутом виде.", "startAdvCollapsed": "Раздел «Дополнительные параметры» в задачах свернут по умолчанию", "startAdvCollapsedPop": "Когда этот параметр включен, при открытии задания для редактирования раздел «Дополнительные параметры» будет отображаться в свернутом виде.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Показать тур", "restartTour": "Запустить ознакомительный тур, который вы видели, когда зарегистрировались на Habitica.", "showBailey": "Показать Бэйли", @@ -81,7 +86,6 @@ "emailChange1": "Чтобы изменить ваш email, пожалуйста, отправьте email на", "emailChange2": "admin@habitica.com", "emailChange3": "включая ваш старый и новый адреса электронной почты, а также ваш User ID", - "username": "Имя пользователя", "usernameOrEmail": "Имя пользователя или e-mail", "email": "Электронная почта", "registeredWithFb": "Зарегистрирован с помощью Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "Пользователь->Профиль", "loginNameDescription3": "чтобы изменить имя, которое появляется на вашем аватаре и в чате.", "emailNotifications": "Уведомления по электронной почте", - "wonChallenge": "Вы выиграли испытание", + "wonChallenge": "You won a Challenge!", "newPM": "Получено личное сообщение", "giftedGems": "Подаренные самоцветы", "giftedGemsInfo": "<%= amount %> самоцветов от <%= name %>", diff --git a/common/locales/sk/challenge.json b/common/locales/sk/challenge.json index 014b93d8c1..b499fd1143 100644 --- a/common/locales/sk/challenge.json +++ b/common/locales/sk/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "You don't have permissions to edit this challenge", "noPermissionDeleteChallenge": "You don't have permissions to delete this challenge", "noPermissionCloseChallenge": "You don't have permissions to close this challenge", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "no owner", "noChallengeOwnerPopover": "This challenge does not have an owner because the person who created the challenge deleted their account." } \ No newline at end of file diff --git a/common/locales/sk/character.json b/common/locales/sk/character.json index 0ee2043984..f22dc8034b 100644 --- a/common/locales/sk/character.json +++ b/common/locales/sk/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Has upgraded to the maximum weapon and armor set for the following classes:", "level": "Level", "levelUp": "Získal si nový level!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "HP", "mp": "MP", diff --git a/common/locales/sk/content.json b/common/locales/sk/content.json index 5775a55aed..fe555e67d3 100644 --- a/common/locales/sk/content.json +++ b/common/locales/sk/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Frog", "questEggFrogMountText": "Frog", "questEggFrogAdjective": "a princely", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Základný", "hatchingPotionWhite": "Biely", diff --git a/common/locales/sk/front.json b/common/locales/sk/front.json index c3c8df6bd7..264f9bb539 100644 --- a/common/locales/sk/front.json +++ b/common/locales/sk/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] has really helped me impart structure to my life in graduate school.", "invalidEmail": "Ak chceš resetovať heslo, musíš zadať platnú emailovú adresu.", "irishfeet123Quote": "I've had horrible habits with clearing my place completely after meals and leaving cups all over the place. [Habitica] has cured that!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Before [Habitica], I was stuck with my thesis, as well as dissatisfied with my personal discipline regarding housework and things like learning vocabulary and studying Go theory. It turns out breaking down these tasks into smaller manageable checklists is quite the thing to keep me motivated and constantly working.", "landingadminlink": "balíčky", "landingend": "Ešte stále sme ťa nepresvedčili?", @@ -182,5 +182,11 @@ "tweet": "Tweet", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/sk/generic.json b/common/locales/sk/generic.json index 6d89ec7f79..60aecb388e 100644 --- a/common/locales/sk/generic.json +++ b/common/locales/sk/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Sending you a thousand thanks.", "thankyou3": "I'm very grateful - thank you!", "thankyouCardAchievementTitle": "Greatly Grateful", - "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards." + "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/sk/pets.json b/common/locales/sk/pets.json index 342937c20e..4661ca7549 100644 --- a/common/locales/sk/pets.json +++ b/common/locales/sk/pets.json @@ -58,8 +58,16 @@ "firstDrop": "You've unlocked the Drop System! Now when you complete tasks, you have a small chance of finding an item, including eggs, potions, and food! You just found a <%= eggText %> Egg! <%= eggNotes %>", "useGems": "If you've got your eye on a pet, but can't wait any longer for it to drop, use Gems in Inventory > Market to buy one!", "hatchAPot": "Chceš vyliahnuť takéto zvieratko: <%= potion %> <%= egg %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Chceš nakŕmiť toto zvieratko: <%= name %> týmto: <%= article %><%= text %>?", "useSaddle": "Chceš osedlať toto zvieratko: <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Kľúč ku klietkam", diff --git a/common/locales/sk/quests.json b/common/locales/sk/quests.json index 1cad87ea5b..4fa20544a8 100644 --- a/common/locales/sk/quests.json +++ b/common/locales/sk/quests.json @@ -76,5 +76,7 @@ "startAQuest": "START A QUEST", "startQuest": "Start Quest", "whichQuestStart": "Which quest do you want to start?", - "getMoreQuests": "Get more quests" + "getMoreQuests": "Get more quests", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/sk/questscontent.json b/common/locales/sk/questscontent.json index 60e5d826a3..bacc7f11c9 100644 --- a/common/locales/sk/questscontent.json +++ b/common/locales/sk/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/sk/settings.json b/common/locales/sk/settings.json index d6b647e7d3..e66d198ff1 100644 --- a/common/locales/sk/settings.json +++ b/common/locales/sk/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Keď je zvolená táto možnosť, keď začneš upravovať úlohu, zoznam štítkov bude skrytý.", "startAdvCollapsed": "Zrolované pokročilé možnosti v úlohách", "startAdvCollapsedPop": "S nastavením tejto možnosti budú pokročilé možnosti v momente, keď prvý krát otvoríš úlohu na úpravy, skryté.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Zobraziť prehliadku", "restartTour": "Reštartovať úvodnú prehliadku prvej návštevy Habitica.", "showBailey": "Zobraziť Bailey", @@ -81,7 +86,6 @@ "emailChange1": "Pre zmenu emailovej adresy nás kontaktujte na", "emailChange2": "admin@habitica.com", "emailChange3": "including both your old and new email address as well as your User ID.", - "username": "Prihlasovacie meno", "usernameOrEmail": "Prihlasovacie meno alebo email", "email": "Email", "registeredWithFb": "Registrovať pomocou Facebook účtu", @@ -89,7 +93,7 @@ "loginNameDescription2": "Používateľ->Profil", "loginNameDescription3": "to change the name that appears in your avatar and chat messages.", "emailNotifications": "Email notifikácie", - "wonChallenge": "Vyhral si výzvu", + "wonChallenge": "You won a Challenge!", "newPM": "Received Private Message", "giftedGems": "Gifted Gems", "giftedGemsInfo": "<%= amount %> Gems - by <%= name %>", diff --git a/common/locales/sr/challenge.json b/common/locales/sr/challenge.json index 90b86f94d9..79500b1f12 100644 --- a/common/locales/sr/challenge.json +++ b/common/locales/sr/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "Nemate ovlašćenje da prepravite ovaj izazov.", "noPermissionDeleteChallenge": "Nemate ovlašćenje da izbrišete ovaj izazov.", "noPermissionCloseChallenge": "Nemate ovlašćenje da zatvorite ovaj izazov.", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "no owner", "noChallengeOwnerPopover": "This challenge does not have an owner because the person who created the challenge deleted their account." } \ No newline at end of file diff --git a/common/locales/sr/character.json b/common/locales/sr/character.json index 66ee7fe798..458a6d5a25 100644 --- a/common/locales/sr/character.json +++ b/common/locales/sr/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Unapredio oružje i oklop do maksimalnog nivoa za sledeće klase:", "level": "Nivo", "levelUp": "Novi nivo!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "HP", "mp": "MP", diff --git a/common/locales/sr/content.json b/common/locales/sr/content.json index 3ff416dbb1..d33c405804 100644 --- a/common/locales/sr/content.json +++ b/common/locales/sr/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Frog", "questEggFrogMountText": "Frog", "questEggFrogAdjective": "a princely", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Običan", "hatchingPotionWhite": "Beli", diff --git a/common/locales/sr/front.json b/common/locales/sr/front.json index 0d0fc00c7a..df08766e82 100644 --- a/common/locales/sr/front.json +++ b/common/locales/sr/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] has really helped me impart structure to my life in graduate school.", "invalidEmail": "Morate ukucati važeću adresu da biste zatražili novu lozinku.", "irishfeet123Quote": "I've had horrible habits with clearing my place completely after meals and leaving cups all over the place. [Habitica] has cured that!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Before [Habitica], I was stuck with my thesis, as well as dissatisfied with my personal discipline regarding housework and things like learning vocabulary and studying Go theory. It turns out breaking down these tasks into smaller manageable checklists is quite the thing to keep me motivated and constantly working.", "landingadminlink": "administrativnim paketima", "landingend": "Još uvek niste uvereni?", @@ -182,5 +182,11 @@ "tweet": "Tweet", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/sr/generic.json b/common/locales/sr/generic.json index 8968ce1609..1c1ab1fd5f 100644 --- a/common/locales/sr/generic.json +++ b/common/locales/sr/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Sending you a thousand thanks.", "thankyou3": "I'm very grateful - thank you!", "thankyouCardAchievementTitle": "Greatly Grateful", - "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards." + "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/sr/pets.json b/common/locales/sr/pets.json index ec6b227221..13cf85ec6c 100644 --- a/common/locales/sr/pets.json +++ b/common/locales/sr/pets.json @@ -58,8 +58,16 @@ "firstDrop": "Sistem nalaženja predmeta je otključan! Ubuduće, kad završite zadatak, imaćete malu šansu da nađete predmete, uključujući jaja, napitke, i hranu. Upravi ste našli <%= eggText %> Jaje! <%= eggNotes %>", "useGems": "Ako želite neku zver i ne možete više da čekate da je nađete, u Inventar > Pijaca možete da ih kupite za dragulje.", "hatchAPot": "Želite li da se izlegne <%= potion %> <%= egg %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Želite li da <%= name %> pojede <%= article %><%= text %>?", "useSaddle": "Staviti sedlo na <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Ključ štenare", diff --git a/common/locales/sr/quests.json b/common/locales/sr/quests.json index 00a7d7e6eb..946f9ceaad 100644 --- a/common/locales/sr/quests.json +++ b/common/locales/sr/quests.json @@ -76,5 +76,7 @@ "startAQuest": "START A QUEST", "startQuest": "Start Quest", "whichQuestStart": "Which quest do you want to start?", - "getMoreQuests": "Get more quests" + "getMoreQuests": "Get more quests", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/sr/questscontent.json b/common/locales/sr/questscontent.json index 7a2f5014fc..22f7911467 100644 --- a/common/locales/sr/questscontent.json +++ b/common/locales/sr/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/sr/settings.json b/common/locales/sr/settings.json index d3ba00e8c3..86219943c0 100644 --- a/common/locales/sr/settings.json +++ b/common/locales/sr/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Ako je opcija odabrana, spisak tagova će biti skriven kad otvorite prozor za izmenu zadatka.", "startAdvCollapsed": "Sakriti Napredna podešavanja", "startAdvCollapsedPop": "Ako je opcija odabrana, Napredna podešavanja će biti skrivena kad otvorite prozor za izmenu zadatka.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Prikazati uvod", "restartTour": "Pogledajte ponovo uvod koji ste videli kad ste prvi put došli u Habitica.", "showBailey": "Prikazati Bejli", @@ -81,7 +86,6 @@ "emailChange1": "Ako želite da promenite imejl adresu, pošaljite poruku na", "emailChange2": "admin@habitica.com", "emailChange3": "sa svojom novom i starom adresom, i sa svojim UID kodom.", - "username": "Korisničko ime", "usernameOrEmail": "Korisničko ime ili imejl-adresa", "email": "E-mail adresa", "registeredWithFb": "Prijava / Registracija preko Facebook-a", @@ -89,7 +93,7 @@ "loginNameDescription2": "Korisnik -> Profil", "loginNameDescription3": "da promenite ime koje se pojavljuje na Vašem avataru i u Krčmi.", "emailNotifications": "Obaveštenja imejlom", - "wonChallenge": "Savladali ste izazov", + "wonChallenge": "You won a Challenge!", "newPM": "Primljena privatna poruka", "giftedGems": "Poklonjeni dragulji", "giftedGemsInfo": "<%= amount %> Dragulja - od <%= name %>", diff --git a/common/locales/sv/challenge.json b/common/locales/sv/challenge.json index df013d6dcd..1c92faac8b 100644 --- a/common/locales/sv/challenge.json +++ b/common/locales/sv/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "Du har inte tillstånd att ändra den här utmaningen.", "noPermissionDeleteChallenge": "Du har inte tillstånd att ta bort den här utmaningen.", "noPermissionCloseChallenge": "Du har inte tillstånd att stänga den här utmaningen.", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "no owner", "noChallengeOwnerPopover": "This challenge does not have an owner because the person who created the challenge deleted their account." } \ No newline at end of file diff --git a/common/locales/sv/character.json b/common/locales/sv/character.json index 2d5f2315b6..d06d0f4899 100644 --- a/common/locales/sv/character.json +++ b/common/locales/sv/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Har uppgraderat till max för vapen och utrustning för de följande klasserna:", "level": "Level", "levelUp": "Level upp!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Mana", "hp": "HP", "mp": "MP", diff --git a/common/locales/sv/content.json b/common/locales/sv/content.json index 6da299dcc0..7635bd95e6 100644 --- a/common/locales/sv/content.json +++ b/common/locales/sv/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Frog", "questEggFrogMountText": "Frog", "questEggFrogAdjective": "a princely", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Hitta en kläckningsdryck och häll på det här ägget så kommer det kläckas till <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Standard", "hatchingPotionWhite": "Vit", diff --git a/common/locales/sv/front.json b/common/locales/sv/front.json index c5cfa1d6d5..505722ab23 100644 --- a/common/locales/sv/front.json +++ b/common/locales/sv/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] has really helped me impart structure to my life in graduate school.", "invalidEmail": "En giltig e-postadress krävs för att kunna utföra en lösenordsåterställning.", "irishfeet123Quote": "I've had horrible habits with clearing my place completely after meals and leaving cups all over the place. [Habitica] has cured that!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Before [Habitica], I was stuck with my thesis, as well as dissatisfied with my personal discipline regarding housework and things like learning vocabulary and studying Go theory. It turns out breaking down these tasks into smaller manageable checklists is quite the thing to keep me motivated and constantly working.", "landingadminlink": "adminpaket", "landingend": "Inte övertalad än?", @@ -182,5 +182,11 @@ "tweet": "Tweet", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/sv/generic.json b/common/locales/sv/generic.json index f4b645e1e2..e6ece65ac2 100644 --- a/common/locales/sv/generic.json +++ b/common/locales/sv/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Sending you a thousand thanks.", "thankyou3": "I'm very grateful - thank you!", "thankyouCardAchievementTitle": "Greatly Grateful", - "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards." + "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/sv/pets.json b/common/locales/sv/pets.json index 3588343330..3f1603f17a 100644 --- a/common/locales/sv/pets.json +++ b/common/locales/sv/pets.json @@ -58,8 +58,16 @@ "firstDrop": "You've unlocked the Drop System! Now when you complete tasks, you have a small chance of finding an item, including eggs, potions, and food! You just found a <%= eggText %> Egg! <%= eggNotes %>", "useGems": "If you've got your eye on a pet, but can't wait any longer for it to drop, use Gems in Inventory > Market to buy one!", "hatchAPot": "Kläck ett <%= potion %> <%= egg %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Mata <%= article %><%= text %> till din <%= name %>?", "useSaddle": "Sadla <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "Kläck ett <%= potion %> <%= egg %>?", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Key to the Kennels", diff --git a/common/locales/sv/quests.json b/common/locales/sv/quests.json index 0b76c56631..fe42e4f1fe 100644 --- a/common/locales/sv/quests.json +++ b/common/locales/sv/quests.json @@ -76,5 +76,7 @@ "startAQuest": "START A QUEST", "startQuest": "Start Quest", "whichQuestStart": "Which quest do you want to start?", - "getMoreQuests": "Get more quests" + "getMoreQuests": "Get more quests", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/sv/questscontent.json b/common/locales/sv/questscontent.json index f6b67d207f..1a68c43748 100644 --- a/common/locales/sv/questscontent.json +++ b/common/locales/sv/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/sv/settings.json b/common/locales/sv/settings.json index 4b54c6870d..8f866a8417 100644 --- a/common/locales/sv/settings.json +++ b/common/locales/sv/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Med den här inställningen är tagg-listan dold när du öppnar en uppgift för redigering.", "startAdvCollapsed": "Avancerade Inställningar i uppgifter startar som minimerade.", "startAdvCollapsedPop": "Med den här inställningen är Avancerade Inställningar dolda när du öppnar en uppgift för redigering.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Visa Rundtur", "restartTour": "Starta om den introducerande rundturen från när du började med Habitica.", "showBailey": "Visa Bailey", @@ -81,7 +86,6 @@ "emailChange1": "För att ändra din e-postadress, skicka ett e-postmeddelande till", "emailChange2": "admin@habitica.com", "emailChange3": "inklusive både din gamla och din nya e-postadress, samt ditt User ID.", - "username": "Inloggningsnamn", "usernameOrEmail": "Login Name or Email", "email": "E-postadress", "registeredWithFb": "Registrerad via Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "Användare->Profil", "loginNameDescription3": "för att byta namnet som visas tillsammans med din avatar och i chat-meddelanden.", "emailNotifications": "E-postnotiser", - "wonChallenge": "Du vann en utmaning", + "wonChallenge": "You won a Challenge!", "newPM": "Mottagit privatmeddelande", "giftedGems": "Skänkta juveler", "giftedGemsInfo": "<%= amount %> Gems - by <%= name %>", diff --git a/common/locales/uk/challenge.json b/common/locales/uk/challenge.json index dbaedffb8c..5de527e5c3 100644 --- a/common/locales/uk/challenge.json +++ b/common/locales/uk/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "У вас немає дозволу редагувати це випробування", "noPermissionDeleteChallenge": "У вас немає дозволу видаляти це випробування", "noPermissionCloseChallenge": "У вас немає дозволу закривати це випробування", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "немає власника", "noChallengeOwnerPopover": "У цього випробування немає власника, тому що людина, що створила його, вилучила свій акаунт." } \ No newline at end of file diff --git a/common/locales/uk/character.json b/common/locales/uk/character.json index 28a9b53b75..b7ee3f6cf6 100644 --- a/common/locales/uk/character.json +++ b/common/locales/uk/character.json @@ -65,6 +65,10 @@ "ultimGearText": "Повністю вдосконалено зброю та набір броні для наступних класів:", "level": "Рівень", "levelUp": "Новий рівень!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "Мана", "hp": "ОЗ", "mp": "ОМ", diff --git a/common/locales/uk/content.json b/common/locales/uk/content.json index aadc85438c..067fb1de1a 100644 --- a/common/locales/uk/content.json +++ b/common/locales/uk/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "Frog", "questEggFrogMountText": "Frog", "questEggFrogAdjective": "a princely", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "Find a hatching potion to pour on this egg, and it will hatch into <%= eggAdjective(locale) %> <%= eggText(locale) %>.", "hatchingPotionBase": "Простий", "hatchingPotionWhite": "Білий", diff --git a/common/locales/uk/front.json b/common/locales/uk/front.json index a725e7258d..83f0c07918 100644 --- a/common/locales/uk/front.json +++ b/common/locales/uk/front.json @@ -74,7 +74,7 @@ "infhQuote": "[Habitica] has really helped me impart structure to my life in graduate school.", "invalidEmail": "A valid email address is required in order to perform a password reset.", "irishfeet123Quote": "I've had horrible habits with clearing my place completely after meals and leaving cups all over the place. [Habitica] has cured that!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Before [Habitica], I was stuck with my thesis, as well as dissatisfied with my personal discipline regarding housework and things like learning vocabulary and studying Go theory. It turns out breaking down these tasks into smaller manageable checklists is quite the thing to keep me motivated and constantly working.", "landingadminlink": "адміністраційні набори,", "landingend": "Вам і цього замало?", @@ -182,5 +182,11 @@ "tweet": "Tweet", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/uk/generic.json b/common/locales/uk/generic.json index ed2882f035..1c75b9e9a6 100644 --- a/common/locales/uk/generic.json +++ b/common/locales/uk/generic.json @@ -134,5 +134,17 @@ "thankyou2": "Посилаю тобі тисячі подяк", "thankyou3": "Я вдячний(а) - спасибі тобі!", "thankyouCardAchievementTitle": "Дуже вдячний(а)", - "thankyouCardAchievementText": "Дякую за вдячність! Надіслав(ла) чи отримав(ла) <%= cards %> листівок-подяк" + "thankyouCardAchievementText": "Дякую за вдячність! Надіслав(ла) чи отримав(ла) <%= cards %> листівок-подяк", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/uk/pets.json b/common/locales/uk/pets.json index f5fcf222d9..1d75ed46b5 100644 --- a/common/locales/uk/pets.json +++ b/common/locales/uk/pets.json @@ -58,8 +58,16 @@ "firstDrop": "You've unlocked the Drop System! Now when you complete tasks, you have a small chance of finding an item, including eggs, potions, and food! You just found a <%= eggText %> Egg! <%= eggNotes %>", "useGems": "If you've got your eye on a pet, but can't wait any longer for it to drop, use Gems in Inventory > Market to buy one!", "hatchAPot": "Пролупити <%= egg %>, використавши <%= potion %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "Згодувати <%= article %><%= text %> Вашому <%= name %>?", "useSaddle": "Осідлати <%= pet %>?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "Ключ до розсадників", diff --git a/common/locales/uk/quests.json b/common/locales/uk/quests.json index fd2339ac03..2188053f60 100644 --- a/common/locales/uk/quests.json +++ b/common/locales/uk/quests.json @@ -76,5 +76,7 @@ "startAQuest": "START A QUEST", "startQuest": "Start Quest", "whichQuestStart": "Which quest do you want to start?", - "getMoreQuests": "Get more quests" + "getMoreQuests": "Get more quests", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/uk/questscontent.json b/common/locales/uk/questscontent.json index 7b076bc221..cb9309c268 100644 --- a/common/locales/uk/questscontent.json +++ b/common/locales/uk/questscontent.json @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/uk/settings.json b/common/locales/uk/settings.json index ee239845da..feaa0a3acd 100644 --- a/common/locales/uk/settings.json +++ b/common/locales/uk/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "Якщо ввімкнено, перелік міток завдання буде приховано, коли Ви вперше відкриваєте завдання.", "startAdvCollapsed": "Додаткове показувати згорнутим", "startAdvCollapsedPop": "Якщо ввімкнено, секція Додаткове буде прихована, коли Ви вперше відкриваєте завдання.", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "Показати тур", "restartTour": "Показати тур для ознайомлення, який Ви бачили, коли приєдналися до Habitica.", "showBailey": "Показати Бейлі", @@ -81,7 +86,6 @@ "emailChange1": "To change your email address, please send an email to", "emailChange2": "admin@habitica.com", "emailChange3": "including both your old and new email address as well as your User ID.", - "username": "Login Name", "usernameOrEmail": "Login Name or Email", "email": "Email", "registeredWithFb": "Зареєструватися через Facebook", @@ -89,7 +93,7 @@ "loginNameDescription2": "User->Profile", "loginNameDescription3": "to change the name that appears in your avatar and chat messages.", "emailNotifications": "Email Notifications", - "wonChallenge": "You Won a Challenge", + "wonChallenge": "You won a Challenge!", "newPM": "Received Private Message", "giftedGems": "Gifted Gems", "giftedGemsInfo": "<%= amount %> Gems - by <%= name %>", diff --git a/common/locales/zh/backgrounds.json b/common/locales/zh/backgrounds.json index a72cd36540..b7a9949950 100644 --- a/common/locales/zh/backgrounds.json +++ b/common/locales/zh/backgrounds.json @@ -119,11 +119,11 @@ "backgroundSlimySwampNotes": "在黏糊糊的沼泽中奋勇前进", "backgroundSwarmingDarknessText": "遮天蔽日的黑暗", "backgroundSwarmingDarknessNotes": "在遮天蔽日的黑暗中颤抖", - "backgrounds112015": "SET 18: Released November 2015", - "backgroundFloatingIslandsText": "Floating Islands", - "backgroundFloatingIslandsNotes": "Hop across the Floating Islands.", - "backgroundNightDunesText": "Night Dunes", - "backgroundNightDunesNotes": "Walk peacefully through the Night Dunes.", - "backgroundSunsetOasisText": "Sunset Oasis", - "backgroundSunsetOasisNotes": "Bask in the Sunset Oasis." + "backgrounds112015": "第18组:2015年11月推出", + "backgroundFloatingIslandsText": "浮游岛", + "backgroundFloatingIslandsNotes": "在浮游岛上跳跃", + "backgroundNightDunesText": "夜幕沙丘", + "backgroundNightDunesNotes": "在夜幕沙丘中静静穿行", + "backgroundSunsetOasisText": "日落绿洲", + "backgroundSunsetOasisNotes": "沐浴在日落绿洲" } \ No newline at end of file diff --git a/common/locales/zh/challenge.json b/common/locales/zh/challenge.json index 48f5abe399..9f8d5f566a 100644 --- a/common/locales/zh/challenge.json +++ b/common/locales/zh/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "你没有权限修改这个挑战。", "noPermissionDeleteChallenge": "你没有权限删除这个挑战。", "noPermissionCloseChallenge": "你没有权限关闭这个挑战。", + "congratulations": "Congratulations!", + "hurray": "Hurray!", "noChallengeOwner": "没有主持人", "noChallengeOwnerPopover": "这项挑战没有主持人,因为创建了这个挑战项目的用户删除了他们的帐号" } \ No newline at end of file diff --git a/common/locales/zh/character.json b/common/locales/zh/character.json index 414764eb36..d4293016af 100644 --- a/common/locales/zh/character.json +++ b/common/locales/zh/character.json @@ -52,7 +52,7 @@ "classEquipBonus": "职业奖励", "battleGear": "战斗装备", "battleGearText": "这是你在战斗中的装备;这会影响您在任务重的各项数值", - "autoEquipBattleGear": "自动装备新装甲", + "autoEquipBattleGear": "自动换新装备", "costume": "服装", "costumeText": "如果你更喜欢其它装备的样子,勾选\"显示服装\"的按钮,在装备战斗装备的情况下换一个造型。", "useCostume": "显示服装", @@ -65,6 +65,10 @@ "ultimGearText": "已经将以下职业的武器和装备升级到满级:", "level": "级", "levelUp": "升级了!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "魔法值", "hp": "生命值", "mp": "MP", diff --git a/common/locales/zh/content.json b/common/locales/zh/content.json index f5f9001803..ba621443fd 100644 --- a/common/locales/zh/content.json +++ b/common/locales/zh/content.json @@ -98,6 +98,9 @@ "questEggFrogText": "青蛙", "questEggFrogMountText": "青蛙", "questEggFrogAdjective": "一只王子一般的", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "将一瓶孵化药水倒在这个宠物蛋上,你就能孵化出一只<%= eggAdjective(locale) %><%= eggText(locale) %>。", "hatchingPotionBase": "普通", "hatchingPotionWhite": "白色", diff --git a/common/locales/zh/faq.json b/common/locales/zh/faq.json index f1c45ebb47..d3c3376113 100644 --- a/common/locales/zh/faq.json +++ b/common/locales/zh/faq.json @@ -16,7 +16,7 @@ "iosFaqAnswer4": "有这样一些东西会减少你的生命值,第一,如果你有每日任务没完成,它会克扣你的生命值,第二,如果你“点击”了一个坏习惯,它也会伤害你的生命值,最后,如果你在和你的队员一起进行BOSS战时,一旦队伍中有一个成员没能完成每日任务,BOSS就会攻击你。\n\n回复生命值最主要的办法是升级,每一次升级时,所有的生命值都会回复。你也用金币从奖励栏里可以购买生命药剂。另外,在达到10级以上的级数时,你可以选择成为一个医师,然后学习治疗技能。如果你的队伍里有一个医师,他也能治疗你。", "webFaqAnswer4": "有这样一些东西会减少你的生命值,第一,如果你有每日任务没完成,它会克扣你的生命值,第二,如果你“点击”了一个坏习惯,它也会伤害你的生命值,最后,如果你在和你的队员一起进行BOSS战时,一旦队伍中有一个成员没能完成每日任务,BOSS就会攻击你。\n

\n回复生命值最主要的办法是升级,每一次升级时,所有的生命值都会回复。你也用金币从奖励栏里可以购买生命药剂。另外,在达到10级以上的级数时,你可以选择成为一个医师,然后学习治疗技能。如果你的队伍(可在社交>队伍里查看)里有一个医师,他也能治疗你。", "faqQuestion5": "我怎么和朋友们以前玩Habitica?", - "iosFaqAnswer5": "The best way is to invite them to a Party with you! Parties can go on quests, battle monsters, and cast skills to support each other. Go to Menu > Party and click \"Create New Party\" if you don't already have a Party. Then tap on the Members list, and tap Invite in the upper right-hand corner to invite your friends by entering their User ID (a string of numbers and letters that they can find under Settings > Account Details on the app, and Settings > API on the website). On the website, you can also invite friends via email, which we will add to the app in a future update.\n\nOn the website, you and your friends can also join Guilds, which are public chat rooms. Guilds will be added to the app in a future update!", + "iosFaqAnswer5": "最好的办法是邀请他们加入你的战队!战队可以接受任务,和怪物作战,使用技能互相支持。 如果你还没有自己的队伍,进入目录 > 队伍点击“建立新的队伍”。 然后点击成员列表,在右上角选择邀请,输入朋友们的用户ID (一串由数字和字母组成的列表,可以在手机APP的设置 > 账户明细或者网页版的设置 > API下查看)。在网站上,你还可以使用email地址邀请朋友,在手机APP会在未来增加这个功能。\n\n在网页版上你和朋友们还能加入公会,即公共聊天室,APP也会跟进公会功能!", "webFaqAnswer5": "最好的方法就是邀请他们跟你一起加入队伍,选择「社交」>「队伍」。队伍可以参加任务卷轴、和魔王对抗、使用技能来支援彼此。你也可以加入公会(「社交」>「公会」),公会里面有聊天室,你可以在上面分享些新鲜事或者说说你想要达成的好习惯目标,你可以自由的选择要公开聊天或者私下。公会可以重复加入数个,但是队伍一次只能加入一组喔!\n

\n想要知道更多资讯,请点选我们的wiki页面\n[队伍](http://habitrpg.wikia.com/wiki/Party) \n[公会](http://habitrpg.wikia.com/wiki/Guilds)", "faqQuestion6": "我要怎样才能得到宠物或是坐骑呢?", "iosFaqAnswer6": "当你等级升到3的时候,就会解锁掉落系统。每当你完成任务时,你就会有一定的机率收到宠物蛋、孵化药水,或是喂养宠物的食物。当你收到时系统就会自动存入「选单」>「物品」。\n\n想要孵化宠物,你需要同时拥有宠物蛋和孵化药水各一。点选宠物蛋确认你要孵化的种类,接着点击「孵化」,然后选择孵化药水就能够确认宠物的颜色啰!孵化完成后你可以到「选单」>「宠物」将你的宠物装备到角色上。\n\n你也可以用喂食的方式让宠物进化成坐骑。点选宠物选择「喂食」,你会看到一条绿色的状态列随着你喂食次数而增长,当状态列额满后就会进化成坐骑。这需要花点时间,不过如果你能找到宠物最喜欢的食物,就可以加速宠物进化的速度啰!请多多尝试食物种类或者看这个[剧透]。 (http://habitica.wikia.com/wiki/Food#Food_Preferences)\n当你拥有了一只座骑,你可以到「选单」>「坐骑」将它装备到角色上。\n\n当你完成某些任务卷轴时,你也可能收到任务宠物蛋。 (你可以看看下面有一些关于任务卷轴的介绍)。", @@ -26,11 +26,11 @@ "webFaqAnswer7": "在达到第 10级时,你可以在战士,法师,盗贼和医师当中选择自己的职业(所有玩家的初始职业都是战士)。每个职业有不同的装备选择和在11级时可以使用的技能,以及不同的优点。战士可以很轻松地击退BOSS们,还能够抵挡来自任务的伤害,同时也是队伍的凝聚力。法师也能够给予魔王有效的攻击,等级提升快速且能够帮助队伍的成员补充魔力。盗贼能赚取最多的金币,也是能捡到最多掉落物品的职业,而这些优点也能回馈给队伍。最后,医师拥有特殊技能可以治愈他们自身以及队伍成员的生命值。\n

\n如果你还不想立刻选择职业的话--比如,如果你觉得与​​其马上选择职业,不如先补足目前所需的装备的--你可以点选「之后再决定」,等你觉得时机到了就可以到「选单」>「选择职业」。", "faqQuestion8": "在达到第10级成为医师以后,头像里出现的蓝条是什么?", "iosFaqAnswer8": "在你达到第10级,选择一个职业之后出现在头像里的蓝条是你的法力条。在你接下来不断升级的过程中,你会解锁各种特殊技能,它们需要耗费魔法才能使用。每个职业都有不同技能,在到达11级以后会在 目录 > 使用技能 下面出现。和你的健康值不同,你的法力条在你升级时不会回复,只有在培养了好的习惯,完成了每日任务和待办事项时才会获取法力。每过一夜你也会回复小部分的法力——完成的日常任务越多,回复的法力也越多。", - "webFaqAnswer8": "The blue bar that appeared when you hit level 10 and chose a Class is your Mana bar. As you continue to level up, you will unlock special Skills that cost Mana to use. Each Class has different Skills, which appear after level 11 in a special section in the Rewards Column. Unlike your Health bar, your Mana bar does not reset when you gain a level. Instead, Mana is gained when you complete Good Habits, Dailies, and To-Dos, and lost when you indulge bad Habits. You’ll also regain some Mana overnight -- the more Dailies you completed, the more you will gain.", + "webFaqAnswer8": "在你达到第10级,选择一个职业之后出现在头像里的蓝条是你的法力条。在你接下来不断升级的过程中,你会解锁各种特殊技能,它们需要耗费魔法才能使用。每个职业都有不同技能,在到达11级以后会在奖励栏的的一块专门区域出现。和你的健康值不同,你的法力条在你升级时不会回复,只有在培养了好的习惯,完成了每日任务和待办事项时才会获取法力。每过一夜你也会回复小部分的法力——完成的日常任务越多,回复的法力也越多。", "faqQuestion9": "我怎么和怪兽战斗,继续任务?", - "iosFaqAnswer9": "First, you need to join or start a Party (see above). Although you can battle monsters alone, we recommend playing in a group, because this will make Quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n\n Next, you need a Quest Scroll, which are stored under Menu > Items. There are three ways to get a scroll:\n\n - At level 15, you get a Quest-line, aka three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively. \n - When you invite people to your Party, you'll be rewarded with the Basi-List Scroll!\n - You can buy Quests from the Quests Page on the [website](https://habitica.com/#/options/inventory/quests) for Gold and Gems. (We will add this feature to the app in a future update.)\n\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading by pulling down on the screen may be required to see the Boss's health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your Party at the same time that you damage the Boss. \n\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", - "webFaqAnswer9": "First, you need to join or start a party (under Social > Party). Although you can battle monsters alone, we recommend playing in a group, because this will make quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n

\n Next, you need a Quest Scroll, which are stored under Inventory > Quests. There are three ways to get a scroll:\n

\n * When you invite people to your party, you’ll be rewarded with the Basi-List Scroll!\n * At level 15, you get a Quest-line, i.e., three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively.\n * You can buy Quests from the Quests Page (Inventory > Quests) for Gold and Gems.\n

\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading may be required to see the Boss's Health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your party at the same time that you damage the Boss.\n

\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", - "faqQuestion10": "What are Gems, and how do I get them?", + "iosFaqAnswer9": "首先,你需要加入或者成立一个战队 (见上面内容),虽然你可以一个人对抗怪物们,我们还是建议组队作战,因为这样可以让任务变得简单很多。另外,在完成任务时有一个可以鼓励你的朋友也是非常有动力的!\n\n然后,你需要一个任务卷轴,在目录 > 道具 下面可以找到,得到一个任务卷轴有三个办法:\n\n- 在15级的时候,你会得到一条任务线,有三个互相联系的任务,在30,40和60级还会解锁更多任务线\n- 当你邀请朋友加入你的战队,你会被奖励基础卷轴!\n- 在网页版你可以在[这里] (https://habitica.com/#/options/inventory/quests) 用金币和宝石购买任务。(我们会在未来把这项功能加到手机APP上)\n\n要在一项收集任务中击败BOSS收集道具,只需要照常完成你的日常任务,每过一夜,它们会被追踪到对BOSS的伤害值上 (下拉页面刷新就能看见BOSS的生命值在降低)。如果在和BOSS对战时错过了某些日常任务,BOSS会在你和你的队友对BOSS造成伤害的同时反伤你们。\n\n在11级时法师和战士可以学习到能造成更多伤害的技能,所以在第10级选择职业时,如果你想做一个高输出角色,这两个职业是极佳的选择。", + "webFaqAnswer9": "首先,你需要加入或者成立一个战队 (见 社交 > 队伍),虽然你可以一个人对抗怪物们,我们还是建议组队作战,因为这样可以让任务变得简单很多。另外,在完成任务时有一个可以鼓励你的朋友也是非常有动力的! \n

\n然后,你需要一个任务卷轴,在目录 > 道具 下面可以找到,得到一个任务卷轴有三个办法: \n

\n* 在15级的时候,你会得到一条任务线,有三个互相联系的任务,在30,40和60级还会解锁更多任务线 - 当你邀请朋友加入你的战队,你会被奖励基础卷轴! \n* 在网页版你可以在任务页面 (见 物品栏 > 任务) 用金币和宝石购买任务。\n

\n要在一项收集任务中击败BOSS收集道具,只需要照常完成你的日常任务,每过一夜,它们会被追踪到对BOSS的伤害值上 (下拉页面刷新就能看见BOSS的生命值在降低)。如果在和BOSS对战时错过了某些日常任务,BOSS会在你和你的队友对BOSS造成伤害的同时反伤你们。 \n

\n在11级时法师和战士可以学习到能造成更多伤害的技能,所以在第10级选择职业时,如果你想做一个高输出角色,这两个职业是极佳的选择。", + "faqQuestion10": "什么是宝石?我如何获得宝石?", "iosFaqAnswer10": "Gems are purchased with real money by tapping on the gem icon in the header. When people buy gems, they are helping us to keep the site running. We're very grateful for their support!\n\n In addition to buying gems directly, there are three other ways players can gain gems:\n\n * Win a Challenge on the [website](https://habitica.com) that has been set up by another player under Social > Challenges. (We will be adding Challenges to the app in a future update!)\n * Subscribe on the [website](https://habitica.com/#/options/settings/subscription) and unlock the ability to buy a certain number of gems per month.\n * Contribute your skills to the Habitica project. See this wiki page for more details: [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica).\n\n Keep in mind that items purchased with gems do not offer any statistical advantages, so players can still make use of the app without them!", "webFaqAnswer10": "Gems are [purchased with real money](https://habitica.com/#/options/settings/subscription), although [subscribers](https://habitica.com/#/options/settings/subscription) can purchase them with Gold. When people subscribe or buy Gems, they are helping us to keep the site running. We're very grateful for their support!\n

\n In addition to buying Gems directly or becoming a subscriber, there are two other ways players can gain Gems:\n

\n * Win a Challenge that has been set up by another player under Social > Challenges.\n * Contribute your skills to the Habitica project. See this wiki page for more details: [Contributing to Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica)\n

\n Keep in mind that items purchased with Gems do not offer any statistical advantages, so players can still make use of the site without them!", "faqQuestion11": "我怎么才能报告一个bug,或者请求增加功能?", diff --git a/common/locales/zh/front.json b/common/locales/zh/front.json index d3507d47d0..1b5fab4920 100644 --- a/common/locales/zh/front.json +++ b/common/locales/zh/front.json @@ -11,7 +11,7 @@ "businessSample3": "整理收件箱", "businessSample4": "Prepare 1 Document for Client", "businessSample5": "Call Clients/Put Off Phone Calls", - "businessText": "Use Habitica at your business", + "businessText": "在工作中利用Habitica", "choreSample1": "Put Dirty Clothes in Hamper", "choreSample2": "20分钟的家务", "choreSample3": "洗了大量的餐具", @@ -47,9 +47,9 @@ "featurePetByline": "完成你的任务时就可以收到掉落的宠物蛋或道具,尽可能勤快地完成任务,去收集宠物和坐骑!", "featurePetHeading": "宠物和坐骑", "featureSocialByline": "加入志同道合的伙伴们,设立挑战来互相竞赛。", - "featureSocialHeading": "Social play", - "featuredIn": "Featured in", - "featuresHeading": "We also feature...", + "featureSocialHeading": "多人游戏", + "featuredIn": "特别提供", + "featuresHeading": "我们还有这些特别的……", "footerCommunity": "社区", "footerCompany": "公司", "footerMobile": "手机版", @@ -73,8 +73,8 @@ "history": "历史", "infhQuote": "[Habitica]真的帮了我,让我把研究生生活整理得井井有条。", "invalidEmail": "执行密码重置需要一个有效的电子邮件地址。", - "irishfeet123Quote": "I've had horrible habits with clearing my place completely after meals and leaving cups all over the place. [Habitica] has cured that!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "irishfeet123Quote": "我曾经习惯很烂,在吃饭之后不好好收拾,茶杯放得到处都是, [Habitica]解决了这个问题!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "Before [Habitica], I was stuck with my thesis, as well as dissatisfied with my personal discipline regarding housework and things like learning vocabulary and studying Go theory. It turns out breaking down these tasks into smaller manageable checklists is quite the thing to keep me motivated and constantly working.", "landingadminlink": "管理包", "landingend": "还没被说服?", @@ -109,7 +109,7 @@ "marketing3Lead1": "iPhone 和 安卓 应用程式可以让你外出时也能处理你的习惯。我们明白有时要登录网站点点按钮可能会成为一个负担。", "marketing3Lead2": "Other 3rd Party Tools tie Habitica into various aspects of your life. Our API provides easy integration for things like the Chrome Extension, for which you lose points when browsing unproductive websites, and gain points when on productive ones. See more here", "marketing4Header": "组织使用", - "marketing4Lead1": "Education is one of the best sectors for gamification. We all know how glued to phones and games students are these days; harness that power! Pit your students against eachother in friendly competition. Reward good behavior with rare prizes. Watch their grades and behavior soar.", + "marketing4Lead1": "教育是游戏化最适合的领域。我们都知道最近学生们多么热衷于手机和游戏,利用这种力量!给你的学生引入良性竞争。用稀有奖励奖赏那些好的行为。等着看他们的成绩和表现腾飞吧。", "marketing4Lead1Title": "教育游戏化", "marketing4Lead2": "医疗保健的花销越来越高,是时候做出一些改变了。虽然有数以百计的用来改善健康的程序,我们相信Habitica可以从本质上帮助你走向更健康的生活方式。", "marketing4Lead2Title": "健康游戏化", @@ -129,14 +129,14 @@ "playButtonFull": "玩Habitica游戏", "presskit": "资料包", "presskitDownload": "下载图片", - "presskitText": "Thanks for your interest in Habitica! The following images can be used for articles or videos about Habitica. For more information, please contact Siena Leslie at leslie@habitica.com.", + "presskitText": "感谢您对Habitica的大力支持!下面的图片可以用来制作有关Habitica的文章或视频,详情请联系Siena Leslie:leslie@habitica.com。", "privacy": "隐私政策", "psst": "嘘!", - "punishByline": "Break bad habits and procrastination cycles with immediate consequences.", + "punishByline": "用即时奖励打败坏习惯和强迫症。", "punishHeading1": "错过了日常任务?", "punishHeading2": "失去生命值", - "questByline1": "Playing with your friends keeps you accountable for your tasks.", - "questByline2": "Issue each other Challenges to complete a goal together!", + "questByline1": "和朋友一起玩,督促自己完成任务。", + "questByline2": "各自接受挑战,一起达成目标!", "questHeading1": "与朋友一起大战怪兽!", "questHeading2": "If you slack off, they all get hurt!", "register": "注册", @@ -152,7 +152,7 @@ "schoolSample3": "和学习小组碰头", "schoolSample4": "第1章的注释", "schoolSample5": "读1个章节", - "sixteenBitFilQuote": "I'm getting my jobs and tasks done in record time thanks to [Habitica]. I'm just always so eager to reach my next level-up!", + "sixteenBitFilQuote": "多亏 [Habitica],现在我的工作和任务都能及时完成了。我太盼望升到下一级了!", "skysailorQuote": "My party and our quests keep me engaged in the game, which keeps me motivated to get things done and change my life in positive ways", "socialTitle": "Habitica - 游戏化你的生活", "supermouse35Quote": "I'm exercising more and I haven't forgotten to take my meds for months! Thanks, Habit. :D", @@ -180,7 +180,13 @@ "merchandiseInquiries": "Merchandise Inquiries", "marketingInquiries": "Marketing/Social Media Inquiries", "tweet": "发布推特", - "apps": "Apps", - "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "apps": "手机应用", + "notifyAndroidApp": "希望我们在安卓应用发布时通知你吗?注册这个邮件通知!", + "checkOutIOSApp": "看看我们的新IOS应用!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/zh/gear.json b/common/locales/zh/gear.json index 7a0f3153f8..63eec79016 100644 --- a/common/locales/zh/gear.json +++ b/common/locales/zh/gear.json @@ -68,8 +68,8 @@ "weaponSpecial3Notes": "怪物统统捣烂!增加力量,智力,体质各<%= attrs %>点。", "weaponSpecialCriticalText": "碾碎臭虫的批判战锤", "weaponSpecialCriticalNotes": "这位勇士杀死了一个使无数战士陨落的吹毛求疵的 Github 敌人。这把战锤由臭虫的骨头打造,能造成强大的致命一击。增加力量和感知各<%= attrs %>点。", - "weaponSpecialTridentOfCrashingTidesText": "Trident of Crashing Tides", - "weaponSpecialTridentOfCrashingTidesNotes": "Gives you the ability to command fish, and also deliver some mighty stabs to your tasks. Increases Intelligence by <%= int %>.", + "weaponSpecialTridentOfCrashingTidesText": "怒潮三叉戟", + "weaponSpecialTridentOfCrashingTidesNotes": "赐予你给鱼下命令的本领, 还能有力刺激你完成任务。.增加 <%= int %> 点智力。", "weaponSpecialYetiText": "雪人驯化矛", "weaponSpecialYetiNotes": "雪人驯化矛允许它的玩家指挥任何雪人。增加<%= str %>力量。2013-2014冬季装备限量版。", "weaponSpecialSkiText": "滑雪刺客杖", @@ -87,7 +87,7 @@ "weaponSpecialSpringHealerText": "可爱的骨头", "weaponSpecialSpringHealerNotes": "拿来!增加<%= int %>点智力。2014年春季限量版装备。", "weaponSpecialSummerRogueText": "海盗弯刀", - "weaponSpecialSummerRogueNotes": "Avast! You'll make those Dailies walk the plank! Increases Strength by <%= str %>. Limited Edition 2014 Summer Gear.", + "weaponSpecialSummerRogueNotes": "停止吧!你会让那些日常任务自取灭亡!增强力量 <%= str %> 点。限量版2014夏季装备。", "weaponSpecialSummerWarriorText": "航海片刀", "weaponSpecialSummerWarriorNotes": "沒有任何待办事项中的任务愿意与这把粗糙的刀纠缠!增加<%= str %>点力量。限量版2014夏季装备。", "weaponSpecialSummerMageText": "海带捕捉器", @@ -115,17 +115,17 @@ "weaponSpecialSpring2015WarriorText": "骨棒", "weaponSpecialSpring2015WarriorNotes": "这是为真正凶猛的狗狗们准备的真正的骨棒,绝对不是那种季节魔女给你的咀嚼玩具!乖狗狗是谁?谁~~~是乖狗狗呀??就是你呀!!你是只乖狗狗哦!!!提高 <%= str %>点力量。2015春季限定版装备。", "weaponSpecialSpring2015MageText": "魔法师魔杖", - "weaponSpecialSpring2015MageNotes": "Conjure up a carrot for yourself with this fancy wand. Increases Intelligence by <%= int %> and Perception by <%= per %>. Limited Edition 2015 Spring Gear.", + "weaponSpecialSpring2015MageNotes": "可以用这支魔杖召唤一个属于你自己的迷人胡萝卜。提高 <%= int %> 点智力和 <%= per %> 点感知。2015春季限定版装备。", "weaponSpecialSpring2015HealerText": "猫咪拨浪鼓", "weaponSpecialSpring2015HealerNotes": "当你摇动这只拨浪鼓,它会发出叮当声,让所有人保持愉悦好几小时。提高<%= int %>点智力。2015春季限定版装备。", "weaponSpecialSummer2015RogueText": "炽烈珊瑚", "weaponSpecialSummer2015RogueNotes": "这个是烈焰珊瑚的分支装备,它拥有在水中散播毒液的能力。提高<%= str %>点力量。2015年夏季限量装备", - "weaponSpecialSummer2015WarriorText": "Sun Swordfish", + "weaponSpecialSummer2015WarriorText": "日剑鱼", "weaponSpecialSummer2015WarriorNotes": "The Sun Swordfish is a fearsome weapon, provided that it can be induced to stop wriggling. Increases Strength by <%= str %>. Limited Edition 2015 Summer Gear.", - "weaponSpecialSummer2015MageText": "Soothsayer Staff", + "weaponSpecialSummer2015MageText": "轻语者之杖", "weaponSpecialSummer2015MageNotes": "Hidden power glimmers in the jewels of this staff. Increases Intelligence by <%= int %> and Perception by <%= per %>. Limited Edition 2015 Summer Gear.", - "weaponSpecialSummer2015HealerText": "Wand of the Waves", - "weaponSpecialSummer2015HealerNotes": "Cures seasickness and sea sickness! Increases Intelligence by <%= int %>. Limited Edition 2015 Summer Gear.", + "weaponSpecialSummer2015HealerText": "涛之魔杖", + "weaponSpecialSummer2015HealerNotes": "治疗晕船,和船晕!增加 <%= int %> 点智力。2015年夏天限量版装备。", "weaponSpecialFall2015RogueText": "Bat-tle Ax", "weaponSpecialFall2015RogueNotes": "Fearsome To-Dos cower before the flapping of this ax. Increases Strength by <%= str %>. Limited Edition 2015 Autumn Gear.", "weaponSpecialFall2015WarriorText": "Wooden Plank", @@ -152,9 +152,9 @@ "weaponArmoireMythmakerSwordNotes": "Though it may seem humble, this sword has made many mythic heroes. Increases Perception and Strength by <%= attrs %> each. Enchanted Armoire: Golden Toga Set (Item 3 of 3)", "weaponArmoireIronCrookText": "钢铁手杖", "weaponArmoireIronCrookNotes": "由铁打制而成。这个钢铁手杖十分适合用来驱赶羊群。加强感知和力量 <%= attrs %> 点。魔法衣橱:钢铁号角系列(第3件物品)", - "weaponArmoireGoldWingStaffText": "Gold Wing Staff", + "weaponArmoireGoldWingStaffText": "金翅法仗", "weaponArmoireGoldWingStaffNotes": "The wings on this staff constantly flutter and twist. Increases all attributes by <%= attrs %> each. Enchanted Armoire: Independent Item.", - "weaponArmoireBatWandText": "Bat Wand", + "weaponArmoireBatWandText": "蝙蝠法仗", "weaponArmoireBatWandNotes": "This wand can turn any task into a bat! Wave it about and watch them fly away. Increases Intelligence by <%= int %> and Perception by <%= per %>. Enchanted Armoire: Independent Item.", "weaponArmoireShepherdsCrookText": "Shepherd's Crook", "weaponArmoireShepherdsCrookNotes": "Useful for herding gryphons. Increases Constitution by <%= con %>. Enchanted Armoire: Shepherd Set (Item 1 of 3).", @@ -263,7 +263,7 @@ "armorSpecialSpring2015MageNotes": "你的燕尾服尾巴很配你的棉尾巴哦!提高<%= int %>点智力。2015春季限定版装备。", "armorSpecialSpring2015HealerText": "抚慰连衣裤", "armorSpecialSpring2015HealerNotes": "这条柔软的连衣裤非常舒适,就像薄荷茶一样抚慰人心。提高<%= con %>点体质。2015春季限定版装备。", - "armorSpecialSummer2015RogueText": "Ruby Tail", + "armorSpecialSummer2015RogueText": "红宝石尾", "armorSpecialSummer2015RogueNotes": "This garment of shimmering scales transforms its wearer into a real Reef Renegade! Increases Perception by <%= per %>. Limited Edition 2015 Summer Gear.", "armorSpecialSummer2015WarriorText": "黄金尾巴", "armorSpecialSummer2015WarriorNotes": "This garment of shimmering scales transforms its wearer into a real Sunfish Warrior! Increases Constitution by <%= con %>. Limited Edition 2015 Summer Gear.", diff --git a/common/locales/zh/generic.json b/common/locales/zh/generic.json index 26cc665844..e2bc440ed2 100644 --- a/common/locales/zh/generic.json +++ b/common/locales/zh/generic.json @@ -7,14 +7,14 @@ "collapseToolbar": "隐藏列表", "markdownBlurb": "Habitica uses markdown for message formatting. See the Markdown Cheat Sheet for more info.", "showFormattingHelp": "查看格式相关帮助", - "hideFormattingHelp": "Hide formatting help", + "hideFormattingHelp": "缩小格式相关帮助", "youType": "你输入了:", "youSee": "你会看到:", "italics": "*Italics*", "bold": "**Bold**", "strikethrough": "~~Strikethrough~~", "emojiExample": ":笑:", - "markdownLinkEx": "[Habitica is great!](https://habitica.com)", + "markdownLinkEx": "[Habitica 真好!](https://habitica.com)", "markdownImageEx": "![mandatory alt text](https://habitica.com/cake.png \"optional mouseover title\")", "unorderedListHTML": "+ First item
+ Second item
+ Third item", "unorderedListMarkdown": "+ First item\n+ Second item\n+ Third item", @@ -28,7 +28,7 @@ "market": "市场", "subscriberItem": "神秘物品", "newSubscriberItem": "新的神秘物品", - "subscriberItemText": "Each month, subscribers will receive a mystery item. This is usually released about one week before the end of the month. See the wiki's 'Mystery Item' page for more information.", + "subscriberItemText": "每月,定期捐款者会收到一个神秘物品。这物品一般是在月底前一个月推出。Wiki里的‘神秘物品’网址将有更多信息。", "all": "全部", "none": "无", "or": "或", @@ -65,7 +65,7 @@ "habitBirthdayText": "欢庆Habitica的生日派对", "habitBirthdayPluralText": "欢庆第<%= number %>个 Habitica生日派对", "habiticaDay": "Habitica命名日", - "habiticaDaySingularText": "Celebrated Habitica's Naming Day! Thanks for being a fantastic user.", + "habiticaDaySingularText": "庆祝了Habitica的命名日!谢谢您陪伴我们,客户朋友!", "habiticaDayPluralText": "Celebrated <%= number %> Naming Days! Thanks for being a fantastic user.", "achievementDilatory": "拖延的救世者", "achievementDilatoryText": "2014年夏季世界事件中协助打败了恐怖的拖延巨龙!", @@ -91,8 +91,8 @@ "audioTheme_off": "关", "audioTheme_danielTheBard": "诗人丹尼尔", "audioTheme_wattsTheme": "瓦特的主题", - "audioTheme_gokulTheme": "Gokul Theme", - "audioTheme_luneFoxTheme": "LuneFox's Theme", + "audioTheme_gokulTheme": "郭克的主题", + "audioTheme_luneFoxTheme": "鲁聂狐狸的主题", "askQuestion": "问个问题", "reportBug": "报告一个问题", "contributeToHRPG": "为Habitica作出贡献", @@ -112,27 +112,39 @@ "dateFormat": "日期格式", "achievementStressbeast": "Stoïkalm的救星", "achievementStressbeastText": "Helped defeat the Abominable Stressbeast during the 2014 Winter Wonderland Event!", - "achievementBurnout": "Savior of the Flourishing Fields", + "achievementBurnout": "全盛田野的救护者", "achievementBurnoutText": "Helped defeat Burnout and restore the Exhaust Spirits during the 2015 Fall Festival Event!", - "checkOutProgress": "Check out my progress in Habitica!", - "cardReceived": "Received a card!", + "checkOutProgress": "看一下我在Habitica的进步!", + "cardReceived": "收到一个卡片!", "cardReceivedFrom": "<%= cardType %> from <%= userName %>", - "greetingCard": "Greeting Card", - "greetingCardExplanation": "You both receive the Cheery Chum achievement!", - "greetingCardNotes": "Send a greeting card to a party member.", - "greeting0": "Hi there!", - "greeting1": "Just saying hello :)", - "greeting2": "`waves frantically`", - "greeting3": "Hey you!", - "greetingCardAchievementTitle": "Cheery Chum", + "greetingCard": "祝贺卡", + "greetingCardExplanation": "你俩都获得“欢乐伙伴”的成就!", + "greetingCardNotes": "给一个队伍者个祝贺卡。", + "greeting0": "嗨!你好!", + "greeting1": "就说声你好 :)", + "greeting2": "`疯狂的招手`", + "greeting3": "嗨!喊你呐!", + "greetingCardAchievementTitle": "快乐伙伴", "greetingCardAchievementText": "Hey! Hi! Hello! Sent or received <%= cards %> greeting cards.", "thankyouCard": "Thank-You Card", "thankyouCardExplanation": "You both receive the Greatly Grateful achievement!", "thankyouCardNotes": "Send a Thank-You card to a party member.", "thankyou0": "Thank you very much!", "thankyou1": "Thank you, thank you, thank you!", - "thankyou2": "Sending you a thousand thanks.", + "thankyou2": "万谢,万谢!", "thankyou3": "I'm very grateful - thank you!", "thankyouCardAchievementTitle": "Greatly Grateful", - "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards." + "thankyouCardAchievementText": "Thanks for being thankful! Sent or received <%= cards %> Thank-You cards.", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/zh/messages.json b/common/locales/zh/messages.json index a210354183..126ee8c6ae 100644 --- a/common/locales/zh/messages.json +++ b/common/locales/zh/messages.json @@ -44,11 +44,11 @@ "messageGroupOnlyLeaderCanUpdate": "只有小组官员才可以更新小组信息", "messageGroupRequiresInvite": "无法加入没有邀请你的小组", "messageGroupCannotRemoveSelf": "你不能将自己移除", - "messageGroupChatBlankMessage": "You cannot send a blank message", - "messageGroupChatLikeOwnMessage": "Can't like your own message. Don't be that person.", + "messageGroupChatBlankMessage": "你不能发送空白消息", + "messageGroupChatLikeOwnMessage": "不能赞自己的消息,不要做这种人。", "messageGroupChatFlagOwnMessage": "Can't report your own message.", "messageGroupChatFlagAlreadyReported": "You have already reported this message", - "messageGroupChatNotFound": "Message not found!", + "messageGroupChatNotFound": "找不到消息。", "messageGroupChatAdminClearFlagCount": "Only an admin can clear the flag count!", "messageUserOperationProtected": "path `<%= operation %>` was not saved, as it's a protected path.", "messageUserOperationNotFound": "<%= operation %> operation not found" diff --git a/common/locales/zh/npc.json b/common/locales/zh/npc.json index d146951176..d23659587a 100644 --- a/common/locales/zh/npc.json +++ b/common/locales/zh/npc.json @@ -11,10 +11,10 @@ "danielText2Broken": "哦……如果你正在一场BOSS战当中,你仍然会因为队友未完成的每日任务受到BOSS的伤害……同样,你对Boss的伤害(或者道具的收集)在你离开客栈之前不会结算……", "alexander": "商人Alexander", "welcomeMarket": "欢迎来到市场!在这里购买稀有的蛋和药水!卖掉你多余的物品!委托服务!来瞧瞧我们能为你提供什么。", - "displayItemForGold": "Do you want to sell a <%= itemType %>?", - "displayEggForGold": "Do you want to sell a <%= itemType %> Egg?", - "displayPotionForGold": "Do you want to sell a <%= itemType %> Potion?", - "sellForGold": "Sell it for <%= gold %> Gold", + "displayItemForGold": "你希望出售一个<%= itemType %>吗?", + "displayEggForGold": "你希望出售一个<%= itemType %> 蛋吗?", + "displayPotionForGold": "你希望出售一个<%= itemType %> 药剂吗?", + "sellForGold": "售出,获得 <%= gold %> 金币", "buyGems": "购买宝石", "justin": "Justin", "ian": "岚", diff --git a/common/locales/zh/pets.json b/common/locales/zh/pets.json index 9f19b4f74b..c590dca400 100644 --- a/common/locales/zh/pets.json +++ b/common/locales/zh/pets.json @@ -58,8 +58,16 @@ "firstDrop": "你解锁了物品掉落功能!从今以后,只要你完成每个任务都会有一定的几率能找到一件物品,包括蛋,药水和食物。刚刚你找到了一颗<%= eggText %>蛋!<%= eggNotes %>", "useGems": "如果你很想拥有某只宠物,但又不想慢慢等蛋掉落的话,你可以在 物品柜>市场用宝石购买!", "hatchAPot": "孵化一隻<%= potion %><%= egg %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "喂你的<%= name %>一个<%= article %><%= text %>?", "useSaddle": "把鞍用在<%= pet %>上?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "狗舍的钥匙", diff --git a/common/locales/zh/quests.json b/common/locales/zh/quests.json index be9d645351..2de3a0bcd9 100644 --- a/common/locales/zh/quests.json +++ b/common/locales/zh/quests.json @@ -13,7 +13,7 @@ "youReceived": "你收到了", "dropQuestCongrats": "恭喜得到探索任务卷轴!你可以现在立即邀请队伍并开始任务,或以后再从你的物品栏>任务里开始该任务。", "questSend": "点击\"邀请\" 向队友发送一封邀请函。当所有队友都回应接受或拒绝,任务就会开始。在社交>队伍查看详细。", - "questSendBroken": "Clicking \"Invite\" will send an invitation to your party members... When all members have accepted or denied, the quest begins... See status under Social > Party...", + "questSendBroken": "点击\"邀请\" 向队友发送一封邀请函。当所有队友都回应接受或拒绝,任务就会开始。在社交>队伍查看详细。", "inviteParty": "邀请队伍参加探索任务", "questInvitation": "任务邀请:", "questInvitationTitle": "任务邀请", @@ -25,7 +25,7 @@ "rejected": "拒绝的", "pending": "等待中", "questStart": "一旦所有成员都接受或拒绝,任务就开始了。只有那些点击“接受”者可以参加任务并取得掉落物。如果成员回应时间太长(无活动?),任务拥有者可以透过点击“开始”,略过他们启动任务。任务拥有者还可以透过点击“取消”取消任务,并恢复任务卷轴。", - "questStartBroken": "Once all members have either accepted or rejected, the quest begins... Only those that clicked \"accept\" will be able to participate in the quest and receive the drops... If members are pending too long (inactive?), the quest owner can start the quest without them by clicking \"Begin\"... The quest owner can also cancel the quest and regain the quest scroll by clicking \"Cancel\"...", + "questStartBroken": "一旦所有成员都接受或拒绝,任务就开始了。只有那些点击“接受”者可以参加任务并取得掉落物。如果成员回应时间太长(无活动?),任务拥有者可以透过点击“开始”,略过他们启动任务。任务拥有者还可以透过点击“取消”取消任务,并恢复任务卷轴。", "begin": "开始", "bossHP": "Boss的生命值", "bossStrength": "Boss的力量", @@ -35,15 +35,15 @@ "collectionItems": "<%= number %> <%= items %>", "itemsToCollect": "需要收集的道具", "bossDmg1": "每一个完成的每日任务和待办事项,或是每培养一次好习惯都能攻击到BOSS。完成更加红色的任务或使用碎裂一击及火球术能给BOSS造成更多伤害。除了你自己的日常任务外,一旦队伍中的任何一人错过了自己的每日任务,你都会从BOSS那里受到额外的伤害值 (按BOSS的力量值成倍增加)! 所有对BOSS和来自BOSS的伤害会在重置时间进行结算 (你的日常重置时间)", - "bossDmg2": "只有参与者会跟boss战斗并共享任务掉落。", - "bossDmg1Broken": "Each completed Daily and To-Do and each positive Habit hurts the boss... Hurt it more with redder tasks or Brutal Smash and Burst of Flames... The boss will deal damage to every quest participant for every Daily you've missed (multiplied by the boss's Strength) in addition to your regular damage, so keep your party healthy by completing your Dailies... All damage to and from a boss is tallied on cron (your day roll-over)...", - "bossDmg2Broken": "Only participants will fight the boss and share in the quest loot...", - "tavernBossInfo": "Complete Dailies and To-Dos and score positive Habits to damage the World Boss! Incomplete Dailies fill the Exhaust Strike Bar. When the Exhaust Strike bar is full, the World Boss will attack an NPC. A World Boss will never damage individual players or accounts in any way. Only active accounts not resting in the Inn will have their tasks tallied.", - "tavernBossInfoBroken": "Complete Dailies and To-Dos and score positive Habits to damage the World Boss... Incomplete Dailies fill the Exhaust Strike Bar... When the Exhaust Strike bar is full, the World Boss will attack an NPC... A World Boss will never damage individual players or accounts in any way... Only active accounts not resting in the Inn will have their tasks tallied...", + "bossDmg2": "只有参与者才能与boss战斗并共享任务掉落。", + "bossDmg1Broken": "每一个完成的每日任务和待办事项,或是每培养一次好习惯都能攻击到BOSS。完成深红色的任务或使用碎裂一击及火球术能给BOSS造成更多伤害。除了你自己的日常任务外,一旦队伍中的任何一人未完成自己的每日任务,你都会从BOSS那里受到额外的伤害值 (按BOSS的力量值成倍增加)! 所有对BOSS和来自BOSS的伤害会在重置时间进行结算 (你的日常重置时间)", + "bossDmg2Broken": "只有参与者才能跟boss战斗并共享任务掉落。", + "tavernBossInfo": "通过完成每日任务、待办事项或记录好习惯来打败世界Boss!未完成的每日任务会填充颓废打击进度条,当颓废打击进度条满的时候,世界Boss会攻击1个NPC。世界Boss不会攻击个人或账户。没有在客栈的玩家才能执行该任务。", + "tavernBossInfoBroken": "通过完成每日任务、待办事项或记录好习惯来打败世界Boss!未完成的每日任务会填充BOSS的颓废值,当它颓废值满的时候会攻击1个NPC。世界Boss不会攻击个人或账户。另外,只有不在客栈的玩家才能做这个任务。", "bossColl1": "为了收集物品,做那些正的任务。任务物品会像正常物品一样掉落;但是你直到第二天才能看得见这些掉落,然后找到的所有物品会被结算然后堆叠到一起。", "bossColl2": "只有参与者才能收集物品并共享任务掉落。", - "bossColl1Broken": "To collect items, do your positive tasks... Quest items drop just like normal items; however, you won't see the drops until the next day, then everything you've found will be tallied up and contributed to the pile...", - "bossColl2Broken": "Only participants can collect items and share in the quest loot...", + "bossColl1Broken": "做一些任务和好习惯来收集任务物品…任务物品会像其它正常的物品一样掉落;但是你在第二天才能看到这些任务物品的掉落,之后所有的任务物品将堆叠在一起统一结算。", + "bossColl2Broken": "只有参与者才能收集物品并共享任务掉落。", "abort": "舍弃", "leaveQuest": "放弃任务", "sureLeave": "你确定你要舍弃这个任务吗?这样做会消除所有进度。", @@ -70,11 +70,13 @@ "sureAbort": "你是否确定要放弃这个任务?这样做会让你的所有队员都退出这个任务,并且消除所有进度。任务卷轴将会回到任务拥有者手上。", "doubleSureAbort": "你真的真的要这样做吗?要确保他们不会讨厌你一辈子哟!", "questWarning": "如果一个新的小队成员在任务开始前加入,他们会收到一个邀请。但是一旦任务开始了,新成员就无法再加入这个任务了。", - "questWarningBroken": "If new players join the party before the quest starts, they will also receive an invitation... However once the quest has started, no new party members can join the quest...", - "bossRageTitle": "愤怒值", + "questWarningBroken": "如果一个新的小队成员在任务开始前加入,他们会收到一个邀请。但是一旦任务开始了,新成员就无法再加入这个任务了……", + "bossRageTitle": "怒气值", "bossRageDescription": "当这个条满的时候,boss会释放一个特殊攻击!", "startAQuest": "开始一个探索任务", "startQuest": "开始探索任务", "whichQuestStart": "你想要开始哪个探索任务?", - "getMoreQuests": "获取更多探索任务" + "getMoreQuests": "获取更多探索任务", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/zh/questscontent.json b/common/locales/zh/questscontent.json index e4be04a4e3..c667e92c0e 100644 --- a/common/locales/zh/questscontent.json +++ b/common/locales/zh/questscontent.json @@ -237,7 +237,7 @@ "questDilatoryDistress3Boss": "Adva, the Usurping Mermaid", "questDilatoryDistress3DropFish": "鱼(食物)", "questDilatoryDistress3DropWeapon": "Trident of Crashing Tides (Weapon)", - "questDilatoryDistress3DropShield": "Moonpearl Shield (Shield-Hand Item)", + "questDilatoryDistress3DropShield": "玉轮明珠盾(手持防御物品)", "questCheetahText": "真是一个猎豹", "questCheetahNotes": "As you hike across the Sloensteadi Savannah with your friends @PainterProphet, @tivaquinn, @Unruly Hyena, and @Crawford, you're startled to see a Cheetah screeching past with a new Habitican clamped in its jaws. Under the Cheetah's scorching paws, tasks burn away as though complete -- before anyone has the chance to actually finish them! The Habitican sees you and yells, \"Please help me! This Cheetah is making me level too quickly, but I'm not getting anything done. I want to slow down and enjoy the game. Make it stop!\" You fondly remember your own fledgling days, and know that you have to help the newbie by stopping the Cheetah!", "questCheetahCompletion": "The new Habitican is breathing heavily after the wild ride, but thanks you and your friends for your help. \"I'm glad that Cheetah won't be able to grab anyone else. It did leave some Cheetah eggs for us, so maybe we can raise them into more trustworthy pets!\"", @@ -247,7 +247,7 @@ "questHorseText": "Ride the Night-Mare", "questHorseNotes": "While relaxing in the Tavern with @beffymaroo and @JessicaChase, the talk turns to good-natured boasting about your adventuring accomplishments. Proud of your deeds, and perhaps getting a bit carried away, you brag that you can tame any task around. A nearby stranger turns toward you and smiles. One eye twinkles as he invites you to prove your claim by riding his horse.\nAs you all head for the stables, @UncommonCriminal whispers, \"You may have bitten off more than you can chew. That's no horse - that's a Night-Mare!\" Looking at its stamping hooves, you begin to regret your words...", "questHorseCompletion": "It takes all your skill, but finally the horse stamps a couple of hooves and nuzzles you in the shoulder before allowing you to mount. You ride briefly but proudly around the Tavern grounds while your friends cheer. The stranger breaks into a broad grin.\n\"I can see that was no idle boast! Your determination is truly impressive. Take these eggs to raise horses of your own, and perhaps we'll meet again one day.\" You take the eggs, the stranger tips his hat... and vanishes.", - "questHorseBoss": "Night-Mare", + "questHorseBoss": "夜魇", "questHorseDropHorseEgg": "马(蛋)", "questHorseUnlockText": "解锁购买马蛋功能", "questBurnoutText": "Burnout and the Exhaust Spirits", @@ -262,10 +262,16 @@ "questBurnoutBossRageQuests": "`Burnout uses EXHAUST STRIKE!`\n\nOh no! Despite our best efforts, we've let some Dailies get away from us, and now Burnout is inflamed with energy! With a crackling snarl, it engulfs Ian the Quest Master in a surge of spectral fire. As fallen quest scrolls smolder, the smoke clears, and you see that Ian has been drained of energy and turned into a drifting Exhaust Spirit!\n\nOnly defeating Burnout can break the spell and restore our beloved Quest Master. Let's keep our Dailies in check and defeat this monster before it attacks again!", "questBurnoutBossRageSeasonalShop": "`Burnout uses EXHAUST STRIKE!`\n\nAhh!!! Our incomplete Dailies have fed the flames of Burnout, and now it has enough energy to strike again! It lets loose a gout of spectral flame that sears the Seasonal Shop. You're horrified to see that the cheery Seasonal Sorceress has been transformed into a drooping Exhaust Spirit.\n\nWe have to rescue our NPCs! Hurry, Habiticans, complete your tasks and defeat Burnout before it strikes for a third time!", "questBurnoutBossRageTavern": "`Burnout uses EXHAUST STRIKE!`\n\nMany Habiticans have been hiding from Burnout in the Tavern, but no longer! With a screeching howl, Burnout rakes the Tavern with its white-hot hands. As the Tavern patrons flee, Daniel is caught in Burnout's grip, and transforms into an Exhaust Spirit right in front of you!\n\nThis hot-headed horror has gone on for too long. Don't give up... we're so close to vanquishing Burnout for once and for all!", - "questFrogText": "Swamp of the Clutter Frog", + "questFrogText": "蛙泽", "questFrogNotes": "As you and your friends are slogging through the Swamps of Stagnation, @starsystemic points at a large sign. \"Stay on the path -- if you can.\"

\"Surely that isn't hard!\" @RosemonkeyCT says. \"It's broad and clear.\"

But as you continue, you notice that path is gradually overtaken by the muck of the swamp, laced with bits of strange blue debris and clutter, until it's impossible to proceed.

As you look around, wondering how it got this messy, @Jon Arjinborn shouts, \"Look out!\" An angry frog leaps from the sludge, clad in dirty laundry and lit by blue fire. You will have to overcome this poisonous Clutter Frog to progress!", "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "一群青蛙", "questFrogDropFrogEgg": "青蛙 (宠物蛋)", - "questFrogUnlockText": "解锁购买青蛙蛋功能" + "questFrogUnlockText": "解锁购买青蛙蛋功能", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/zh/rebirth.json b/common/locales/zh/rebirth.json index 81985bb42d..0e5605d115 100644 --- a/common/locales/zh/rebirth.json +++ b/common/locales/zh/rebirth.json @@ -16,11 +16,11 @@ "rebirthEarnAchievement": "你会因为开始一段新冒险而获得一个成就!", "beReborn": "重生", "rebirthAchievement": "你开始了一段新冒险!这是你的第<%= number %>次冒险,你曾经获得的最高级别是<%= level %>级。有这个成就加持,当你开始下一次新冒险会达到更高的水平!", - "rebirthAchievement100": "You've begun a new adventure! This is Rebirth <%= number %> for you, and the highest Level you've attained is 100 or higher. To stack this Achievement, begin your next new adventure when you've reached at least 100!", + "rebirthAchievement100": "你开始了一段新冒险!这是你的第<%= number %>次冒险,你曾经获得的最高级别是100或更高的等级。有这个成就加持,当你达到至少100级时,开始下一次新的冒险!", "rebirthBegan": "开始新的冒险", "rebirthText": "开始了<%= rebirths %> 个新的冒险", "rebirthOrb": "使用重生球来重新开始获得级别", - "rebirthOrb100": "Used an Orb of Rebirth to start over after attaining Level 100 or higher", + "rebirthOrb100": "在达到100级或更高等级的情况下,使用重生之球重新开始", "rebirthPop": "开始一个1级的新角色并保留成就,物品和任务历史。", "rebirthName": "重生球", "reborn": "重生, 最高级别 <%= reLevel %>" diff --git a/common/locales/zh/settings.json b/common/locales/zh/settings.json index fa74b0ee95..1880d4d41b 100644 --- a/common/locales/zh/settings.json +++ b/common/locales/zh/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "选择这个选项后,展开编辑新任务的时候标签列表是隐藏的。", "startAdvCollapsed": "默认隐藏高级选项", "startAdvCollapsedPop": "选择这个选项后,展开编辑新任务的时候高级选项是隐藏的。", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "显示教程", "restartTour": "重新开始刚加入Habitica时显示的教程", "showBailey": "显示Bailey", @@ -81,7 +86,6 @@ "emailChange1": "要改变你的邮箱地址,请发送邮件到", "emailChange2": "admin@habitica.com", "emailChange3": "包括你的新旧邮箱地址以及你的用户ID。", - "username": "登陆名", "usernameOrEmail": "登录用户名或者邮箱", "email": "邮箱", "registeredWithFb": "通过 Facebook 注册", @@ -89,7 +93,7 @@ "loginNameDescription2": "用户 -> 档案", "loginNameDescription3": "来改变你显示在你的角色形象和聊天信息中的名字。", "emailNotifications": "电子邮件通知", - "wonChallenge": "你赢得了挑战", + "wonChallenge": "You won a Challenge!", "newPM": "收到悄悄话", "giftedGems": "自然宝石", "giftedGemsInfo": "<%= amount %> 宝石 - 来自 <%= name %>", @@ -129,14 +133,14 @@ "enabled": "已启用", "webhookURL": "Webhook链接", "add": "添加", - "buyGemsGoldCap": "Cap raised to <%= amount %>", + "buyGemsGoldCap": "上限提升至 <%= amount %>", "mysticHourglass": "<%= amount %> 个神秘沙漏", "mysticHourglassText": "神秘沙漏能让你购买几个月之前的神秘道具套装。", - "purchasedPlanId": "Recurring $<%= price %> each <%= months %> Month(s) (<%= plan %>)", + "purchasedPlanId": "每 <%= months %> (月)充值 $<%= price %> (<%= plan %>)", "purchasedPlanExtraMonths": "你的剩余捐助时长为: <%= months %> 个月", "consecutiveSubscription": "连续捐助", "consecutiveMonths": "持续的月份:", - "gemCapExtra": "Gem Cap Extra:", + "gemCapExtra": "宝石额外上限:", "mysticHourglasses": "神秘沙漏:", "paypal": "PayPal", "amazonPayments": "亚马逊支付" diff --git a/common/locales/zh_TW/backgrounds.json b/common/locales/zh_TW/backgrounds.json index 6aef3f5d84..48f26a2c2b 100644 --- a/common/locales/zh_TW/backgrounds.json +++ b/common/locales/zh_TW/backgrounds.json @@ -119,11 +119,11 @@ "backgroundSlimySwampNotes": "跋涉過黏糊糊的沼澤", "backgroundSwarmingDarknessText": "蜂擁黑暗", "backgroundSwarmingDarknessNotes": "在蜂擁黑暗瑟瑟發抖", - "backgrounds112015": "SET 18: Released November 2015", - "backgroundFloatingIslandsText": "Floating Islands", - "backgroundFloatingIslandsNotes": "Hop across the Floating Islands.", - "backgroundNightDunesText": "Night Dunes", - "backgroundNightDunesNotes": "Walk peacefully through the Night Dunes.", - "backgroundSunsetOasisText": "Sunset Oasis", - "backgroundSunsetOasisNotes": "Bask in the Sunset Oasis." + "backgrounds112015": "第 18 組:2015 年 11 月推出", + "backgroundFloatingIslandsText": "漂浮島", + "backgroundFloatingIslandsNotes": "跳躍過整座漂浮島", + "backgroundNightDunesText": "夜之砂丘", + "backgroundNightDunesNotes": "悠哉地散步過夜之砂丘", + "backgroundSunsetOasisText": "日落綠洲", + "backgroundSunsetOasisNotes": "在日落綠洲裡面曬曬夕陽" } \ No newline at end of file diff --git a/common/locales/zh_TW/challenge.json b/common/locales/zh_TW/challenge.json index d9094b414f..1850e7c48c 100644 --- a/common/locales/zh_TW/challenge.json +++ b/common/locales/zh_TW/challenge.json @@ -60,6 +60,8 @@ "noPermissionEditChallenge": "你沒有權限更動這個挑戰的內容", "noPermissionDeleteChallenge": "你沒有權限撤回這個挑戰要求", "noPermissionCloseChallenge": "你沒有權限關閉這個挑戰", - "noChallengeOwner": "no owner", - "noChallengeOwnerPopover": "This challenge does not have an owner because the person who created the challenge deleted their account." + "congratulations": "Congratulations!", + "hurray": "Hurray!", + "noChallengeOwner": "無人擁有", + "noChallengeOwnerPopover": "由於開創這個挑戰的人已經刪除他們的帳號,所以這個挑戰無人擁有。" } \ No newline at end of file diff --git a/common/locales/zh_TW/character.json b/common/locales/zh_TW/character.json index 8c1cda2e00..55080af12f 100644 --- a/common/locales/zh_TW/character.json +++ b/common/locales/zh_TW/character.json @@ -52,11 +52,11 @@ "classEquipBonus": "職業加成", "battleGear": "戰鬥裝備", "battleGearText": "這是你帶上戰場的裝備,在你做任務時會影響一些數值。", - "autoEquipBattleGear": "Auto-equip new gear", + "autoEquipBattleGear": "自動裝上新裝備", "costume": "服裝", "costumeText": "如果你喜歡其他裝備的外觀更勝於你現在的裝備,勾選\"使用服裝\"框穿上想被看到的服裝,而你的戰鬥裝備會穿在裡面。", "useCostume": "使用服裝", - "useCostumeInfo1": "點選\"使用服裝\"可以讓你的角色圖像裝備而不改變實際在戰鬥裡的數值(只改變外觀),也就是說妳可以隨意裝扮你的角色圖像,雖然他們並不是最強的戰鬥配置。", + "useCostumeInfo1": "點選\"使用服裝\"可以讓你的角色圖像裝備而不改變實際在戰鬥裡的數值(只改變外觀),也就是說你可以隨意裝扮你的角色圖像,雖然他們並不是最強的戰鬥配置。", "useCostumeInfo2": "當你第一次按下\"使用服裝\"時,你的頭像看起來會很簡陋...不過沒關係,可以看到畫面左邊武器裝備的狀態還在,接下來可以在畫面右邊隨意穿上各種裝備,這雖不會影響到實際戰鬥數據,但是看起來十分帥氣!試著組合所有武器、防具、寵物、坐騎、還有背景

有問題嗎?在遊戲維基裡看一看 這個 on 找到你最佳的組合?到這裡或是酒館秀給大家看吧!", "gearAchievement": "你已達成「終極裝備」成就:升級到最高裝備!你已完成以下組合:", "moreGearAchievements": "欲取得終極裝備徽章,到這裡選擇職業並開始購買職業專屬物品!", @@ -65,6 +65,10 @@ "ultimGearText": "已升級到此種職業之最高武器和盔甲:", "level": "等級", "levelUp": "升級了!", + "gainedLevel": "You gained a level!", + "leveledUp": "By accomplishing your real-life goals, you've grown to Level <%= level %>!", + "fullyHealed": "You have been fully healed!", + "huzzah": "Huzzah!", "mana": "魔力", "hp": "HP", "mp": "MP", diff --git a/common/locales/zh_TW/communityguidelines.json b/common/locales/zh_TW/communityguidelines.json index 1e02923ee3..554ea51eeb 100644 --- a/common/locales/zh_TW/communityguidelines.json +++ b/common/locales/zh_TW/communityguidelines.json @@ -44,7 +44,7 @@ "commGuidePara019": "在個人空間中, 玩家能更自由的討論任何喜歡的話題,但是,他們仍不能違反條款與要求,包括發布任何歧視性的、暴力的、恐嚇性的內容。", "commGuidePara020": "私人信息(私信)有一些附加要求。如果某人將你加入黑名單,請不要在任何別的地方聯繫對方要求解除。並且你不應該用私信來尋求幫助(對幫助問題的公開回答會幫助整個社區)。最後,不要給任何人發私信要求寶石或訂閱來作為禮物,因為這樣的行為會被認為是在發送垃圾信息。", "commGuidePara021": "此外,Habit大陸中的一些公共區域還有另外的準則.", - "commGuideHeadingTavern": "旅店", + "commGuideHeadingTavern": "酒館", "commGuidePara022": "酒館是Habiticans交流的地方。酒館主人Daniel將店裡打理得一塵不染,Lemoness樂意在你坐下來聊天時,變出一杯檸檬水。只是要記住……", "commGuidePara023": "話題往往圍繞閒聊和提高生產力或改善生活的技巧。", "commGuidePara024": "因為酒館只能保留200條信息,所以它不是個適合延長話題的地方,尤其是敏感話題 (例如政治、宗教、抑鬱等,即使是獵殺哥布林的話題也應被禁止)。這些討論必需符合相關準則或是the Back Corner(詳情參見下方信息)。", diff --git a/common/locales/zh_TW/content.json b/common/locales/zh_TW/content.json index 9a02ee0c58..84ec2ad74a 100644 --- a/common/locales/zh_TW/content.json +++ b/common/locales/zh_TW/content.json @@ -95,9 +95,12 @@ "questEggHorseText": "馬", "questEggHorseMountText": "馬", "questEggHorseAdjective": "一隻奔馳的", - "questEggFrogText": "Frog", - "questEggFrogMountText": "Frog", - "questEggFrogAdjective": "a princely", + "questEggFrogText": "青蛙", + "questEggFrogMountText": "青蛙", + "questEggFrogAdjective": "一隻王子般的", + "questEggSnakeText": "Snake", + "questEggSnakeMountText": "Snake", + "questEggSnakeAdjective": "a slithering", "eggNotes": "找瓶孵化藥水倒在這顆蛋上,接著等蛋孵化出<%= eggAdjective(locale) %> <%= eggText(locale) %>。", "hatchingPotionBase": "普通", "hatchingPotionWhite": "白色", diff --git a/common/locales/zh_TW/faq.json b/common/locales/zh_TW/faq.json index 429a107661..e160a8dc79 100644 --- a/common/locales/zh_TW/faq.json +++ b/common/locales/zh_TW/faq.json @@ -16,7 +16,7 @@ "iosFaqAnswer4": "有很多方式都會減少角色的生命值。第一,如果你沒有如期完成每日任務的話,角色會在隔天受到傷害。第二,如果你做了壞習慣,它也會使生命值受損。最後,若你正在隊伍裡並且處於活動任務捲軸狀態的話,如果隊友沒有乖乖完成他自己的每日任務,那麼任務魔王也會攻擊你喔。\n\n主要回復生命值的方法就是提升等級,當你升等就會自動補足生命值。你也可以用金幣購買獎勵框框裡的治療藥水。另外,當你等級大於或等於10時,你可以選擇成為醫者,這樣一來你就能夠學習治癒術。或者你的隊伍中「社交」>「隊伍」,有人是醫者的話,可以請他們治療你喔。", "webFaqAnswer4": "有很多方式都會減少角色的生命值。第一,如果你沒有如期完成每日任務的話,角色會在隔天受到傷害。第二,如果你做了壞習慣,它也會使生命值受損。最後,若你正在隊伍裡並且處於活動任務捲軸狀態的話,如果隊友沒有乖乖完成他自己的每日任務,那麼任務魔王也會攻擊你喔。

\n主要回復生命值的方法就是提升等級,當你升等就會自動補足生命值。你也可以用金幣購買獎勵框框裡的治療藥水。另外,當你等級大於或等於10時,你可以選擇成為醫者,這樣一來你就能夠學習治癒術。或者你的隊伍中 (「社交」> 「隊伍」),有人是醫者的話,可以請他們治療你喔。", "faqQuestion5": "要怎麼做才能夠跟朋友一起玩Habitica?", - "iosFaqAnswer5": "The best way is to invite them to a Party with you! Parties can go on quests, battle monsters, and cast skills to support each other. Go to Menu > Party and click \"Create New Party\" if you don't already have a Party. Then tap on the Members list, and tap Invite in the upper right-hand corner to invite your friends by entering their User ID (a string of numbers and letters that they can find under Settings > Account Details on the app, and Settings > API on the website). On the website, you can also invite friends via email, which we will add to the app in a future update.\n\nOn the website, you and your friends can also join Guilds, which are public chat rooms. Guilds will be added to the app in a future update!", + "iosFaqAnswer5": "最好的方法就是邀請他們加入你的隊伍!隊伍可以參加活動任務、跟魔王對抗、施放技能來支援彼此。如果你並沒有加入任一隊伍的話,可前往選單>隊伍,接著點選\"建立新隊伍\"。然後點選成員名單,就可以在右上角看到邀請朋友選項,輸入他們的使用者ID (UUID:一串由數字和英文字母組成的字串,每個人都可以在手機app中的設定 >帳號 ,或是網站裡的設定 >API 裡面找到自己的UUID。)在網站上,你還可以用電子郵件邀請朋友,而這項功能也會增加到之後的app更新中。\n\n在網站裡你可以和朋友加入公會,裡面有一個公共的聊天室。公會也會增加到之後的app更新中。", "webFaqAnswer5": "最好的方法就是邀請他們跟你一起加入隊伍,選擇「社交」>「隊伍」。隊伍可以參加任務捲軸、和魔王對抗、使用技能來支援彼此。你也可以加入公會 (「社交」>「公會」),公會裡面有聊天室,你可以在上面分享些新鮮事或者說說你想要達成的好習慣目標,你可以自由的選擇要公開聊天或者私下。公會可以重複加入數個,但是隊伍一次只能加入一組喔!\n

\n想要知道更多資訊,請點選我們的wiki頁面 [隊伍](http://habitrpg.wikia.com/wiki/Party) and [公會](http://habitrpg.wikia.com/wiki/Guilds)", "faqQuestion6": "我要怎麼做才能得到寵物或是坐騎呢?", "iosFaqAnswer6": "當你等級升到3的時候,就會解鎖掉落系統。每當你完成任務時,你就會有一定的機率收到寵物蛋、孵化藥水,或是餵養寵物的食物。當你收到時系統就會自動存入「選單」>「物品」。\n\n想要孵化寵物,你需要同時擁有寵物蛋和孵化藥水各一。點選寵物蛋確認你要孵化的種類,接著點擊「孵化」,然後選擇孵化藥水就能夠確認寵物的顏色囉!孵化完成後你可以到「選單」>「寵物」將你的寵物裝備到角色上。\n\n你也可以用餵食的方式讓寵物進化成坐騎。點選寵物選擇「餵食」,你會看到一條綠色的狀態列隨著你餵食次數而增長,當狀態列額滿後就會進化成坐騎。這需要花點時間,不過如果你能找到寵物最喜歡的食物,就可以加速寵物進化的速度囉!請多多嘗試食物種類或者看這個[see the spoilers here]。(http://habitica.wikia.com/wiki/Food#Food_Preferences)\n當你擁有了一隻座騎,你可以到「選單」>「坐騎」將它裝備到角色上。\n\n當你完成某些任務捲軸時,你也可能收到任務寵物蛋。(你可以看看下面有一些關於任務捲軸的介紹)。", @@ -28,17 +28,17 @@ "iosFaqAnswer8": "當你等級10的時候,除了能夠選擇職業外,還會出現一條藍色的狀態列,它是你的魔力值。當你繼續升等後,你還會陸續解鎖一些特殊的職業技能,使用技能會使你的魔力減少。每種職業都有各自獨特的技能,當等級11時你會在「選單」>「使用技能」內找到它們。魔力值不像生命值一樣會隨著你等級提升而補滿,它會因為你完成好習慣、每日任務和待辦事項而增加,也會因為你做了壞習慣而減少。順帶一提,每隔一天魔力值也會悄悄回復一點,當你完成越多每日任務,隔天也能補充越多魔力值喔。", "webFaqAnswer8": "當你等級10的時候,除了能夠選擇職業外,還會出現一條藍色的狀態列,它是你的魔力值。當你繼續升等後,你還會陸續解鎖一些特殊的職業技能,使用技能會使你的魔力減少。每種職業都有各自獨特的技能,當等級11時你會在主畫面右方的「獎勵」內找到它們。魔力值不像生命值一樣會隨著你等級提升而補滿,它會因為你完成好習慣、每日任務和待辦事項而增加,也會因為你做了壞習慣而減少。順帶一提,每隔一天魔力值也會悄悄回復一點,當你完成越多每日任務,隔天也能補充越多魔力值喔。", "faqQuestion9": "我要怎麼做才能夠攻擊魔王而且參與任務卷軸呢?", - "iosFaqAnswer9": "First, you need to join or start a Party (see above). Although you can battle monsters alone, we recommend playing in a group, because this will make Quests much easier. Plus, having a friend to cheer you on as you accomplish your tasks is very motivating!\n\n Next, you need a Quest Scroll, which are stored under Menu > Items. There are three ways to get a scroll:\n\n - At level 15, you get a Quest-line, aka three linked quests. More Quest-lines unlock at levels 30, 40, and 60 respectively. \n - When you invite people to your Party, you'll be rewarded with the Basi-List Scroll!\n - You can buy Quests from the Quests Page on the [website](https://habitica.com/#/options/inventory/quests) for Gold and Gems. (We will add this feature to the app in a future update.)\n\n To battle the Boss or collect items for a Collection Quest, simply complete your tasks normally, and they will be tallied into damage overnight. (Reloading by pulling down on the screen may be required to see the Boss's health bar go down.) If you are fighting a Boss and you missed any Dailies, the Boss will damage your Party at the same time that you damage the Boss. \n\n After level 11 Mages and Warriors will gain Skills that allow them to deal additional damage to the Boss, so these are excellent classes to choose at level 10 if you want to be a heavy hitter.", + "iosFaqAnswer9": "首先,你要先加入或者建立一個隊伍(往上滑有相關說明),當然你也可以獨自一人解任務,但我們還是推薦加入隊伍啦,因為多點人會比較輕鬆,而且跟朋友一起行動也比較能激勵你!\n\n接著,你要有一個任務捲軸,它會被存在「選單」>「物品」裡面。你有三種方式可以獲得捲軸:\n\n -當你等級15時,你會得到一個任務線,它是由三個任務組合而成的。而每當你等級達30級、40級、60級的時候,系統也會自動開啟各自的任務線。\n -當你邀請別人進入你的隊伍,你會得到一個基本任務卷軸做為獎勵。\n -你也可以在網站上的任務頁面裡,用金幣或寶石購買任務捲軸。[網站](https://habitica.com/#/options/inventory/quests) (我們往後也會新增這項功能在手機版上。) \n\n通常情況下,任務捲軸的任務會是和魔王決鬥或是收集特定物品,當你完成後它會在隔天顯示目前收集狀態或是魔王的生命值還剩多少。(你只需要按住螢幕往下拉就可以看到。)如果你在解任務途中錯過任何每日任務沒有完成的話,在你攻擊魔王的同時魔王也會攻擊你的隊員哦!\n\n在11 級過後,戰士和法師會有職業技能可以對魔王造成額外傷害,所以如果你現在已經等級10了,想成為一個優秀的前鋒就對著這兩個職業點下去吧!", "webFaqAnswer9": "首先,你要先加入或者創建一個隊伍(在「社交」>「隊伍」中),當然你也可以獨自一人解任務,但我們還是推薦你加入隊伍啦,因為多點人會比較輕鬆打卷軸,而且跟朋友一起行動也比較能激勵你!\n

\n接著,你要有一個任務卷軸,它會被存在「背包」>「任務」裡面。你有三種方式可以獲得卷軸:\n

\n*當你等級15時,你會得到一個任務線,它是由三個任務組合而成的。而每當你等級達30級、40級、60級的時候,系統也會自動開啟各自的任務線。\n\n*當你邀請別人進入你的隊伍,系統也會自動發送一個任務卷軸給你哦!\n\n*你也可以用金幣或是寶石購買任務捲軸。(在「背包」>「任務」中)\n

\n通常情況下,任務卷軸的任務會是和魔王決鬥或是收集特定物品,當你完成後它會在隔天顯示目前收集狀態或是魔王的生命值還剩多少。(你只需要重新整理網頁就可以看到。)如果你在解任務途中錯過任何每日任務沒有完成的話,在你攻擊魔王的同時魔王也會攻擊你的隊員哦!\n

\n在11級過後,戰士和法師會有職業技能能夠對魔王造成額外傷害,所以如果你現在已經等級10了,想成為一個優秀的前鋒就對著這兩個職業點下去吧!", - "faqQuestion10": "What are Gems, and how do I get them?", + "faqQuestion10": "寶石是什麼?我要怎麼得到呢?", "iosFaqAnswer10": "如果要購買寶石,你必須要點擊上方寶石圖示後使用你錢包裡真真實實的錢來購買。當你購買寶石的同時,也代表你幫助我們把網站建立的更加完善。我們超感謝你的支持!\n\n除了用現金購買才能得到寶石之外,還有三種方法可以獲得:\n\n*使用電腦版在網站贏得挑戰。 [網站](https://habitica.com)你可以在「社交」>「挑戰」裡找到許多由他人設定好的挑戰可以選擇。(我們日後也會增加此功能在手機版上!)\n*使用電腦版在網站上訂閱我們,[網站](https://habitica.com/#/options/settings/subscription)就能夠使用金幣在每個月購買特定數量的寶石哦! \n*為Habitica作出貢獻,看看wiki頁面就能得到更多資訊:[幫助Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica).\n\n小提醒!不論你有沒有購買寶石,它們不會使你變得比別人更有優勢,所以就算你沒有寶石你還是能夠開開心心順利玩Habitica哦!", "webFaqAnswer10": "如果要購買寶石,你必須要點擊寶石圖示後使用你錢包裡真真實實的錢來購買 [新台幣/美金](https://habitica.com/#/options/settings/subscription)\n或者成為訂閱用戶也能夠使用遊戲裡的金幣購買一定數量的寶石, [訂閱用戶](https://habitica.com/#/options/settings/subscription)\n當你成為訂閱用戶或者購買寶石的同時,也代表你幫助我們把網站建立的更加完善。我們超感謝你的支持!\n

\n除了用現金購買或者成為訂閱用戶才能得到寶石之外,還有兩種方法可以獲得:\n

\n*贏得挑戰。你可以在「社交」>「挑戰」裡找到許多由他人設定好的挑戰可以選擇。\n\n*為Habitica作出貢獻,看看wiki頁面就能得到更多資訊:[幫助Habitica](http://habitica.wikia.com/wiki/Contributing_to_Habitica)\n

\n小提醒!不論你有沒有購買寶石,它們不會使你變得比別人更有優勢,所以就算你沒有寶石你還是能夠開開心心順利玩Habitica哦!", "faqQuestion11": "我要怎麼做才能回報問題或者請求新功能呢?", "iosFaqAnswer11": "在「選單」>「回饋意見」裡,你可以回報錯誤、請求新功能或者只是給個意見,我們會盡其所能的協助你!", "webFaqAnswer11": "回報錯誤的話要到[幫助 > 回報問題](https://github.com/HabitRPG/habitrpg/issues/2760),跟著步驟填寫資訊即可,我們一定會使命必達的,別怕!\n

\n建議我們增加新功能的話,則是要到[幫助 > 請求新功能](https://trello.com/c/odmhIqyW/440-read-first-table-of-contents) ,然後跟著指示做就沒錯啦!", - "faqQuestion12": "How do I battle a World Boss?", - "iosFaqAnswer12": "World Bosses are special monsters that appear in the Tavern. All active users are automatically battling the Boss, and their tasks and skills will damage the Boss as usual.\n\n You can also be in a normal Quest at the same time. Your tasks and skills will count towards both the World Boss and the Boss/Collection Quest in your party.\n\n A World Boss will never hurt you or your account in any way. Instead, it has a Rage Bar that fills when users skip Dailies. If its Rage bar fills, it will attack one of the Non-Player Characters around the site and their image will change.\n\n You can read more about [past World Bosses](http://habitica.wikia.com/wiki/World_Bosses) on the wiki.", - "webFaqAnswer12": "World Bosses are special monsters that appear in the Tavern. All active users are automatically battling the Boss, and their tasks and skills will damage the Boss as usual.\n

\n You can also be in a normal Quest at the same time. Your tasks and skills will count towards both the World Boss and the Boss/Collection Quest in your party.\n

\n A World Boss will never hurt you or your account in any way. Instead, it has a Rage Bar that fills when users skip Dailies. If its Rage bar fills, it will attack one of the Non-Player Characters around the site and their image will change.\n

\n You can read more about [past World Bosses](http://habitica.wikia.com/wiki/World_Bosses) on the wiki.", + "faqQuestion12": "我要如何才能夠挑戰世界BOSS?", + "iosFaqAnswer12": "世界BOSS是出現在酒館的特別怪獸。所有使用者都會自動跟Boss作戰,完成日常任務和使用技能都會自動對Boss造成傷害。\n\n你也可以同時解任務,當你完成每日任務和使用技能都會同時對隊伍正在解的活動任務的Boss和世界Boss造成傷害。\n\n世界Boss無法傷害你或者你的帳號。取而代之,它有一個憤怒值,當使用者沒有完成日常任務時就會增加。當憤怒值滿了,它就會攻擊網站裡其中一位非玩家角色,而且改變他們的圖像。\n\n你可以從wiki中獲得更多關於以往世界BOSS的歷史。 [以往 World Bosses](http://habitica.wikia.com/wiki/World_Bosses) ", + "webFaqAnswer12": "世界BOSS是出現在酒館的特別怪獸。所有使用者都會自動跟Boss作戰,完成日常任務和使用技能都會自動對Boss造成傷害。

\n\n你也可以同時解任務,當你完成每日任務和使用技能都會同時對隊伍正在解的活動任務的Boss和世界Boss造成傷害。\n

\n世界Boss無法傷害你或者你的帳號。取而代之,它有一個憤怒值,當使用者沒有完成日常任務時就會增加。當憤怒值滿了,它就會攻擊網站裡其中一位非玩家角色,而且改變他們的圖像。\n

\n你可以從wiki中獲得更多關於以往世界BOSS的歷史。 [以往 World Bosses](http://habitica.wikia.com/wiki/World_Bosses) ", "iosFaqStillNeedHelp": "如果你有疑問,可是沒在這裡看到解答的話,來「選單」>「酒館」的聊天室問問,我們很高興為你服務!", "webFaqStillNeedHelp": "如果你有疑問,可是沒在這裡看到解答的話,來這裏問問 [新手公會](https://habitica.com/#/options/groups/guilds/5481ccf3-5d2d-48a9-a871-70a7380cee5a),我們很高興為你服務!" } \ No newline at end of file diff --git a/common/locales/zh_TW/front.json b/common/locales/zh_TW/front.json index 2a87d13785..118e3cc7e3 100644 --- a/common/locales/zh_TW/front.json +++ b/common/locales/zh_TW/front.json @@ -74,7 +74,7 @@ "infhQuote": "在我讀研究所的時候,[Habitica]幫我重建了生活重心!", "invalidEmail": "需要有效的電子郵件地址,以便進行密碼重置。", "irishfeet123Quote": "我曾經有個很糟的習慣,就是吃完飯後不去整理,而把杯子放得到處都是不放回原位。[Habitica] 救了我!", - "joinOthers": "Join 850,000 people making it fun to achieve goals!", + "joinOthers": "Join <%= userCount %> people making it fun to achieve goals!", "kazuiQuote": "還沒有遇到[Habitica]之前,我被論文給卡住了,而且我要求自己要做到的事也都進度緩慢,像是做家事、背單字,學圍棋等。至從遇到它之後我才發現,原來我把事情分散開來會更好管理,現在做這些每日任務成了我的動力來源!", "landingadminlink": "管理方案", "landingend": "還沒被說服嗎?", @@ -182,5 +182,11 @@ "tweet": "推特", "apps": "Apps", "notifyAndroidApp": "Want us to notify you when the Android app is ready? Sign up for this mailing list!", - "checkOutIOSApp": "Check out our new iOS App!" + "checkOutIOSApp": "Check out our new iOS App!", + "imagine1": "Imagine if improving your life were as fun as playing a game.", + "landingCopy1": "Advance in the game by completing your real-life tasks.", + "landingCopy2": "Battle monsters with friends to stay accountable to your goals.", + "landingCopy3": "Join over <%= userCount %> people having fun as they improve their lives.", + "alreadyHaveAccount": "I already have an account!", + "getStartedNow": "Get Started Now!" } \ No newline at end of file diff --git a/common/locales/zh_TW/gear.json b/common/locales/zh_TW/gear.json index 8c239fa823..81a5b9a37a 100644 --- a/common/locales/zh_TW/gear.json +++ b/common/locales/zh_TW/gear.json @@ -146,8 +146,8 @@ "weaponArmoireBasicCrossbowNotes": "不管從多遠,都能夠用這把十字弓刺破任務的鎧甲!增加<%= str %>點力量, <%= per %>點感知和<%= con %>點體質。神祕寶箱:獨立物品。", "weaponArmoireLunarSceptreText": "潤月權杖", "weaponArmoireLunarSceptreNotes": "從這把魔杖所帶來的治癒能量,會隨著月亮盈缺而增減。提高<%= con %>點體質和<%= int %>點智力。神祕寶箱:潤月系列(3/3)。", - "weaponArmoireRancherLassoText": "牧人套索", - "weaponArmoireRancherLassoNotes": "套索:為圍補和牽繩的理想工具。增加<%= str %>點力量, <%= per %>點感知和<%= int %>點智力。神祕寶箱:牧人系列(3/3)。", + "weaponArmoireRancherLassoText": "牛仔套索", + "weaponArmoireRancherLassoNotes": "套索:為圍補和牽繩的理想工具。增加<%= str %>點力量, <%= per %>點感知和<%= int %>點智力。神祕寶箱:牛仔系列(3/3)。", "weaponArmoireMythmakerSwordText": "神話英雄之劍", "weaponArmoireMythmakerSwordNotes": "雖然這把劍看起來有點破舊,但它可是見證了無數個神話英雄的誕生。增加感知和力量各<%= attrs %>點。神祕寶箱:黃金袍系列(3/3)。", "weaponArmoireIronCrookText": "鐵彎杖", @@ -156,8 +156,8 @@ "weaponArmoireGoldWingStaffNotes": "法杖上的風不斷地旋轉扭動,增加所有屬性各<%= attrs %>點。神祕寶箱:獨立物品。", "weaponArmoireBatWandText": "蝙蝠魔杖", "weaponArmoireBatWandNotes": "這個魔杖可以把任何任務轉變成一隻蝙蝠!只要揮動它然後等著看蝙蝠飛走吧。增加<%= int %> 點智力,和<%= per %>點感知。神祕寶箱:獨立物品。", - "weaponArmoireShepherdsCrookText": "Shepherd's Crook", - "weaponArmoireShepherdsCrookNotes": "Useful for herding gryphons. Increases Constitution by <%= con %>. Enchanted Armoire: Shepherd Set (Item 1 of 3).", + "weaponArmoireShepherdsCrookText": "牧羊杖", + "weaponArmoireShepherdsCrookNotes": "想要放牧獅鷲獸的話,選這把牧羊杖就對了。增加<%= con %>感知。神秘寶箱:牧羊人系列(1/3)", "armor": "盔甲", "armorBase0Text": "正常服裝", "armorBase0Notes": "普通的衣服。 沒有屬性加成。", @@ -315,18 +315,18 @@ "armorArmoireLunarArmorNotes": "月光會使你堅強和機警。提高 <%= str %> 點力量和 <%= int %>點智力。神祕寶箱:潤月系列(2/3)。", "armorArmoireGladiatorArmorText": "角鬥士鎧甲", "armorArmoireGladiatorArmorNotes": "想成為一名夠格的角鬥士,你不僅要夠狡猾⋯⋯還要強到破表。增加感知<%= per %>點和力量<%= str %>。神祕寶箱:角鬥士系列(2/3)。", - "armorArmoireRancherRobesText": "牧人袍", - "armorArmoireRancherRobesNotes": "穿著這身神奇的牧人袍,帶上你的坐騎和寵物們吧!增加<%= str %>點力量, <%= per %>點感知和<%= int %>點智力。神祕寶箱:牧人系列(2/3)。", + "armorArmoireRancherRobesText": "牛仔裝", + "armorArmoireRancherRobesNotes": "穿著這身神奇的牧人袍,帶上你的坐騎和寵物們吧!增加<%= str %>點力量, <%= per %>點感知和<%= int %>點智力。神祕寶箱:牛仔系列(2/3)。", "armorArmoireGoldenTogaText": "黃金長袍", "armorArmoireGoldenTogaNotes": "這件閃閃發光的長袍只有真英雄才夠格穿戴。增加力量和體質各<%= attrs %>點。神祕寶箱:黃金袍系列(1/3)。", "armorArmoireHornedIronArmorText": "鐵角鎧甲", "armorArmoireHornedIronArmorNotes": "用鐵激烈地鍛造而成,這件角盔甲無懈可擊!增加<%= con %>點體質和<%= per %>點感知。神祕寶箱:鐵角系列 (2/3)。", "armorArmoirePlagueDoctorOvercoatText": "瘟疫醫袍", "armorArmoirePlagueDoctorOvercoatNotes": "和拖拉瘟疫戰鬥的醫生,值得一件真真正正的大衣!增加<%= int %>點智力,<%= str %>點力量和<%= con %>點體質。神祕寶箱:瘟疫醫師系列(3/3)。", - "armorArmoireShepherdRobesText": "Shepherd Robes", - "armorArmoireShepherdRobesNotes": "The fabric is cool and breathable, perfect for a hot day herding gryphons in the desert. Increases Strength and Perception by <%= attrs %> each. Enchanted Armoire: Shepherd Set (Item 2 of 3).", - "armorArmoireRoyalRobesText": "Royal Robes", - "armorArmoireRoyalRobesNotes": "Wonderful ruler, rule all day long! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 3 of 3).", + "armorArmoireShepherdRobesText": "牧羊人長袍", + "armorArmoireShepherdRobesNotes": "布料材質涼爽,透氣,非常適合在沙漠中的大熱天放牧獅鷲。增加力量和感知各<%= attrs %>點。神秘寶箱:牧羊人系列(2/3)", + "armorArmoireRoyalRobesText": "皇家長袍", + "armorArmoireRoyalRobesNotes": "精彩的統治者,整天都在統治來統治去!增加體質、智力和感知各<%= attrs %>點。神秘寶箱:皇家系列(3/3)", "headgear": "頭飾", "headBase0Text": "沒有頭盔", "headBase0Notes": "沒有頭飾", @@ -479,15 +479,15 @@ "headArmoireRedHairbowText": "紅蝴蝶結頭飾", "headArmoireRedHairbowNotes": "當你戴上紅蝴蝶結頭飾,你就能變得更強壯、堅毅而且更聰明!增加<%= str %>點力量,<%= con %>點體質和<%= int %>點智力。神祕寶箱:獨立物品。", "headArmoireVioletFloppyHatText": "紫色軟帽", - "headArmoireVioletFloppyHatNotes": "許多咒術被縫進這頂帽子裡,最後在給它一抹惹人喜愛的紫色。增加<%= per %>點感知,<%= int %>點智力和<%= con %>點體質。神祕寶箱:獨立物品。", + "headArmoireVioletFloppyHatNotes": "許多咒術被縫進這頂帽子裡,最後再給它一抹惹人喜愛的紫色。增加<%= per %>點感知,<%= int %>點智力和<%= con %>點體質。神祕寶箱:獨立物品。", "headArmoireGladiatorHelmText": "角鬥士頭盔", "headArmoireGladiatorHelmNotes": "要成為一名鬥士,你必須要不僅是強壯⋯⋯還要狡猾。增加智力<%= int %>點和<%= per %>點感知。神祕寶箱:角鬥士系列(1/3)。", - "headArmoireRancherHatText": "牧人帽", - "headArmoireRancherHatNotes": "戴著這頂神奇的牧人帽,帶上你的坐騎和寵物們吧!增加<%= str %>點力量,<%= per %>點感知和<%= int %>點智力。神祕寶箱:牧人系列(1/3)。", + "headArmoireRancherHatText": "牛仔帽", + "headArmoireRancherHatNotes": "戴著這頂神奇的牧人帽,帶上你的坐騎和寵物們吧!增加<%= str %>點力量,<%= per %>點感知和<%= int %>點智力。神祕寶箱:牛仔系列(1/3)。", "headArmoireBlueHairbowText": "藍蝴蝶結頭飾", "headArmoireBlueHairbowNotes": "當你戴上藍蝴蝶結頭飾,你就能變得更敏銳、堅毅而且更聰明!增加<%= per %>點感知,<%= con %>點體質和<%= int %>點智力。神祕寶箱:獨立物品。", "headArmoireRoyalCrownText": "王者之冠", - "headArmoireRoyalCrownNotes": "Hooray for the ruler, mighty and strong! Increases Strength by <%= str %>. Enchanted Armoire: Royal Set (Item 1 of 3).", + "headArmoireRoyalCrownNotes": "吾王萬歲萬萬歲,年年有今日歲歲有今朝!增加 <%= str %>點力量。神秘寶箱:皇家系列(1/3)", "headArmoireGoldenLaurelsText": "黃金桂冠", "headArmoireGoldenLaurelsNotes": "這頂金色桂冠用來獎勵那些克服壞習慣的人們。增加感知和體質各<%= attrs %>點。神祕寶箱:黃金袍系列(2/3)。", "headArmoireHornedIronHelmText": "鐵角頭盔", @@ -495,17 +495,17 @@ "headArmoireYellowHairbowText": "黃蝴蝶結頭飾", "headArmoireYellowHairbowNotes": "當你戴上黃蝴蝶結頭飾,你就能變得更敏銳、堅毅而且更聰明!增加感知、體質和智力各<%= attrs %>點。神祕寶箱:獨立物品。", "headArmoireRedFloppyHatText": "紅色軟帽", - "headArmoireRedFloppyHatNotes": "許多咒術被縫進這頂帽子裡,最後在給它一抹光芒四射的紅色。增加感知、智力和體質各<%= attrs %>點。神祕寶箱:獨立物品。", + "headArmoireRedFloppyHatNotes": "許多咒術被縫進這頂帽子裡,最後再給它一抹光芒四射的紅色。增加感知、智力和體質各<%= attrs %>點。神祕寶箱:獨立物品。", "headArmoirePlagueDoctorHatText": "瘟疫醫帽", "headArmoirePlagueDoctorHatNotes": "和拖拉瘟疫戰鬥的醫生,值得一件真真正正的帽子!增加<%= int %>點智力,<%= str %>點力量和<%= con %>點體質。神祕寶箱:瘟疫醫師系列(1/3)。", "headArmoireBlackCatText": "黑貓帽", - "headArmoireBlackCatNotes": "這頂黑帽在⋯⋯打呼嚕,還甩動著尾巴,而且還在呼吸?沒錯,在你頭上的是一隻正在睡覺的貓。增加智力和感知各<%= attrs %>點。神祕寶箱:獨立物品。", + "headArmoireBlackCatNotes": "這頂黑帽在⋯⋯打呼嚕,甩動著尾巴,而且還在呼吸?沒錯,在你頭上的是一隻正在睡覺的貓。增加智力和感知各<%= attrs %>點。神祕寶箱:獨立物品。", "headArmoireOrangeCatText": "橘貓帽", - "headArmoireOrangeCatNotes": "這頂橘帽在⋯⋯打呼嚕,還甩動著尾巴,而且還在呼吸?沒錯,在你頭上的是一隻正在睡覺的貓。增加力量和體質各<%= attrs %>點。神祕寶箱:獨立物品。", - "headArmoireBlueFloppyHatText": "Blue Floppy Hat", - "headArmoireBlueFloppyHatNotes": "Many spells have been sewn into this simple hat, giving it a brilliant blue color. Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Independent Item.", - "headArmoireShepherdHeaddressText": "Shepherd Headdress", - "headArmoireShepherdHeaddressNotes": "Sometimes the gryphons that you herd like to chew on this headdress, but it makes you seem more intelligent nonetheless. Increases Intelligence by <%= int %>. Enchanted Armoire: Shepherd Set (Item 3 of 3).", + "headArmoireOrangeCatNotes": "這頂橘帽在⋯⋯打呼嚕,甩動著尾巴,而且還在呼吸?沒錯,在你頭上的是一隻正在睡覺的貓。增加力量和體質各<%= attrs %>點。神祕寶箱:獨立物品。", + "headArmoireBlueFloppyHatText": "藍色軟帽", + "headArmoireBlueFloppyHatNotes": "許多咒術被縫進這頂帽子裡,最後再給它一抹燦爛的藍色。增加感知、智力和體質各<%= attrs %>點。神祕寶箱:獨立物品。", + "headArmoireShepherdHeaddressText": "牧羊人頭飾", + "headArmoireShepherdHeaddressNotes": "你戴上這頂頭飾顯得智力非凡,不過有時候,你放養的獅鷲們喜歡咀嚼它。增加<%= int %>點智力。神秘寶箱:牧羊人系列(3/3)", "offhand": "副手物品", "shieldBase0Text": "沒有副手裝備", "shieldBase0Notes": "沒有盾牌或副武器。", @@ -589,8 +589,8 @@ "shieldArmoireGladiatorShieldNotes": "想成為一名夠格的角鬥士,你不僅要⋯⋯算了隨便啦,用盾牌打爆他們就對了。增加體質 <%= con %> 點和力量<%= str %>。神祕寶箱:角鬥士系列(1/3)。", "shieldArmoireMidnightShieldText": "午夜之盾", "shieldArmoireMidnightShieldNotes": "在午夜鐘聲響起時,這面盾牌將會展現它最大的力量!增加<%= con %> 點體質和<%= str %>點力量。神祕寶箱:獨立物品。", - "shieldArmoireRoyalCaneText": "Royal Cane", - "shieldArmoireRoyalCaneNotes": "Hooray for the ruler, worthy of song! Increases Constitution, Intelligence, and Perception by <%= attrs %> each. Enchanted Armoire: Royal Set (Item 2 of 3).", + "shieldArmoireRoyalCaneText": "皇家手杖", + "shieldArmoireRoyalCaneNotes": "皇上吉祥!為此高唱!增加體質、智力和感知各<%= attrs %>點。神秘寶箱:皇家系列(2/3)", "back": "後背附件", "backBase0Text": "沒有後背附件", "backBase0Notes": "沒有後背附件。", diff --git a/common/locales/zh_TW/generic.json b/common/locales/zh_TW/generic.json index d01d5c11a6..d687ad9177 100644 --- a/common/locales/zh_TW/generic.json +++ b/common/locales/zh_TW/generic.json @@ -134,5 +134,17 @@ "thankyou2": "無限的感謝。", "thankyou3": "我非常感謝你!", "thankyouCardAchievementTitle": "大大感恩", - "thankyouCardAchievementText": "感謝你如此感恩! 你收到或送出 <%= cards %> 張感謝卡。" + "thankyouCardAchievementText": "感謝你如此感恩! 你收到或送出 <%= cards %> 張感謝卡。", + "streakAchievement": "You earned a streak achievement!", + "firstStreakAchievement": "21-Day Streak", + "streakAchievementCount": "<%= streaks %> 21-Day Streaks", + "twentyOneDays": "You've completed your Daily for 21 days in a row!", + "dontBreakStreak": "Amazing job. Don't break the streak!", + "dontStop": "Don't Stop Now!", + "levelUpShare": "I leveled up in Habitica by improving my real-life habits!", + "questUnlockShare": "I unlocked a new quest in Habitica!", + "hatchPetShare": "I hatched a new pet by completing my real-life tasks!", + "raisePetShare": "I raised a pet into a mount by completing my real-life tasks!", + "wonChallengeShare": "I won a challenge in Habitica!", + "achievementShare": "I earned a new achievement in Habitica!" } \ No newline at end of file diff --git a/common/locales/zh_TW/npc.json b/common/locales/zh_TW/npc.json index 9381d85070..42a2d9ce5a 100644 --- a/common/locales/zh_TW/npc.json +++ b/common/locales/zh_TW/npc.json @@ -2,12 +2,12 @@ "npc": "NPC", "npcText": "全力支持了我們的Kickstarter項目!", "mattBoch": "Matt Boch", - "mattShall": "需要我把你的坐騎<%= name %>帶出來嗎?當寵物夠飽時就會變成坐騎顯示在這邊。點擊一隻坐騎來騎上牠吧 !", - "mattBochText1": "歡迎來到馬廄!我是野獸大師Matt . 從3等開始,你就夠使用藥水和寵物蛋來孵化寵物 ! 當你在市場孵化了寵物,牠就會顯示在這裡。點選一隻寵物的圖片把牠加入你的角色。 用你在升上4等後尋獲的食物餵食牠們,牠們將會成長為力量充沛的坐騎! ", + "mattShall": "需要我把你的坐騎<%= name %>帶出來嗎?當寵物吃飽時就會變成坐騎顯示在這邊。點擊一隻坐騎來騎上牠吧 !", + "mattBochText1": "歡迎來到馬廄!我是野獸大師Matt。從3等級開始,你就夠使用藥水和寵物蛋來孵化寵物!當你在市場孵化了寵物,牠就會顯示在這裡。點選一隻寵物的圖片把牠加入你的角色。 用你在升上4等級後所尋獲的食物餵食牠們,牠們將會成長為力量充沛的坐騎! ", "daniel": "Daniel", - "danielText": "歡迎來到酒館!稍微坐一下且認識其他人。如果你需要休息(休假?生病?),我會讓你入住旅館。一旦入住,你的每日任務會原地凍結,直到退房的隔天。你將不用為錯過每日任務受傷,但是你仍然能點選完成那些任務。", - "danielText2": "警告:如果你正在參與一個boss戰任務,你仍然會因為隊友未完成的每日任務,受到boss的傷害。而且你讓boss得到傷害(或是收到東西)將會在妳離開旅館時才生效。", - "danielTextBroken": "歡迎來到酒館...吧...如果你想休息,我會幫你安排到旅館...在內休息的期間,你的每日任務在每天結算時不會對你造成傷害,但你還是可以完成他們...如果你有體力的話...", + "danielText": "歡迎來到酒館!在這裡坐一下來認識其他人吧。如果你需要休息(休假?生病?),我會讓你入住旅館。一旦入住,你的每日任務會原地凍結,直到退房的隔天。你將不用為錯過每日任務受傷,但是你仍然能點選完成那些任務。", + "danielText2": "警告:如果你正在參與一個boss戰任務,你仍然會因為隊友未完成的每日任務,受到boss的傷害。而且你給boss的傷害(或是收到東西)將會在妳離開旅館時才生效。", + "danielTextBroken": "歡迎來到酒館...痾應該是吧...如果你想休息,我會幫你安排到旅館...在旅館裡休息的期間,你的每日任務在每天結算時不會對你造成傷害,但你還是可以完成他們...如果你有體力的話...", "danielText2Broken": "哦...如果你正參與一場 boss 任務,boss 還是會因為隊友未完成的每日任務而傷害你...另外,你無法對 Boss 造成傷害 ( 或獲得物品 ),直到你離開旅館為止...", "alexander": "商人Alexander", "welcomeMarket": "歡迎來到市場!在這裡買少見的蛋和藥水!賣掉你多餘的物品!委託服務!來瞧瞧我們能為你提供什麼。", @@ -19,14 +19,14 @@ "justin": "Justin", "ian": "Ian", "ianText": "歡迎來到任務商店! 這裡可以買任務卷軸,與朋友一起打怪。記得常來看看有什麼可以買!", - "ianBrokenText": "Welcome to the Quest Shop... Here you can use Quest Scrolls to battle monsters with your friends... Be sure to check out our fine array of Quest Scrolls for purchase on the right...", + "ianBrokenText": "歡迎來到任務商店...你可以跟你朋友們在這裡使用任務卷軸打怪...一定要來看看我們右邊販售的精美任務卷軸哦...", "USD": "美金", "newStuff": "新品", "cool": "稍候再跟我說", "dismissAlert": "不再顯示", "donateText1": "在你的帳號裡增加20個寶石。寶石可以用來購買特殊的虛擬物品,例如衣服和髮型。", "donateText2": "請幫助Habitica", - "donateText3": "這是一個開放原始碼的專案,因此它需要所有得到的帮助。遊戲運行的伺服器費用、維護功能與創造新功能都來自於買寶石的錢,感謝你的大力幫忙!", + "donateText3": "Habitica是一個開源的專案,因此需要我們使用者的贊助。當你購買寶石的同時,也幫助了我們維護遊戲運行的伺服器費用、付小員工薪水、創造新功能還有提供獎勵機制給為網站貢獻的人,感謝你的大力幫忙!", "donationDesc": "捐贈給Habitica 20 顆寶石", "payWithCard": "用信用卡購買", "payNote": "請注意: PayPal 有時候付款會蠻花時間的,我們建議你用信用卡購買。", @@ -60,8 +60,8 @@ "tourChallengesPage": "一些夥伴會創造挑戰,參與挑戰會加入一些工作到你的工作中,贏得挑戰會得到成就甚至是寶石!", "tourMarketPage": "從4級開始,當你完成任務時,蛋和孵化藥水會隨機掉落。他們會出現在這裡—使用它們來孵化寵物!你也可以從集市購買物品。", "tourHallPage": "這裡是英雄館。那些對開源有貢獻的玩家,包含在程式、美術、音樂、著作,或是到處幫忙的人們列於其中。他們已經獲得 寶石、特殊裝備、與偉大的名聲。你也可以為 Habitica 做出貢獻!", - "tourPetsPage": "This is the Stable! After level 4, you can hatch pets using eggs and potions. When you hatch a pet in the Market, it will appear here! Click a pet's image to add it to your avatar. Feed them with the food you find after level 4, and they'll grow into powerful mounts.", - "tourMountsPage": "Once you've fed a pet enough food to turn it into a mount, it will appear here. (Pets, mounts, and food are available after level 4.) Click a mount to saddle up!", + "tourPetsPage": "這裡是馬廄!在你滿3等級時,你可以用寵物蛋和藥水來孵化寵物。當你在市集孵化出寵物時,牠會自動出現在這裡!點選寵物的圖像來加入到你的角色中。你4等級時會找到食物,用食物餵飽寵物的話,牠們就會成長為精力充沛的坐騎哦。", + "tourMountsPage": "一旦你餵飽了一隻寵物,牠就會進化成坐騎。坐騎會出現在這裡(當你等級3的時候,就會開放寵物、坐騎和食物。)點選一隻坐騎裝備上鞍吧! ", "tourEquipmentPage": "這裡是放置裝備的地方! 你的戰鬥裝備影響你的數值。如果你想要讓你的角色大頭貼有不一樣的感覺,請點選 \"使用服裝\"。", "tourOkay": "好!", "tourAwesome": "太棒了!", @@ -79,9 +79,9 @@ "welcome1": "創造一個角色圖像。", "welcome1notes": "這個角色將伴隨你一起進步!", "welcome2": "設定你的任務。", - "welcome2notes": "你在現實裡做得多好將影響你在遊戲中能玩得多棒 !", - "welcome3": "在現實與遊戲中同時進步提升吧!!!", - "welcome3notes": "當你的生活進步,你的角色也會隨著升級並解鎖寵物,任務,裝備和更多功能!", + "welcome2notes": "你在現實裡做得多好,將影響你在遊戲中能玩得多棒 !", + "welcome3": "在現實與遊戲中同時進步提升吧!", + "welcome3notes": "當你的生活進步,你的角色也會隨著升級並解鎖寵物,任務,裝備和更多功能!", "welcome4": "避免壞習慣的發生,因為它會奪走你的生命 (HP),你的角色將會因此死亡!", "welcome5": "現在你可以裝扮你的角色與設定你的任務...", "imReady": "進入 Habitica的世界" diff --git a/common/locales/zh_TW/pets.json b/common/locales/zh_TW/pets.json index f8c932be10..5cac11a898 100644 --- a/common/locales/zh_TW/pets.json +++ b/common/locales/zh_TW/pets.json @@ -58,8 +58,16 @@ "firstDrop": "你解鎖了掉落物系統!你現在每完成一項任務,你將有一定機率找到物品,包括蛋、孵化藥水、和食物!你剛剛發現了<%= eggText %>蛋! <%= eggNotes %>", "useGems": "如果你很中意某之寵物,但又不想慢慢等蛋掉落的話,可以在背包>市集使用寶石買下它!", "hatchAPot": "孵化一隻<%= potion %><%= egg %>?", + "hatchedPet": "You hatched a <%= potion %> <%= egg %>!", + "displayNow": "Display Now", + "displayLater": "Display Later", + "earnedCompanion": "With all your productivity, you've earned a new companion. Feed it to make it grow!", "feedPet": "餵你的<%= name %>一個<%= article %><%= text %>?", "useSaddle": "把鞍用在<%= pet %>上?", + "raisedPet": "You grew a <%= pet %>!", + "earnedSteed": "By completing your tasks, you've earned a faithful steed!", + "rideNow": "Ride Now", + "rideLater": "Ride Later", "petName": "<%= potion %> <%= egg %>", "mountName": "<%= potion %> <%= mount %>", "petKeyName": "寵物之家的鑰匙", diff --git a/common/locales/zh_TW/quests.json b/common/locales/zh_TW/quests.json index d0611e9be3..75fc29e764 100644 --- a/common/locales/zh_TW/quests.json +++ b/common/locales/zh_TW/quests.json @@ -11,7 +11,7 @@ "invitations": "邀請", "completed": "完成了!", "youReceived": "你收到了", - "dropQuestCongrats": "恭喜妳拿到任務卷軸! 你可以邀請你的隊伍開始任務,或隨時透過 背包->任務 回來查看。", + "dropQuestCongrats": "恭喜你拿到任務卷軸! 你可以邀請你的隊伍開始任務,或隨時透過 背包>任務 回來查看。", "questSend": "點擊「邀請」會向你的隊友發送邀請。當所有成員接受或拒絕後任務開始。在選項> 社交> 組隊裡查看任務狀態。", "questSendBroken": "按下「邀請」後會向隊伍成員們送出邀請...在所有隊員選擇接受或拒絕後,任務就會開始...在社交 > 隊伍頁面可以看到資訊...", "inviteParty": "邀請隊伍參予任務", @@ -25,25 +25,25 @@ "rejected": "拒絕", "pending": "等待中", "questStart": "一旦所有成員都接受或拒絕,任務就開始了。只有那些點擊接受者,可以參加任務並取得掉落物品。如果成員回應時間太長(無動作?),任務擁有者可以略過他們直接按「開始」來啟動任務。任務擁有者還可以透過點擊「取消」取消任務,並恢復任務捲軸。", - "questStartBroken": "Once all members have either accepted or rejected, the quest begins... Only those that clicked \"accept\" will be able to participate in the quest and receive the drops... If members are pending too long (inactive?), the quest owner can start the quest without them by clicking \"Begin\"... The quest owner can also cancel the quest and regain the quest scroll by clicking \"Cancel\"...", + "questStartBroken": "一旦所有成員都接受或拒絕,任務就開始了...只有那些點擊接受者,可以參加任務並取得掉落物品。如果成員回應時間太長(無動作?),任務擁有者可以略過他們直接按「開始」來啟動任務。任務擁有者還可以透過點擊「取消」取消任務,並恢復任務捲軸...", "begin": "開始", "bossHP": "Boss的生命值", "bossStrength": "Boss的力量", - "rage": "Rage", + "rage": "憤怒值", "collect": "收集", "collected": "已收集", "collectionItems": "<%= number %>個<%= items %>", "itemsToCollect": "需收集的物品", - "bossDmg1": "想要攻擊魔王,你必須完成你的每日任務和待辦事項。任務傷害越高,你對魔王的傷害也越大,達成紅色事項、法師的法術、戰士的攻擊等等。如果你未能完成每日任務,除了本來就會遭受的傷害,魔王會針對你遺漏的事項(乘上魔王的力量)額外再傷害你和你的隊友。所以想要保持隊伍健康,就去完成你的每日任務! 所有從魔王和你攻擊的傷害將在跨日(一天結束)時結算。 ", + "bossDmg1": "想要攻擊魔王,你必須完成你的每日任務和待辦事項。任務傷害越高,你對魔王的傷害也越大,達成紅色事項、法師的法術、戰士的攻擊等等。如果你未能完成每日任務,除了本來就會遭受的傷害,魔王會針對你遺漏的事項(乘上魔王的力量)額外再傷害你和你的隊友。所以想要使隊員的生命值不受損,就去完成你的每日任務! 所有從魔王和你攻擊的傷害將在跨日(一天結束)時結算。 ", "bossDmg2": "只有參與者會跟魔王戰鬥,並共享任務獎勵。", - "bossDmg1Broken": "Each completed Daily and To-Do and each positive Habit hurts the boss... Hurt it more with redder tasks or Brutal Smash and Burst of Flames... The boss will deal damage to every quest participant for every Daily you've missed (multiplied by the boss's Strength) in addition to your regular damage, so keep your party healthy by completing your Dailies... All damage to and from a boss is tallied on cron (your day roll-over)...", - "bossDmg2Broken": "Only participants will fight the boss and share in the quest loot...", - "tavernBossInfo": "Complete Dailies and To-Dos and score positive Habits to damage the World Boss! Incomplete Dailies fill the Exhaust Strike Bar. When the Exhaust Strike bar is full, the World Boss will attack an NPC. A World Boss will never damage individual players or accounts in any way. Only active accounts not resting in the Inn will have their tasks tallied.", - "tavernBossInfoBroken": "Complete Dailies and To-Dos and score positive Habits to damage the World Boss... Incomplete Dailies fill the Exhaust Strike Bar... When the Exhaust Strike bar is full, the World Boss will attack an NPC... A World Boss will never damage individual players or accounts in any way... Only active accounts not resting in the Inn will have their tasks tallied...", + "bossDmg1Broken": "想要攻擊魔王,你必須完成你的每日任務和待辦事項。任務傷害越高,你對魔王的傷害也越大...達成紅色事項、法師的法術、戰士的攻擊等等...如果你未能完成每日任務,除了本來就會遭受的傷害,魔王會針對你遺漏的事項(乘上魔王的力量)額外再傷害你和你的隊友。所以想要使隊員的生命值不受損,就去完成你的每日任務... 所有從魔王和你攻擊的傷害將在跨日(一天結束)時結算... ", + "bossDmg2Broken": "只有參與者會跟魔王戰鬥,並共享任務獎勵。", + "tavernBossInfo": "想要攻擊世界Boss,你必須完成每日任務、待辦事項和正面的習慣!未完成的任務將增加廢氣攻擊值。當廢氣攻擊值被填滿,世界Boss就會對 NPC發動攻擊。世界Boss永遠不會對玩家或是玩家帳號造成傷害。不過若是在旅館休息的帳號就會被排除在世界Boss任務之外囉。", + "tavernBossInfoBroken": "想要攻擊世界Boss,你必須完成每日任務、待辦事項和正面的習慣...未完成的任務將增加廢氣攻擊值...當廢氣攻擊值被填滿,世界Boss就會對 NPC發動攻擊...世界Boss永遠不會對玩家或是玩家帳號造成傷害...不過若是在旅館休息的帳號就會被排除在世界Boss任務之外囉...", "bossColl1": "要撿到物品,你必須完成你的「正向」任務。任務獎勵品會像普通物品一樣掉落;但要在隔天才看到。你撿到的物品會被計算並累積到戰利品堆當中。", "bossColl2": "只有參與者會跟魔王戰鬥,並共享任務獎勵。", - "bossColl1Broken": "To collect items, do your positive tasks... Quest items drop just like normal items; however, you won't see the drops until the next day, then everything you've found will be tallied up and contributed to the pile...", - "bossColl2Broken": "Only participants can collect items and share in the quest loot...", + "bossColl1Broken": "要撿到物品,你必須完成你的「正向」任務...任務獎勵品會像普通物品一樣掉落;但要在隔天你才能看到,你撿到的物品會被計算並累積到戰利品堆當中。", + "bossColl2Broken": "只有參與者會跟魔王戰鬥,並共享任務獎勵...", "abort": "放棄", "leaveQuest": "退出任務", "sureLeave": "你確定要退出執行中的任務嗎?所有執行任務的成果將會遺失。", @@ -70,11 +70,13 @@ "sureAbort": "你是否確定要放棄這個任務?這樣做會讓你的所有隊員都退出這個任務,並且消除所有進度。任務捲軸將會回到任務擁有者手上。", "doubleSureAbort": "你真的真的要這樣做嗎?要確保他們不會一輩子討厭你喲!", "questWarning": "如果新的隊友在開始前加入了隊伍,他們也會收到邀請。但是一旦任務已經開始,新的隊友就無法再加入這個任務了。", - "questWarningBroken": "If new players join the party before the quest starts, they will also receive an invitation... However once the quest has started, no new party members can join the quest...", + "questWarningBroken": "如果新的隊友在開始前加入了隊伍,他們也會收到邀請...但是一旦任務已經開始,新的隊友就無法再加入這個任務了...", "bossRageTitle": "憤怒值", "bossRageDescription": "當此欄全滿時,Boss就會發動特殊攻擊!", "startAQuest": "開始一個任務", "startQuest": "任務開始", "whichQuestStart": "你要開始哪個任務?", - "getMoreQuests": "取得更多任務" + "getMoreQuests": "取得更多任務", + "unlockedAQuest": "You unlocked a quest!", + "leveledUpReceivedQuest": "You leveled up to Level <%= level %> and received a quest scroll!" } \ No newline at end of file diff --git a/common/locales/zh_TW/questscontent.json b/common/locales/zh_TW/questscontent.json index ef0f25a12a..5d58d71a9f 100644 --- a/common/locales/zh_TW/questscontent.json +++ b/common/locales/zh_TW/questscontent.json @@ -238,19 +238,19 @@ "questDilatoryDistress3DropFish": "魚 (食物)", "questDilatoryDistress3DropWeapon": "擊潰浪潮的三叉戟 (武器)", "questDilatoryDistress3DropShield": "月亮珍珠盾 (副手物品)", - "questCheetahText": "Such a Cheetah", - "questCheetahNotes": "As you hike across the Sloensteadi Savannah with your friends @PainterProphet, @tivaquinn, @Unruly Hyena, and @Crawford, you're startled to see a Cheetah screeching past with a new Habitican clamped in its jaws. Under the Cheetah's scorching paws, tasks burn away as though complete -- before anyone has the chance to actually finish them! The Habitican sees you and yells, \"Please help me! This Cheetah is making me level too quickly, but I'm not getting anything done. I want to slow down and enjoy the game. Make it stop!\" You fondly remember your own fledgling days, and know that you have to help the newbie by stopping the Cheetah!", - "questCheetahCompletion": "The new Habitican is breathing heavily after the wild ride, but thanks you and your friends for your help. \"I'm glad that Cheetah won't be able to grab anyone else. It did leave some Cheetah eggs for us, so maybe we can raise them into more trustworthy pets!\"", + "questCheetahText": "就像獵豹一樣", + "questCheetahNotes": "當你和友人們 @PainterProphet, @tivaquinn, @Unruly Hyena, 和 @Crawford, 在 Sloensteadi Savannah遠足時,你驚訝地發現有位新加入的Habiti公民被壓在獵豹的腳下,在獵豹炙熱的爪子下,在新Habit公民有機會真的完成自己的任務前-把任務燒毀就像被完成過似地消失殆盡!Habiti公民看到你們便求救 \"拜託幫幫我! 這隻獵豹讓我的等級急速飆升, 但我什麼都沒有做。我想要慢慢享受這個遊戲。拜託讓牠停下來!\"你想起自己當初羽翼未豐的日子,你認為你必須要停止獵豹的舉動來幫助這位新人!", + "questCheetahCompletion": "新人Habit公民大力地喘氣,但依舊感謝你和你的朋友的幫助。 “我很高興,獵豹再也無法抓住任何人。它還留下了一些獵豹蛋給我們,所以也許我們可以培養這些小獵豹成為更值得信賴的寵物!”", "questCheetahBoss": "獵豹", - "questCheetahDropCheetahEgg": "Cheetah (Egg)", - "questCheetahUnlockText": "Unlocks purchasable Cheetah eggs in the Market", - "questHorseText": "Ride the Night-Mare", - "questHorseNotes": "While relaxing in the Tavern with @beffymaroo and @JessicaChase, the talk turns to good-natured boasting about your adventuring accomplishments. Proud of your deeds, and perhaps getting a bit carried away, you brag that you can tame any task around. A nearby stranger turns toward you and smiles. One eye twinkles as he invites you to prove your claim by riding his horse.\nAs you all head for the stables, @UncommonCriminal whispers, \"You may have bitten off more than you can chew. That's no horse - that's a Night-Mare!\" Looking at its stamping hooves, you begin to regret your words...", - "questHorseCompletion": "It takes all your skill, but finally the horse stamps a couple of hooves and nuzzles you in the shoulder before allowing you to mount. You ride briefly but proudly around the Tavern grounds while your friends cheer. The stranger breaks into a broad grin.\n\"I can see that was no idle boast! Your determination is truly impressive. Take these eggs to raise horses of your own, and perhaps we'll meet again one day.\" You take the eggs, the stranger tips his hat... and vanishes.", - "questHorseBoss": "Night-Mare", - "questHorseDropHorseEgg": "Horse (Egg)", - "questHorseUnlockText": "Unlocks purchasable Horse eggs in the Market", - "questBurnoutText": "Burnout and the Exhaust Spirits", + "questCheetahDropCheetahEgg": "獵豹(蛋)", + "questCheetahUnlockText": "解鎖-可在市集中購買獵豹蛋", + "questHorseText": "騎乘夢饜", + "questHorseNotes": "跟@beffymaroo 和 @JessicaChase在酒館休息時,談話漸漸轉變成善意的謊言來吹噓你的冒險。為自己的成就感到驕傲的同時,也許變得有些得意忘形,你開始吹噓自己可以馴服任何周遭的任務。身旁一位陌生人笑笑地轉向你。眼神閃爍地邀請你試乘他的坐騎來證明你自己。\n當大家都走到馬廄時, @UncommonCriminal悄悄地說 \"你這次真的砸了自己屁股,他的坐騎根本就不是馬-是一隻夢饜!\"看著夢饜跺著自己的蹄子,你開始後悔自己的嘴巴...", + "questHorseCompletion": "你吃盡了苦頭使出全力,最終夢饜在跺幾次步之後用鼻子磨襯了你的肩膀,願意讓你在牠背上鞍上馬鞍。你驕傲地在酒館四周短暫地騎乘,而你的朋友們在旁助威。陌生人打斷了你們的笑聲。\n“我現在知道你並沒有吹噓自己!你的決心令人印象深刻。這些蛋送你,請扶養牠們長大成為坐騎,也許我們會有再見面的一天。”你收下了蛋,陌生人點了點他的帽子......就消失了。", + "questHorseBoss": "夢饜", + "questHorseDropHorseEgg": "馬(蛋)", + "questHorseUnlockText": "解鎖-可在市集中購買馬蛋", + "questBurnoutText": "倦怠和廢氣精神", "questBurnoutNotes": "It is well past midnight, still and stiflingly hot, when Redphoenix and scout captain Kiwibot abruptly burst through the city gates. \"We need to evacuate all the wooden buildings!\" Redphoenix shouts. \"Hurry!\"

Kiwibot grips the wall as she catches her breath. \"It's draining people and turning them into Exhaust Spirits! That's why everything was delayed. That's where the missing people have gone. It's been stealing their energy!\"

\"'It'?'\" asks Lemoness.

And then the heat takes form.

It rises from the earth in a billowing, twisting mass, and the air chokes with the scent of smoke and sulphur. Flames lick across the molten ground and contort into limbs, writhing to horrific heights. Smoldering eyes snap open, and the creature lets out a deep and crackling cackle.

Kiwibot whispers a single word.

\"Burnout.\"", "questBurnoutCompletion": "Burnout is DEFEATED!

With a great, soft sigh, Burnout slowly releases the ardent energy that was fueling its fire. As the monster curls quietly into ashes, its stolen energy shimmers through the air, rejuvenating the Exhaust Spirits and returning them to their true forms.

Ian, Daniel, and the Seasonal Sorceress cheer as Habiticans rush to greet them, and all the missing citizens of the Flourishing Fields embrace their friends and families. The final Exhaust Spirit transforms into the Joyful Reaper herself!

\"Look!\" whispers @Baconsaur, as the ashes begin to glitter. Slowly, they resolve into hundreds of shining phoenixes!

One of the glowing birds alights on the Joyful Reaper's skeletal arm, and she grins at it. \"It has been a long time since I've had the exquisite privilege to behold a phoenix in the Flourishing Fields,\" she says. \"Although given recent occurrences, I must say, this is highly thematically appropriate!\"

Her tone sobers, although (naturally) her grin remains. \"We're known for being hard-working here, but we are also known for our feasts and festivities. Rather ironic, I suppose, that as we strove to plan a spectacular party, we refused to permit ourselves any time for fun. We certainly won't make the same mistake twice!\"

She claps her hands. \"Now - let's celebrate!\"", "questBurnoutCompletionChat": "`Burnout is DEFEATED!`\n\nWith a great, soft sigh, Burnout slowly releases the ardent energy that was fueling its fire. As the monster curls quietly into ashes, its stolen energy shimmers through the air, rejuvenating the Exhaust Spirits and returning them to their true forms.\n\nIan, Daniel, and the Seasonal Sorceress cheer as Habiticans rush to greet them, and all the missing citizens of the Flourishing Fields embrace their friends and families. The final Exhaust Spirit transforms into the Joyful Reaper herself!\n\n\"Look!\" whispers @Baconsaur, as the ashes begin to glitter. Slowly, they resolve into hundreds of shining phoenixes!\n\nOne of the glowing birds alights on the Joyful Reaper's skeletal arm, and she grins at it. \"It has been a long time since I've had the exquisite privilege to behold a phoenix in the Flourishing Fields,\" she says. \"Although given recent occurrences, I must say, this is highly thematically appropriate!\"\n\nHer tone sobers, although (naturally) her grin remains. \"We're known for being hard-working here, but we are also known for our feasts and festivities. Rather ironic, I suppose, that as we strove to plan a spectacular party, we refused to permit ourselves any time for fun. We certainly won't make the same mistake twice!\"\n\nShe claps her hands. \"Now - let's celebrate!\"\n\nAll Habiticans receive:\n\nPhoenix Pet\nPhoenix Mount\nAchievement: Savior of the Flourishing Fields\nBasic Candy\nVanilla Candy\nSand Candy\nCinnamon Candy\nChocolate Candy\nRotten Candy\nSour Pink Candy\nSour Blue Candy\nHoney Candy", @@ -267,5 +267,11 @@ "questFrogCompletion": "The frog cowers back into the muck, defeated. As it slinks away, the blue slime fades, leaving the way ahead clear.

Sitting in the middle of the path are three pristine eggs. \"You can even see the tiny tadpoles and through the clear casing!\" @Breadstrings says. \"Here, you should take them.\"", "questFrogBoss": "Clutter Frog", "questFrogDropFrogEgg": "Frog (Egg)", - "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market" + "questFrogUnlockText": "Unlocks purchasable Frog eggs in the Market", + "questSnakeText": "The Serpent of Distraction", + "questSnakeNotes": "It takes a hardy soul to live in the Sand Dunes of Distraction. The arid desert is hardly a productive place, and the shimmering dunes have led many a traveler astray. However, something has even the locals spooked. The sands have been shifting and upturning entire villages. Residents claim a monster with an enormous serpentine body lies in wait under the sands, and they have all pooled together a reward for whomever will help them find and stop it. The much-lauded snake charmers @EmeraldOx and @PainterProphet have agreed to help you summon the beast. Can you stop the Serpent of Distraction?", + "questSnakeCompletion": "With assistance from the charmers, you banish the Serpent of Distraction. Though you were happy to help the inhabitants of the Dunes, you can't help but feel a little sad for your fallen foe. While you contemplate the sights, @LordDarkly approaches you. \"Thank you! It's not much, but I hope this can express our gratitude properly.\" He hands you some Gold and... some Snake eggs! You will see that majestic animal again after all.", + "questSnakeBoss": "Serpent of Distraction", + "questSnakeDropSnakeEgg": "Snake (Egg)", + "questSnakeUnlockText": "Unlocks purchasable Snake eggs in the Market" } \ No newline at end of file diff --git a/common/locales/zh_TW/settings.json b/common/locales/zh_TW/settings.json index 10e3d80633..e54895ee51 100644 --- a/common/locales/zh_TW/settings.json +++ b/common/locales/zh_TW/settings.json @@ -14,6 +14,11 @@ "startCollapsedPop": "選擇這個選項後,展開編輯新任務時,標籤列表是隱藏的。", "startAdvCollapsed": "預設隱藏進階選項", "startAdvCollapsedPop": "選擇這個選項後,展開編輯新任務時,進階選項是隱藏的。", + "dontShowAgain": "Don't show this again", + "suppressLevelUpModal": "Don't show popup when gaining a level", + "suppressHatchPetModal": "Don't show popup when hatching a pet", + "suppressRaisePetModal": "Don't show popup when raising a pet into a mount", + "suppressStreakModal": "Don't show popup when attaining a Streak achievement", "showTour": "顯示教學", "restartTour": "重新開始剛加入 Habitica 時,所顯示的教學", "showBailey": "顯示 Bailey", @@ -81,7 +86,6 @@ "emailChange1": "如果想修改 email 地址,請寄信到", "emailChange2": "admin@habitica.com", "emailChange3": "包括你新的和舊的 eamil 地址,和你的UUID。", - "username": "帳號", "usernameOrEmail": "登入名稱或電子郵件", "email": "Email", "registeredWithFb": "Facebook 已註冊", @@ -89,7 +93,7 @@ "loginNameDescription2": "玩家→基本資料", "loginNameDescription3": "來修改你的你的角色和在聊天室的名字。", "emailNotifications": "電子郵件通知", - "wonChallenge": "你贏得挑戰", + "wonChallenge": "You won a Challenge!", "newPM": "收到的私密訊息", "giftedGems": "禮物用寶石", "giftedGemsInfo": "<%= name %> 的 <%= amount %> 個寶石", diff --git a/common/script/content/faq.js b/common/script/content/faq.js index 7d8468ee3e..e65f8969e6 100644 --- a/common/script/content/faq.js +++ b/common/script/content/faq.js @@ -1,6 +1,5 @@ 'use strict'; -require('coffee-script'); var t = require('./translation.js'); var NUMBER_OF_QUESTIONS = 12; diff --git a/common/script/content/index.js b/common/script/content/index.js new file mode 100644 index 0000000000..0005d09460 --- /dev/null +++ b/common/script/content/index.js @@ -0,0 +1,7005 @@ +var _, api, calculateBonus, classes, diminishingReturns, events, gear, gearTypes, moment, t; + +api = module.exports; + +_ = require('lodash'); + +moment = require('moment'); + +t = require('./translation.js'); + + +/* + --------------------------------------------------------------- + Gear (Weapons, Armor, Head, Shield) + Item definitions: {index, text, notes, value, str, def, int, per, classes, type} + --------------------------------------------------------------- + */ + +classes = ['warrior', 'rogue', 'healer', 'wizard']; + +gearTypes = ['weapon', 'armor', 'head', 'shield', 'body', 'back', 'headAccessory', 'eyewear']; + +events = { + winter: { + start: '2013-12-31', + end: '2014-02-01' + }, + birthday: { + start: '2013-01-30', + end: '2014-02-01' + }, + spring: { + start: '2014-03-21', + end: '2014-05-01' + }, + summer: { + start: '2014-06-20', + end: '2014-08-01' + }, + gaymerx: { + start: '2014-07-02', + end: '2014-08-01' + }, + fall: { + start: '2014-09-21', + end: '2014-11-01' + }, + winter2015: { + start: '2014-12-21', + end: '2015-02-02' + }, + spring2015: { + start: '2015-03-20', + end: '2015-05-02' + }, + summer2015: { + start: '2015-06-20', + end: '2015-08-02' + }, + fall2015: { + start: '2015-09-21', + end: '2015-11-02' + } +}; + +api.mystery = { + 201402: { + start: '2014-02-22', + end: '2014-02-28', + text: 'Winged Messenger Set' + }, + 201403: { + start: '2014-03-24', + end: '2014-04-02', + text: 'Forest Walker Set' + }, + 201404: { + start: '2014-04-24', + end: '2014-05-02', + text: 'Twilight Butterfly Set' + }, + 201405: { + start: '2014-05-21', + end: '2014-06-02', + text: 'Flame Wielder Set' + }, + 201406: { + start: '2014-06-23', + end: '2014-07-02', + text: 'Octomage Set' + }, + 201407: { + start: '2014-07-23', + end: '2014-08-02', + text: 'Undersea Explorer Set' + }, + 201408: { + start: '2014-08-23', + end: '2014-09-02', + text: 'Sun Sorcerer Set' + }, + 201409: { + start: '2014-09-24', + end: '2014-10-02', + text: 'Autumn Strider Set' + }, + 201410: { + start: '2014-10-24', + end: '2014-11-02', + text: 'Winged Goblin Set' + }, + 201411: { + start: '2014-11-24', + end: '2014-12-02', + text: 'Feast and Fun Set' + }, + 201412: { + start: '2014-12-25', + end: '2015-01-02', + text: 'Penguin Set' + }, + 201501: { + start: '2015-01-26', + end: '2015-02-02', + text: 'Starry Knight Set' + }, + 201502: { + start: '2015-02-24', + end: '2015-03-02', + text: 'Winged Enchanter Set' + }, + 201503: { + start: '2015-03-25', + end: '2015-04-02', + text: 'Aquamarine Set' + }, + 201504: { + start: '2015-04-24', + end: '2015-05-02', + text: 'Busy Bee Set' + }, + 201505: { + start: '2015-05-25', + end: '2015-06-02', + text: 'Green Knight Set' + }, + 201506: { + start: '2015-06-25', + end: '2015-07-02', + text: 'Neon Snorkeler Set' + }, + 201507: { + start: '2015-07-24', + end: '2015-08-02', + text: 'Rad Surfer Set' + }, + 201508: { + start: '2015-08-23', + end: '2015-09-02', + text: 'Cheetah Costume Set' + }, + 201509: { + start: '2015-09-24', + end: '2015-10-02', + text: 'Werewolf Set' + }, + 201510: { + start: '2015-10-26', + end: '2015-11-02', + text: 'Horned Goblin Set' + }, + 301404: { + start: '3014-03-24', + end: '3014-04-02', + text: 'Steampunk Standard Set' + }, + 301405: { + start: '3014-04-24', + end: '3014-05-02', + text: 'Steampunk Accessories Set' + }, + wondercon: { + start: '2014-03-24', + end: '2014-04-01' + } +}; + +_.each(api.mystery, function(v, k) { + return v.key = k; +}); + +api.itemList = { + 'weapon': { + localeKey: 'weapon', + isEquipment: true + }, + 'armor': { + localeKey: 'armor', + isEquipment: true + }, + 'head': { + localeKey: 'headgear', + isEquipment: true + }, + 'shield': { + localeKey: 'offhand', + isEquipment: true + }, + 'back': { + localeKey: 'back', + isEquipment: true + }, + 'body': { + localeKey: 'body', + isEquipment: true + }, + 'headAccessory': { + localeKey: 'headAccessory', + isEquipment: true + }, + 'eyewear': { + localeKey: 'eyewear', + isEquipment: true + }, + 'hatchingPotions': { + localeKey: 'hatchingPotion', + isEquipment: false + }, + 'eggs': { + localeKey: 'eggSingular', + isEquipment: false + }, + 'quests': { + localeKey: 'quest', + isEquipment: false + }, + 'food': { + localeKey: 'foodText', + isEquipment: false + }, + 'Saddle': { + localeKey: 'foodSaddleText', + isEquipment: false + } +}; + +gear = { + weapon: { + base: { + 0: { + text: t('weaponBase0Text'), + notes: t('weaponBase0Notes'), + value: 0 + } + }, + warrior: { + 0: { + text: t('weaponWarrior0Text'), + notes: t('weaponWarrior0Notes'), + value: 1 + }, + 1: { + text: t('weaponWarrior1Text'), + notes: t('weaponWarrior1Notes', { + str: 3 + }), + str: 3, + value: 20 + }, + 2: { + text: t('weaponWarrior2Text'), + notes: t('weaponWarrior2Notes', { + str: 6 + }), + str: 6, + value: 30 + }, + 3: { + text: t('weaponWarrior3Text'), + notes: t('weaponWarrior3Notes', { + str: 9 + }), + str: 9, + value: 45 + }, + 4: { + text: t('weaponWarrior4Text'), + notes: t('weaponWarrior4Notes', { + str: 12 + }), + str: 12, + value: 65 + }, + 5: { + text: t('weaponWarrior5Text'), + notes: t('weaponWarrior5Notes', { + str: 15 + }), + str: 15, + value: 90 + }, + 6: { + text: t('weaponWarrior6Text'), + notes: t('weaponWarrior6Notes', { + str: 18 + }), + str: 18, + value: 120, + last: true + } + }, + rogue: { + 0: { + text: t('weaponRogue0Text'), + notes: t('weaponRogue0Notes'), + str: 0, + value: 0 + }, + 1: { + text: t('weaponRogue1Text'), + notes: t('weaponRogue1Notes', { + str: 2 + }), + str: 2, + value: 20 + }, + 2: { + text: t('weaponRogue2Text'), + notes: t('weaponRogue2Notes', { + str: 3 + }), + str: 3, + value: 35 + }, + 3: { + text: t('weaponRogue3Text'), + notes: t('weaponRogue3Notes', { + str: 4 + }), + str: 4, + value: 50 + }, + 4: { + text: t('weaponRogue4Text'), + notes: t('weaponRogue4Notes', { + str: 6 + }), + str: 6, + value: 70 + }, + 5: { + text: t('weaponRogue5Text'), + notes: t('weaponRogue5Notes', { + str: 8 + }), + str: 8, + value: 90 + }, + 6: { + text: t('weaponRogue6Text'), + notes: t('weaponRogue6Notes', { + str: 10 + }), + str: 10, + value: 120, + last: true + } + }, + wizard: { + 0: { + twoHanded: true, + text: t('weaponWizard0Text'), + notes: t('weaponWizard0Notes'), + value: 0 + }, + 1: { + twoHanded: true, + text: t('weaponWizard1Text'), + notes: t('weaponWizard1Notes', { + int: 3, + per: 1 + }), + int: 3, + per: 1, + value: 30 + }, + 2: { + twoHanded: true, + text: t('weaponWizard2Text'), + notes: t('weaponWizard2Notes', { + int: 6, + per: 2 + }), + int: 6, + per: 2, + value: 50 + }, + 3: { + twoHanded: true, + text: t('weaponWizard3Text'), + notes: t('weaponWizard3Notes', { + int: 9, + per: 3 + }), + int: 9, + per: 3, + value: 80 + }, + 4: { + twoHanded: true, + text: t('weaponWizard4Text'), + notes: t('weaponWizard4Notes', { + int: 12, + per: 5 + }), + int: 12, + per: 5, + value: 120 + }, + 5: { + twoHanded: true, + text: t('weaponWizard5Text'), + notes: t('weaponWizard5Notes', { + int: 15, + per: 7 + }), + int: 15, + per: 7, + value: 160 + }, + 6: { + twoHanded: true, + text: t('weaponWizard6Text'), + notes: t('weaponWizard6Notes', { + int: 18, + per: 10 + }), + int: 18, + per: 10, + value: 200, + last: true + } + }, + healer: { + 0: { + text: t('weaponHealer0Text'), + notes: t('weaponHealer0Notes'), + value: 0 + }, + 1: { + text: t('weaponHealer1Text'), + notes: t('weaponHealer1Notes', { + int: 2 + }), + int: 2, + value: 20 + }, + 2: { + text: t('weaponHealer2Text'), + notes: t('weaponHealer2Notes', { + int: 3 + }), + int: 3, + value: 30 + }, + 3: { + text: t('weaponHealer3Text'), + notes: t('weaponHealer3Notes', { + int: 5 + }), + int: 5, + value: 45 + }, + 4: { + text: t('weaponHealer4Text'), + notes: t('weaponHealer4Notes', { + int: 7 + }), + int: 7, + value: 65 + }, + 5: { + text: t('weaponHealer5Text'), + notes: t('weaponHealer5Notes', { + int: 9 + }), + int: 9, + value: 90 + }, + 6: { + text: t('weaponHealer6Text'), + notes: t('weaponHealer6Notes', { + int: 11 + }), + int: 11, + value: 120, + last: true + } + }, + special: { + 0: { + text: t('weaponSpecial0Text'), + notes: t('weaponSpecial0Notes', { + str: 20 + }), + str: 20, + value: 150, + canOwn: (function(u) { + var ref; + return +((ref = u.backer) != null ? ref.tier : void 0) >= 70; + }) + }, + 1: { + text: t('weaponSpecial1Text'), + notes: t('weaponSpecial1Notes', { + attrs: 6 + }), + str: 6, + per: 6, + con: 6, + int: 6, + value: 170, + canOwn: (function(u) { + var ref; + return +((ref = u.contributor) != null ? ref.level : void 0) >= 4; + }) + }, + 2: { + text: t('weaponSpecial2Text'), + notes: t('weaponSpecial2Notes', { + attrs: 25 + }), + str: 25, + per: 25, + value: 200, + canOwn: (function(u) { + var ref; + return (+((ref = u.backer) != null ? ref.tier : void 0) >= 300) || (u.items.gear.owned.weapon_special_2 != null); + }) + }, + 3: { + text: t('weaponSpecial3Text'), + notes: t('weaponSpecial3Notes', { + attrs: 17 + }), + str: 17, + int: 17, + con: 17, + value: 200, + canOwn: (function(u) { + var ref; + return (+((ref = u.backer) != null ? ref.tier : void 0) >= 300) || (u.items.gear.owned.weapon_special_3 != null); + }) + }, + critical: { + text: t('weaponSpecialCriticalText'), + notes: t('weaponSpecialCriticalNotes', { + attrs: 40 + }), + str: 40, + per: 40, + value: 200, + canOwn: (function(u) { + var ref; + return !!((ref = u.contributor) != null ? ref.critical : void 0); + }) + }, + tridentOfCrashingTides: { + text: t('weaponSpecialTridentOfCrashingTidesText'), + notes: t('weaponSpecialTridentOfCrashingTidesNotes', { + int: 15 + }), + int: 15, + value: 130, + canOwn: (function(u) { + return u.items.gear.owned.weapon_special_tridentOfCrashingTides != null; + }) + }, + yeti: { + event: events.winter, + specialClass: 'warrior', + text: t('weaponSpecialYetiText'), + notes: t('weaponSpecialYetiNotes', { + str: 15 + }), + str: 15, + value: 90 + }, + ski: { + event: events.winter, + specialClass: 'rogue', + text: t('weaponSpecialSkiText'), + notes: t('weaponSpecialSkiNotes', { + str: 8 + }), + str: 8, + value: 90 + }, + candycane: { + event: events.winter, + specialClass: 'wizard', + twoHanded: true, + text: t('weaponSpecialCandycaneText'), + notes: t('weaponSpecialCandycaneNotes', { + int: 15, + per: 7 + }), + int: 15, + per: 7, + value: 160 + }, + snowflake: { + event: events.winter, + specialClass: 'healer', + text: t('weaponSpecialSnowflakeText'), + notes: t('weaponSpecialSnowflakeNotes', { + int: 9 + }), + int: 9, + value: 90 + }, + springRogue: { + event: events.spring, + specialClass: 'rogue', + text: t('weaponSpecialSpringRogueText'), + notes: t('weaponSpecialSpringRogueNotes', { + str: 8 + }), + value: 80, + str: 8 + }, + springWarrior: { + event: events.spring, + specialClass: 'warrior', + text: t('weaponSpecialSpringWarriorText'), + notes: t('weaponSpecialSpringWarriorNotes', { + str: 15 + }), + value: 90, + str: 15 + }, + springMage: { + event: events.spring, + specialClass: 'wizard', + twoHanded: true, + text: t('weaponSpecialSpringMageText'), + notes: t('weaponSpecialSpringMageNotes', { + int: 15, + per: 7 + }), + value: 160, + int: 15, + per: 7 + }, + springHealer: { + event: events.spring, + specialClass: 'healer', + text: t('weaponSpecialSpringHealerText'), + notes: t('weaponSpecialSpringHealerNotes', { + int: 9 + }), + value: 90, + int: 9 + }, + summerRogue: { + event: events.summer, + specialClass: 'rogue', + text: t('weaponSpecialSummerRogueText'), + notes: t('weaponSpecialSummerRogueNotes', { + str: 8 + }), + value: 80, + str: 8 + }, + summerWarrior: { + event: events.summer, + specialClass: 'warrior', + text: t('weaponSpecialSummerWarriorText'), + notes: t('weaponSpecialSummerWarriorNotes', { + str: 15 + }), + value: 90, + str: 15 + }, + summerMage: { + event: events.summer, + specialClass: 'wizard', + twoHanded: true, + text: t('weaponSpecialSummerMageText'), + notes: t('weaponSpecialSummerMageNotes', { + int: 15, + per: 7 + }), + value: 160, + int: 15, + per: 7 + }, + summerHealer: { + event: events.summer, + specialClass: 'healer', + text: t('weaponSpecialSummerHealerText'), + notes: t('weaponSpecialSummerHealerNotes', { + int: 9 + }), + value: 90, + int: 9 + }, + fallRogue: { + event: events.fall, + specialClass: 'rogue', + text: t('weaponSpecialFallRogueText'), + notes: t('weaponSpecialFallRogueNotes', { + str: 8 + }), + value: 80, + str: 8, + canBuy: (function() { + return true; + }) + }, + fallWarrior: { + event: events.fall, + specialClass: 'warrior', + text: t('weaponSpecialFallWarriorText'), + notes: t('weaponSpecialFallWarriorNotes', { + str: 15 + }), + value: 90, + str: 15, + canBuy: (function() { + return true; + }) + }, + fallMage: { + event: events.fall, + specialClass: 'wizard', + twoHanded: true, + text: t('weaponSpecialFallMageText'), + notes: t('weaponSpecialFallMageNotes', { + int: 15, + per: 7 + }), + value: 160, + int: 15, + per: 7, + canBuy: (function() { + return true; + }) + }, + fallHealer: { + event: events.fall, + specialClass: 'healer', + text: t('weaponSpecialFallHealerText'), + notes: t('weaponSpecialFallHealerNotes', { + int: 9 + }), + value: 90, + int: 9, + canBuy: (function() { + return true; + }) + }, + winter2015Rogue: { + event: events.winter2015, + specialClass: 'rogue', + text: t('weaponSpecialWinter2015RogueText'), + notes: t('weaponSpecialWinter2015RogueNotes', { + str: 8 + }), + value: 80, + str: 8 + }, + winter2015Warrior: { + event: events.winter2015, + specialClass: 'warrior', + text: t('weaponSpecialWinter2015WarriorText'), + notes: t('weaponSpecialWinter2015WarriorNotes', { + str: 15 + }), + value: 90, + str: 15 + }, + winter2015Mage: { + event: events.winter2015, + specialClass: 'wizard', + twoHanded: true, + text: t('weaponSpecialWinter2015MageText'), + notes: t('weaponSpecialWinter2015MageNotes', { + int: 15, + per: 7 + }), + value: 160, + int: 15, + per: 7 + }, + winter2015Healer: { + event: events.winter2015, + specialClass: 'healer', + text: t('weaponSpecialWinter2015HealerText'), + notes: t('weaponSpecialWinter2015HealerNotes', { + int: 9 + }), + value: 90, + int: 9 + }, + spring2015Rogue: { + event: events.spring2015, + specialClass: 'rogue', + text: t('weaponSpecialSpring2015RogueText'), + notes: t('weaponSpecialSpring2015RogueNotes', { + str: 8 + }), + value: 80, + str: 8 + }, + spring2015Warrior: { + event: events.spring2015, + specialClass: 'warrior', + text: t('weaponSpecialSpring2015WarriorText'), + notes: t('weaponSpecialSpring2015WarriorNotes', { + str: 15 + }), + value: 90, + str: 15 + }, + spring2015Mage: { + event: events.spring2015, + specialClass: 'wizard', + twoHanded: true, + text: t('weaponSpecialSpring2015MageText'), + notes: t('weaponSpecialSpring2015MageNotes', { + int: 15, + per: 7 + }), + value: 160, + int: 15, + per: 7 + }, + spring2015Healer: { + event: events.spring2015, + specialClass: 'healer', + text: t('weaponSpecialSpring2015HealerText'), + notes: t('weaponSpecialSpring2015HealerNotes', { + int: 9 + }), + value: 90, + int: 9 + }, + summer2015Rogue: { + event: events.summer2015, + specialClass: 'rogue', + text: t('weaponSpecialSummer2015RogueText'), + notes: t('weaponSpecialSummer2015RogueNotes', { + str: 8 + }), + value: 80, + str: 8 + }, + summer2015Warrior: { + event: events.summer2015, + specialClass: 'warrior', + text: t('weaponSpecialSummer2015WarriorText'), + notes: t('weaponSpecialSummer2015WarriorNotes', { + str: 15 + }), + value: 90, + str: 15 + }, + summer2015Mage: { + event: events.summer2015, + specialClass: 'wizard', + twoHanded: true, + text: t('weaponSpecialSummer2015MageText'), + notes: t('weaponSpecialSummer2015MageNotes', { + int: 15, + per: 7 + }), + value: 160, + int: 15, + per: 7 + }, + summer2015Healer: { + event: events.summer2015, + specialClass: 'healer', + text: t('weaponSpecialSummer2015HealerText'), + notes: t('weaponSpecialSummer2015HealerNotes', { + int: 9 + }), + value: 90, + int: 9 + }, + fall2015Rogue: { + event: events.fall2015, + specialClass: 'rogue', + text: t('weaponSpecialFall2015RogueText'), + notes: t('weaponSpecialFall2015RogueNotes', { + str: 8 + }), + value: 80, + str: 8 + }, + fall2015Warrior: { + event: events.fall2015, + specialClass: 'warrior', + text: t('weaponSpecialFall2015WarriorText'), + notes: t('weaponSpecialFall2015WarriorNotes', { + str: 15 + }), + value: 90, + str: 15 + }, + fall2015Mage: { + event: events.fall2015, + specialClass: 'wizard', + twoHanded: true, + text: t('weaponSpecialFall2015MageText'), + notes: t('weaponSpecialFall2015MageNotes', { + int: 15, + per: 7 + }), + value: 160, + int: 15, + per: 7 + }, + fall2015Healer: { + event: events.fall2015, + specialClass: 'healer', + text: t('weaponSpecialFall2015HealerText'), + notes: t('weaponSpecialFall2015HealerNotes', { + int: 9 + }), + value: 90, + int: 9 + } + }, + mystery: { + 201411: { + text: t('weaponMystery201411Text'), + notes: t('weaponMystery201411Notes'), + mystery: '201411', + value: 0 + }, + 201502: { + text: t('weaponMystery201502Text'), + notes: t('weaponMystery201502Notes'), + mystery: '201502', + value: 0 + }, + 201505: { + text: t('weaponMystery201505Text'), + notes: t('weaponMystery201505Notes'), + mystery: '201505', + value: 0 + }, + 301404: { + text: t('weaponMystery301404Text'), + notes: t('weaponMystery301404Notes'), + mystery: '301404', + value: 0 + } + }, + armoire: { + basicCrossbow: { + text: t('weaponArmoireBasicCrossbowText'), + notes: t('weaponArmoireBasicCrossbowNotes', { + str: 5, + per: 5, + con: 5 + }), + value: 100, + str: 5, + per: 5, + con: 5, + canOwn: (function(u) { + return u.items.gear.owned.weapon_armoire_basicCrossbow != null; + }) + }, + lunarSceptre: { + text: t('weaponArmoireLunarSceptreText'), + notes: t('weaponArmoireLunarSceptreNotes', { + con: 7, + int: 7 + }), + value: 100, + con: 7, + int: 7, + set: 'soothing', + canOwn: (function(u) { + return u.items.gear.owned.weapon_armoire_lunarSceptre != null; + }) + }, + rancherLasso: { + twoHanded: true, + text: t('weaponArmoireRancherLassoText'), + notes: t('weaponArmoireRancherLassoNotes', { + str: 5, + per: 5, + int: 5 + }), + value: 100, + str: 5, + per: 5, + int: 5, + set: 'rancher', + canOwn: (function(u) { + return u.items.gear.owned.weapon_armoire_rancherLasso != null; + }) + }, + mythmakerSword: { + text: t('weaponArmoireMythmakerSwordText'), + notes: t('weaponArmoireMythmakerSwordNotes', { + attrs: 6 + }), + value: 100, + str: 6, + per: 6, + set: 'goldenToga', + canOwn: (function(u) { + return u.items.gear.owned.weapon_armoire_mythmakerSword != null; + }) + }, + ironCrook: { + text: t('weaponArmoireIronCrookText'), + notes: t('weaponArmoireIronCrookNotes', { + attrs: 7 + }), + value: 100, + str: 7, + per: 7, + set: 'hornedIron', + canOwn: (function(u) { + return u.items.gear.owned.weapon_armoire_ironCrook != null; + }) + }, + goldWingStaff: { + text: t('weaponArmoireGoldWingStaffText'), + notes: t('weaponArmoireGoldWingStaffNotes', { + attrs: 4 + }), + value: 100, + con: 4, + int: 4, + per: 4, + str: 4, + canOwn: (function(u) { + return u.items.gear.owned.weapon_armoire_goldWingStaff != null; + }) + }, + batWand: { + text: t('weaponArmoireBatWandText'), + notes: t('weaponArmoireBatWandNotes', { + int: 10, + per: 2 + }), + value: 100, + int: 10, + per: 2, + canOwn: (function(u) { + return u.items.gear.owned.weapon_armoire_batWand != null; + }) + }, + shepherdsCrook: { + text: t('weaponArmoireShepherdsCrookText'), + notes: t('weaponArmoireShepherdsCrookNotes', { + con: 9 + }), + value: 100, + con: 9, + set: 'shepherd', + canOwn: (function(u) { + return u.items.gear.owned.weapon_armoire_shepherdsCrook != null; + }) + } + } + }, + armor: { + base: { + 0: { + text: t('armorBase0Text'), + notes: t('armorBase0Notes'), + value: 0 + } + }, + warrior: { + 1: { + text: t('armorWarrior1Text'), + notes: t('armorWarrior1Notes', { + con: 3 + }), + con: 3, + value: 30 + }, + 2: { + text: t('armorWarrior2Text'), + notes: t('armorWarrior2Notes', { + con: 5 + }), + con: 5, + value: 45 + }, + 3: { + text: t('armorWarrior3Text'), + notes: t('armorWarrior3Notes', { + con: 7 + }), + con: 7, + value: 65 + }, + 4: { + text: t('armorWarrior4Text'), + notes: t('armorWarrior4Notes', { + con: 9 + }), + con: 9, + value: 90 + }, + 5: { + text: t('armorWarrior5Text'), + notes: t('armorWarrior5Notes', { + con: 11 + }), + con: 11, + value: 120, + last: true + } + }, + rogue: { + 1: { + text: t('armorRogue1Text'), + notes: t('armorRogue1Notes', { + per: 6 + }), + per: 6, + value: 30 + }, + 2: { + text: t('armorRogue2Text'), + notes: t('armorRogue2Notes', { + per: 9 + }), + per: 9, + value: 45 + }, + 3: { + text: t('armorRogue3Text'), + notes: t('armorRogue3Notes', { + per: 12 + }), + per: 12, + value: 65 + }, + 4: { + text: t('armorRogue4Text'), + notes: t('armorRogue4Notes', { + per: 15 + }), + per: 15, + value: 90 + }, + 5: { + text: t('armorRogue5Text'), + notes: t('armorRogue5Notes', { + per: 18 + }), + per: 18, + value: 120, + last: true + } + }, + wizard: { + 1: { + text: t('armorWizard1Text'), + notes: t('armorWizard1Notes', { + int: 2 + }), + int: 2, + value: 30 + }, + 2: { + text: t('armorWizard2Text'), + notes: t('armorWizard2Notes', { + int: 4 + }), + int: 4, + value: 45 + }, + 3: { + text: t('armorWizard3Text'), + notes: t('armorWizard3Notes', { + int: 6 + }), + int: 6, + value: 65 + }, + 4: { + text: t('armorWizard4Text'), + notes: t('armorWizard4Notes', { + int: 9 + }), + int: 9, + value: 90 + }, + 5: { + text: t('armorWizard5Text'), + notes: t('armorWizard5Notes', { + int: 12 + }), + int: 12, + value: 120, + last: true + } + }, + healer: { + 1: { + text: t('armorHealer1Text'), + notes: t('armorHealer1Notes', { + con: 6 + }), + con: 6, + value: 30 + }, + 2: { + text: t('armorHealer2Text'), + notes: t('armorHealer2Notes', { + con: 9 + }), + con: 9, + value: 45 + }, + 3: { + text: t('armorHealer3Text'), + notes: t('armorHealer3Notes', { + con: 12 + }), + con: 12, + value: 65 + }, + 4: { + text: t('armorHealer4Text'), + notes: t('armorHealer4Notes', { + con: 15 + }), + con: 15, + value: 90 + }, + 5: { + text: t('armorHealer5Text'), + notes: t('armorHealer5Notes', { + con: 18 + }), + con: 18, + value: 120, + last: true + } + }, + special: { + 0: { + text: t('armorSpecial0Text'), + notes: t('armorSpecial0Notes', { + con: 20 + }), + con: 20, + value: 150, + canOwn: (function(u) { + var ref; + return +((ref = u.backer) != null ? ref.tier : void 0) >= 45; + }) + }, + 1: { + text: t('armorSpecial1Text'), + notes: t('armorSpecial1Notes', { + attrs: 6 + }), + con: 6, + str: 6, + per: 6, + int: 6, + value: 170, + canOwn: (function(u) { + var ref; + return +((ref = u.contributor) != null ? ref.level : void 0) >= 2; + }) + }, + 2: { + text: t('armorSpecial2Text'), + notes: t('armorSpecial2Notes', { + attrs: 25 + }), + int: 25, + con: 25, + value: 200, + canOwn: (function(u) { + var ref; + return +((ref = u.backer) != null ? ref.tier : void 0) >= 300 || (u.items.gear.owned.armor_special_2 != null); + }) + }, + finnedOceanicArmor: { + text: t('armorSpecialFinnedOceanicArmorText'), + notes: t('armorSpecialFinnedOceanicArmorNotes', { + str: 15 + }), + str: 15, + value: 130, + canOwn: (function(u) { + return u.items.gear.owned.armor_special_finnedOceanicArmor != null; + }) + }, + yeti: { + event: events.winter, + specialClass: 'warrior', + text: t('armorSpecialYetiText'), + notes: t('armorSpecialYetiNotes', { + con: 9 + }), + con: 9, + value: 90 + }, + ski: { + event: events.winter, + specialClass: 'rogue', + text: t('armorSpecialSkiText'), + notes: t('armorSpecialSkiNotes', { + per: 15 + }), + per: 15, + value: 90 + }, + candycane: { + event: events.winter, + specialClass: 'wizard', + text: t('armorSpecialCandycaneText'), + notes: t('armorSpecialCandycaneNotes', { + int: 9 + }), + int: 9, + value: 90 + }, + snowflake: { + event: events.winter, + specialClass: 'healer', + text: t('armorSpecialSnowflakeText'), + notes: t('armorSpecialSnowflakeNotes', { + con: 15 + }), + con: 15, + value: 90 + }, + birthday: { + event: events.birthday, + text: t('armorSpecialBirthdayText'), + notes: t('armorSpecialBirthdayNotes'), + value: 0 + }, + springRogue: { + event: events.spring, + specialClass: 'rogue', + text: t('armorSpecialSpringRogueText'), + notes: t('armorSpecialSpringRogueNotes', { + per: 15 + }), + value: 90, + per: 15 + }, + springWarrior: { + event: events.spring, + specialClass: 'warrior', + text: t('armorSpecialSpringWarriorText'), + notes: t('armorSpecialSpringWarriorNotes', { + con: 9 + }), + value: 90, + con: 9 + }, + springMage: { + event: events.spring, + specialClass: 'wizard', + text: t('armorSpecialSpringMageText'), + notes: t('armorSpecialSpringMageNotes', { + int: 9 + }), + value: 90, + int: 9 + }, + springHealer: { + event: events.spring, + specialClass: 'healer', + text: t('armorSpecialSpringHealerText'), + notes: t('armorSpecialSpringHealerNotes', { + con: 15 + }), + value: 90, + con: 15 + }, + summerRogue: { + event: events.summer, + specialClass: 'rogue', + text: t('armorSpecialSummerRogueText'), + notes: t('armorSpecialSummerRogueNotes', { + per: 15 + }), + value: 90, + per: 15 + }, + summerWarrior: { + event: events.summer, + specialClass: 'warrior', + text: t('armorSpecialSummerWarriorText'), + notes: t('armorSpecialSummerWarriorNotes', { + con: 9 + }), + value: 90, + con: 9 + }, + summerMage: { + event: events.summer, + specialClass: 'wizard', + text: t('armorSpecialSummerMageText'), + notes: t('armorSpecialSummerMageNotes', { + int: 9 + }), + value: 90, + int: 9 + }, + summerHealer: { + event: events.summer, + specialClass: 'healer', + text: t('armorSpecialSummerHealerText'), + notes: t('armorSpecialSummerHealerNotes', { + con: 15 + }), + value: 90, + con: 15 + }, + fallRogue: { + event: events.fall, + specialClass: 'rogue', + text: t('armorSpecialFallRogueText'), + notes: t('armorSpecialFallRogueNotes', { + per: 15 + }), + value: 90, + per: 15, + canBuy: (function() { + return true; + }) + }, + fallWarrior: { + event: events.fall, + specialClass: 'warrior', + text: t('armorSpecialFallWarriorText'), + notes: t('armorSpecialFallWarriorNotes', { + con: 9 + }), + value: 90, + con: 9, + canBuy: (function() { + return true; + }) + }, + fallMage: { + event: events.fall, + specialClass: 'wizard', + text: t('armorSpecialFallMageText'), + notes: t('armorSpecialFallMageNotes', { + int: 9 + }), + value: 90, + int: 9, + canBuy: (function() { + return true; + }) + }, + fallHealer: { + event: events.fall, + specialClass: 'healer', + text: t('armorSpecialFallHealerText'), + notes: t('armorSpecialFallHealerNotes', { + con: 15 + }), + value: 90, + con: 15, + canBuy: (function() { + return true; + }) + }, + winter2015Rogue: { + event: events.winter2015, + specialClass: 'rogue', + text: t('armorSpecialWinter2015RogueText'), + notes: t('armorSpecialWinter2015RogueNotes', { + per: 15 + }), + value: 90, + per: 15 + }, + winter2015Warrior: { + event: events.winter2015, + specialClass: 'warrior', + text: t('armorSpecialWinter2015WarriorText'), + notes: t('armorSpecialWinter2015WarriorNotes', { + con: 9 + }), + value: 90, + con: 9 + }, + winter2015Mage: { + event: events.winter2015, + specialClass: 'wizard', + text: t('armorSpecialWinter2015MageText'), + notes: t('armorSpecialWinter2015MageNotes', { + int: 9 + }), + value: 90, + int: 9 + }, + winter2015Healer: { + event: events.winter2015, + specialClass: 'healer', + text: t('armorSpecialWinter2015HealerText'), + notes: t('armorSpecialWinter2015HealerNotes', { + con: 15 + }), + value: 90, + con: 15 + }, + birthday2015: { + text: t('armorSpecialBirthday2015Text'), + notes: t('armorSpecialBirthday2015Notes'), + value: 0, + canOwn: (function(u) { + return u.items.gear.owned.armor_special_birthday2015 != null; + }) + }, + spring2015Rogue: { + event: events.spring2015, + specialClass: 'rogue', + text: t('armorSpecialSpring2015RogueText'), + notes: t('armorSpecialSpring2015RogueNotes', { + per: 15 + }), + value: 90, + per: 15 + }, + spring2015Warrior: { + event: events.spring2015, + specialClass: 'warrior', + text: t('armorSpecialSpring2015WarriorText'), + notes: t('armorSpecialSpring2015WarriorNotes', { + con: 9 + }), + value: 90, + con: 9 + }, + spring2015Mage: { + event: events.spring2015, + specialClass: 'wizard', + text: t('armorSpecialSpring2015MageText'), + notes: t('armorSpecialSpring2015MageNotes', { + int: 9 + }), + value: 90, + int: 9 + }, + spring2015Healer: { + event: events.spring2015, + specialClass: 'healer', + text: t('armorSpecialSpring2015HealerText'), + notes: t('armorSpecialSpring2015HealerNotes', { + con: 15 + }), + value: 90, + con: 15 + }, + summer2015Rogue: { + event: events.summer2015, + specialClass: 'rogue', + text: t('armorSpecialSummer2015RogueText'), + notes: t('armorSpecialSummer2015RogueNotes', { + per: 15 + }), + value: 90, + per: 15 + }, + summer2015Warrior: { + event: events.summer2015, + specialClass: 'warrior', + text: t('armorSpecialSummer2015WarriorText'), + notes: t('armorSpecialSummer2015WarriorNotes', { + con: 9 + }), + value: 90, + con: 9 + }, + summer2015Mage: { + event: events.summer2015, + specialClass: 'wizard', + text: t('armorSpecialSummer2015MageText'), + notes: t('armorSpecialSummer2015MageNotes', { + int: 9 + }), + value: 90, + int: 9 + }, + summer2015Healer: { + event: events.summer2015, + specialClass: 'healer', + text: t('armorSpecialSummer2015HealerText'), + notes: t('armorSpecialSummer2015HealerNotes', { + con: 15 + }), + value: 90, + con: 15 + }, + fall2015Rogue: { + event: events.fall2015, + specialClass: 'rogue', + text: t('armorSpecialFall2015RogueText'), + notes: t('armorSpecialFall2015RogueNotes', { + per: 15 + }), + value: 90, + per: 15 + }, + fall2015Warrior: { + event: events.fall2015, + specialClass: 'warrior', + text: t('armorSpecialFall2015WarriorText'), + notes: t('armorSpecialFall2015WarriorNotes', { + con: 9 + }), + value: 90, + con: 9 + }, + fall2015Mage: { + event: events.fall2015, + specialClass: 'wizard', + text: t('armorSpecialFall2015MageText'), + notes: t('armorSpecialFall2015MageNotes', { + int: 9 + }), + value: 90, + int: 9 + }, + fall2015Healer: { + event: events.fall2015, + specialClass: 'healer', + text: t('armorSpecialFall2015HealerText'), + notes: t('armorSpecialFall2015HealerNotes', { + con: 15 + }), + value: 90, + con: 15 + }, + gaymerx: { + event: events.gaymerx, + text: t('armorSpecialGaymerxText'), + notes: t('armorSpecialGaymerxNotes'), + value: 0 + } + }, + mystery: { + 201402: { + text: t('armorMystery201402Text'), + notes: t('armorMystery201402Notes'), + mystery: '201402', + value: 0 + }, + 201403: { + text: t('armorMystery201403Text'), + notes: t('armorMystery201403Notes'), + mystery: '201403', + value: 0 + }, + 201405: { + text: t('armorMystery201405Text'), + notes: t('armorMystery201405Notes'), + mystery: '201405', + value: 0 + }, + 201406: { + text: t('armorMystery201406Text'), + notes: t('armorMystery201406Notes'), + mystery: '201406', + value: 0 + }, + 201407: { + text: t('armorMystery201407Text'), + notes: t('armorMystery201407Notes'), + mystery: '201407', + value: 0 + }, + 201408: { + text: t('armorMystery201408Text'), + notes: t('armorMystery201408Notes'), + mystery: '201408', + value: 0 + }, + 201409: { + text: t('armorMystery201409Text'), + notes: t('armorMystery201409Notes'), + mystery: '201409', + value: 0 + }, + 201410: { + text: t('armorMystery201410Text'), + notes: t('armorMystery201410Notes'), + mystery: '201410', + value: 0 + }, + 201412: { + text: t('armorMystery201412Text'), + notes: t('armorMystery201412Notes'), + mystery: '201412', + value: 0 + }, + 201501: { + text: t('armorMystery201501Text'), + notes: t('armorMystery201501Notes'), + mystery: '201501', + value: 0 + }, + 201503: { + text: t('armorMystery201503Text'), + notes: t('armorMystery201503Notes'), + mystery: '201503', + value: 0 + }, + 201504: { + text: t('armorMystery201504Text'), + notes: t('armorMystery201504Notes'), + mystery: '201504', + value: 0 + }, + 201506: { + text: t('armorMystery201506Text'), + notes: t('armorMystery201506Notes'), + mystery: '201506', + value: 0 + }, + 201508: { + text: t('armorMystery201508Text'), + notes: t('armorMystery201508Notes'), + mystery: '201508', + value: 0 + }, + 201509: { + text: t('armorMystery201509Text'), + notes: t('armorMystery201509Notes'), + mystery: '201509', + value: 0 + }, + 301404: { + text: t('armorMystery301404Text'), + notes: t('armorMystery301404Notes'), + mystery: '301404', + value: 0 + } + }, + armoire: { + lunarArmor: { + text: t('armorArmoireLunarArmorText'), + notes: t('armorArmoireLunarArmorNotes', { + str: 7, + int: 7 + }), + value: 100, + str: 7, + int: 7, + set: 'soothing', + canOwn: (function(u) { + return u.items.gear.owned.armor_armoire_lunarArmor != null; + }) + }, + gladiatorArmor: { + text: t('armorArmoireGladiatorArmorText'), + notes: t('armorArmoireGladiatorArmorNotes', { + str: 7, + per: 7 + }), + value: 100, + str: 7, + per: 7, + set: 'gladiator', + canOwn: (function(u) { + return u.items.gear.owned.armor_armoire_gladiatorArmor != null; + }) + }, + rancherRobes: { + text: t('armorArmoireRancherRobesText'), + notes: t('armorArmoireRancherRobesNotes', { + str: 5, + per: 5, + int: 5 + }), + value: 100, + str: 5, + per: 5, + int: 5, + set: 'rancher', + canOwn: (function(u) { + return u.items.gear.owned.armor_armoire_rancherRobes != null; + }) + }, + goldenToga: { + text: t('armorArmoireGoldenTogaText'), + notes: t('armorArmoireGoldenTogaNotes', { + attrs: 8 + }), + value: 100, + str: 8, + con: 8, + set: 'goldenToga', + canOwn: (function(u) { + return u.items.gear.owned.armor_armoire_goldenToga != null; + }) + }, + hornedIronArmor: { + text: t('armorArmoireHornedIronArmorText'), + notes: t('armorArmoireHornedIronArmorNotes', { + con: 9, + per: 7 + }), + value: 100, + con: 9, + per: 7, + set: 'hornedIron', + canOwn: (function(u) { + return u.items.gear.owned.armor_armoire_hornedIronArmor != null; + }) + }, + plagueDoctorOvercoat: { + text: t('armorArmoirePlagueDoctorOvercoatText'), + notes: t('armorArmoirePlagueDoctorOvercoatNotes', { + int: 6, + str: 5, + con: 6 + }), + value: 100, + int: 6, + str: 5, + con: 6, + set: 'plagueDoctor', + canOwn: (function(u) { + return u.items.gear.owned.armor_armoire_plagueDoctorOvercoat != null; + }) + }, + shepherdRobes: { + text: t('armorArmoireShepherdRobesText'), + notes: t('armorArmoireShepherdRobesNotes', { + attrs: 9 + }), + value: 100, + str: 9, + per: 9, + set: 'shepherd', + canOwn: (function(u) { + return u.items.gear.owned.armor_armoire_shepherdRobes != null; + }) + }, + royalRobes: { + text: t('armorArmoireRoyalRobesText'), + notes: t('armorArmoireRoyalRobesNotes', { + attrs: 5 + }), + value: 100, + con: 5, + per: 5, + int: 5, + set: 'royal', + canOwn: (function(u) { + return u.items.gear.owned.armor_armoire_royalRobes != null; + }) + } + } + }, + head: { + base: { + 0: { + text: t('headBase0Text'), + notes: t('headBase0Notes'), + value: 0 + } + }, + warrior: { + 1: { + text: t('headWarrior1Text'), + notes: t('headWarrior1Notes', { + str: 2 + }), + str: 2, + value: 15 + }, + 2: { + text: t('headWarrior2Text'), + notes: t('headWarrior2Notes', { + str: 4 + }), + str: 4, + value: 25 + }, + 3: { + text: t('headWarrior3Text'), + notes: t('headWarrior3Notes', { + str: 6 + }), + str: 6, + value: 40 + }, + 4: { + text: t('headWarrior4Text'), + notes: t('headWarrior4Notes', { + str: 9 + }), + str: 9, + value: 60 + }, + 5: { + text: t('headWarrior5Text'), + notes: t('headWarrior5Notes', { + str: 12 + }), + str: 12, + value: 80, + last: true + } + }, + rogue: { + 1: { + text: t('headRogue1Text'), + notes: t('headRogue1Notes', { + per: 2 + }), + per: 2, + value: 15 + }, + 2: { + text: t('headRogue2Text'), + notes: t('headRogue2Notes', { + per: 4 + }), + per: 4, + value: 25 + }, + 3: { + text: t('headRogue3Text'), + notes: t('headRogue3Notes', { + per: 6 + }), + per: 6, + value: 40 + }, + 4: { + text: t('headRogue4Text'), + notes: t('headRogue4Notes', { + per: 9 + }), + per: 9, + value: 60 + }, + 5: { + text: t('headRogue5Text'), + notes: t('headRogue5Notes', { + per: 12 + }), + per: 12, + value: 80, + last: true + } + }, + wizard: { + 1: { + text: t('headWizard1Text'), + notes: t('headWizard1Notes', { + per: 2 + }), + per: 2, + value: 15 + }, + 2: { + text: t('headWizard2Text'), + notes: t('headWizard2Notes', { + per: 3 + }), + per: 3, + value: 25 + }, + 3: { + text: t('headWizard3Text'), + notes: t('headWizard3Notes', { + per: 5 + }), + per: 5, + value: 40 + }, + 4: { + text: t('headWizard4Text'), + notes: t('headWizard4Notes', { + per: 7 + }), + per: 7, + value: 60 + }, + 5: { + text: t('headWizard5Text'), + notes: t('headWizard5Notes', { + per: 10 + }), + per: 10, + value: 80, + last: true + } + }, + healer: { + 1: { + text: t('headHealer1Text'), + notes: t('headHealer1Notes', { + int: 2 + }), + int: 2, + value: 15 + }, + 2: { + text: t('headHealer2Text'), + notes: t('headHealer2Notes', { + int: 3 + }), + int: 3, + value: 25 + }, + 3: { + text: t('headHealer3Text'), + notes: t('headHealer3Notes', { + int: 5 + }), + int: 5, + value: 40 + }, + 4: { + text: t('headHealer4Text'), + notes: t('headHealer4Notes', { + int: 7 + }), + int: 7, + value: 60 + }, + 5: { + text: t('headHealer5Text'), + notes: t('headHealer5Notes', { + int: 9 + }), + int: 9, + value: 80, + last: true + } + }, + special: { + 0: { + text: t('headSpecial0Text'), + notes: t('headSpecial0Notes', { + int: 20 + }), + int: 20, + value: 150, + canOwn: (function(u) { + var ref; + return +((ref = u.backer) != null ? ref.tier : void 0) >= 45; + }) + }, + 1: { + text: t('headSpecial1Text'), + notes: t('headSpecial1Notes', { + attrs: 6 + }), + con: 6, + str: 6, + per: 6, + int: 6, + value: 170, + canOwn: (function(u) { + var ref; + return +((ref = u.contributor) != null ? ref.level : void 0) >= 3; + }) + }, + 2: { + text: t('headSpecial2Text'), + notes: t('headSpecial2Notes', { + attrs: 25 + }), + int: 25, + str: 25, + value: 200, + canOwn: (function(u) { + var ref; + return (+((ref = u.backer) != null ? ref.tier : void 0) >= 300) || (u.items.gear.owned.head_special_2 != null); + }) + }, + fireCoralCirclet: { + text: t('headSpecialFireCoralCircletText'), + notes: t('headSpecialFireCoralCircletNotes', { + per: 15 + }), + per: 15, + value: 130, + canOwn: (function(u) { + return u.items.gear.owned.head_special_fireCoralCirclet != null; + }) + }, + nye: { + event: events.winter, + text: t('headSpecialNyeText'), + notes: t('headSpecialNyeNotes'), + value: 0 + }, + yeti: { + event: events.winter, + specialClass: 'warrior', + text: t('headSpecialYetiText'), + notes: t('headSpecialYetiNotes', { + str: 9 + }), + str: 9, + value: 60 + }, + ski: { + event: events.winter, + specialClass: 'rogue', + text: t('headSpecialSkiText'), + notes: t('headSpecialSkiNotes', { + per: 9 + }), + per: 9, + value: 60 + }, + candycane: { + event: events.winter, + specialClass: 'wizard', + text: t('headSpecialCandycaneText'), + notes: t('headSpecialCandycaneNotes', { + per: 7 + }), + per: 7, + value: 60 + }, + snowflake: { + event: events.winter, + specialClass: 'healer', + text: t('headSpecialSnowflakeText'), + notes: t('headSpecialSnowflakeNotes', { + int: 7 + }), + int: 7, + value: 60 + }, + springRogue: { + event: events.spring, + specialClass: 'rogue', + text: t('headSpecialSpringRogueText'), + notes: t('headSpecialSpringRogueNotes', { + per: 9 + }), + value: 60, + per: 9 + }, + springWarrior: { + event: events.spring, + specialClass: 'warrior', + text: t('headSpecialSpringWarriorText'), + notes: t('headSpecialSpringWarriorNotes', { + str: 9 + }), + value: 60, + str: 9 + }, + springMage: { + event: events.spring, + specialClass: 'wizard', + text: t('headSpecialSpringMageText'), + notes: t('headSpecialSpringMageNotes', { + per: 7 + }), + value: 60, + per: 7 + }, + springHealer: { + event: events.spring, + specialClass: 'healer', + text: t('headSpecialSpringHealerText'), + notes: t('headSpecialSpringHealerNotes', { + int: 7 + }), + value: 60, + int: 7 + }, + summerRogue: { + event: events.summer, + specialClass: 'rogue', + text: t('headSpecialSummerRogueText'), + notes: t('headSpecialSummerRogueNotes', { + per: 9 + }), + value: 60, + per: 9 + }, + summerWarrior: { + event: events.summer, + specialClass: 'warrior', + text: t('headSpecialSummerWarriorText'), + notes: t('headSpecialSummerWarriorNotes', { + str: 9 + }), + value: 60, + str: 9 + }, + summerMage: { + event: events.summer, + specialClass: 'wizard', + text: t('headSpecialSummerMageText'), + notes: t('headSpecialSummerMageNotes', { + per: 7 + }), + value: 60, + per: 7 + }, + summerHealer: { + event: events.summer, + specialClass: 'healer', + text: t('headSpecialSummerHealerText'), + notes: t('headSpecialSummerHealerNotes', { + int: 7 + }), + value: 60, + int: 7 + }, + fallRogue: { + event: events.fall, + specialClass: 'rogue', + text: t('headSpecialFallRogueText'), + notes: t('headSpecialFallRogueNotes', { + per: 9 + }), + value: 60, + per: 9, + canBuy: (function() { + return true; + }) + }, + fallWarrior: { + event: events.fall, + specialClass: 'warrior', + text: t('headSpecialFallWarriorText'), + notes: t('headSpecialFallWarriorNotes', { + str: 9 + }), + value: 60, + str: 9, + canBuy: (function() { + return true; + }) + }, + fallMage: { + event: events.fall, + specialClass: 'wizard', + text: t('headSpecialFallMageText'), + notes: t('headSpecialFallMageNotes', { + per: 7 + }), + value: 60, + per: 7, + canBuy: (function() { + return true; + }) + }, + fallHealer: { + event: events.fall, + specialClass: 'healer', + text: t('headSpecialFallHealerText'), + notes: t('headSpecialFallHealerNotes', { + int: 7 + }), + value: 60, + int: 7, + canBuy: (function() { + return true; + }) + }, + winter2015Rogue: { + event: events.winter2015, + specialClass: 'rogue', + text: t('headSpecialWinter2015RogueText'), + notes: t('headSpecialWinter2015RogueNotes', { + per: 9 + }), + value: 60, + per: 9 + }, + winter2015Warrior: { + event: events.winter2015, + specialClass: 'warrior', + text: t('headSpecialWinter2015WarriorText'), + notes: t('headSpecialWinter2015WarriorNotes', { + str: 9 + }), + value: 60, + str: 9 + }, + winter2015Mage: { + event: events.winter2015, + specialClass: 'wizard', + text: t('headSpecialWinter2015MageText'), + notes: t('headSpecialWinter2015MageNotes', { + per: 7 + }), + value: 60, + per: 7 + }, + winter2015Healer: { + event: events.winter2015, + specialClass: 'healer', + text: t('headSpecialWinter2015HealerText'), + notes: t('headSpecialWinter2015HealerNotes', { + int: 7 + }), + value: 60, + int: 7 + }, + nye2014: { + text: t('headSpecialNye2014Text'), + notes: t('headSpecialNye2014Notes'), + value: 0, + canOwn: (function(u) { + return u.items.gear.owned.head_special_nye2014 != null; + }) + }, + spring2015Rogue: { + event: events.spring2015, + specialClass: 'rogue', + text: t('headSpecialSpring2015RogueText'), + notes: t('headSpecialSpring2015RogueNotes', { + per: 9 + }), + value: 60, + per: 9 + }, + spring2015Warrior: { + event: events.spring2015, + specialClass: 'warrior', + text: t('headSpecialSpring2015WarriorText'), + notes: t('headSpecialSpring2015WarriorNotes', { + str: 9 + }), + value: 60, + str: 9 + }, + spring2015Mage: { + event: events.spring2015, + specialClass: 'wizard', + text: t('headSpecialSpring2015MageText'), + notes: t('headSpecialSpring2015MageNotes', { + per: 7 + }), + value: 60, + per: 7 + }, + spring2015Healer: { + event: events.spring2015, + specialClass: 'healer', + text: t('headSpecialSpring2015HealerText'), + notes: t('headSpecialSpring2015HealerNotes', { + int: 7 + }), + value: 60, + int: 7 + }, + summer2015Rogue: { + event: events.summer2015, + specialClass: 'rogue', + text: t('headSpecialSummer2015RogueText'), + notes: t('headSpecialSummer2015RogueNotes', { + per: 9 + }), + value: 60, + per: 9 + }, + summer2015Warrior: { + event: events.summer2015, + specialClass: 'warrior', + text: t('headSpecialSummer2015WarriorText'), + notes: t('headSpecialSummer2015WarriorNotes', { + str: 9 + }), + value: 60, + str: 9 + }, + summer2015Mage: { + event: events.summer2015, + specialClass: 'wizard', + text: t('headSpecialSummer2015MageText'), + notes: t('headSpecialSummer2015MageNotes', { + per: 7 + }), + value: 60, + per: 7 + }, + summer2015Healer: { + event: events.summer2015, + specialClass: 'healer', + text: t('headSpecialSummer2015HealerText'), + notes: t('headSpecialSummer2015HealerNotes', { + int: 7 + }), + value: 60, + int: 7 + }, + fall2015Rogue: { + event: events.fall2015, + specialClass: 'rogue', + text: t('headSpecialFall2015RogueText'), + notes: t('headSpecialFall2015RogueNotes', { + per: 9 + }), + value: 60, + per: 9 + }, + fall2015Warrior: { + event: events.fall2015, + specialClass: 'warrior', + text: t('headSpecialFall2015WarriorText'), + notes: t('headSpecialFall2015WarriorNotes', { + str: 9 + }), + value: 60, + str: 9 + }, + fall2015Mage: { + event: events.fall2015, + specialClass: 'wizard', + text: t('headSpecialFall2015MageText'), + notes: t('headSpecialFall2015MageNotes', { + per: 7 + }), + value: 60, + per: 7 + }, + fall2015Healer: { + event: events.fall2015, + specialClass: 'healer', + text: t('headSpecialFall2015HealerText'), + notes: t('headSpecialFall2015HealerNotes', { + int: 7 + }), + value: 60, + int: 7 + }, + gaymerx: { + event: events.gaymerx, + text: t('headSpecialGaymerxText'), + notes: t('headSpecialGaymerxNotes'), + value: 0 + } + }, + mystery: { + 201402: { + text: t('headMystery201402Text'), + notes: t('headMystery201402Notes'), + mystery: '201402', + value: 0 + }, + 201405: { + text: t('headMystery201405Text'), + notes: t('headMystery201405Notes'), + mystery: '201405', + value: 0 + }, + 201406: { + text: t('headMystery201406Text'), + notes: t('headMystery201406Notes'), + mystery: '201406', + value: 0 + }, + 201407: { + text: t('headMystery201407Text'), + notes: t('headMystery201407Notes'), + mystery: '201407', + value: 0 + }, + 201408: { + text: t('headMystery201408Text'), + notes: t('headMystery201408Notes'), + mystery: '201408', + value: 0 + }, + 201411: { + text: t('headMystery201411Text'), + notes: t('headMystery201411Notes'), + mystery: '201411', + value: 0 + }, + 201412: { + text: t('headMystery201412Text'), + notes: t('headMystery201412Notes'), + mystery: '201412', + value: 0 + }, + 201501: { + text: t('headMystery201501Text'), + notes: t('headMystery201501Notes'), + mystery: '201501', + value: 0 + }, + 201505: { + text: t('headMystery201505Text'), + notes: t('headMystery201505Notes'), + mystery: '201505', + value: 0 + }, + 201508: { + text: t('headMystery201508Text'), + notes: t('headMystery201508Notes'), + mystery: '201508', + value: 0 + }, + 201509: { + text: t('headMystery201509Text'), + notes: t('headMystery201509Notes'), + mystery: '201509', + value: 0 + }, + 301404: { + text: t('headMystery301404Text'), + notes: t('headMystery301404Notes'), + mystery: '301404', + value: 0 + }, + 301405: { + text: t('headMystery301405Text'), + notes: t('headMystery301405Notes'), + mystery: '301405', + value: 0 + } + }, + armoire: { + lunarCrown: { + text: t('headArmoireLunarCrownText'), + notes: t('headArmoireLunarCrownNotes', { + con: 7, + per: 7 + }), + value: 100, + con: 7, + per: 7, + set: 'soothing', + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_lunarCrown != null; + }) + }, + redHairbow: { + text: t('headArmoireRedHairbowText'), + notes: t('headArmoireRedHairbowNotes', { + str: 5, + int: 5, + con: 5 + }), + value: 100, + str: 5, + int: 5, + con: 5, + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_redHairbow != null; + }) + }, + violetFloppyHat: { + text: t('headArmoireVioletFloppyHatText'), + notes: t('headArmoireVioletFloppyHatNotes', { + per: 5, + int: 5, + con: 5 + }), + value: 100, + per: 5, + int: 5, + con: 5, + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_violetFloppyHat != null; + }) + }, + gladiatorHelm: { + text: t('headArmoireGladiatorHelmText'), + notes: t('headArmoireGladiatorHelmNotes', { + per: 7, + int: 7 + }), + value: 100, + per: 7, + int: 7, + set: 'gladiator', + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_gladiatorHelm != null; + }) + }, + rancherHat: { + text: t('headArmoireRancherHatText'), + notes: t('headArmoireRancherHatNotes', { + str: 5, + per: 5, + int: 5 + }), + value: 100, + str: 5, + per: 5, + int: 5, + set: 'rancher', + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_rancherHat != null; + }) + }, + royalCrown: { + text: t('headArmoireRoyalCrownText'), + notes: t('headArmoireRoyalCrownNotes', { + str: 10 + }), + value: 100, + str: 10, + set: 'royal', + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_royalCrown != null; + }) + }, + blueHairbow: { + text: t('headArmoireBlueHairbowText'), + notes: t('headArmoireBlueHairbowNotes', { + per: 5, + int: 5, + con: 5 + }), + value: 100, + per: 5, + int: 5, + con: 5, + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_blueHairbow != null; + }) + }, + goldenLaurels: { + text: t('headArmoireGoldenLaurelsText'), + notes: t('headArmoireGoldenLaurelsNotes', { + attrs: 8 + }), + value: 100, + per: 8, + con: 8, + set: 'goldenToga', + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_goldenLaurels != null; + }) + }, + hornedIronHelm: { + text: t('headArmoireHornedIronHelmText'), + notes: t('headArmoireHornedIronHelmNotes', { + con: 9, + str: 7 + }), + value: 100, + con: 9, + str: 7, + set: 'hornedIron', + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_hornedIronHelm != null; + }) + }, + yellowHairbow: { + text: t('headArmoireYellowHairbowText'), + notes: t('headArmoireYellowHairbowNotes', { + attrs: 5 + }), + value: 100, + int: 5, + per: 5, + str: 5, + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_yellowHairbow != null; + }) + }, + redFloppyHat: { + text: t('headArmoireRedFloppyHatText'), + notes: t('headArmoireRedFloppyHatNotes', { + attrs: 6 + }), + value: 100, + con: 6, + int: 6, + per: 6, + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_redFloppyHat != null; + }) + }, + plagueDoctorHat: { + text: t('headArmoirePlagueDoctorHatText'), + notes: t('headArmoirePlagueDoctorHatNotes', { + int: 5, + str: 6, + con: 5 + }), + value: 100, + int: 5, + str: 6, + con: 5, + set: 'plagueDoctor', + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_plagueDoctorHat != null; + }) + }, + blackCat: { + text: t('headArmoireBlackCatText'), + notes: t('headArmoireBlackCatNotes', { + attrs: 9 + }), + value: 100, + int: 9, + per: 9, + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_blackCat != null; + }) + }, + orangeCat: { + text: t('headArmoireOrangeCatText'), + notes: t('headArmoireOrangeCatNotes', { + attrs: 9 + }), + value: 100, + con: 9, + str: 9, + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_orangeCat != null; + }) + }, + blueFloppyHat: { + text: t('headArmoireBlueFloppyHatText'), + notes: t('headArmoireBlueFloppyHatNotes', { + attrs: 7 + }), + value: 100, + per: 7, + int: 7, + con: 7, + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_blueFloppyHat != null; + }) + }, + shepherdHeaddress: { + text: t('headArmoireShepherdHeaddressText'), + notes: t('headArmoireShepherdHeaddressNotes', { + int: 9 + }), + value: 100, + int: 9, + set: 'shepherd', + canOwn: (function(u) { + return u.items.gear.owned.head_armoire_shepherdHeaddress != null; + }) + } + } + }, + shield: { + base: { + 0: { + text: t('shieldBase0Text'), + notes: t('shieldBase0Notes'), + value: 0 + } + }, + warrior: { + 1: { + text: t('shieldWarrior1Text'), + notes: t('shieldWarrior1Notes', { + con: 2 + }), + con: 2, + value: 20 + }, + 2: { + text: t('shieldWarrior2Text'), + notes: t('shieldWarrior2Notes', { + con: 3 + }), + con: 3, + value: 35 + }, + 3: { + text: t('shieldWarrior3Text'), + notes: t('shieldWarrior3Notes', { + con: 5 + }), + con: 5, + value: 50 + }, + 4: { + text: t('shieldWarrior4Text'), + notes: t('shieldWarrior4Notes', { + con: 7 + }), + con: 7, + value: 70 + }, + 5: { + text: t('shieldWarrior5Text'), + notes: t('shieldWarrior5Notes', { + con: 9 + }), + con: 9, + value: 90, + last: true + } + }, + rogue: { + 0: { + text: t('weaponRogue0Text'), + notes: t('weaponRogue0Notes'), + str: 0, + value: 0 + }, + 1: { + text: t('weaponRogue1Text'), + notes: t('weaponRogue1Notes', { + str: 2 + }), + str: 2, + value: 20 + }, + 2: { + text: t('weaponRogue2Text'), + notes: t('weaponRogue2Notes', { + str: 3 + }), + str: 3, + value: 35 + }, + 3: { + text: t('weaponRogue3Text'), + notes: t('weaponRogue3Notes', { + str: 4 + }), + str: 4, + value: 50 + }, + 4: { + text: t('weaponRogue4Text'), + notes: t('weaponRogue4Notes', { + str: 6 + }), + str: 6, + value: 70 + }, + 5: { + text: t('weaponRogue5Text'), + notes: t('weaponRogue5Notes', { + str: 8 + }), + str: 8, + value: 90 + }, + 6: { + text: t('weaponRogue6Text'), + notes: t('weaponRogue6Notes', { + str: 10 + }), + str: 10, + value: 120, + last: true + } + }, + wizard: {}, + healer: { + 1: { + text: t('shieldHealer1Text'), + notes: t('shieldHealer1Notes', { + con: 2 + }), + con: 2, + value: 20 + }, + 2: { + text: t('shieldHealer2Text'), + notes: t('shieldHealer2Notes', { + con: 4 + }), + con: 4, + value: 35 + }, + 3: { + text: t('shieldHealer3Text'), + notes: t('shieldHealer3Notes', { + con: 6 + }), + con: 6, + value: 50 + }, + 4: { + text: t('shieldHealer4Text'), + notes: t('shieldHealer4Notes', { + con: 9 + }), + con: 9, + value: 70 + }, + 5: { + text: t('shieldHealer5Text'), + notes: t('shieldHealer5Notes', { + con: 12 + }), + con: 12, + value: 90, + last: true + } + }, + special: { + 0: { + text: t('shieldSpecial0Text'), + notes: t('shieldSpecial0Notes', { + per: 20 + }), + per: 20, + value: 150, + canOwn: (function(u) { + var ref; + return +((ref = u.backer) != null ? ref.tier : void 0) >= 45; + }) + }, + 1: { + text: t('shieldSpecial1Text'), + notes: t('shieldSpecial1Notes', { + attrs: 6 + }), + con: 6, + str: 6, + per: 6, + int: 6, + value: 170, + canOwn: (function(u) { + var ref; + return +((ref = u.contributor) != null ? ref.level : void 0) >= 5; + }) + }, + goldenknight: { + text: t('shieldSpecialGoldenknightText'), + notes: t('shieldSpecialGoldenknightNotes', { + attrs: 25 + }), + con: 25, + per: 25, + value: 200, + canOwn: (function(u) { + return u.items.gear.owned.shield_special_goldenknight != null; + }) + }, + moonpearlShield: { + text: t('shieldSpecialMoonpearlShieldText'), + notes: t('shieldSpecialMoonpearlShieldNotes', { + con: 15 + }), + con: 15, + value: 130, + canOwn: (function(u) { + return u.items.gear.owned.shield_special_moonpearlShield != null; + }) + }, + yeti: { + event: events.winter, + specialClass: 'warrior', + text: t('shieldSpecialYetiText'), + notes: t('shieldSpecialYetiNotes', { + con: 7 + }), + con: 7, + value: 70 + }, + ski: { + event: events.winter, + specialClass: 'rogue', + text: t('weaponSpecialSkiText'), + notes: t('weaponSpecialSkiNotes', { + str: 8 + }), + str: 8, + value: 90 + }, + snowflake: { + event: events.winter, + specialClass: 'healer', + text: t('shieldSpecialSnowflakeText'), + notes: t('shieldSpecialSnowflakeNotes', { + con: 9 + }), + con: 9, + value: 70 + }, + springRogue: { + event: events.spring, + specialClass: 'rogue', + text: t('shieldSpecialSpringRogueText'), + notes: t('shieldSpecialSpringRogueNotes', { + str: 8 + }), + value: 80, + str: 8 + }, + springWarrior: { + event: events.spring, + specialClass: 'warrior', + text: t('shieldSpecialSpringWarriorText'), + notes: t('shieldSpecialSpringWarriorNotes', { + con: 7 + }), + value: 70, + con: 7 + }, + springHealer: { + event: events.spring, + specialClass: 'healer', + text: t('shieldSpecialSpringHealerText'), + notes: t('shieldSpecialSpringHealerNotes', { + con: 9 + }), + value: 70, + con: 9 + }, + summerRogue: { + event: events.summer, + specialClass: 'rogue', + text: t('shieldSpecialSummerRogueText'), + notes: t('shieldSpecialSummerRogueNotes', { + str: 8 + }), + value: 80, + str: 8 + }, + summerWarrior: { + event: events.summer, + specialClass: 'warrior', + text: t('shieldSpecialSummerWarriorText'), + notes: t('shieldSpecialSummerWarriorNotes', { + con: 7 + }), + value: 70, + con: 7 + }, + summerHealer: { + event: events.summer, + specialClass: 'healer', + text: t('shieldSpecialSummerHealerText'), + notes: t('shieldSpecialSummerHealerNotes', { + con: 9 + }), + value: 70, + con: 9 + }, + fallRogue: { + event: events.fall, + specialClass: 'rogue', + text: t('shieldSpecialFallRogueText'), + notes: t('shieldSpecialFallRogueNotes', { + str: 8 + }), + value: 80, + str: 8, + canBuy: (function() { + return true; + }) + }, + fallWarrior: { + event: events.fall, + specialClass: 'warrior', + text: t('shieldSpecialFallWarriorText'), + notes: t('shieldSpecialFallWarriorNotes', { + con: 7 + }), + value: 70, + con: 7, + canBuy: (function() { + return true; + }) + }, + fallHealer: { + event: events.fall, + specialClass: 'healer', + text: t('shieldSpecialFallHealerText'), + notes: t('shieldSpecialFallHealerNotes', { + con: 9 + }), + value: 70, + con: 9, + canBuy: (function() { + return true; + }) + }, + winter2015Rogue: { + event: events.winter2015, + specialClass: 'rogue', + text: t('shieldSpecialWinter2015RogueText'), + notes: t('shieldSpecialWinter2015RogueNotes', { + str: 8 + }), + value: 80, + str: 8 + }, + winter2015Warrior: { + event: events.winter2015, + specialClass: 'warrior', + text: t('shieldSpecialWinter2015WarriorText'), + notes: t('shieldSpecialWinter2015WarriorNotes', { + con: 7 + }), + value: 70, + con: 7 + }, + winter2015Healer: { + event: events.winter2015, + specialClass: 'healer', + text: t('shieldSpecialWinter2015HealerText'), + notes: t('shieldSpecialWinter2015HealerNotes', { + con: 9 + }), + value: 70, + con: 9 + }, + spring2015Rogue: { + event: events.spring2015, + specialClass: 'rogue', + text: t('shieldSpecialSpring2015RogueText'), + notes: t('shieldSpecialSpring2015RogueNotes', { + str: 8 + }), + value: 80, + str: 8 + }, + spring2015Warrior: { + event: events.spring2015, + specialClass: 'warrior', + text: t('shieldSpecialSpring2015WarriorText'), + notes: t('shieldSpecialSpring2015WarriorNotes', { + con: 7 + }), + value: 70, + con: 7 + }, + spring2015Healer: { + event: events.spring2015, + specialClass: 'healer', + text: t('shieldSpecialSpring2015HealerText'), + notes: t('shieldSpecialSpring2015HealerNotes', { + con: 9 + }), + value: 70, + con: 9 + }, + summer2015Rogue: { + event: events.summer2015, + specialClass: 'rogue', + text: t('shieldSpecialSummer2015RogueText'), + notes: t('shieldSpecialSummer2015RogueNotes', { + str: 8 + }), + value: 80, + str: 8 + }, + summer2015Warrior: { + event: events.summer2015, + specialClass: 'warrior', + text: t('shieldSpecialSummer2015WarriorText'), + notes: t('shieldSpecialSummer2015WarriorNotes', { + con: 7 + }), + value: 70, + con: 7 + }, + summer2015Healer: { + event: events.summer2015, + specialClass: 'healer', + text: t('shieldSpecialSummer2015HealerText'), + notes: t('shieldSpecialSummer2015HealerNotes', { + con: 9 + }), + value: 70, + con: 9 + }, + fall2015Rogue: { + event: events.fall2015, + specialClass: 'rogue', + text: t('shieldSpecialFall2015RogueText'), + notes: t('shieldSpecialFall2015RogueNotes', { + str: 8 + }), + value: 80, + str: 8 + }, + fall2015Warrior: { + event: events.fall2015, + specialClass: 'warrior', + text: t('shieldSpecialFall2015WarriorText'), + notes: t('shieldSpecialFall2015WarriorNotes', { + con: 7 + }), + value: 70, + con: 7 + }, + fall2015Healer: { + event: events.fall2015, + specialClass: 'healer', + text: t('shieldSpecialFall2015HealerText'), + notes: t('shieldSpecialFall2015HealerNotes', { + con: 9 + }), + value: 70, + con: 9 + } + }, + mystery: { + 301405: { + text: t('shieldMystery301405Text'), + notes: t('shieldMystery301405Notes'), + mystery: '301405', + value: 0 + } + }, + armoire: { + gladiatorShield: { + text: t('shieldArmoireGladiatorShieldText'), + notes: t('shieldArmoireGladiatorShieldNotes', { + con: 5, + str: 5 + }), + value: 100, + con: 5, + str: 5, + set: 'gladiator', + canOwn: (function(u) { + return u.items.gear.owned.shield_armoire_gladiatorShield != null; + }) + }, + midnightShield: { + text: t('shieldArmoireMidnightShieldText'), + notes: t('shieldArmoireMidnightShieldNotes', { + con: 10, + str: 2 + }), + value: 100, + con: 10, + str: 2, + canOwn: (function(u) { + return u.items.gear.owned.shield_armoire_midnightShield != null; + }) + }, + royalCane: { + text: t('shieldArmoireRoyalCaneText'), + notes: t('shieldArmoireRoyalCaneNotes', { + attrs: 5 + }), + value: 100, + con: 5, + int: 5, + per: 5, + set: 'royal', + canOwn: (function(u) { + return u.items.gear.owned.shield_armoire_royalCane != null; + }) + } + } + }, + back: { + base: { + 0: { + text: t('backBase0Text'), + notes: t('backBase0Notes'), + value: 0 + } + }, + mystery: { + 201402: { + text: t('backMystery201402Text'), + notes: t('backMystery201402Notes'), + mystery: '201402', + value: 0 + }, + 201404: { + text: t('backMystery201404Text'), + notes: t('backMystery201404Notes'), + mystery: '201404', + value: 0 + }, + 201410: { + text: t('backMystery201410Text'), + notes: t('backMystery201410Notes'), + mystery: '201410', + value: 0 + }, + 201504: { + text: t('backMystery201504Text'), + notes: t('backMystery201504Notes'), + mystery: '201504', + value: 0 + }, + 201507: { + text: t('backMystery201507Text'), + notes: t('backMystery201507Notes'), + mystery: '201507', + value: 0 + }, + 201510: { + text: t('backMystery201510Text'), + notes: t('backMystery201510Notes'), + mystery: '201510', + value: 0 + } + }, + special: { + wondercon_red: { + text: t('backSpecialWonderconRedText'), + notes: t('backSpecialWonderconRedNotes'), + value: 0, + mystery: 'wondercon' + }, + wondercon_black: { + text: t('backSpecialWonderconBlackText'), + notes: t('backSpecialWonderconBlackNotes'), + value: 0, + mystery: 'wondercon' + } + } + }, + body: { + base: { + 0: { + text: t('bodyBase0Text'), + notes: t('bodyBase0Notes'), + value: 0 + } + }, + special: { + wondercon_red: { + text: t('bodySpecialWonderconRedText'), + notes: t('bodySpecialWonderconRedNotes'), + value: 0, + mystery: 'wondercon' + }, + wondercon_gold: { + text: t('bodySpecialWonderconGoldText'), + notes: t('bodySpecialWonderconGoldNotes'), + value: 0, + mystery: 'wondercon' + }, + wondercon_black: { + text: t('bodySpecialWonderconBlackText'), + notes: t('bodySpecialWonderconBlackNotes'), + value: 0, + mystery: 'wondercon' + }, + summerHealer: { + event: events.summer, + specialClass: 'healer', + text: t('bodySpecialSummerHealerText'), + notes: t('bodySpecialSummerHealerNotes'), + value: 20 + }, + summerMage: { + event: events.summer, + specialClass: 'wizard', + text: t('bodySpecialSummerMageText'), + notes: t('bodySpecialSummerMageNotes'), + value: 20 + }, + summer2015Healer: { + event: events.summer2015, + specialClass: 'healer', + text: t('bodySpecialSummer2015HealerText'), + notes: t('bodySpecialSummer2015HealerNotes'), + value: 20 + }, + summer2015Mage: { + event: events.summer2015, + specialClass: 'wizard', + text: t('bodySpecialSummer2015MageText'), + notes: t('bodySpecialSummer2015MageNotes'), + value: 20 + }, + summer2015Rogue: { + event: events.summer2015, + specialClass: 'rogue', + text: t('bodySpecialSummer2015RogueText'), + notes: t('bodySpecialSummer2015RogueNotes'), + value: 20 + }, + summer2015Warrior: { + event: events.summer2015, + specialClass: 'warrior', + text: t('bodySpecialSummer2015WarriorText'), + notes: t('bodySpecialSummer2015WarriorNotes'), + value: 20 + } + } + }, + headAccessory: { + base: { + 0: { + text: t('headAccessoryBase0Text'), + notes: t('headAccessoryBase0Notes'), + value: 0, + last: true + } + }, + special: { + springRogue: { + event: events.spring, + specialClass: 'rogue', + text: t('headAccessorySpecialSpringRogueText'), + notes: t('headAccessorySpecialSpringRogueNotes'), + value: 20 + }, + springWarrior: { + event: events.spring, + specialClass: 'warrior', + text: t('headAccessorySpecialSpringWarriorText'), + notes: t('headAccessorySpecialSpringWarriorNotes'), + value: 20 + }, + springMage: { + event: events.spring, + specialClass: 'wizard', + text: t('headAccessorySpecialSpringMageText'), + notes: t('headAccessorySpecialSpringMageNotes'), + value: 20 + }, + springHealer: { + event: events.spring, + specialClass: 'healer', + text: t('headAccessorySpecialSpringHealerText'), + notes: t('headAccessorySpecialSpringHealerNotes'), + value: 20 + }, + spring2015Rogue: { + event: events.spring2015, + specialClass: 'rogue', + text: t('headAccessorySpecialSpring2015RogueText'), + notes: t('headAccessorySpecialSpring2015RogueNotes'), + value: 20 + }, + spring2015Warrior: { + event: events.spring2015, + specialClass: 'warrior', + text: t('headAccessorySpecialSpring2015WarriorText'), + notes: t('headAccessorySpecialSpring2015WarriorNotes'), + value: 20 + }, + spring2015Mage: { + event: events.spring2015, + specialClass: 'wizard', + text: t('headAccessorySpecialSpring2015MageText'), + notes: t('headAccessorySpecialSpring2015MageNotes'), + value: 20 + }, + spring2015Healer: { + event: events.spring2015, + specialClass: 'healer', + text: t('headAccessorySpecialSpring2015HealerText'), + notes: t('headAccessorySpecialSpring2015HealerNotes'), + value: 20 + }, + bearEars: { + gearSet: 'animal', + text: t('headAccessoryBearEarsText'), + notes: t('headAccessoryBearEarsNotes'), + value: 20, + canOwn: (function(u) { + return u.items.gear.owned.headAccessory_special_bearEars != null; + }), + canBuy: (function() { + return true; + }) + }, + cactusEars: { + gearSet: 'animal', + text: t('headAccessoryCactusEarsText'), + notes: t('headAccessoryCactusEarsNotes'), + value: 20, + canOwn: (function(u) { + return u.items.gear.owned.headAccessory_special_cactusEars != null; + }), + canBuy: (function() { + return true; + }) + }, + foxEars: { + gearSet: 'animal', + text: t('headAccessoryFoxEarsText'), + notes: t('headAccessoryFoxEarsNotes'), + value: 20, + canOwn: (function(u) { + return u.items.gear.owned.headAccessory_special_foxEars != null; + }), + canBuy: (function() { + return true; + }) + }, + lionEars: { + gearSet: 'animal', + text: t('headAccessoryLionEarsText'), + notes: t('headAccessoryLionEarsNotes'), + value: 20, + canOwn: (function(u) { + return u.items.gear.owned.headAccessory_special_lionEars != null; + }), + canBuy: (function() { + return true; + }) + }, + pandaEars: { + gearSet: 'animal', + text: t('headAccessoryPandaEarsText'), + notes: t('headAccessoryPandaEarsNotes'), + value: 20, + canOwn: (function(u) { + return u.items.gear.owned.headAccessory_special_pandaEars != null; + }), + canBuy: (function() { + return true; + }) + }, + pigEars: { + gearSet: 'animal', + text: t('headAccessoryPigEarsText'), + notes: t('headAccessoryPigEarsNotes'), + value: 20, + canOwn: (function(u) { + return u.items.gear.owned.headAccessory_special_pigEars != null; + }), + canBuy: (function() { + return true; + }) + }, + tigerEars: { + gearSet: 'animal', + text: t('headAccessoryTigerEarsText'), + notes: t('headAccessoryTigerEarsNotes'), + value: 20, + canOwn: (function(u) { + return u.items.gear.owned.headAccessory_special_tigerEars != null; + }), + canBuy: (function() { + return true; + }) + }, + wolfEars: { + gearSet: 'animal', + text: t('headAccessoryWolfEarsText'), + notes: t('headAccessoryWolfEarsNotes'), + value: 20, + canOwn: (function(u) { + return u.items.gear.owned.headAccessory_special_wolfEars != null; + }), + canBuy: (function() { + return true; + }) + } + }, + mystery: { + 201403: { + text: t('headAccessoryMystery201403Text'), + notes: t('headAccessoryMystery201403Notes'), + mystery: '201403', + value: 0 + }, + 201404: { + text: t('headAccessoryMystery201404Text'), + notes: t('headAccessoryMystery201404Notes'), + mystery: '201404', + value: 0 + }, + 201409: { + text: t('headAccessoryMystery201409Text'), + notes: t('headAccessoryMystery201409Notes'), + mystery: '201409', + value: 0 + }, + 201502: { + text: t('headAccessoryMystery201502Text'), + notes: t('headAccessoryMystery201502Notes'), + mystery: '201502', + value: 0 + }, + 201510: { + text: t('headAccessoryMystery201510Text'), + notes: t('headAccessoryMystery201510Notes'), + mystery: '201510', + value: 0 + }, + 301405: { + text: t('headAccessoryMystery301405Text'), + notes: t('headAccessoryMystery301405Notes'), + mystery: '301405', + value: 0 + } + } + }, + eyewear: { + base: { + 0: { + text: t('eyewearBase0Text'), + notes: t('eyewearBase0Notes'), + value: 0, + last: true + } + }, + special: { + wondercon_red: { + text: t('eyewearSpecialWonderconRedText'), + notes: t('eyewearSpecialWonderconRedNotes'), + value: 0, + mystery: 'wondercon' + }, + wondercon_black: { + text: t('eyewearSpecialWonderconBlackText'), + notes: t('eyewearSpecialWonderconBlackNotes'), + value: 0, + mystery: 'wondercon' + }, + summerRogue: { + event: events.summer, + specialClass: 'rogue', + text: t('eyewearSpecialSummerRogueText'), + notes: t('eyewearSpecialSummerRogueNotes'), + value: 20 + }, + summerWarrior: { + event: events.summer, + specialClass: 'warrior', + text: t('eyewearSpecialSummerWarriorText'), + notes: t('eyewearSpecialSummerWarriorNotes'), + value: 20 + } + }, + mystery: { + 201503: { + text: t('eyewearMystery201503Text'), + notes: t('eyewearMystery201503Notes'), + mystery: '201503', + value: 0 + }, + 201506: { + text: t('eyewearMystery201506Text'), + notes: t('eyewearMystery201506Notes'), + mystery: '201506', + value: 0 + }, + 201507: { + text: t('eyewearMystery201507Text'), + notes: t('eyewearMystery201507Notes'), + mystery: '201507', + value: 0 + }, + 301404: { + text: t('eyewearMystery301404Text'), + notes: t('eyewearMystery301404Notes'), + mystery: '301404', + value: 0 + }, + 301405: { + text: t('eyewearMystery301405Text'), + notes: t('eyewearMystery301405Notes'), + mystery: '301405', + value: 0 + } + }, + armoire: { + plagueDoctorMask: { + text: t('eyewearArmoirePlagueDoctorMaskText'), + notes: t('eyewearArmoirePlagueDoctorMaskNotes'), + value: 100, + set: 'plagueDoctor', + canOwn: (function(u) { + return u.items.gear.owned.eyewear_armoire_plagueDoctorMask != null; + }) + } + } + } +}; + + +/* + The gear is exported as a tree (defined above), and a flat list (eg, {weapon_healer_1: .., shield_special_0: ...}) since + they are needed in different forms at different points in the app + */ + +api.gear = { + tree: gear, + flat: {} +}; + +_.each(gearTypes, function(type) { + return _.each(classes.concat(['base', 'special', 'mystery', 'armoire']), function(klass) { + return _.each(gear[type][klass], function(item, i) { + var _canOwn, key; + key = type + "_" + klass + "_" + i; + _.defaults(item, { + type: type, + key: key, + klass: klass, + index: i, + str: 0, + int: 0, + per: 0, + con: 0, + canBuy: (function() { + return false; + }) + }); + if (item.event) { + _canOwn = item.canOwn || (function() { + return true; + }); + item.canOwn = function(u) { + return _canOwn(u) && ((u.items.gear.owned[key] != null) || (moment().isAfter(item.event.start) && moment().isBefore(item.event.end))) && (item.specialClass ? u.stats["class"] === item.specialClass : true); + }; + } + if (item.mystery) { + item.canOwn = function(u) { + return u.items.gear.owned[key] != null; + }; + } + return api.gear.flat[key] = item; + }); + }); +}); + + +/* + Time Traveler Store, mystery sets need their items mapped in + */ + +_.each(api.mystery, function(v, k) { + return v.items = _.where(api.gear.flat, { + mystery: k + }); +}); + +api.timeTravelerStore = function(owned) { + var ownedKeys; + ownedKeys = _.keys((typeof owned.toObject === "function" ? owned.toObject() : void 0) || owned); + return _.reduce(api.mystery, function(m, v, k) { + if (k === 'wondercon' || ~ownedKeys.indexOf(v.items[0].key)) { + return m; + } + m[k] = v; + return m; + }, {}); +}; + + +/* + --------------------------------------------------------------- + Unique Rewards: Potion and Armoire + --------------------------------------------------------------- + */ + +api.potion = { + type: 'potion', + text: t('potionText'), + notes: t('potionNotes'), + value: 25, + key: 'potion' +}; + +api.armoire = { + type: 'armoire', + text: t('armoireText'), + notes: (function(user, count) { + if (user.flags.armoireEmpty) { + return t('armoireNotesEmpty')(); + } + return t('armoireNotesFull')() + count; + }), + value: 100, + key: 'armoire', + canOwn: (function(u) { + return _.contains(u.achievements.ultimateGearSets, true); + }) +}; + + +/* + --------------------------------------------------------------- + Classes + --------------------------------------------------------------- + */ + +api.classes = classes; + + +/* + --------------------------------------------------------------- + Gear Types + --------------------------------------------------------------- + */ + +api.gearTypes = gearTypes; + + +/* + --------------------------------------------------------------- + Spells + --------------------------------------------------------------- + Text, notes, and mana are obvious. The rest: + + * {target}: one of [task, self, party, user]. This is very important, because if the cast() function is expecting one + thing and receives another, it will cause errors. `self` is used for self buffs, multi-task debuffs, AOEs (eg, meteor-shower), + etc. Basically, use self for anything that's not [task, party, user] and is an instant-cast + + * {cast}: the function that's run to perform the ability's action. This is pretty slick - because this is exported to the + web, this function can be performed on the client and on the server. `user` param is self (needed for determining your + own stats for effectiveness of cast), and `target` param is one of [task, party, user]. In the case of `self` spells, + you act on `user` instead of `target`. You can trust these are the correct objects, as long as the `target` attr of the + spell is correct. Take a look at habitrpg/src/models/user.js and habitrpg/src/models/task.js for what attributes are + available on each model. Note `task.value` is its "redness". If party is passed in, it's an array of users, + so you'll want to iterate over them like: `_.each(target,function(member){...})` + + Note, user.stats.mp is docked after automatically (it's appended to functions automatically down below in an _.each) + */ + +diminishingReturns = function(bonus, max, halfway) { + if (halfway == null) { + halfway = max / 2; + } + return max * (bonus / (bonus + halfway)); +}; + +calculateBonus = function(value, stat, crit, stat_scale) { + if (crit == null) { + crit = 1; + } + if (stat_scale == null) { + stat_scale = 0.5; + } + return (value < 0 ? 1 : value + 1) + (stat * stat_scale * crit); +}; + +api.spells = { + wizard: { + fireball: { + text: t('spellWizardFireballText'), + mana: 10, + lvl: 11, + target: 'task', + notes: t('spellWizardFireballNotes'), + cast: function(user, target) { + var base, bonus, req; + bonus = user._statsComputed.int * user.fns.crit('per'); + bonus *= Math.ceil((target.value < 0 ? 1 : target.value + 1) * .075); + user.stats.exp += diminishingReturns(bonus, 75); + if ((base = user.party.quest.progress).up == null) { + base.up = 0; + } + user.party.quest.progress.up += Math.ceil(user._statsComputed.int * .1); + req = { + language: user.preferences.language + }; + return user.fns.updateStats(user.stats, req); + } + }, + mpheal: { + text: t('spellWizardMPHealText'), + mana: 30, + lvl: 12, + target: 'party', + notes: t('spellWizardMPHealNotes'), + cast: function(user, target) { + return _.each(target, function(member) { + var bonus; + bonus = user._statsComputed.int; + if (user._id !== member._id) { + return member.stats.mp += Math.ceil(diminishingReturns(bonus, 25, 125)); + } + }); + } + }, + earth: { + text: t('spellWizardEarthText'), + mana: 35, + lvl: 13, + target: 'party', + notes: t('spellWizardEarthNotes'), + cast: function(user, target) { + return _.each(target, function(member) { + var base, bonus; + bonus = user._statsComputed.int - user.stats.buffs.int; + if ((base = member.stats.buffs).int == null) { + base.int = 0; + } + return member.stats.buffs.int += Math.ceil(diminishingReturns(bonus, 30, 200)); + }); + } + }, + frost: { + text: t('spellWizardFrostText'), + mana: 40, + lvl: 14, + target: 'self', + notes: t('spellWizardFrostNotes'), + cast: function(user, target) { + return user.stats.buffs.streaks = true; + } + } + }, + warrior: { + smash: { + text: t('spellWarriorSmashText'), + mana: 10, + lvl: 11, + target: 'task', + notes: t('spellWarriorSmashNotes'), + cast: function(user, target) { + var base, bonus; + bonus = user._statsComputed.str * user.fns.crit('con'); + target.value += diminishingReturns(bonus, 2.5, 35); + if ((base = user.party.quest.progress).up == null) { + base.up = 0; + } + return user.party.quest.progress.up += diminishingReturns(bonus, 55, 70); + } + }, + defensiveStance: { + text: t('spellWarriorDefensiveStanceText'), + mana: 25, + lvl: 12, + target: 'self', + notes: t('spellWarriorDefensiveStanceNotes'), + cast: function(user, target) { + var base, bonus; + bonus = user._statsComputed.con - user.stats.buffs.con; + if ((base = user.stats.buffs).con == null) { + base.con = 0; + } + return user.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 40, 200)); + } + }, + valorousPresence: { + text: t('spellWarriorValorousPresenceText'), + mana: 20, + lvl: 13, + target: 'party', + notes: t('spellWarriorValorousPresenceNotes'), + cast: function(user, target) { + return _.each(target, function(member) { + var base, bonus; + bonus = user._statsComputed.str - user.stats.buffs.str; + if ((base = member.stats.buffs).str == null) { + base.str = 0; + } + return member.stats.buffs.str += Math.ceil(diminishingReturns(bonus, 20, 200)); + }); + } + }, + intimidate: { + text: t('spellWarriorIntimidateText'), + mana: 15, + lvl: 14, + target: 'party', + notes: t('spellWarriorIntimidateNotes'), + cast: function(user, target) { + return _.each(target, function(member) { + var base, bonus; + bonus = user._statsComputed.con - user.stats.buffs.con; + if ((base = member.stats.buffs).con == null) { + base.con = 0; + } + return member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 24, 200)); + }); + } + } + }, + rogue: { + pickPocket: { + text: t('spellRoguePickPocketText'), + mana: 10, + lvl: 11, + target: 'task', + notes: t('spellRoguePickPocketNotes'), + cast: function(user, target) { + var bonus; + bonus = calculateBonus(target.value, user._statsComputed.per); + return user.stats.gp += diminishingReturns(bonus, 25, 75); + } + }, + backStab: { + text: t('spellRogueBackStabText'), + mana: 15, + lvl: 12, + target: 'task', + notes: t('spellRogueBackStabNotes'), + cast: function(user, target) { + var _crit, bonus, req; + _crit = user.fns.crit('str', .3); + bonus = calculateBonus(target.value, user._statsComputed.str, _crit); + user.stats.exp += diminishingReturns(bonus, 75, 50); + user.stats.gp += diminishingReturns(bonus, 18, 75); + req = { + language: user.preferences.language + }; + return user.fns.updateStats(user.stats, req); + } + }, + toolsOfTrade: { + text: t('spellRogueToolsOfTradeText'), + mana: 25, + lvl: 13, + target: 'party', + notes: t('spellRogueToolsOfTradeNotes'), + cast: function(user, target) { + return _.each(target, function(member) { + var base, bonus; + bonus = user._statsComputed.per - user.stats.buffs.per; + if ((base = member.stats.buffs).per == null) { + base.per = 0; + } + return member.stats.buffs.per += Math.ceil(diminishingReturns(bonus, 100, 50)); + }); + } + }, + stealth: { + text: t('spellRogueStealthText'), + mana: 45, + lvl: 14, + target: 'self', + notes: t('spellRogueStealthNotes'), + cast: function(user, target) { + var base; + if ((base = user.stats.buffs).stealth == null) { + base.stealth = 0; + } + return user.stats.buffs.stealth += Math.ceil(diminishingReturns(user._statsComputed.per, user.dailys.length * 0.64, 55)); + } + } + }, + healer: { + heal: { + text: t('spellHealerHealText'), + mana: 15, + lvl: 11, + target: 'self', + notes: t('spellHealerHealNotes'), + cast: function(user, target) { + user.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * .075; + if (user.stats.hp > 50) { + return user.stats.hp = 50; + } + } + }, + brightness: { + text: t('spellHealerBrightnessText'), + mana: 15, + lvl: 12, + target: 'self', + notes: t('spellHealerBrightnessNotes'), + cast: function(user, target) { + return _.each(user.tasks, function(target) { + if (target.type === 'reward') { + return; + } + return target.value += 4 * (user._statsComputed.int / (user._statsComputed.int + 40)); + }); + } + }, + protectAura: { + text: t('spellHealerProtectAuraText'), + mana: 30, + lvl: 13, + target: 'party', + notes: t('spellHealerProtectAuraNotes'), + cast: function(user, target) { + return _.each(target, function(member) { + var base, bonus; + bonus = user._statsComputed.con - user.stats.buffs.con; + if ((base = member.stats.buffs).con == null) { + base.con = 0; + } + return member.stats.buffs.con += Math.ceil(diminishingReturns(bonus, 200, 200)); + }); + } + }, + heallAll: { + text: t('spellHealerHealAllText'), + mana: 25, + lvl: 14, + target: 'party', + notes: t('spellHealerHealAllNotes'), + cast: function(user, target) { + return _.each(target, function(member) { + member.stats.hp += (user._statsComputed.con + user._statsComputed.int + 5) * .04; + if (member.stats.hp > 50) { + return member.stats.hp = 50; + } + }); + } + } + }, + special: { + snowball: { + text: t('spellSpecialSnowballAuraText'), + mana: 0, + value: 15, + target: 'user', + notes: t('spellSpecialSnowballAuraNotes'), + cast: function(user, target) { + var base; + target.stats.buffs.snowball = true; + target.stats.buffs.spookDust = false; + target.stats.buffs.shinySeed = false; + target.stats.buffs.seafoam = false; + if ((base = target.achievements).snowball == null) { + base.snowball = 0; + } + target.achievements.snowball++; + return user.items.special.snowball--; + } + }, + salt: { + text: t('spellSpecialSaltText'), + mana: 0, + value: 5, + immediateUse: true, + target: 'self', + notes: t('spellSpecialSaltNotes'), + cast: function(user, target) { + user.stats.buffs.snowball = false; + return user.stats.gp -= 5; + } + }, + spookDust: { + text: t('spellSpecialSpookDustText'), + mana: 0, + value: 15, + target: 'user', + notes: t('spellSpecialSpookDustNotes'), + cast: function(user, target) { + var base; + target.stats.buffs.snowball = false; + target.stats.buffs.spookDust = true; + target.stats.buffs.shinySeed = false; + target.stats.buffs.seafoam = false; + if ((base = target.achievements).spookDust == null) { + base.spookDust = 0; + } + target.achievements.spookDust++; + return user.items.special.spookDust--; + } + }, + opaquePotion: { + text: t('spellSpecialOpaquePotionText'), + mana: 0, + value: 5, + immediateUse: true, + target: 'self', + notes: t('spellSpecialOpaquePotionNotes'), + cast: function(user, target) { + user.stats.buffs.spookDust = false; + return user.stats.gp -= 5; + } + }, + shinySeed: { + text: t('spellSpecialShinySeedText'), + mana: 0, + value: 15, + target: 'user', + notes: t('spellSpecialShinySeedNotes'), + cast: function(user, target) { + var base; + target.stats.buffs.snowball = false; + target.stats.buffs.spookDust = false; + target.stats.buffs.shinySeed = true; + target.stats.buffs.seafoam = false; + if ((base = target.achievements).shinySeed == null) { + base.shinySeed = 0; + } + target.achievements.shinySeed++; + return user.items.special.shinySeed--; + } + }, + petalFreePotion: { + text: t('spellSpecialPetalFreePotionText'), + mana: 0, + value: 5, + immediateUse: true, + target: 'self', + notes: t('spellSpecialPetalFreePotionNotes'), + cast: function(user, target) { + user.stats.buffs.shinySeed = false; + return user.stats.gp -= 5; + } + }, + seafoam: { + text: t('spellSpecialSeafoamText'), + mana: 0, + value: 15, + target: 'user', + notes: t('spellSpecialSeafoamNotes'), + cast: function(user, target) { + var base; + target.stats.buffs.snowball = false; + target.stats.buffs.spookDust = false; + target.stats.buffs.shinySeed = false; + target.stats.buffs.seafoam = true; + if ((base = target.achievements).seafoam == null) { + base.seafoam = 0; + } + target.achievements.seafoam++; + return user.items.special.seafoam--; + } + }, + sand: { + text: t('spellSpecialSandText'), + mana: 0, + value: 5, + immediateUse: true, + target: 'self', + notes: t('spellSpecialSandNotes'), + cast: function(user, target) { + user.stats.buffs.seafoam = false; + return user.stats.gp -= 5; + } + }, + nye: { + text: t('nyeCard'), + mana: 0, + value: 10, + immediateUse: true, + silent: true, + target: 'user', + notes: t('nyeCardNotes'), + cast: function(user, target) { + var base; + if (user === target) { + if ((base = user.achievements).nye == null) { + base.nye = 0; + } + user.achievements.nye++; + } else { + _.each([user, target], function(t) { + var base1; + if ((base1 = t.achievements).nye == null) { + base1.nye = 0; + } + return t.achievements.nye++; + }); + } + if (!target.items.special.nyeReceived) { + target.items.special.nyeReceived = []; + } + target.items.special.nyeReceived.push(user.profile.name); + target.flags.cardReceived = true; + if (typeof target.markModified === "function") { + target.markModified('items.special.nyeReceived'); + } + return user.stats.gp -= 10; + } + }, + valentine: { + text: t('valentineCard'), + mana: 0, + value: 10, + immediateUse: true, + silent: true, + target: 'user', + notes: t('valentineCardNotes'), + cast: function(user, target) { + var base; + if (user === target) { + if ((base = user.achievements).valentine == null) { + base.valentine = 0; + } + user.achievements.valentine++; + } else { + _.each([user, target], function(t) { + var base1; + if ((base1 = t.achievements).valentine == null) { + base1.valentine = 0; + } + return t.achievements.valentine++; + }); + } + if (!target.items.special.valentineReceived) { + target.items.special.valentineReceived = []; + } + target.items.special.valentineReceived.push(user.profile.name); + target.flags.cardReceived = true; + if (typeof target.markModified === "function") { + target.markModified('items.special.valentineReceived'); + } + return user.stats.gp -= 10; + } + }, + greeting: { + text: t('greetingCard'), + mana: 0, + value: 10, + immediateUse: true, + silent: true, + target: 'user', + notes: t('greetingCardNotes'), + cast: function(user, target) { + var base; + if (user === target) { + if ((base = user.achievements).greeting == null) { + base.greeting = 0; + } + user.achievements.greeting++; + } else { + _.each([user, target], function(t) { + var base1; + if ((base1 = t.achievements).greeting == null) { + base1.greeting = 0; + } + return t.achievements.greeting++; + }); + } + if (!target.items.special.greetingReceived) { + target.items.special.greetingReceived = []; + } + target.items.special.greetingReceived.push(user.profile.name); + target.flags.cardReceived = true; + if (typeof target.markModified === "function") { + target.markModified('items.special.greetingReceived'); + } + return user.stats.gp -= 10; + } + }, + thankyou: { + text: t('thankyouCard'), + mana: 0, + value: 10, + immediateUse: true, + silent: true, + target: 'user', + notes: t('thankyouCardNotes'), + cast: function(user, target) { + var base; + if (user === target) { + if ((base = user.achievements).thankyou == null) { + base.thankyou = 0; + } + user.achievements.thankyou++; + } else { + _.each([user, target], function(t) { + var base1; + if ((base1 = t.achievements).thankyou == null) { + base1.thankyou = 0; + } + return t.achievements.thankyou++; + }); + } + if (!target.items.special.thankyouReceived) { + target.items.special.thankyouReceived = []; + } + target.items.special.thankyouReceived.push(user.profile.name); + target.flags.cardReceived = true; + if (typeof target.markModified === "function") { + target.markModified('items.special.thankyouReceived'); + } + return user.stats.gp -= 10; + } + } + } +}; + +api.cardTypes = { + greeting: { + key: 'greeting', + messageOptions: 4, + yearRound: true + }, + nye: { + key: 'nye', + messageOptions: 5 + }, + thankyou: { + key: 'thankyou', + messageOptions: 4, + yearRound: true + }, + valentine: { + key: 'valentine', + messageOptions: 4 + } +}; + +_.each(api.spells, function(spellClass) { + return _.each(spellClass, function(spell, key) { + var _cast; + spell.key = key; + _cast = spell.cast; + return spell.cast = function(user, target) { + _cast(user, target); + return user.stats.mp -= spell.mana; + }; + }); +}); + +api.special = api.spells.special; + + +/* + --------------------------------------------------------------- + Drops + --------------------------------------------------------------- + */ + +api.dropEggs = { + Wolf: { + text: t('dropEggWolfText'), + adjective: t('dropEggWolfAdjective') + }, + TigerCub: { + text: t('dropEggTigerCubText'), + mountText: t('dropEggTigerCubMountText'), + adjective: t('dropEggTigerCubAdjective') + }, + PandaCub: { + text: t('dropEggPandaCubText'), + mountText: t('dropEggPandaCubMountText'), + adjective: t('dropEggPandaCubAdjective') + }, + LionCub: { + text: t('dropEggLionCubText'), + mountText: t('dropEggLionCubMountText'), + adjective: t('dropEggLionCubAdjective') + }, + Fox: { + text: t('dropEggFoxText'), + adjective: t('dropEggFoxAdjective') + }, + FlyingPig: { + text: t('dropEggFlyingPigText'), + adjective: t('dropEggFlyingPigAdjective') + }, + Dragon: { + text: t('dropEggDragonText'), + adjective: t('dropEggDragonAdjective') + }, + Cactus: { + text: t('dropEggCactusText'), + adjective: t('dropEggCactusAdjective') + }, + BearCub: { + text: t('dropEggBearCubText'), + mountText: t('dropEggBearCubMountText'), + adjective: t('dropEggBearCubAdjective') + } +}; + +_.each(api.dropEggs, function(egg, key) { + return _.defaults(egg, { + canBuy: (function() { + return true; + }), + value: 3, + key: key, + notes: t('eggNotes', { + eggText: egg.text, + eggAdjective: egg.adjective + }), + mountText: egg.text + }); +}); + +api.questEggs = { + Gryphon: { + text: t('questEggGryphonText'), + adjective: t('questEggGryphonAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.gryphon != null) > 0; + }) + }, + Hedgehog: { + text: t('questEggHedgehogText'), + adjective: t('questEggHedgehogAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.hedgehog != null) > 0; + }) + }, + Deer: { + text: t('questEggDeerText'), + adjective: t('questEggDeerAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.ghost_stag != null) > 0; + }) + }, + Egg: { + text: t('questEggEggText'), + adjective: t('questEggEggAdjective'), + mountText: t('questEggEggMountText') + }, + Rat: { + text: t('questEggRatText'), + adjective: t('questEggRatAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.rat != null) > 0; + }) + }, + Octopus: { + text: t('questEggOctopusText'), + adjective: t('questEggOctopusAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.octopus != null) > 0; + }) + }, + Seahorse: { + text: t('questEggSeahorseText'), + adjective: t('questEggSeahorseAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.dilatory_derby != null) > 0; + }) + }, + Parrot: { + text: t('questEggParrotText'), + adjective: t('questEggParrotAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.harpy != null) > 0; + }) + }, + Rooster: { + text: t('questEggRoosterText'), + adjective: t('questEggRoosterAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.rooster != null) > 0; + }) + }, + Spider: { + text: t('questEggSpiderText'), + adjective: t('questEggSpiderAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.spider != null) > 0; + }) + }, + Owl: { + text: t('questEggOwlText'), + adjective: t('questEggOwlAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.owl != null) > 0; + }) + }, + Penguin: { + text: t('questEggPenguinText'), + adjective: t('questEggPenguinAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.penguin != null) > 0; + }) + }, + TRex: { + text: t('questEggTRexText'), + adjective: t('questEggTRexAdjective'), + canBuy: (function(u) { + return u.achievements.quests && ((u.achievements.quests.trex != null) > 0 || (u.achievements.quests.trex_undead != null) > 0); + }) + }, + Rock: { + text: t('questEggRockText'), + adjective: t('questEggRockAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.rock != null) > 0; + }) + }, + Bunny: { + text: t('questEggBunnyText'), + adjective: t('questEggBunnyAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.bunny != null) > 0; + }) + }, + Slime: { + text: t('questEggSlimeText'), + adjective: t('questEggSlimeAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.slime != null) > 0; + }) + }, + Sheep: { + text: t('questEggSheepText'), + adjective: t('questEggSheepAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.sheep != null) > 0; + }) + }, + Cuttlefish: { + text: t('questEggCuttlefishText'), + adjective: t('questEggCuttlefishAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.kraken != null) > 0; + }) + }, + Whale: { + text: t('questEggWhaleText'), + adjective: t('questEggWhaleAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.whale != null) > 0; + }) + }, + Cheetah: { + text: t('questEggCheetahText'), + adjective: t('questEggCheetahAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.cheetah != null) > 0; + }) + }, + Horse: { + text: t('questEggHorseText'), + adjective: t('questEggHorseAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.horse != null) > 0; + }) + }, + Frog: { + text: t('questEggFrogText'), + adjective: t('questEggFrogAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.frog != null) > 0; + }) + }, + Snake: { + text: t('questEggSnakeText'), + adjective: t('questEggSnakeAdjective'), + canBuy: (function(u) { + return u.achievements.quests && (u.achievements.quests.snake != null) > 0; + }) + } +}; + +_.each(api.questEggs, function(egg, key) { + return _.defaults(egg, { + canBuy: (function() { + return false; + }), + value: 3, + key: key, + notes: t('eggNotes', { + eggText: egg.text, + eggAdjective: egg.adjective + }), + mountText: egg.text + }); +}); + +api.eggs = _.assign(_.cloneDeep(api.dropEggs), api.questEggs); + +api.specialPets = { + 'Wolf-Veteran': 'veteranWolf', + 'Wolf-Cerberus': 'cerberusPup', + 'Dragon-Hydra': 'hydra', + 'Turkey-Base': 'turkey', + 'BearCub-Polar': 'polarBearPup', + 'MantisShrimp-Base': 'mantisShrimp', + 'JackOLantern-Base': 'jackolantern', + 'Mammoth-Base': 'mammoth', + 'Tiger-Veteran': 'veteranTiger', + 'Phoenix-Base': 'phoenix' +}; + +api.specialMounts = { + 'BearCub-Polar': 'polarBear', + 'LionCub-Ethereal': 'etherealLion', + 'MantisShrimp-Base': 'mantisShrimp', + 'Turkey-Base': 'turkey', + 'Mammoth-Base': 'mammoth', + 'Orca-Base': 'orca', + 'Gryphon-RoyalPurple': 'royalPurpleGryphon', + 'Phoenix-Base': 'phoenix', + 'JackOLantern-Base': 'jackolantern' +}; + +api.timeTravelStable = { + pets: { + 'Mammoth-Base': t('mammoth'), + 'MantisShrimp-Base': t('mantisShrimp') + }, + mounts: { + 'Mammoth-Base': t('mammoth'), + 'MantisShrimp-Base': t('mantisShrimp') + } +}; + +api.dropHatchingPotions = { + Base: { + value: 2, + text: t('hatchingPotionBase') + }, + White: { + value: 2, + text: t('hatchingPotionWhite') + }, + Desert: { + value: 2, + text: t('hatchingPotionDesert') + }, + Red: { + value: 3, + text: t('hatchingPotionRed') + }, + Shade: { + value: 3, + text: t('hatchingPotionShade') + }, + Skeleton: { + value: 3, + text: t('hatchingPotionSkeleton') + }, + Zombie: { + value: 4, + text: t('hatchingPotionZombie') + }, + CottonCandyPink: { + value: 4, + text: t('hatchingPotionCottonCandyPink') + }, + CottonCandyBlue: { + value: 4, + text: t('hatchingPotionCottonCandyBlue') + }, + Golden: { + value: 5, + text: t('hatchingPotionGolden') + } +}; + +api.premiumHatchingPotions = { + Spooky: { + value: 2, + text: t('hatchingPotionSpooky'), + limited: true, + canBuy: (function() { + return false; + }) + } +}; + +_.each(api.dropHatchingPotions, function(pot, key) { + return _.defaults(pot, { + key: key, + value: 2, + notes: t('hatchingPotionNotes', { + potText: pot.text + }), + premium: false, + limited: false, + canBuy: (function() { + return true; + }) + }); +}); + +_.each(api.premiumHatchingPotions, function(pot, key) { + return _.defaults(pot, { + key: key, + value: 2, + notes: t('hatchingPotionNotes', { + potText: pot.text + }), + addlNotes: t('premiumPotionAddlNotes'), + premium: true, + limited: false, + canBuy: (function() { + return true; + }) + }); +}); + +api.hatchingPotions = {}; + +_.merge(api.hatchingPotions, api.dropHatchingPotions); + +_.merge(api.hatchingPotions, api.premiumHatchingPotions); + +api.pets = _.transform(api.dropEggs, function(m, egg) { + return _.defaults(m, _.transform(api.hatchingPotions, function(m2, pot) { + if (!pot.premium) { + return m2[egg.key + "-" + pot.key] = true; + } + })); +}); + +api.premiumPets = _.transform(api.dropEggs, function(m, egg) { + return _.defaults(m, _.transform(api.hatchingPotions, function(m2, pot) { + if (pot.premium) { + return m2[egg.key + "-" + pot.key] = true; + } + })); +}); + +api.questPets = _.transform(api.questEggs, function(m, egg) { + return _.defaults(m, _.transform(api.hatchingPotions, function(m2, pot) { + if (!pot.premium) { + return m2[egg.key + "-" + pot.key] = true; + } + })); +}); + +api.mounts = _.transform(api.dropEggs, function(m, egg) { + return _.defaults(m, _.transform(api.hatchingPotions, function(m2, pot) { + if (!pot.premium) { + return m2[egg.key + "-" + pot.key] = true; + } + })); +}); + +api.questMounts = _.transform(api.questEggs, function(m, egg) { + return _.defaults(m, _.transform(api.hatchingPotions, function(m2, pot) { + if (!pot.premium) { + return m2[egg.key + "-" + pot.key] = true; + } + })); +}); + +api.food = { + Meat: { + text: t('foodMeat'), + canBuy: (function() { + return true; + }), + canDrop: true, + target: 'Base', + article: '' + }, + Milk: { + text: t('foodMilk'), + canBuy: (function() { + return true; + }), + canDrop: true, + target: 'White', + article: '' + }, + Potatoe: { + text: t('foodPotatoe'), + canBuy: (function() { + return true; + }), + canDrop: true, + target: 'Desert', + article: 'a ' + }, + Strawberry: { + text: t('foodStrawberry'), + canBuy: (function() { + return true; + }), + canDrop: true, + target: 'Red', + article: 'a ' + }, + Chocolate: { + text: t('foodChocolate'), + canBuy: (function() { + return true; + }), + canDrop: true, + target: 'Shade', + article: '' + }, + Fish: { + text: t('foodFish'), + canBuy: (function() { + return true; + }), + canDrop: true, + target: 'Skeleton', + article: 'a ' + }, + RottenMeat: { + text: t('foodRottenMeat'), + canBuy: (function() { + return true; + }), + canDrop: true, + target: 'Zombie', + article: '' + }, + CottonCandyPink: { + text: t('foodCottonCandyPink'), + canBuy: (function() { + return true; + }), + canDrop: true, + target: 'CottonCandyPink', + article: '' + }, + CottonCandyBlue: { + text: t('foodCottonCandyBlue'), + canBuy: (function() { + return true; + }), + canDrop: true, + target: 'CottonCandyBlue', + article: '' + }, + Honey: { + text: t('foodHoney'), + canBuy: (function() { + return true; + }), + canDrop: true, + target: 'Golden', + article: '' + }, + Saddle: { + canBuy: (function() { + return true; + }), + text: t('foodSaddleText'), + value: 5, + notes: t('foodSaddleNotes') + }, + Cake_Skeleton: { + text: t('foodCakeSkeleton'), + target: 'Skeleton', + article: '' + }, + Cake_Base: { + text: t('foodCakeBase'), + target: 'Base', + article: '' + }, + Cake_CottonCandyBlue: { + text: t('foodCakeCottonCandyBlue'), + target: 'CottonCandyBlue', + article: '' + }, + Cake_CottonCandyPink: { + text: t('foodCakeCottonCandyPink'), + target: 'CottonCandyPink', + article: '' + }, + Cake_Shade: { + text: t('foodCakeShade'), + target: 'Shade', + article: '' + }, + Cake_White: { + text: t('foodCakeWhite'), + target: 'White', + article: '' + }, + Cake_Golden: { + text: t('foodCakeGolden'), + target: 'Golden', + article: '' + }, + Cake_Zombie: { + text: t('foodCakeZombie'), + target: 'Zombie', + article: '' + }, + Cake_Desert: { + text: t('foodCakeDesert'), + target: 'Desert', + article: '' + }, + Cake_Red: { + text: t('foodCakeRed'), + target: 'Red', + article: '' + }, + Candy_Skeleton: { + text: t('foodCandySkeleton'), + target: 'Skeleton', + article: '' + }, + Candy_Base: { + text: t('foodCandyBase'), + target: 'Base', + article: '' + }, + Candy_CottonCandyBlue: { + text: t('foodCandyCottonCandyBlue'), + target: 'CottonCandyBlue', + article: '' + }, + Candy_CottonCandyPink: { + text: t('foodCandyCottonCandyPink'), + target: 'CottonCandyPink', + article: '' + }, + Candy_Shade: { + text: t('foodCandyShade'), + target: 'Shade', + article: '' + }, + Candy_White: { + text: t('foodCandyWhite'), + target: 'White', + article: '' + }, + Candy_Golden: { + text: t('foodCandyGolden'), + target: 'Golden', + article: '' + }, + Candy_Zombie: { + text: t('foodCandyZombie'), + target: 'Zombie', + article: '' + }, + Candy_Desert: { + text: t('foodCandyDesert'), + target: 'Desert', + article: '' + }, + Candy_Red: { + text: t('foodCandyRed'), + target: 'Red', + article: '' + } +}; + +_.each(api.food, function(food, key) { + return _.defaults(food, { + value: 1, + key: key, + notes: t('foodNotes'), + canBuy: (function() { + return false; + }), + canDrop: false + }); +}); + +api.userCanOwnQuestCategories = ['unlockable', 'gold', 'pet']; + +api.quests = { + dilatory: { + text: t("questDilatoryText"), + notes: t("questDilatoryNotes"), + completion: t("questDilatoryCompletion"), + value: 0, + canBuy: (function() { + return false; + }), + category: 'world', + boss: { + name: t("questDilatoryBoss"), + hp: 5000000, + str: 1, + def: 1, + rage: { + title: t("questDilatoryBossRageTitle"), + description: t("questDilatoryBossRageDescription"), + value: 4000000, + tavern: t('questDilatoryBossRageTavern'), + stables: t('questDilatoryBossRageStables'), + market: t('questDilatoryBossRageMarket') + } + }, + drop: { + items: [ + { + type: 'pets', + key: 'MantisShrimp-Base', + text: t('questDilatoryDropMantisShrimpPet') + }, { + type: 'mounts', + key: 'MantisShrimp-Base', + text: t('questDilatoryDropMantisShrimpMount') + }, { + type: 'food', + key: 'Meat', + text: t('foodMeat') + }, { + type: 'food', + key: 'Milk', + text: t('foodMilk') + }, { + type: 'food', + key: 'Potatoe', + text: t('foodPotatoe') + }, { + type: 'food', + key: 'Strawberry', + text: t('foodStrawberry') + }, { + type: 'food', + key: 'Chocolate', + text: t('foodChocolate') + }, { + type: 'food', + key: 'Fish', + text: t('foodFish') + }, { + type: 'food', + key: 'RottenMeat', + text: t('foodRottenMeat') + }, { + type: 'food', + key: 'CottonCandyPink', + text: t('foodCottonCandyPink') + }, { + type: 'food', + key: 'CottonCandyBlue', + text: t('foodCottonCandyBlue') + }, { + type: 'food', + key: 'Honey', + text: t('foodHoney') + } + ], + gp: 0, + exp: 0 + } + }, + stressbeast: { + text: t("questStressbeastText"), + notes: t("questStressbeastNotes"), + completion: t("questStressbeastCompletion"), + completionChat: t("questStressbeastCompletionChat"), + value: 0, + canBuy: (function() { + return false; + }), + category: 'world', + boss: { + name: t("questStressbeastBoss"), + hp: 2750000, + str: 1, + def: 1, + rage: { + title: t("questStressbeastBossRageTitle"), + description: t("questStressbeastBossRageDescription"), + value: 1450000, + healing: .3, + stables: t('questStressbeastBossRageStables'), + bailey: t('questStressbeastBossRageBailey'), + guide: t('questStressbeastBossRageGuide') + }, + desperation: { + threshold: 500000, + str: 3.5, + def: 2, + text: t('questStressbeastDesperation') + } + }, + drop: { + items: [ + { + type: 'pets', + key: 'Mammoth-Base', + text: t('questStressbeastDropMammothPet') + }, { + type: 'mounts', + key: 'Mammoth-Base', + text: t('questStressbeastDropMammothMount') + }, { + type: 'food', + key: 'Meat', + text: t('foodMeat') + }, { + type: 'food', + key: 'Milk', + text: t('foodMilk') + }, { + type: 'food', + key: 'Potatoe', + text: t('foodPotatoe') + }, { + type: 'food', + key: 'Strawberry', + text: t('foodStrawberry') + }, { + type: 'food', + key: 'Chocolate', + text: t('foodChocolate') + }, { + type: 'food', + key: 'Fish', + text: t('foodFish') + }, { + type: 'food', + key: 'RottenMeat', + text: t('foodRottenMeat') + }, { + type: 'food', + key: 'CottonCandyPink', + text: t('foodCottonCandyPink') + }, { + type: 'food', + key: 'CottonCandyBlue', + text: t('foodCottonCandyBlue') + }, { + type: 'food', + key: 'Honey', + text: t('foodHoney') + } + ], + gp: 0, + exp: 0 + } + }, + burnout: { + text: t('questBurnoutText'), + notes: t('questBurnoutNotes'), + completion: t('questBurnoutCompletion'), + completionChat: t('questBurnoutCompletionChat'), + value: 0, + canBuy: (function() { + return false; + }), + category: 'world', + boss: { + name: t('questBurnoutBoss'), + hp: 11000000, + str: 2.5, + def: 1, + rage: { + title: t('questBurnoutBossRageTitle'), + description: t('questBurnoutBossRageDescription'), + value: 1000000, + quests: t('questBurnoutBossRageQuests'), + seasonalShop: t('questBurnoutBossRageSeasonalShop'), + tavern: t('questBurnoutBossRageTavern') + } + }, + drop: { + items: [ + { + type: 'pets', + key: 'Phoenix-Base', + text: t('questBurnoutDropPhoenixPet') + }, { + type: 'mounts', + key: 'Phoenix-Base', + text: t('questBurnoutDropPhoenixMount') + }, { + type: 'food', + key: 'Candy_Base', + text: t('foodCandyBase') + }, { + type: 'food', + key: 'Candy_White', + text: t('foodCandyWhite') + }, { + type: 'food', + key: 'Candy_Desert', + text: t('foodCandyDesert') + }, { + type: 'food', + key: 'Candy_Red', + text: t('foodCandyRed') + }, { + type: 'food', + key: 'Candy_Shade', + text: t('foodCandyShade') + }, { + type: 'food', + key: 'Candy_Skeleton', + text: t('foodCandySkeleton') + }, { + type: 'food', + key: 'Candy_Zombie', + text: t('foodCandyZombie') + }, { + type: 'food', + key: 'Candy_CottonCandyPink', + text: t('foodCandyCottonCandyPink') + }, { + type: 'food', + key: 'Candy_CottonCandyBlue', + text: t('foodCandyCottonCandyBlue') + }, { + type: 'food', + key: 'Candy_Golden', + text: t('foodCandyGolden') + } + ], + gp: 0, + exp: 0 + } + }, + evilsanta: { + canBuy: (function() { + return false; + }), + text: t('questEvilSantaText'), + notes: t('questEvilSantaNotes'), + completion: t('questEvilSantaCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questEvilSantaBoss'), + hp: 300, + str: 1 + }, + drop: { + items: [ + { + type: 'mounts', + key: 'BearCub-Polar', + text: t('questEvilSantaDropBearCubPolarMount') + } + ], + gp: 20, + exp: 100 + } + }, + evilsanta2: { + canBuy: (function() { + return false; + }), + text: t('questEvilSanta2Text'), + notes: t('questEvilSanta2Notes'), + completion: t('questEvilSanta2Completion'), + value: 4, + previous: 'evilsanta', + category: 'pet', + collect: { + tracks: { + text: t('questEvilSanta2CollectTracks'), + count: 20 + }, + branches: { + text: t('questEvilSanta2CollectBranches'), + count: 10 + } + }, + drop: { + items: [ + { + type: 'pets', + key: 'BearCub-Polar', + text: t('questEvilSanta2DropBearCubPolarPet') + } + ], + gp: 20, + exp: 100 + } + }, + gryphon: { + text: t('questGryphonText'), + notes: t('questGryphonNotes'), + completion: t('questGryphonCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questGryphonBoss'), + hp: 300, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Gryphon', + text: t('questGryphonDropGryphonEgg') + }, { + type: 'eggs', + key: 'Gryphon', + text: t('questGryphonDropGryphonEgg') + }, { + type: 'eggs', + key: 'Gryphon', + text: t('questGryphonDropGryphonEgg') + } + ], + gp: 25, + exp: 125, + unlock: t('questGryphonUnlockText') + } + }, + hedgehog: { + text: t('questHedgehogText'), + notes: t('questHedgehogNotes'), + completion: t('questHedgehogCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questHedgehogBoss'), + hp: 400, + str: 1.25 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Hedgehog', + text: t('questHedgehogDropHedgehogEgg') + }, { + type: 'eggs', + key: 'Hedgehog', + text: t('questHedgehogDropHedgehogEgg') + }, { + type: 'eggs', + key: 'Hedgehog', + text: t('questHedgehogDropHedgehogEgg') + } + ], + gp: 30, + exp: 125, + unlock: t('questHedgehogUnlockText') + } + }, + ghost_stag: { + text: t('questGhostStagText'), + notes: t('questGhostStagNotes'), + completion: t('questGhostStagCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questGhostStagBoss'), + hp: 1200, + str: 2.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Deer', + text: t('questGhostStagDropDeerEgg') + }, { + type: 'eggs', + key: 'Deer', + text: t('questGhostStagDropDeerEgg') + }, { + type: 'eggs', + key: 'Deer', + text: t('questGhostStagDropDeerEgg') + } + ], + gp: 80, + exp: 800, + unlock: t('questGhostStagUnlockText') + } + }, + vice1: { + text: t('questVice1Text'), + notes: t('questVice1Notes'), + value: 4, + lvl: 30, + category: 'unlockable', + boss: { + name: t('questVice1Boss'), + hp: 750, + str: 1.5 + }, + drop: { + items: [ + { + type: 'quests', + key: "vice2", + text: t('questVice1DropVice2Quest') + } + ], + gp: 20, + exp: 100 + } + }, + vice2: { + text: t('questVice2Text'), + notes: t('questVice2Notes'), + value: 4, + lvl: 30, + category: 'unlockable', + previous: 'vice1', + collect: { + lightCrystal: { + text: t('questVice2CollectLightCrystal'), + count: 45 + } + }, + drop: { + items: [ + { + type: 'quests', + key: 'vice3', + text: t('questVice2DropVice3Quest') + } + ], + gp: 20, + exp: 75 + } + }, + vice3: { + text: t('questVice3Text'), + notes: t('questVice3Notes'), + completion: t('questVice3Completion'), + previous: 'vice2', + value: 4, + lvl: 30, + category: 'unlockable', + boss: { + name: t('questVice3Boss'), + hp: 1500, + str: 3 + }, + drop: { + items: [ + { + type: 'gear', + key: "weapon_special_2", + text: t('questVice3DropWeaponSpecial2') + }, { + type: 'eggs', + key: 'Dragon', + text: t('questVice3DropDragonEgg') + }, { + type: 'eggs', + key: 'Dragon', + text: t('questVice3DropDragonEgg') + }, { + type: 'hatchingPotions', + key: 'Shade', + text: t('questVice3DropShadeHatchingPotion') + }, { + type: 'hatchingPotions', + key: 'Shade', + text: t('questVice3DropShadeHatchingPotion') + } + ], + gp: 100, + exp: 1000 + } + }, + egg: { + text: t('questEggHuntText'), + notes: t('questEggHuntNotes'), + completion: t('questEggHuntCompletion'), + value: 1, + canBuy: (function() { + return false; + }), + category: 'pet', + collect: { + plainEgg: { + text: t('questEggHuntCollectPlainEgg'), + count: 100 + } + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Egg', + text: t('questEggHuntDropPlainEgg') + }, { + type: 'eggs', + key: 'Egg', + text: t('questEggHuntDropPlainEgg') + }, { + type: 'eggs', + key: 'Egg', + text: t('questEggHuntDropPlainEgg') + }, { + type: 'eggs', + key: 'Egg', + text: t('questEggHuntDropPlainEgg') + }, { + type: 'eggs', + key: 'Egg', + text: t('questEggHuntDropPlainEgg') + }, { + type: 'eggs', + key: 'Egg', + text: t('questEggHuntDropPlainEgg') + }, { + type: 'eggs', + key: 'Egg', + text: t('questEggHuntDropPlainEgg') + }, { + type: 'eggs', + key: 'Egg', + text: t('questEggHuntDropPlainEgg') + }, { + type: 'eggs', + key: 'Egg', + text: t('questEggHuntDropPlainEgg') + }, { + type: 'eggs', + key: 'Egg', + text: t('questEggHuntDropPlainEgg') + } + ], + gp: 0, + exp: 0 + } + }, + rat: { + text: t('questRatText'), + notes: t('questRatNotes'), + completion: t('questRatCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questRatBoss'), + hp: 1200, + str: 2.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Rat', + text: t('questRatDropRatEgg') + }, { + type: 'eggs', + key: 'Rat', + text: t('questRatDropRatEgg') + }, { + type: 'eggs', + key: 'Rat', + text: t('questRatDropRatEgg') + } + ], + gp: 80, + exp: 800, + unlock: t('questRatUnlockText') + } + }, + octopus: { + text: t('questOctopusText'), + notes: t('questOctopusNotes'), + completion: t('questOctopusCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questOctopusBoss'), + hp: 1200, + str: 2.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Octopus', + text: t('questOctopusDropOctopusEgg') + }, { + type: 'eggs', + key: 'Octopus', + text: t('questOctopusDropOctopusEgg') + }, { + type: 'eggs', + key: 'Octopus', + text: t('questOctopusDropOctopusEgg') + } + ], + gp: 80, + exp: 800, + unlock: t('questOctopusUnlockText') + } + }, + dilatory_derby: { + text: t('questSeahorseText'), + notes: t('questSeahorseNotes'), + completion: t('questSeahorseCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questSeahorseBoss'), + hp: 300, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Seahorse', + text: t('questSeahorseDropSeahorseEgg') + }, { + type: 'eggs', + key: 'Seahorse', + text: t('questSeahorseDropSeahorseEgg') + }, { + type: 'eggs', + key: 'Seahorse', + text: t('questSeahorseDropSeahorseEgg') + } + ], + gp: 25, + exp: 125, + unlock: t('questSeahorseUnlockText') + } + }, + atom1: { + text: t('questAtom1Text'), + notes: t('questAtom1Notes'), + value: 4, + lvl: 15, + category: 'unlockable', + collect: { + soapBars: { + text: t('questAtom1CollectSoapBars'), + count: 20 + } + }, + drop: { + items: [ + { + type: 'quests', + key: "atom2", + text: t('questAtom1Drop') + } + ], + gp: 7, + exp: 50 + } + }, + atom2: { + text: t('questAtom2Text'), + notes: t('questAtom2Notes'), + previous: 'atom1', + value: 4, + lvl: 15, + category: 'unlockable', + boss: { + name: t('questAtom2Boss'), + hp: 300, + str: 1 + }, + drop: { + items: [ + { + type: 'quests', + key: "atom3", + text: t('questAtom2Drop') + } + ], + gp: 20, + exp: 100 + } + }, + atom3: { + text: t('questAtom3Text'), + notes: t('questAtom3Notes'), + previous: 'atom2', + completion: t('questAtom3Completion'), + value: 4, + lvl: 15, + category: 'unlockable', + boss: { + name: t('questAtom3Boss'), + hp: 800, + str: 1.5 + }, + drop: { + items: [ + { + type: 'gear', + key: "head_special_2", + text: t('headSpecial2Text') + }, { + type: 'hatchingPotions', + key: "Base", + text: t('questAtom3DropPotion') + }, { + type: 'hatchingPotions', + key: "Base", + text: t('questAtom3DropPotion') + } + ], + gp: 25, + exp: 125 + } + }, + harpy: { + text: t('questHarpyText'), + notes: t('questHarpyNotes'), + completion: t('questHarpyCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questHarpyBoss'), + hp: 600, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Parrot', + text: t('questHarpyDropParrotEgg') + }, { + type: 'eggs', + key: 'Parrot', + text: t('questHarpyDropParrotEgg') + }, { + type: 'eggs', + key: 'Parrot', + text: t('questHarpyDropParrotEgg') + } + ], + gp: 43, + exp: 350, + unlock: t('questHarpyUnlockText') + } + }, + rooster: { + text: t('questRoosterText'), + notes: t('questRoosterNotes'), + completion: t('questRoosterCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questRoosterBoss'), + hp: 300, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Rooster', + text: t('questRoosterDropRoosterEgg') + }, { + type: 'eggs', + key: 'Rooster', + text: t('questRoosterDropRoosterEgg') + }, { + type: 'eggs', + key: 'Rooster', + text: t('questRoosterDropRoosterEgg') + } + ], + gp: 25, + exp: 125, + unlock: t('questRoosterUnlockText') + } + }, + spider: { + text: t('questSpiderText'), + notes: t('questSpiderNotes'), + completion: t('questSpiderCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questSpiderBoss'), + hp: 400, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Spider', + text: t('questSpiderDropSpiderEgg') + }, { + type: 'eggs', + key: 'Spider', + text: t('questSpiderDropSpiderEgg') + }, { + type: 'eggs', + key: 'Spider', + text: t('questSpiderDropSpiderEgg') + } + ], + gp: 31, + exp: 200, + unlock: t('questSpiderUnlockText') + } + }, + moonstone1: { + text: t('questMoonstone1Text'), + notes: t('questMoonstone1Notes'), + value: 4, + lvl: 60, + category: 'unlockable', + collect: { + moonstone: { + text: t('questMoonstone1CollectMoonstone'), + count: 500 + } + }, + drop: { + items: [ + { + type: 'quests', + key: "moonstone2", + text: t('questMoonstone1DropMoonstone2Quest') + } + ], + gp: 50, + exp: 100 + } + }, + moonstone2: { + text: t('questMoonstone2Text'), + notes: t('questMoonstone2Notes'), + value: 4, + lvl: 60, + previous: 'moonstone1', + category: 'unlockable', + boss: { + name: t('questMoonstone2Boss'), + hp: 1500, + str: 3 + }, + drop: { + items: [ + { + type: 'quests', + key: 'moonstone3', + text: t('questMoonstone2DropMoonstone3Quest') + } + ], + gp: 500, + exp: 1000 + } + }, + moonstone3: { + text: t('questMoonstone3Text'), + notes: t('questMoonstone3Notes'), + completion: t('questMoonstone3Completion'), + previous: 'moonstone2', + value: 4, + lvl: 60, + category: 'unlockable', + boss: { + name: t('questMoonstone3Boss'), + hp: 2000, + str: 3.5 + }, + drop: { + items: [ + { + type: 'gear', + key: "armor_special_2", + text: t('armorSpecial2Text') + }, { + type: 'food', + key: 'RottenMeat', + text: t('questMoonstone3DropRottenMeat') + }, { + type: 'food', + key: 'RottenMeat', + text: t('questMoonstone3DropRottenMeat') + }, { + type: 'food', + key: 'RottenMeat', + text: t('questMoonstone3DropRottenMeat') + }, { + type: 'food', + key: 'RottenMeat', + text: t('questMoonstone3DropRottenMeat') + }, { + type: 'food', + key: 'RottenMeat', + text: t('questMoonstone3DropRottenMeat') + }, { + type: 'hatchingPotions', + key: 'Zombie', + text: t('questMoonstone3DropZombiePotion') + }, { + type: 'hatchingPotions', + key: 'Zombie', + text: t('questMoonstone3DropZombiePotion') + }, { + type: 'hatchingPotions', + key: 'Zombie', + text: t('questMoonstone3DropZombiePotion') + } + ], + gp: 900, + exp: 1500 + } + }, + goldenknight1: { + text: t('questGoldenknight1Text'), + notes: t('questGoldenknight1Notes'), + value: 4, + lvl: 40, + category: 'unlockable', + collect: { + testimony: { + text: t('questGoldenknight1CollectTestimony'), + count: 300 + } + }, + drop: { + items: [ + { + type: 'quests', + key: "goldenknight2", + text: t('questGoldenknight1DropGoldenknight2Quest') + } + ], + gp: 15, + exp: 120 + } + }, + goldenknight2: { + text: t('questGoldenknight2Text'), + notes: t('questGoldenknight2Notes'), + value: 4, + previous: 'goldenknight1', + lvl: 40, + category: 'unlockable', + boss: { + name: t('questGoldenknight2Boss'), + hp: 1000, + str: 3 + }, + drop: { + items: [ + { + type: 'quests', + key: 'goldenknight3', + text: t('questGoldenknight2DropGoldenknight3Quest') + } + ], + gp: 75, + exp: 750 + } + }, + goldenknight3: { + text: t('questGoldenknight3Text'), + notes: t('questGoldenknight3Notes'), + completion: t('questGoldenknight3Completion'), + previous: 'goldenknight2', + value: 4, + lvl: 40, + category: 'unlockable', + boss: { + name: t('questGoldenknight3Boss'), + hp: 1700, + str: 3.5 + }, + drop: { + items: [ + { + type: 'food', + key: 'Honey', + text: t('questGoldenknight3DropHoney') + }, { + type: 'food', + key: 'Honey', + text: t('questGoldenknight3DropHoney') + }, { + type: 'food', + key: 'Honey', + text: t('questGoldenknight3DropHoney') + }, { + type: 'hatchingPotions', + key: 'Golden', + text: t('questGoldenknight3DropGoldenPotion') + }, { + type: 'hatchingPotions', + key: 'Golden', + text: t('questGoldenknight3DropGoldenPotion') + }, { + type: 'gear', + key: 'shield_special_goldenknight', + text: t('questGoldenknight3DropWeapon') + } + ], + gp: 900, + exp: 1500 + } + }, + basilist: { + text: t('questBasilistText'), + notes: t('questBasilistNotes'), + completion: t('questBasilistCompletion'), + value: 4, + category: 'unlockable', + unlockCondition: { + condition: 'party invite', + text: t('inviteFriends') + }, + boss: { + name: t('questBasilistBoss'), + hp: 100, + str: 0.5 + }, + drop: { + gp: 8, + exp: 42 + } + }, + owl: { + text: t('questOwlText'), + notes: t('questOwlNotes'), + completion: t('questOwlCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questOwlBoss'), + hp: 500, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Owl', + text: t('questOwlDropOwlEgg') + }, { + type: 'eggs', + key: 'Owl', + text: t('questOwlDropOwlEgg') + }, { + type: 'eggs', + key: 'Owl', + text: t('questOwlDropOwlEgg') + } + ], + gp: 37, + exp: 275, + unlock: t('questOwlUnlockText') + } + }, + penguin: { + text: t('questPenguinText'), + notes: t('questPenguinNotes'), + completion: t('questPenguinCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questPenguinBoss'), + hp: 400, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Penguin', + text: t('questPenguinDropPenguinEgg') + }, { + type: 'eggs', + key: 'Penguin', + text: t('questPenguinDropPenguinEgg') + }, { + type: 'eggs', + key: 'Penguin', + text: t('questPenguinDropPenguinEgg') + } + ], + gp: 31, + exp: 200, + unlock: t('questPenguinUnlockText') + } + }, + trex: { + text: t('questTRexText'), + notes: t('questTRexNotes'), + completion: t('questTRexCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questTRexBoss'), + hp: 800, + str: 2 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'TRex', + text: t('questTRexDropTRexEgg') + }, { + type: 'eggs', + key: 'TRex', + text: t('questTRexDropTRexEgg') + }, { + type: 'eggs', + key: 'TRex', + text: t('questTRexDropTRexEgg') + } + ], + gp: 55, + exp: 500, + unlock: t('questTRexUnlockText') + } + }, + trex_undead: { + text: t('questTRexUndeadText'), + notes: t('questTRexUndeadNotes'), + completion: t('questTRexUndeadCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questTRexUndeadBoss'), + hp: 500, + str: 2, + rage: { + title: t("questTRexUndeadRageTitle"), + description: t("questTRexUndeadRageDescription"), + value: 50, + healing: .3, + effect: t('questTRexUndeadRageEffect') + } + }, + drop: { + items: [ + { + type: 'eggs', + key: 'TRex', + text: t('questTRexDropTRexEgg') + }, { + type: 'eggs', + key: 'TRex', + text: t('questTRexDropTRexEgg') + }, { + type: 'eggs', + key: 'TRex', + text: t('questTRexDropTRexEgg') + } + ], + gp: 55, + exp: 500, + unlock: t('questTRexUnlockText') + } + }, + rock: { + text: t('questRockText'), + notes: t('questRockNotes'), + completion: t('questRockCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questRockBoss'), + hp: 400, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Rock', + text: t('questRockDropRockEgg') + }, { + type: 'eggs', + key: 'Rock', + text: t('questRockDropRockEgg') + }, { + type: 'eggs', + key: 'Rock', + text: t('questRockDropRockEgg') + } + ], + gp: 31, + exp: 200, + unlock: t('questRockUnlockText') + } + }, + bunny: { + text: t('questBunnyText'), + notes: t('questBunnyNotes'), + completion: t('questBunnyCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questBunnyBoss'), + hp: 300, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Bunny', + text: t('questBunnyDropBunnyEgg') + }, { + type: 'eggs', + key: 'Bunny', + text: t('questBunnyDropBunnyEgg') + }, { + type: 'eggs', + key: 'Bunny', + text: t('questBunnyDropBunnyEgg') + } + ], + gp: 25, + exp: 125, + unlock: t('questBunnyUnlockText') + } + }, + slime: { + text: t('questSlimeText'), + notes: t('questSlimeNotes'), + completion: t('questSlimeCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questSlimeBoss'), + hp: 400, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Slime', + text: t('questSlimeDropSlimeEgg') + }, { + type: 'eggs', + key: 'Slime', + text: t('questSlimeDropSlimeEgg') + }, { + type: 'eggs', + key: 'Slime', + text: t('questSlimeDropSlimeEgg') + } + ], + gp: 31, + exp: 200, + unlock: t('questSlimeUnlockText') + } + }, + sheep: { + text: t('questSheepText'), + notes: t('questSheepNotes'), + completion: t('questSheepCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questSheepBoss'), + hp: 300, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Sheep', + text: t('questSheepDropSheepEgg') + }, { + type: 'eggs', + key: 'Sheep', + text: t('questSheepDropSheepEgg') + }, { + type: 'eggs', + key: 'Sheep', + text: t('questSheepDropSheepEgg') + } + ], + gp: 25, + exp: 125, + unlock: t('questSheepUnlockText') + } + }, + kraken: { + text: t('questKrakenText'), + notes: t('questKrakenNotes'), + completion: t('questKrakenCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questKrakenBoss'), + hp: 800, + str: 2 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Cuttlefish', + text: t('questKrakenDropCuttlefishEgg') + }, { + type: 'eggs', + key: 'Cuttlefish', + text: t('questKrakenDropCuttlefishEgg') + }, { + type: 'eggs', + key: 'Cuttlefish', + text: t('questKrakenDropCuttlefishEgg') + } + ], + gp: 55, + exp: 500, + unlock: t('questKrakenUnlockText') + } + }, + whale: { + text: t('questWhaleText'), + notes: t('questWhaleNotes'), + completion: t('questWhaleCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questWhaleBoss'), + hp: 500, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Whale', + text: t('questWhaleDropWhaleEgg') + }, { + type: 'eggs', + key: 'Whale', + text: t('questWhaleDropWhaleEgg') + }, { + type: 'eggs', + key: 'Whale', + text: t('questWhaleDropWhaleEgg') + } + ], + gp: 37, + exp: 275, + unlock: t('questWhaleUnlockText') + } + }, + dilatoryDistress1: { + text: t('questDilatoryDistress1Text'), + notes: t('questDilatoryDistress1Notes'), + completion: t('questDilatoryDistress1Completion'), + value: 4, + goldValue: 200, + category: 'gold', + collect: { + fireCoral: { + text: t('questDilatoryDistress1CollectFireCoral'), + count: 25 + }, + blueFins: { + text: t('questDilatoryDistress1CollectBlueFins'), + count: 25 + } + }, + drop: { + items: [ + { + type: 'gear', + key: "armor_special_finnedOceanicArmor", + text: t('questDilatoryDistress1DropArmor') + } + ], + gp: 0, + exp: 75 + } + }, + dilatoryDistress2: { + text: t('questDilatoryDistress2Text'), + notes: t('questDilatoryDistress2Notes'), + completion: t('questDilatoryDistress2Completion'), + previous: 'dilatoryDistress1', + value: 4, + goldValue: 300, + category: 'gold', + boss: { + name: t('questDilatoryDistress2Boss'), + hp: 500, + rage: { + title: t("questDilatoryDistress2RageTitle"), + description: t("questDilatoryDistress2RageDescription"), + value: 50, + healing: .3, + effect: t('questDilatoryDistress2RageEffect') + } + }, + drop: { + items: [ + { + type: 'hatchingPotions', + key: 'Skeleton', + text: t('questDilatoryDistress2DropSkeletonPotion') + }, { + type: 'hatchingPotions', + key: 'CottonCandyBlue', + text: t('questDilatoryDistress2DropCottonCandyBluePotion') + }, { + type: 'gear', + key: "head_special_fireCoralCirclet", + text: t('questDilatoryDistress2DropHeadgear') + } + ], + gp: 0, + exp: 500 + } + }, + dilatoryDistress3: { + text: t('questDilatoryDistress3Text'), + notes: t('questDilatoryDistress3Notes'), + completion: t('questDilatoryDistress3Completion'), + previous: 'dilatoryDistress2', + value: 4, + goldValue: 400, + category: 'gold', + boss: { + name: t('questDilatoryDistress3Boss'), + hp: 1000, + str: 2 + }, + drop: { + items: [ + { + type: 'food', + key: 'Fish', + text: t('questDilatoryDistress3DropFish') + }, { + type: 'food', + key: 'Fish', + text: t('questDilatoryDistress3DropFish') + }, { + type: 'food', + key: 'Fish', + text: t('questDilatoryDistress3DropFish') + }, { + type: 'gear', + key: "weapon_special_tridentOfCrashingTides", + text: t('questDilatoryDistress3DropWeapon') + }, { + type: 'gear', + key: "shield_special_moonpearlShield", + text: t('questDilatoryDistress3DropShield') + } + ], + gp: 0, + exp: 650 + } + }, + cheetah: { + text: t('questCheetahText'), + notes: t('questCheetahNotes'), + completion: t('questCheetahCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questCheetahBoss'), + hp: 600, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Cheetah', + text: t('questCheetahDropCheetahEgg') + }, { + type: 'eggs', + key: 'Cheetah', + text: t('questCheetahDropCheetahEgg') + }, { + type: 'eggs', + key: 'Cheetah', + text: t('questCheetahDropCheetahEgg') + } + ], + gp: 43, + exp: 350, + unlock: t('questCheetahUnlockText') + } + }, + horse: { + text: t('questHorseText'), + notes: t('questHorseNotes'), + completion: t('questHorseCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questHorseBoss'), + hp: 500, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Horse', + text: t('questHorseDropHorseEgg') + }, { + type: 'eggs', + key: 'Horse', + text: t('questHorseDropHorseEgg') + }, { + type: 'eggs', + key: 'Horse', + text: t('questHorseDropHorseEgg') + } + ], + gp: 37, + exp: 275, + unlock: t('questHorseUnlockText') + } + }, + frog: { + text: t('questFrogText'), + notes: t('questFrogNotes'), + completion: t('questFrogCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questFrogBoss'), + hp: 300, + str: 1.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Frog', + text: t('questFrogDropFrogEgg') + }, { + type: 'eggs', + key: 'Frog', + text: t('questFrogDropFrogEgg') + }, { + type: 'eggs', + key: 'Frog', + text: t('questFrogDropFrogEgg') + } + ], + gp: 25, + exp: 125, + unlock: t('questFrogUnlockText') + } + }, + snake: { + text: t('questSnakeText'), + notes: t('questSnakeNotes'), + completion: t('questSnakeCompletion'), + value: 4, + category: 'pet', + boss: { + name: t('questSnakeBoss'), + hp: 1100, + str: 2.5 + }, + drop: { + items: [ + { + type: 'eggs', + key: 'Snake', + text: t('questSnakeDropSnakeEgg') + }, { + type: 'eggs', + key: 'Snake', + text: t('questSnakeDropSnakeEgg') + }, { + type: 'eggs', + key: 'Snake', + text: t('questSnakeDropSnakeEgg') + } + ], + gp: 73, + exp: 725, + unlock: t('questSnakeUnlockText') + } + } +}; + +_.each(api.quests, function(v, key) { + var b; + _.defaults(v, { + key: key, + canBuy: (function() { + return true; + }) + }); + b = v.boss; + if (b) { + _.defaults(b, { + str: 1, + def: 1 + }); + if (b.rage) { + return _.defaults(b.rage, { + title: t('bossRageTitle'), + description: t('bossRageDescription') + }); + } + } +}); + +api.questsByLevel = _.sortBy(api.quests, function(quest) { + return quest.lvl || 0; +}); + +api.backgrounds = { + backgrounds062014: { + beach: { + text: t('backgroundBeachText'), + notes: t('backgroundBeachNotes') + }, + fairy_ring: { + text: t('backgroundFairyRingText'), + notes: t('backgroundFairyRingNotes') + }, + forest: { + text: t('backgroundForestText'), + notes: t('backgroundForestNotes') + } + }, + backgrounds072014: { + open_waters: { + text: t('backgroundOpenWatersText'), + notes: t('backgroundOpenWatersNotes') + }, + coral_reef: { + text: t('backgroundCoralReefText'), + notes: t('backgroundCoralReefNotes') + }, + seafarer_ship: { + text: t('backgroundSeafarerShipText'), + notes: t('backgroundSeafarerShipNotes') + } + }, + backgrounds082014: { + volcano: { + text: t('backgroundVolcanoText'), + notes: t('backgroundVolcanoNotes') + }, + clouds: { + text: t('backgroundCloudsText'), + notes: t('backgroundCloudsNotes') + }, + dusty_canyons: { + text: t('backgroundDustyCanyonsText'), + notes: t('backgroundDustyCanyonsNotes') + } + }, + backgrounds092014: { + thunderstorm: { + text: t('backgroundThunderstormText'), + notes: t('backgroundThunderstormNotes') + }, + autumn_forest: { + text: t('backgroundAutumnForestText'), + notes: t('backgroundAutumnForestNotes') + }, + harvest_fields: { + text: t('backgroundHarvestFieldsText'), + notes: t('backgroundHarvestFieldsNotes') + } + }, + backgrounds102014: { + graveyard: { + text: t('backgroundGraveyardText'), + notes: t('backgroundGraveyardNotes') + }, + haunted_house: { + text: t('backgroundHauntedHouseText'), + notes: t('backgroundHauntedHouseNotes') + }, + pumpkin_patch: { + text: t('backgroundPumpkinPatchText'), + notes: t('backgroundPumpkinPatchNotes') + } + }, + backgrounds112014: { + harvest_feast: { + text: t('backgroundHarvestFeastText'), + notes: t('backgroundHarvestFeastNotes') + }, + sunset_meadow: { + text: t('backgroundSunsetMeadowText'), + notes: t('backgroundSunsetMeadowNotes') + }, + starry_skies: { + text: t('backgroundStarrySkiesText'), + notes: t('backgroundStarrySkiesNotes') + } + }, + backgrounds122014: { + iceberg: { + text: t('backgroundIcebergText'), + notes: t('backgroundIcebergNotes') + }, + twinkly_lights: { + text: t('backgroundTwinklyLightsText'), + notes: t('backgroundTwinklyLightsNotes') + }, + south_pole: { + text: t('backgroundSouthPoleText'), + notes: t('backgroundSouthPoleNotes') + } + }, + backgrounds012015: { + ice_cave: { + text: t('backgroundIceCaveText'), + notes: t('backgroundIceCaveNotes') + }, + frigid_peak: { + text: t('backgroundFrigidPeakText'), + notes: t('backgroundFrigidPeakNotes') + }, + snowy_pines: { + text: t('backgroundSnowyPinesText'), + notes: t('backgroundSnowyPinesNotes') + } + }, + backgrounds022015: { + blacksmithy: { + text: t('backgroundBlacksmithyText'), + notes: t('backgroundBlacksmithyNotes') + }, + crystal_cave: { + text: t('backgroundCrystalCaveText'), + notes: t('backgroundCrystalCaveNotes') + }, + distant_castle: { + text: t('backgroundDistantCastleText'), + notes: t('backgroundDistantCastleNotes') + } + }, + backgrounds032015: { + spring_rain: { + text: t('backgroundSpringRainText'), + notes: t('backgroundSpringRainNotes') + }, + stained_glass: { + text: t('backgroundStainedGlassText'), + notes: t('backgroundStainedGlassNotes') + }, + rolling_hills: { + text: t('backgroundRollingHillsText'), + notes: t('backgroundRollingHillsNotes') + } + }, + backgrounds042015: { + cherry_trees: { + text: t('backgroundCherryTreesText'), + notes: t('backgroundCherryTreesNotes') + }, + floral_meadow: { + text: t('backgroundFloralMeadowText'), + notes: t('backgroundFloralMeadowNotes') + }, + gumdrop_land: { + text: t('backgroundGumdropLandText'), + notes: t('backgroundGumdropLandNotes') + } + }, + backgrounds052015: { + marble_temple: { + text: t('backgroundMarbleTempleText'), + notes: t('backgroundMarbleTempleNotes') + }, + mountain_lake: { + text: t('backgroundMountainLakeText'), + notes: t('backgroundMountainLakeNotes') + }, + pagodas: { + text: t('backgroundPagodasText'), + notes: t('backgroundPagodasNotes') + } + }, + backgrounds062015: { + drifting_raft: { + text: t('backgroundDriftingRaftText'), + notes: t('backgroundDriftingRaftNotes') + }, + shimmery_bubbles: { + text: t('backgroundShimmeryBubblesText'), + notes: t('backgroundShimmeryBubblesNotes') + }, + island_waterfalls: { + text: t('backgroundIslandWaterfallsText'), + notes: t('backgroundIslandWaterfallsNotes') + } + }, + backgrounds072015: { + dilatory_ruins: { + text: t('backgroundDilatoryRuinsText'), + notes: t('backgroundDilatoryRuinsNotes') + }, + giant_wave: { + text: t('backgroundGiantWaveText'), + notes: t('backgroundGiantWaveNotes') + }, + sunken_ship: { + text: t('backgroundSunkenShipText'), + notes: t('backgroundSunkenShipNotes') + } + }, + backgrounds082015: { + pyramids: { + text: t('backgroundPyramidsText'), + notes: t('backgroundPyramidsNotes') + }, + sunset_savannah: { + text: t('backgroundSunsetSavannahText'), + notes: t('backgroundSunsetSavannahNotes') + }, + twinkly_party_lights: { + text: t('backgroundTwinklyPartyLightsText'), + notes: t('backgroundTwinklyPartyLightsNotes') + } + }, + backgrounds092015: { + market: { + text: t('backgroundMarketText'), + notes: t('backgroundMarketNotes') + }, + stable: { + text: t('backgroundStableText'), + notes: t('backgroundStableNotes') + }, + tavern: { + text: t('backgroundTavernText'), + notes: t('backgroundTavernNotes') + } + }, + backgrounds102015: { + harvest_moon: { + text: t('backgroundHarvestMoonText'), + notes: t('backgroundHarvestMoonNotes') + }, + slimy_swamp: { + text: t('backgroundSlimySwampText'), + notes: t('backgroundSlimySwampNotes') + }, + swarming_darkness: { + text: t('backgroundSwarmingDarknessText'), + notes: t('backgroundSwarmingDarknessNotes') + } + }, + backgrounds112015: { + floating_islands: { + text: t('backgroundFloatingIslandsText'), + notes: t('backgroundFloatingIslandsNotes') + }, + night_dunes: { + text: t('backgroundNightDunesText'), + notes: t('backgroundNightDunesNotes') + }, + sunset_oasis: { + text: t('backgroundSunsetOasisText'), + notes: t('backgroundSunsetOasisNotes') + } + } +}; + +api.subscriptionBlocks = { + basic_earned: { + months: 1, + price: 5 + }, + basic_3mo: { + months: 3, + price: 15 + }, + basic_6mo: { + months: 6, + price: 30 + }, + google_6mo: { + months: 6, + price: 24, + discount: true, + original: 30 + }, + basic_12mo: { + months: 12, + price: 48 + } +}; + +_.each(api.subscriptionBlocks, function(b, k) { + return b.key = k; +}); + +api.userDefaults = { + habits: [ + { + type: 'habit', + text: t('defaultHabit1Text'), + value: 0, + up: true, + down: false, + attribute: 'per' + }, { + type: 'habit', + text: t('defaultHabit2Text'), + value: 0, + up: false, + down: true, + attribute: 'str' + }, { + type: 'habit', + text: t('defaultHabit3Text'), + value: 0, + up: true, + down: true, + attribute: 'str' + } + ], + dailys: [], + todos: [ + { + type: 'todo', + text: t('defaultTodo1Text'), + notes: t('defaultTodoNotes'), + completed: false, + attribute: 'int' + } + ], + rewards: [ + { + type: 'reward', + text: t('defaultReward1Text'), + value: 10 + } + ], + tags: [ + { + name: t('defaultTag1') + }, { + name: t('defaultTag2') + }, { + name: t('defaultTag3') + } + ] +}; + +api.faq = require('./faq.js'); \ No newline at end of file diff --git a/common/script/content/translation.js b/common/script/content/translation.js index e0e26450c5..da478c2546 100644 --- a/common/script/content/translation.js +++ b/common/script/content/translation.js @@ -1,7 +1,6 @@ 'use strict'; -require('coffee-script'); -var i18n = require('../i18n.coffee'); +var i18n = require('../i18n'); var t = function(string, vars) { var func = function(lang) { diff --git a/common/script/count.js b/common/script/count.js index bc32f4623f..53a4f7eb7a 100644 --- a/common/script/count.js +++ b/common/script/count.js @@ -1,8 +1,7 @@ 'use strict'; -require('coffee-script'); var _ = require('lodash'); -var content = require('./content/index.coffee'); +var content = require('./content/index'); var DROP_ANIMALS = _.keys(content.pets); diff --git a/common/script/i18n.js b/common/script/i18n.js new file mode 100644 index 0000000000..59e5e358da --- /dev/null +++ b/common/script/i18n.js @@ -0,0 +1,51 @@ +var _; + +_ = require('lodash'); + +module.exports = { + strings: null, + translations: {}, + t: function(stringName) { + var clonedVars, e, locale, string, stringNotFound, vars; + vars = arguments[1]; + if (_.isString(arguments[1])) { + vars = null; + locale = arguments[1]; + } else if (arguments[2] != null) { + vars = arguments[1]; + locale = arguments[2]; + } + if ((locale == null) || (!module.exports.strings && !module.exports.translations[locale])) { + locale = 'en'; + } + if (module.exports.strings) { + string = module.exports.strings[stringName]; + } else { + string = module.exports.translations[locale] && module.exports.translations[locale][stringName]; + } + clonedVars = _.clone(vars) || {}; + clonedVars.locale = locale; + if (string) { + try { + return _.template(string, clonedVars); + } catch (_error) { + e = _error; + return 'Error processing the string. Please see Help > Report a Bug.'; + } + } else { + if (module.exports.strings) { + stringNotFound = module.exports.strings.stringNotFound; + } else if (module.exports.translations[locale]) { + stringNotFound = module.exports.translations[locale] && module.exports.translations[locale].stringNotFound; + } + try { + return _.template(stringNotFound, { + string: stringName + }); + } catch (_error) { + e = _error; + return 'Error processing the string. Please see Help > Report a Bug.'; + } + } + } +}; diff --git a/common/script/index.coffee b/common/script/index.coffee deleted file mode 100644 index a69f64fcaf..0000000000 --- a/common/script/index.coffee +++ /dev/null @@ -1,1936 +0,0 @@ -moment = require('moment') -_ = require('lodash') -content = require('./content/index.coffee') -i18n = require('./i18n.coffee') -api = module.exports = {} - -api.i18n = i18n - -# little helper for large arrays of strings. %w"this that another" equivalent from Ruby, I really miss that function -$w = api.$w = (s)->s.split(' ') - -api.dotSet = (obj,path,val)-> - arr = path.split('.') - _.reduce arr, (curr, next, index) => - if (arr.length - 1) == index - curr[next] = val - (curr[next] ?= {}) - , obj -api.dotGet = (obj,path)-> - _.reduce path.split('.'), ((curr, next) => curr?[next]), obj - -### - Reflists are arrays, but stored as objects. Mongoose has a helluvatime working with arrays (the main problem for our - syncing issues) - so the goal is to move away from arrays to objects, since mongoose can reference elements by ID - no problem. To maintain sorting, we use these helper functions: -### -api.refPush = (reflist, item, prune=0) -> - item.sort = if _.isEmpty(reflist) then 0 else _.max(reflist,'sort').sort+1 - item.id = api.uuid() unless item.id and !reflist[item.id] - reflist[item.id] = item - -api.planGemLimits = - convRate: 20 #how much does a gem cost? - convCap: 25 #how many gems can be converted / month? - -### - ------------------------------------------------------ - Time / Day - ------------------------------------------------------ -### - -### - Each time we're performing date math (cron, task-due-days, etc), we need to take user preferences into consideration. - Specifically {dayStart} (custom day start) and {timezoneOffset}. This function sanitizes / defaults those values. - {now} is also passed in for various purposes, one example being the test scripts scripts testing different "now" times -### -sanitizeOptions = (o) -> - dayStart = if (!_.isNaN(+o.dayStart) and 0 <= +o.dayStart <= 24) then +o.dayStart else 0 - timezoneOffset = if o.timezoneOffset then +(o.timezoneOffset) else +moment().zone() - now = if o.now then moment(o.now).zone(timezoneOffset) else moment(+new Date).zone(timezoneOffset) - # return a new object, we don't want to add "now" to user object - {dayStart, timezoneOffset, now} - -api.startOfWeek = api.startOfWeek = (options={}) -> - o = sanitizeOptions(options) - moment(o.now).startOf('week') - -api.startOfDay = (options={}) -> - # This is designed for use with any date that has an important time portion (e.g., when comparing the current date-time with the previous cron's date-time for determing if cron should run now). - # It changes the time portion of the date-time to be the Custom Day Start hour, so that the date-time is now the user's correct start of day. - # It SUBTRACTS a day if the date-time's original hour is before CDS (e.g., if your CDS is 5am and it's currently 4am, it's still the previous day). - # This is NOT suitable for manipulating any dates that are displayed to the user as a date with no time portion, such as a Daily's Start Dates (e.g., a Start Date of today shows only the date, so it should be considered to be today even if the hidden time portion is before CDS). - o = sanitizeOptions(options) - dayStart = moment(o.now).startOf('day').add({hours:o.dayStart}) - if moment(o.now).hour() < o.dayStart - dayStart.subtract({days:1}) - dayStart - -api.dayMapping = {0:'su',1:'m',2:'t',3:'w',4:'th',5:'f',6:'s'} - -### - Absolute diff from "yesterday" till now -### -api.daysSince = (yesterday, options = {}) -> - o = sanitizeOptions options - api.startOfDay(_.defaults {now:o.now}, o).diff(api.startOfDay(_.defaults {now:yesterday}, o), 'days') - -### - Should the user do this task on this date, given the task's repeat options and user.preferences.dayStart? -### -api.shouldDo = (day, dailyTask, options = {}) -> - return false unless dailyTask.type == 'daily' - o = sanitizeOptions options - startOfDayWithCDSTime = api.startOfDay(_.defaults {now:day}, o) # a moment() - - taskStartDate = moment(dailyTask.startDate).zone(o.timezoneOffset) - - # The time portion of the Start Date is never visible to or modifiable by the user so we must ignore it. - # Therefore, we must also ignore the time portion of the user's day start (startOfDayWithCDSTime), otherwise the date comparison will be wrong for some times. - # NB: The user's day start date has already been converted to the PREVIOUS day's date if the time portion was before CDS. - taskStartDate = moment(taskStartDate).startOf('day') - - if taskStartDate > startOfDayWithCDSTime.startOf('day') - return false # Daily starts in the future - - if dailyTask.frequency == 'daily' # "Every X Days" - if !dailyTask.everyX - return false # error condition - daysSinceTaskStart = startOfDayWithCDSTime.startOf('day').diff(taskStartDate, 'days') - everyXCheck = (daysSinceTaskStart % dailyTask.everyX == 0) - return everyXCheck - else if dailyTask.frequency == 'weekly' # "On Certain Days of the Week" - if !dailyTask.repeat - return false # error condition - dayOfWeekNum = startOfDayWithCDSTime.day() # e.g. 0 for Sunday - dayOfWeekCheck = dailyTask.repeat[api.dayMapping[dayOfWeekNum]] - return dayOfWeekCheck - else - # unexpected frequency string - return false - -### - ------------------------------------------------------ - Level cap - ------------------------------------------------------ -### - -api.maxLevel = 100 - -api.capByLevel = (lvl) -> - if lvl > api.maxLevel then api.maxLevel else lvl - -### - ------------------------------------------------------ - Health cap - ------------------------------------------------------ -### - -api.maxHealth = 50 - -### - ------------------------------------------------------ - Scoring - ------------------------------------------------------ -### - -api.tnl = (lvl) -> - Math.round(((Math.pow(lvl, 2) * 0.25) + (10 * lvl) + 139.75) / 10) * 10 - # round to nearest 10? - -### - A hyperbola function that creates diminishing returns, so you can't go to infinite (eg, with Exp gain). - {max} The asymptote - {bonus} All the numbers combined for your point bonus (eg, task.value * user.stats.int * critChance, etc) - {halfway} (optional) the point at which the graph starts bending -### -api.diminishingReturns = (bonus, max, halfway=max/2) -> - max*(bonus/(bonus+halfway)) - -api.monod = (bonus, rateOfIncrease, max) -> - rateOfIncrease*max*bonus/(rateOfIncrease*bonus+max) - -### -Preen history for users with > 7 history entries -This takes an infinite array of single day entries [day day day day day...], and turns it into a condensed array -of averages, condensing more the further back in time we go. Eg, 7 entries each for last 7 days; 1 entry each week -of this month; 1 entry for each month of this year; 1 entry per previous year: [day*7 week*4 month*12 year*infinite] -### -preenHistory = (history) -> - history = _.filter(history, (h) -> !!h) # discard nulls (corrupted somehow) - newHistory = [] - preen = (amount, groupBy) -> - groups = _.chain(history) - .groupBy((h) -> moment(h.date).format groupBy) # get date groupings to average against - .sortBy((h, k) -> k) # sort by date - .value() # turn into an array - groups = groups.slice(-amount) - groups.pop() # get rid of "this week", "this month", etc (except for case of days) - _.each groups, (group) -> - newHistory.push - date: moment(group[0].date).toDate() - #date: moment(group[0].date).format('MM/DD/YYYY') # Use this one when testing - value: _.reduce(group, ((m, obj) -> m + obj.value), 0) / group.length # average - true - - # Keep the last: - preen 50, "YYYY" # 50 years (habit will toootally be around that long!) - preen moment().format('MM'), "YYYYMM" # last MM months (eg, if today is 05, keep the last 5 months) - - # Then keep all days of this month. Note, the extra logic is to account for Habits, which can be counted multiple times per day - # FIXME I'd rather keep 1-entry/week of this month, then last 'd' days in this week. However, I'm having issues where the 1st starts mid week - thisMonth = moment().format('YYYYMM') - newHistory = newHistory.concat _.filter(history, (h)-> moment(h.date).format('YYYYMM') is thisMonth) - #preen Math.ceil(moment().format('D')/7), "YYYYww" # last __ weeks (# weeks so far this month) - #newHistory = newHistory.concat(history.slice -moment().format('D')) # each day of this week - - newHistory - - -### - Preen 3-day past-completed To-Dos from Angular & mobile app -### -api.preenTodos = (tasks) -> - _.where(tasks, (t) -> !t.completed || (t.challenge && t.challenge.id) || moment(t.dateCompleted).isAfter(moment().subtract({days:3}))) - -### - Update the in-browser store with new gear. FIXME this was in user.fns, but it was causing strange issues there -### -sortOrder = _.reduce content.gearTypes,((m,v,k)->m[v]=k;m), {} -api.updateStore = (user) -> - return unless user - changes= [] - _.each content.gearTypes, (type) -> - found = _.find content.gear.tree[type][user.stats.class], (item) -> - !user.items.gear.owned[item.key] - changes.push(found) if found - true - # Add special items (contrib gear, backer gear, etc) - changes = changes.concat _.filter content.gear.flat, (v) -> - v.klass in ['special','mystery','armoire'] and !user.items.gear.owned[v.key] and v.canOwn?(user) - # Return sorted store (array) - _.sortBy changes, (c)->sortOrder[c.type] - -### ------------------------------------------------------- -Content ------------------------------------------------------- -### - -api.content = content - - -### ------------------------------------------------------- -Misc Helpers ------------------------------------------------------- -### - -api.uuid = -> - "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace /[xy]/g, (c) -> - r = Math.random() * 16 | 0 - v = (if c is "x" then r else (r & 0x3 | 0x8)) - v.toString 16 - -api.countExists = (items)-> _.reduce(items,((m,v)->m+(if v then 1 else 0)),0) - -### -Even though Mongoose handles task defaults, we want to make sure defaults are set on the client-side before -sending up to the server for performance -### -api.taskDefaults = (task={}) -> - task.type = 'habit' unless task.type and task.type in ['habit','daily','todo','reward'] - defaults = - id: api.uuid() - text: if task.id? then task.id else '' - notes: '' - priority: 1 - challenge: {} - attribute: 'str' - dateCreated: new Date() - _.defaults task, defaults - _.defaults(task, {up:true,down:true}) if task.type is 'habit' - _.defaults(task, {history: []}) if task.type in ['habit', 'daily'] - _.defaults(task, {completed:false}) if task.type in ['daily', 'todo'] - _.defaults(task, {streak:0, repeat: {su:true,m:true,t:true,w:true,th:true,f:true,s:true}}, startDate: new Date(), everyX: 1, frequency: 'weekly') if task.type is 'daily' - task._id = task.id # may need this for TaskSchema if we go back to using it, see http://goo.gl/a5irq4 - task.value ?= if task.type is 'reward' then 10 else 0 - task.priority = 1 unless _.isNumber(task.priority) # hotfix for apiv1. once we're off apiv1, we can remove this - task - -api.percent = (x,y, dir) -> - switch dir - when "up" then roundFn = Math.ceil - when "down" then roundFn = Math.floor - else roundFn = Math.round - x=1 if x==0 - Math.max(0,roundFn(x/y*100)) - -### -Remove whitespace #FIXME are we using this anywwhere? Should we be? -### -api.removeWhitespace = (str) -> - return '' unless str - str.replace /\s/g, '' - -### -Encode the download link for .ics iCal file -### -api.encodeiCalLink = (uid, apiToken) -> - loc = window?.location.host or process?.env?.BASE_URL or '' - encodeURIComponent "http://#{loc}/v1/users/#{uid}/calendar.ics?apiToken=#{apiToken}" - -### -Gold amount from their money -### -api.gold = (num) -> - if num - return Math.floor num - else - return "0" - -### -Silver amount from their money -### -api.silver = (num) -> - if num - ("0" + Math.floor (num - Math.floor(num))*100).slice -2 - else - return "00" - -### -Task classes given everything about the class -### -api.taskClasses = (task, filters=[], dayStart=0, lastCron=+new Date, showCompleted=false, main=false) -> - return unless task - {type, completed, value, repeat, priority} = task - - # Filters - if main # only show when on your own list - if !task._editing # always show task being edited (even when tag removed) - for filter, enabled of filters - if enabled and not task.tags?[filter] - # All the other classes don't matter - return 'hidden' - - classes = type - - if task._editing - classes += " beingEdited" # Assists filtering by third-party themes. - # Example: theme normally hides daily when not scheduled for today, - # BUT keeps showing daily when being edited to unschedule it for today - - # show as completed if completed (naturally) or not required for today - if type in ['todo', 'daily'] - if completed or (type is 'daily' and !api.shouldDo(+new Date, task, {dayStart})) - classes += " completed" - else - classes += " uncompleted" - else if type is 'habit' - classes += ' habit-wide' if task.down and task.up - classes += ' habit-narrow' if !task.down and !task.up - - if priority == 0.1 - classes += ' difficulty-trivial' - else if priority == 1 - classes += ' difficulty-easy' - else if priority == 1.5 - classes += ' difficulty-medium' - else if priority == 2 - classes += ' difficulty-hard' - - if value < -20 - classes += ' color-worst' - else if value < -10 - classes += ' color-worse' - else if value < -1 - classes += ' color-bad' - else if value < 1 - classes += ' color-neutral' - else if value < 5 - classes += ' color-good' - else if value < 10 - classes += ' color-better' - else - classes += ' color-best' - return classes - -### -Friendly timestamp -### -api.friendlyTimestamp = (timestamp) -> moment(timestamp).format('MM/DD h:mm:ss a') - -### -Does user have new chat messages? -### -api.newChatMessages = (messages, lastMessageSeen) -> - return false unless messages?.length > 0 - messages?[0] and (messages[0].id != lastMessageSeen) - -### -are any tags active? -### -api.noTags = (tags) -> _.isEmpty(tags) or _.isEmpty(_.filter(tags, (t)->t)) - -### -Are there tags applied? -### -api.appliedTags = (userTags, taskTags) -> - arr = [] - _.each userTags, (t) -> - return unless t? - arr.push(t.name) if taskTags?[t.id] - arr.join(', ') - -### -Various counting functions -### -api.count = require('./count') - -### ------------------------------------------------------- -User (prototype wrapper to give it ops, helper funcs, and virtuals ------------------------------------------------------- -### - -### -User is now wrapped (both on client and server), adding a few new properties: - * getters (_statsComputed, tasks, etc) - * user.fns, which is a bunch of helper functions - These were originally up above, but they make more sense belonging to the user object so we don't have to pass - the user object all over the place. In fact, we should pull in more functions such as cron(), updateStats(), etc. - * user.ops, which is super important: - -If a function is inside user.ops, it has magical properties. If you call it on the client it updates the user object in -the browser and when it's done it automatically POSTs to the server, calling src/controllers/user.js#OP_NAME (the exact same name -of the op function). The first argument req is {query, body, params}, it's what the express controller function -expects. This means we call our functions as if we were calling an Express route. Eg, instead of score(task, direction), -we call score({params:{id:task.id,direction:direction}}). This also forces us to think about our routes (whether to use -params, query, or body for variables). see http://stackoverflow.com/questions/4024271/rest-api-best-practices-where-to-put-parameters - -If `src/controllers/user.js#OP_NAME` doesn't exist on the server, it's automatically added. It runs the code in user.ops.OP_NAME -to update the user model server-side, then performs `user.save()`. You can see this in action for `user.ops.buy`. That -function doesn't exist on the server - so the client calls it, it updates user in the browser, auto-POSTs to server, server -handles it by calling `user.ops.buy` again (to update user on the server), and then saves. We can do this for -everything that doesn't need any code difference from what's in user.ops.OP_NAME for special-handling server-side. If we -*do* need special handling, just add `src/controllers/user.js#OP_NAME` to override the user.ops.OP_NAME, and be -sure to call user.ops.OP_NAME at some point within the overridden function. - -TODO - * Is this the best way to wrap the user object? I thought of using user.prototype, but user is an object not a Function. - user on the server is a Mongoose model, so we can use prototype - but to do it on the client, we'd probably have to - move to $resource for user - * Move to $resource! -### -api.wrap = (user, main=true) -> - return if user._wrapped - user._wrapped = true - - # ---------------------------------------------------------------------- - # user.ops shared client/server operations - # ---------------------------------------------------------------------- - - if main - user.ops = - - # ------ - # User - # ------ - - update: (req, cb) -> - _.each req.body, (v,k) -> - user.fns.dotSet(k,v);true - cb? null, user - - sleep: (req, cb) -> - user.preferences.sleep = !user.preferences.sleep - cb? null, {} - - revive: (req, cb, analytics) -> - return cb?({code:400, message: "Cannot revive if not dead"}) unless user.stats.hp <= 0 - - # Reset stats after death - _.merge user.stats, {hp:50, exp:0, gp:0} - user.stats.lvl-- if user.stats.lvl > 1 - - # Lose a stat point - lostStat = user.fns.randomVal _.reduce(['str','con','per','int'], ((m,k)->m[k]=k if user.stats[k];m), {}) - user.stats[lostStat]-- if lostStat - - # Lose a gear piece - # Free items (value:0) cannot be lost to avoid "pay to win". Subscribers have more free (Mystery) items and so would have a higher chance of losing a free one. The only exception is that the weapon_warrior_0 free item can be lost so that a new player who dies before buying any gear does experience equipment loss. - # Note ""+k string-casting. Without this, when run on the server Mongoose returns funny objects - cl = user.stats.class - gearOwned = user.items.gear.owned.toObject?() or user.items.gear.owned - losableItems = {} - _.each gearOwned, (v,k) -> - if v - itm = content.gear.flat[''+k] - if itm - if (itm.value > 0 || k == 'weapon_warrior_0') && ( itm.klass == cl || ( itm.klass == 'special' && (! itm.specialClass || itm.specialClass == cl) ) || itm.klass == 'armoire' ) - losableItems[''+k]=''+k - lostItem = user.fns.randomVal losableItems - if item = content.gear.flat[lostItem] - user.items.gear.owned[lostItem] = false - user.items.gear.equipped[item.type] = "#{item.type}_base_0" if user.items.gear.equipped[item.type] is lostItem - user.items.gear.costume[item.type] = "#{item.type}_base_0" if user.items.gear.costume[item.type] is lostItem - user.markModified? 'items.gear' - - analyticsData = { - uuid: user._id, - lostItem: lostItem, - gaLabel: lostItem, - category: 'behavior' - } - analytics?.track('Death', analyticsData) - - cb? (if item then {code:200,message: i18n.t('messageLostItem', {itemText: item.text(req.language)}, req.language)} else null), user - - reset: (req, cb) -> - user.habits = [] - user.dailys = [] - user.todos = [] - user.rewards = [] - user.stats.hp = 50 - user.stats.lvl = 1 - user.stats.gp = 0 - user.stats.exp = 0 - # TODO handle MP - gear = user.items.gear - _.each ['equipped', 'costume'], (type) -> - gear[type].armor = 'armor_base_0' - gear[type].weapon = 'weapon_base_0' - gear[type].head = 'head_base_0' - gear[type].shield = 'shield_base_0' - gear.owned = {} if typeof gear.owned == 'undefined' - _.each gear.owned, (v, k)-> gear.owned[k]=false if gear.owned[k];true - gear.owned.weapon_warrior_0 = true - user.markModified? 'items.gear.owned' - user.preferences.costume = false - cb? null, user - - reroll: (req, cb, analytics) -> - if user.balance < 1 - return cb? {code:401,message: i18n.t('notEnoughGems', req.language)} - user.balance-- - _.each user.tasks, (task) -> - unless task.type is 'reward' - task.value = 0 - user.stats.hp = 50 - - analyticsData = { - uuid: user._id, - acquireMethod: 'Gems', - gemCost: 4, - category: 'behavior' - } - analytics?.track('Fortify Potion', analyticsData) - - cb? null, user - - rebirth: (req, cb, analytics) -> - # Cost is 8 Gems ($2) - if (user.balance < 2 && user.stats.lvl < api.maxLevel) - return cb? {code:401,message: i18n.t('notEnoughGems', req.language)} - - analyticsData = { - uuid: user._id, - category: 'behavior' - } - # only charge people if they are under the max level - ryan - if user.stats.lvl < api.maxLevel - user.balance -= 2 - analyticsData.acquireMethod = 'Gems' - analyticsData.gemCost = 8 - else - analyticsData.gemCost = 0 - analyticsData.acquireMethod = '> 100' - - analytics?.track('Rebirth', analyticsData) - - # Save off user's level, for calculating achievement eligibility later - lvl = api.capByLevel(user.stats.lvl) - # Turn tasks yellow, zero out streaks - _.each user.tasks, (task) -> - unless task.type is 'reward' - task.value = 0 - if task.type is 'daily' - task.streak = 0 - # Reset all dynamic stats - stats = user.stats - stats.buffs = {} - stats.hp = 50 - stats.lvl = 1 - stats.class = 'warrior' - _.each ['per','int','con','str','points','gp','exp','mp'], (value) -> - stats[value] = 0 - # Deequip character, set back to base armor and training sword - gear = user.items.gear - _.each ['equipped', 'costume'], (type) -> - gear[type] = {}; # deequip weapon, eyewear, headAccessory, etc, plus future new types - gear[type].armor = 'armor_base_0' - gear[type].weapon = 'weapon_warrior_0' - gear[type].head = 'head_base_0' - gear[type].shield = 'shield_base_0' - if user.items.currentPet then user.ops.equip({params:{type: 'pet', key: user.items.currentPet}}) - if user.items.currentMount then user.ops.equip({params:{type: 'mount', key: user.items.currentMount}}) - # Strip owned gear down to the training sword and free items (zero gold value), but preserve purchase history so user can re-purchase limited edition equipment - _.each gear.owned, (v, k) -> if gear.owned[k] and content.gear.flat[k].value then gear.owned[k] = false; true - gear.owned.weapon_warrior_0 = true - user.markModified? 'items.gear.owned' - user.preferences.costume = false - # Remove unlocked features - flags = user.flags - if not user.achievements.beastMaster - flags.rebirthEnabled = false - flags.itemsEnabled = false - flags.dropsEnabled = false - flags.classSelected = false - flags.levelDrops = {} - # Award an achievement if this is their first Rebirth, or if they made it further than last time - if not (user.achievements.rebirths) - user.achievements.rebirths = 1 - user.achievements.rebirthLevel = lvl - else if (lvl > user.achievements.rebirthLevel or lvl is 100) - user.achievements.rebirths++ - user.achievements.rebirthLevel = lvl - user.stats.buffs = {} - # user.markModified? 'stats' - cb? null, user - - allocateNow: (req, cb) -> - _.times user.stats.points, user.fns.autoAllocate - user.stats.points = 0 - user.markModified? 'stats' - cb? null, user.stats - - # ------ - # Tasks - # ------ - - clearCompleted: (req, cb) -> - _.remove user.todos, (t)-> t.completed and !t.challenge?.id - user.markModified? 'todos' - cb? null, user.todos - - sortTask: (req, cb) -> - {id} = req.params - {to, from} = req.query - task = user.tasks[id] - return cb?({code:404, message: i18n.t('messageTaskNotFound', req.language)}) unless task - return cb?('?to=__&from=__ are required') unless to? and from? - tasks = user["#{task.type}s"] - if task.type is 'todo' and tasks[from] isnt task # client indices don't match because of preened tasks - preenedTasks = api.preenTodos(tasks); - to = tasks.indexOf(preenedTasks[to]) unless to == -1 # Push To Bottom doesn't require readjustment - from = tasks.indexOf(preenedTasks[from]) - return cb?({code:404, message: i18n.t('messageTaskNotFound', req.language)}) unless tasks[from] is task - movedTask = tasks.splice(from, 1)[0] - if to == -1 # we've used the Push To Bottom feature - tasks.push(movedTask) - else # any other sort method uses only positive 'to' values - tasks.splice(to, 0, movedTask) - cb? null, tasks - - updateTask: (req, cb) -> - return cb?({code:404,message:i18n.t('messageTaskNotFound', req.language)}) unless task = user.tasks[req.params?.id] - _.merge task, _.omit(req.body,['checklist','id', 'type']) - task.checklist = req.body.checklist if req.body.checklist - task.markModified? 'tags' - cb? null, task - - deleteTask: (req, cb) -> - task = user.tasks[req.params?.id] - return cb?({code:404,message:i18n.t('messageTaskNotFound', req.language)}) unless task - i = user[task.type + "s"].indexOf(task) - user[task.type + "s"].splice(i, 1) if ~i - cb? null, {} - - addTask: (req, cb) -> - task = api.taskDefaults(req.body) - return cb?({code:409,message:i18n.t('messageDuplicateTaskID', req.language)}) if user.tasks[task.id]? - user["#{task.type}s"].unshift(task) - if user.preferences.newTaskEdit then task._editing = true - if user.preferences.tagsCollapsed then task._tags = true - if !user.preferences.advancedCollapsed then task._advanced = true - cb? null, task - task - - # ------ - # Tags - # ------ - - addTag: (req, cb) -> - user.tags ?= [] - user.tags.push - name: req.body.name - id: req.body.id or api.uuid() - cb? null, user.tags - - sortTag: (req, cb) -> - {to, from} = req.query - return cb?('?to=__&from=__ are required') unless to? and from? - user.tags.splice to, 0, user.tags.splice(from, 1)[0] - cb? null, user.tags - - getTags: (req, cb) -> - cb? null, user.tags - - getTag: (req, cb) -> - tid = req.params.id - i = _.findIndex user.tags, {id: tid} - return cb?({code:404,message:i18n.t('messageTagNotFound', req.language)}) if !~i - cb? null, user.tags[i] - - updateTag: (req, cb) -> - tid = req.params.id - i = _.findIndex user.tags, {id: tid} - return cb?({code:404,message:i18n.t('messageTagNotFound', req.language)}) if !~i - user.tags[i].name = req.body.name - cb? null, user.tags[i] - - deleteTag: (req, cb) -> - tid = req.params.id - i = _.findIndex user.tags, {id: tid} - return cb?({code:404,message:i18n.t('messageTagNotFound', req.language)}) if !~i - tag = user.tags[i] - delete user.filters[tag.id] - user.tags.splice i, 1 - - # remove tag from all tasks - _.each user.tasks, (task) -> - delete task.tags[tag.id] - - _.each ['habits','dailys','todos','rewards'], (type) -> - user.markModified? type - cb? null, user.tags - - # ------ - # Webhooks - # ------ - addWebhook: (req, cb) -> - wh = user.preferences.webhooks - api.refPush(wh, {url:req.body.url, enabled: req.body.enabled or true, id:req.body.id}) - user.markModified? 'preferences.webhooks' - cb? null, user.preferences.webhooks - updateWebhook: (req, cb) -> - _.merge(user.preferences.webhooks[req.params.id], req.body) - user.markModified? 'preferences.webhooks' - cb? null, user.preferences.webhooks - deleteWebhook: (req, cb) -> - delete user.preferences.webhooks[req.params.id] - user.markModified? 'preferences.webhooks' - cb? null, user.preferences.webhooks - - # ------ - # Push Notifications - # ------ - addPushDevice: (req, cb) -> - user.pushDevices = [] unless user.pushDevices - pd = user.pushDevices - item = {regId:req.body.regId, type:req.body.type} - i = _.findIndex pd, {regId: item.regId} - - pd.push(item) unless i != -1 - - cb? null, user.pushDevices - - # ------ - # Inbox - # ------ - clearPMs: (req, cb) -> - user.inbox.messages = {} - user.markModified? 'inbox.messages' - cb? null, user.inbox.messages - deletePM: (req, cb) -> - delete user.inbox.messages[req.params.id] - user.markModified? 'inbox.messages.'+req.params.id - cb? null, user.inbox.messages - blockUser: (req, cb) -> - i = user.inbox.blocks.indexOf(req.params.uuid) - if ~i then user.inbox.blocks.splice(i,1) else user.inbox.blocks.push(req.params.uuid) - user.markModified? 'inbox.blocks' - cb? null, user.inbox.blocks - - # ------ - # Inventory - # ------ - - feed: (req, cb) -> - {pet,food} = req.params - food = content.food[food] - [egg, potion] = pet.split('-') - userPets = user.items.pets - - # Generate pet display name variable - potionText = if content.hatchingPotions[potion] then content.hatchingPotions[potion].text() else potion - eggText = if content.eggs[egg] then content.eggs[egg].text() else egg - petDisplayName = i18n.t('petName', { - potion: potionText - egg: eggText - }) - - return cb?({code:404, message:i18n.t('messagePetNotFound', req.language)}) unless userPets[pet] - return cb?({code:404, message:i18n.t('messageFoodNotFound', req.language)}) unless user.items.food?[food.key] - return cb?({code:401, message:i18n.t('messageCannotFeedPet', req.language)}) if content.specialPets[pet] - return cb?({code:401, message:i18n.t('messageAlreadyMount', req.language)}) if user.items.mounts[pet] - - message = '' - evolve = -> - userPets[pet] = -1 - # changed to -1 to mark "owned" pets - user.items.mounts[pet] = true - user.items.currentPet = "" if pet is user.items.currentPet - message = i18n.t('messageEvolve', {egg: petDisplayName}, req.language) - - if food.key is 'Saddle' - evolve() - else - if food.target is potion or content.hatchingPotions[potion].premium - userPets[pet] += 5 - message = i18n.t('messageLikesFood', {egg: petDisplayName, foodText: food.text(req.language)}, req.language) - else - userPets[pet] += 2 - message = i18n.t('messageDontEnjoyFood', {egg: petDisplayName, foodText: food.text(req.language)}, req.language) - if userPets[pet] >= 50 and !user.items.mounts[pet] - evolve() - user.items.food[food.key]-- - cb? {code:200, message}, {value: userPets[pet]} - - buySpecialSpell: (req,cb) -> - {key} = req.params - item = content.special[key] - return cb?({code:401, message: i18n.t('messageNotEnoughGold', req.language)}) if user.stats.gp < item.value - user.stats.gp -= item.value - user.items.special[key] ?= 0 - user.items.special[key]++ - user.markModified? 'items.special' - message = i18n.t('messageBought', {itemText: item.text(req.language)}, req.language) - cb? {code:200,message}, _.pick(user,$w 'items stats') - - # buy is for using Gold, purchase is for Gems (I know, I know...) - purchase: (req, cb, analytics) -> - {type,key} = req.params - - if type is 'gems' and key is 'gem' - {convRate, convCap} = api.planGemLimits - convCap += user.purchased.plan.consecutive.gemCapExtra - return cb?({code:401,message:"Must subscribe to purchase gems with GP"},req) unless user.purchased?.plan?.customerId - return cb?({code:401,message:"Not enough Gold"}) unless user.stats.gp >= convRate - return cb?({code:401,message:"You've reached the Gold=>Gem conversion cap (#{convCap}) for this month. We have this to prevent abuse / farming. The cap will reset within the first three days of next month."}) if user.purchased.plan.gemsBought >= convCap - user.balance += .25 - user.purchased.plan.gemsBought++ - user.stats.gp -= convRate - - analyticsData = { - uuid: user._id, - itemKey: key, - acquireMethod: 'Gold', - goldCost: convRate, - category: 'behavior' - } - analytics?.track('purchase gems', analyticsData) - - return cb? {code:200,message:"+1 Gem"}, _.pick(user,$w 'stats balance') - - return cb?({code:404,message:":type must be in [eggs,hatchingPotions,food,quests,gear]"},req) unless type in ['eggs','hatchingPotions','food','quests','gear'] - if type is 'gear' - item = content.gear.flat[key] - return cb?({code:401, message: i18n.t('alreadyHave', req.language)}) if user.items.gear.owned[key] - price = (if item.twoHanded or item.gearSet is 'animal' then 2 else 1) / 4 - else - item = content[type][key] - price = item.value / 4 - return cb?({code:404,message:":key not found for Content.#{type}"},req) unless item - return cb?({code:403, message: i18n.t('messageNotAvailable', req.language)}) if not item.canBuy(user) - return cb?({code:403, message: i18n.t('notEnoughGems', req.language)}) if (user.balance < price) or !user.balance - user.balance -= price - if type is 'gear' then user.items.gear.owned[key] = true - else - user.items[type][key] = 0 unless user.items[type][key] > 0 - user.items[type][key]++ - - analyticsData = { - uuid: user._id, - itemKey: key, - itemType: 'Market', - acquireMethod: 'Gems', - gemCost: item.value, - category: 'behavior' - } - analytics?.track('acquire item', analyticsData) - - cb? null, _.pick(user,$w 'items balance') - - releasePets: (req, cb, analytics) -> - if user.balance < 1 - return cb? {code:401,message: i18n.t('notEnoughGems', req.language)} - else - user.balance -= 1 - for pet of content.pets - user.items.pets[pet] = 0 - if not user.achievements.beastMasterCount - user.achievements.beastMasterCount = 0 - user.achievements.beastMasterCount++ - user.items.currentPet = "" - - analyticsData = { - uuid: user._id, - acquireMethod: 'Gems', - gemCost: 4, - category: 'behavior' - } - analytics?.track('release pets', analyticsData) - cb? null, user - - releaseMounts: (req, cb, analytics) -> - if user.balance < 1 - return cb? {code:401,message: i18n.t('notEnoughGems', req.language)} - else - user.balance -= 1 - user.items.currentMount = "" - for mount of content.pets - user.items.mounts[mount] = null - if not user.achievements.mountMasterCount - user.achievements.mountMasterCount = 0 - user.achievements.mountMasterCount++ - - analyticsData = { - uuid: user._id, - acquireMethod: 'Gems', - gemCost: 4, - category: 'behavior' - } - analytics?.track('release mounts', analyticsData) - - cb? null, user - - releaseBoth: (req, cb) -> - if user.balance < 1.5 and not user.achievements.triadBingo - return cb? {code:401,message: i18n.t('notEnoughGems', req.language)} - else - giveTriadBingo = true - if not user.achievements.triadBingo - analyticsData = { - uuid: user._id, - acquireMethod: 'Gems', - gemCost: 6, - category: 'behavior' - } - analytics?.track('release pets & mounts', analyticsData) - user.balance -= 1.5 - user.items.currentMount = "" - user.items.currentPet = "" - for animal of content.pets - giveTriadBingo = false if user.items.pets[animal] == -1 - user.items.pets[animal] = 0 - user.items.mounts[animal] = null - if not user.achievements.beastMasterCount - user.achievements.beastMasterCount = 0 - user.achievements.beastMasterCount++ - if not user.achievements.mountMasterCount - user.achievements.mountMasterCount = 0 - user.achievements.mountMasterCount++ - if giveTriadBingo - if not user.achievements.triadBingoCount - user.achievements.triadBingoCount = 0 - user.achievements.triadBingoCount++ - cb? null, user - - # buy is for gear, purchase is for gem-purchaseables (i know, I know...) - buy: (req, cb, analytics) -> - {key} = req.params - - item = if key is 'potion' then content.potion - else if key is 'armoire' then content.armoire - else content.gear.flat[key] - return cb?({code:404, message:"Item '#{key} not found (see https://github.com/HabitRPG/habitrpg/blob/develop/common/script/content/index.coffee)"}) unless item - return cb?({code:401, message: i18n.t('messageNotEnoughGold', req.language)}) if user.stats.gp < item.value - return cb?({code:401, message: "You can't buy this item"}) if item.canOwn? and !item.canOwn(user) - armoireResp = undefined - if item.key is 'potion' - user.stats.hp += 15 - user.stats.hp = 50 if user.stats.hp > 50 - else if item.key is 'armoire' - armoireResult = user.fns.predictableRandom(user.stats.gp) - # We use a different seed to choose the Armoire action than we use - # to choose the sub-action, otherwise only some of the foods can - # be given. E.g., if a seed gives armoireResult < .5 (food) then - # the same seed would give one of the first five foods only. - eligibleEquipment = _.filter(content.gear.flat, ((i)->i.klass is 'armoire' and !user.items.gear.owned[i.key])) - if !_.isEmpty(eligibleEquipment) and (armoireResult < .6 or !user.flags.armoireOpened) - eligibleEquipment.sort() # https://github.com/HabitRPG/habitrpg/issues/5376#issuecomment-111799217 - drop = user.fns.randomVal(eligibleEquipment) - user.items.gear.owned[drop.key] = true - user.flags.armoireOpened = true - message = i18n.t('armoireEquipment', {image: '', dropText: drop.text(req.language)}, req.language) - if api.count.remainingGearInSet(user.items.gear.owned, 'armoire') is 0 then user.flags.armoireEmpty = true - armoireResp = {type: "gear", dropKey: drop.key, dropText: drop.text(req.language)} - else if (!_.isEmpty(eligibleEquipment) and armoireResult < .8) or armoireResult < .5 - drop = user.fns.randomVal _.where(content.food, {canDrop:true}) - user.items.food[drop.key] ?= 0 - user.items.food[drop.key] += 1 - message = i18n.t('armoireFood', {image: '', dropArticle: drop.article, dropText: drop.text(req.language)}, req.language) - armoireResp = {type: "food", dropKey: drop.key, dropArticle: drop.article, dropText: drop.text(req.language)} - else - armoireExp = Math.floor(user.fns.predictableRandom(user.stats.exp) * 40 + 10) - user.stats.exp += armoireExp - message = i18n.t('armoireExp', req.language) - armoireResp = {"type": "experience", "value": armoireExp} - else - if user.preferences.autoEquip then user.items.gear.equipped[item.type] = item.key - user.items.gear.owned[item.key] = true - message = user.fns.handleTwoHanded(item, null, req) - message ?= i18n.t('messageBought', {itemText: item.text(req.language)}, req.language) - if item.last then user.fns.ultimateGear() - user.stats.gp -= item.value - - analyticsData = { - uuid: user._id, - itemKey: key, - acquireMethod: 'Gold', - goldCost: item.value, - category: 'behavior' - } - analytics?.track('acquire item', analyticsData) - - buyResp = _.pick(user,$w 'items achievements stats flags') - buyResp["armoire"] = armoireResp if armoireResp - cb? {code:200, message}, buyResp - - buyQuest: (req, cb, analytics) -> - {key} = req.params - item = content.quests[key] - return cb?({code:404, message:"Quest '#{key} not found (see https://github.com/HabitRPG/habitrpg/blob/develop/common/script/content/index.coffee)"}) unless item - return cb?({code:404, message:"Quest '#{key} is not a Gold-purchasable quest (see https://github.com/HabitRPG/habitrpg/blob/develop/common/script/content/index.coffee)"}) unless item.category is 'gold' and item.goldValue - return cb?({code:401, message: i18n.t('messageNotEnoughGold', req.language)}) if user.stats.gp < item.goldValue - message = i18n.t('messageBought', {itemText: item.text(req.language)}, req.language) - user.items.quests[item.key] ?= 0 - user.items.quests[item.key] += 1 - user.stats.gp -= item.goldValue - analyticsData = { - uuid: user._id, - itemKey: item.key, - itemType: 'Market', - goldCost: item.goldValue, - acquireMethod: 'Gold', - category: 'behavior' - } - analytics?.track('acquire item', analyticsData) - cb? {code:200, message}, user.items.quests - - buyMysterySet: (req, cb, analytics)-> - return cb?({code:401, message:i18n.t('notEnoughHourglasses', req.language)}) unless user.purchased.plan.consecutive.trinkets > 0 - mysterySet = content.timeTravelerStore(user.items.gear.owned)?[req.params.key] - if window?.confirm? - return unless window.confirm(i18n.t('hourglassBuyEquipSetConfirm')) - return cb?({code:404, message:"Mystery set not found, or set already owned"}) unless mysterySet - _.each mysterySet.items, (i)-> - user.items.gear.owned[i.key]=true - analyticsData = { - uuid: user._id, - itemKey: i.key, - itemType: 'Subscriber Gear', - acquireMethod: 'Hourglass', - category: 'behavior' - } - analytics?.track('acquire item', analyticsData) - - user.purchased.plan.consecutive.trinkets-- - cb? {code:200, message:i18n.t('hourglassPurchaseSet', req.language)}, _.pick(user,$w 'items purchased.plan.consecutive') - - hourglassPurchase: (req, cb, analytics)-> - {type, key} = req.params - return cb?({code:403, message:i18n.t('typeNotAllowedHourglass', req.language) + JSON.stringify(_.keys(content.timeTravelStable))}) unless content.timeTravelStable[type] - return cb?({code:403, message:i18n.t(type+'NotAllowedHourglass', req.language)}) unless _.contains(_.keys(content.timeTravelStable[type]), key) - return cb?({code:403, message:i18n.t(type+'AlreadyOwned', req.language)}) if user.items[type][key] - return cb?({code:403, message:i18n.t('notEnoughHourglasses', req.language)}) unless user.purchased.plan.consecutive.trinkets > 0 - user.purchased.plan.consecutive.trinkets-- - if type is 'pets' - user.items.pets[key] = 5 - if type is 'mounts' - user.items.mounts[key] = true - analyticsData = { - uuid: user._id, - itemKey: key, - itemType: type, - acquireMethod: 'Hourglass', - category: 'behavior' - } - analytics?.track('acquire item', analyticsData) - cb? {code:200, message:i18n.t('hourglassPurchase', req.language)}, _.pick(user,$w 'items purchased.plan.consecutive') - - sell: (req, cb) -> - {key, type} = req.params - return cb?({code:404,message:":type not found. Must bes in [eggs, hatchingPotions, food]"}) unless type in ['eggs','hatchingPotions', 'food'] - return cb?({code:404,message:":key not found for user.items.#{type}"}) unless user.items[type][key] - user.items[type][key]-- - user.stats.gp += content[type][key].value - cb? null, _.pick(user,$w 'stats items') - - equip: (req, cb) -> - [type, key] = [req.params.type || 'equipped', req.params.key] - switch type - when 'mount' - return cb?({code:404,message:":You do not own this mount."}) unless user.items.mounts[key] - user.items.currentMount = if user.items.currentMount is key then '' else key - when 'pet' - return cb?({code:404,message:":You do not own this pet."}) unless user.items.pets[key] - user.items.currentPet = if user.items.currentPet is key then '' else key - when 'costume','equipped' - item = content.gear.flat[key] - return cb?({code:404,message:":You do not own this gear."}) unless user.items.gear.owned[key] - if user.items.gear[type][item.type] is key - user.items.gear[type][item.type] = "#{item.type}_base_0" - message = i18n.t('messageUnEquipped', {itemText: item.text(req.language)}, req.language) - else - user.items.gear[type][item.type] = item.key - message = user.fns.handleTwoHanded(item,type,req) - user.markModified? "items.gear.#{type}" - cb? (if message then {code:200,message} else null), user.items - - hatch: (req, cb) -> - {egg, hatchingPotion} = req.params - return cb?({code:400,message:"Please specify query.egg & query.hatchingPotion"}) unless egg and hatchingPotion - return cb?({code:403,message:i18n.t('messageMissingEggPotion', req.language)}) unless user.items.eggs[egg] > 0 and user.items.hatchingPotions[hatchingPotion] > 0 - return cb?({code:403,message:i18n.t('messageInvalidEggPotionCombo', req.language)}) if content.hatchingPotions[hatchingPotion].premium and not content.dropEggs[egg] - pet = "#{egg}-#{hatchingPotion}" - return cb?({code:403, message:i18n.t('messageAlreadyPet', req.language)}) if user.items.pets[pet] and user.items.pets[pet] > 0 - user.items.pets[pet] = 5 - user.items.eggs[egg]-- - user.items.hatchingPotions[hatchingPotion]-- - cb? {code:200, message:i18n.t('messageHatched', req.language)}, user.items - - unlock: (req, cb, analytics) -> - {path} = req.query - fullSet = ~path.indexOf(",") - cost = - # (Backgrounds) 15G per set, 7G per individual - if ~path.indexOf('background.') # FIXME, store prices of things in content/index.coffee instead of hard-coded here? - if fullSet then 3.75 else 1.75 - # (Skin, hair, etc) 5G per set, 2G per individual - else - if fullSet then 1.25 else 0.5 - alreadyOwns = !fullSet and user.fns.dotGet("purchased." + path) is true - return cb?({code:401, message: i18n.t('notEnoughGems', req.language)}) if (user.balance < cost or !user.balance) and !alreadyOwns - if fullSet - _.each path.split(","), (p) -> - if ~path.indexOf('gear.') - user.fns.dotSet("#{p}", true);true - else - user.fns.dotSet("purchased.#{p}", true);true - else - if alreadyOwns - split = path.split('.');v=split.pop();k=split.join('.') - v='' if k is 'background' and v==user.preferences.background - user.fns.dotSet("preferences.#{k}",v) - return cb? null, req - user.fns.dotSet "purchased." + path, true - user.balance -= cost - if ~path.indexOf('gear.') then user.markModified? 'gear.owned' else user.markModified? 'purchased' - - analyticsData = { - uuid: user._id, - itemKey: path, - itemType: 'customization', - acquireMethod: 'Gems', - gemCost: (cost/.25), - category: 'behavior' - } - analytics?.track('acquire item', analyticsData) - - cb? null, _.pick(user,$w 'purchased preferences items') - - # ------ - # Classes - # ------ - - changeClass: (req, cb, analytics) -> - klass = req.query?.class - if klass in ['warrior','rogue','wizard','healer'] - - analyticsData = { - uuid: user._id, - class: klass, - acquireMethod: 'Gems', - gemCost: 3, - category: 'behavior' - } - analytics?.track('change class', analyticsData) - - user.stats.class = klass - user.flags.classSelected = true - # Clear their gear and equip their new class's gear (can still equip old gear from inventory) - # If they've rolled this class before, restore their progress - _.each ["weapon", "armor", "shield", "head"], (type) -> - foundKey = false - _.findLast user.items.gear.owned, (v, k) -> - return foundKey = k if ~k.indexOf(type + "_" + klass) and v is true - # restore progress from when they last rolled this class - # weapon_0 is significant, don't reset to base_0 - # rogues start with an off-hand weapon - user.items.gear.equipped[type] = - if foundKey then foundKey - else if type is "weapon" then "weapon_#{klass}_0" - else if type is "shield" and klass is "rogue" then "shield_rogue_0" - else "#{type}_base_0" # naked for the rest! - - # Grant them their new class's gear - user.items.gear.owned["#{type}_#{klass}_0"] = true if type is "weapon" or (type is "shield" and klass is "rogue") - true - else - # Null ?class value means "reset class" - if user.preferences.disableClasses - user.preferences.disableClasses = false - user.preferences.autoAllocate = false - else - return cb?({code:401,message:i18n.t('notEnoughGems', req.language)}) unless user.balance >= .75 - user.balance -= .75 - _.merge user.stats, {str: 0, con: 0, per: 0, int: 0, points: api.capByLevel(user.stats.lvl)} - user.flags.classSelected = false - #'stats.points': this is handled on the server - cb? null, _.pick(user,$w 'stats flags items preferences') - - disableClasses: (req, cb) -> - user.stats.class = 'warrior' - user.flags.classSelected = true - user.preferences.disableClasses = true - user.preferences.autoAllocate = true - user.stats.str = api.capByLevel(user.stats.lvl) - user.stats.points = 0 - cb? null, _.pick(user,$w 'stats flags preferences') - - allocate: (req, cb) -> - stat = req.query.stat or 'str' - if user.stats.points > 0 - user.stats[stat]++ - user.stats.points-- - user.stats.mp++ if stat is 'int' #increase their MP along with their max MP - cb? null, _.pick(user,$w 'stats') - - readCard: (req, cb) -> - {cardType} = req.params - user.items.special["#{cardType}Received"].shift() - user.markModified? "items.special.#{cardType}Received" - user.flags.cardReceived = false - cb? null, 'items.special flags.cardReceived' - - openMysteryItem: (req,cb,analytics) -> - item = user.purchased.plan?.mysteryItems?.shift() - return cb?(code:400,message:"Empty") unless item - item = content.gear.flat[item] - user.items.gear.owned[item.key] = true - user.markModified? 'purchased.plan.mysteryItems' - item.notificationType = 'Mystery' # needed for website/public/js/controllers/notificationCtrl.js line 59 approx. - analyticsData = { - uuid: user._id, - itemKey: item, - itemType: 'Subscriber Gear', - acquireMethod: 'Subscriber', - category: 'behavior' - } - analytics?.track('open mystery item', analyticsData) - (user._tmp?={}).drop = item if typeof window != 'undefined' - cb? null, user.items.gear.owned - - # ------ - # Score - # ------ - - score: (req, cb) -> - {id, direction} = req.params # up or down - task = user.tasks[id] - options = req.query or {}; _.defaults(options, {times:1, cron:false}) - - # This is for setting one-time temporary flags, such as streakBonus or itemDropped. Useful for notifying - # the API consumer, then cleared afterwards - user._tmp = {} - - # TODO do we need this fail-safe casting anymore? Are we safe now we're off Derby? - stats = {gp: +user.stats.gp, hp: +user.stats.hp, exp: +user.stats.exp} - task.value = +task.value; task.streak = ~~task.streak; task.priority ?= 1 - - # If they're trying to purhcase a too-expensive reward, don't allow them to do that. - if task.value > stats.gp and task.type is 'reward' - return cb? {code:401,message:i18n.t('messageNotEnoughGold', req.language)} - - delta = 0 - - calculateDelta = -> - # Calculates the next task.value based on direction - # Uses a capped inverse log y=.95^x, y>= -5 - - # Min/max on task redness - currVal = - if task.value < -47.27 then -47.27 - else if task.value > 21.27 then 21.27 - else task.value - nextDelta = Math.pow(0.9747, currVal) * (if direction is 'down' then -1 else 1) - - # Checklists - if task.checklist?.length > 0 - # If the Daily, only dock them them a portion based on their checklist completion - if direction is 'down' and task.type is 'daily' and options.cron - nextDelta *= (1 - _.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),0) / task.checklist.length) - # If To-Do, point-match the TD per checklist item completed - if task.type is 'todo' - nextDelta *= (1 + _.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),0)) - nextDelta - - calculateReverseDelta = -> - # Approximates the reverse delta for the task value - # This is meant to return the task value to its original value when unchecking a task. - # First, calculate the the value using the normal way for our first guess although - # it will be a bit off - currVal = - if task.value < -47.27 then -47.27 - else if task.value > 21.27 then 21.27 - else task.value - testVal = currVal + Math.pow(0.9747, currVal) * (if direction is 'down' then -1 else 1) - - # Now keep moving closer to the original value until we get "close enough" - closeEnough = 0.00001 - while true - # Check how close we are to the original value by computing the delta off our guess - # and looking at the difference between that and our current value. - calc = (testVal) + Math.pow(0.9747, testVal) - diff = currVal-calc - if Math.abs(diff) < closeEnough - break - if diff > 0 - testVal -= diff - else - testVal += diff - - # When we get close enough, return the difference between our approximated value - # and the current value. This will be the delta calculated from the original value - # before the task was checked. - nextDelta = testVal - currVal - - # Checklists - if task.checklist?.length > 0 - # If To-Do, point-match the TD per checklist item completed - if task.type is 'todo' - nextDelta *= (1 + _.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),0)) - nextDelta - - - changeTaskValue = -> - # If multiple days have passed, multiply times days missed - _.times options.times, -> - # Each iteration calculate the nextDelta, which is then accumulated in the total delta. - nextDelta = if not options.cron and direction is 'down' then calculateReverseDelta() else calculateDelta() - unless task.type is 'reward' - if (user.preferences.automaticAllocation is true and user.preferences.allocationMode is 'taskbased' and !(task.type is 'todo' and direction is 'down')) then user.stats.training[task.attribute] += nextDelta - if direction is 'up' # Make progress on quest based on STR - user.party.quest.progress.up = user.party.quest.progress.up || 0 - user.party.quest.progress.up += (nextDelta * (1 + (user._statsComputed.str / 200))) if task.type in ['daily','todo'] - user.party.quest.progress.up += (nextDelta * (0.5 + (user._statsComputed.str / 400))) if task.type is 'habit' - task.value += nextDelta - delta += nextDelta - - addPoints = -> - # ===== CRITICAL HITS ===== - # allow critical hit only when checking off a task, not when unchecking it: - _crit = (if delta > 0 then user.fns.crit() else 1) - # if there was a crit, alert the user via notification - user._tmp.crit = _crit if _crit > 1 - - # Exp Modifier - # ===== Intelligence ===== - # TODO Increases Experience gain by .2% per point. - intBonus = 1 + (user._statsComputed.int * .025) - stats.exp += Math.round (delta * intBonus * task.priority * _crit * 6) - - # GP modifier - # ===== PERCEPTION ===== - # TODO Increases Gold gained from tasks by .3% per point. - perBonus = (1 + user._statsComputed.per *.02) - gpMod = (delta * task.priority * _crit * perBonus) - stats.gp += - if task.streak - currStreak = if direction is 'down' then task.streak-1 else task.streak - streakBonus = currStreak / 100 + 1 # eg, 1-day streak is 1.01, 2-day is 1.02, etc - afterStreak = gpMod * streakBonus - if currStreak > 0 - user._tmp.streakBonus = afterStreak - gpMod if (gpMod > 0) # keep this on-hand for later, so we can notify streak-bonus - afterStreak - else gpMod - - # HP modifier - subtractPoints = -> - # ===== CONSTITUTION ===== - # TODO Decreases HP loss from bad habits / missed dailies by 0.5% per point. - conBonus = 1 - (user._statsComputed.con / 250) - conBonus = 0.1 if conBonus < .1 - hpMod = delta * conBonus * task.priority * 2 # constant 2 multiplier for better results - stats.hp += Math.round(hpMod * 10) / 10 # round to 1dp - - gainMP = (delta) -> - delta *= user._tmp.crit or 1 - user.stats.mp += delta - user.stats.mp = user._statsComputed.maxMP if user.stats.mp >= user._statsComputed.maxMP - user.stats.mp = 0 if user.stats.mp < 0 - - # ===== starting to actually do stuff, most of above was definitions ===== - switch task.type - when 'habit' - changeTaskValue() - # Add habit value to habit-history (if different) - if (delta > 0) then addPoints() else subtractPoints() - gainMP(_.max([0.25, (.0025 * user._statsComputed.maxMP)]) * if direction is 'down' then -1 else 1) - - # History - th = (task.history ?= []) - if th[th.length-1] and moment(th[th.length-1].date).isSame(new Date, 'day') - th[th.length-1].value = task.value - else - th.push {date: +new Date, value: task.value} - user.markModified? "habits.#{_.findIndex(user.habits, {id:task.id})}.history" - - when 'daily' - if options.cron - changeTaskValue() - subtractPoints() - task.streak = 0 unless user.stats.buffs.streaks - else - changeTaskValue() - if direction is 'down' - delta = calculateDelta() # recalculate delta for unchecking so the gp and exp come out correctly - addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes - gainMP(_.max([1, (.01 * user._statsComputed.maxMP)]) * if direction is 'down' then -1 else 1) - if direction is 'up' - task.streak = if task.streak then task.streak + 1 else 1 - # Give a streak achievement when the streak is a multiple of 21 - if (task.streak % 21) is 0 - user.achievements.streak = if user.achievements.streak then user.achievements.streak + 1 else 1 - else - # Remove a streak achievement if streak was a multiple of 21 and the daily was undone - if (task.streak % 21) is 0 - user.achievements.streak = if user.achievements.streak then user.achievements.streak - 1 else 0 - task.streak = if task.streak then task.streak - 1 else 0 - - when 'todo' - if options.cron - changeTaskValue() - #don't touch stats on cron - else - task.dateCompleted = if direction is 'up' then new Date else undefined - changeTaskValue() - if direction is 'down' - delta = calculateDelta() # recalculate delta for unchecking so the gp and exp come out correctly - addPoints() # obviously for delta>0, but also a trick to undo accidental checkboxes - # MP++ per checklist item in ToDo, bonus per CLI - multiplier = _.max([(_.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),1)),1]) - gainMP(_.max([(multiplier), (.01 * user._statsComputed.maxMP * multiplier)]) * if direction is 'down' then -1 else 1) - - when 'reward' - # Don't adjust values for rewards - changeTaskValue() - # purchase item - stats.gp -= Math.abs(task.value) - num = parseFloat(task.value).toFixed(2) - # if too expensive, reduce health & zero gp - if stats.gp < 0 - # hp - gp difference - stats.hp += stats.gp - stats.gp = 0 - - user.fns.updateStats stats, req - - # Drop system (don't run on the client, as it would only be discarded since ops are sent to the API, not the results) - if typeof window is 'undefined' - user.fns.randomDrop({task, delta}, req) if direction is 'up' - - cb? null, user - return delta - - # ---------------------------------------------------------------------- - # user.fns helpers - # ---------------------------------------------------------------------- - - user.fns = - - getItem: (type) -> - item = content.gear.flat[user.items.gear.equipped[type]] - return content.gear.flat["#{type}_base_0"] unless item - item - - handleTwoHanded: (item, type='equipped', req) -> - # If they're buying a shield and wearing a staff, dequip the staff - if item.type is "shield" and (weapon = content.gear.flat[user.items.gear[type].weapon])?.twoHanded - user.items.gear[type].weapon = 'weapon_base_0' - message = i18n.t('messageTwoHandled', {gearText: weapon.text(req.language)}, req.language) - # If they're buying a staff and wearing a shield, dequip the shield - if item.twoHanded - user.items.gear[type].shield = "shield_base_0" - message = i18n.t('messageTwoHandled', {gearText: item.text(req.language)}, req.language) - message - - ### - Because the same op needs to be performed on the client and the server (critical hits, item drops, etc), - we need things to be "random", but technically predictable so that they don't go out-of-sync - ### - predictableRandom: (seed) -> - # Default seed is all user stats combined. Fairly safe, meh - pass in a good seed for situations where that doesn't work - seed = _.reduce(user.stats, ((m,v)->if _.isNumber(v) then m+v else m), 0) if !seed or seed is Math.PI - x = Math.sin(seed++) * 10000 - x - Math.floor(x) - - crit: (stat='str', chance=.03) -> - #console.log("Crit Chance:"+chance*(1+user._statsComputed[stat]/100)) - s = user._statsComputed[stat] - if user.fns.predictableRandom() <= chance*(1 + s/100) - 1.5 + 4*s/(s + 200) - else 1 - - ### - Get a random property from an object - returns random property (the value) - ### - randomVal: (obj, options) -> - array = if options?.key then _.keys(obj) else _.values(obj) - rand = user.fns.predictableRandom(options?.seed) - array.sort() - array[Math.floor(rand * array.length)] - - ### - This allows you to set object properties by dot-path. Eg, you can run pathSet('stats.hp',50,user) which is the same as - user.stats.hp = 50. This is useful because in our habitrpg-shared functions we're returning changesets as {path:value}, - so that different consumers can implement setters their own way. Derby needs model.set(path, value) for example, where - Angular sets object properties directly - in which case, this function will be used. - ### - dotSet: (path, val)-> api.dotSet user,path,val - dotGet: (path)-> api.dotGet user,path - - # ---------------------------------------------------------------------- - # Scoring - # ---------------------------------------------------------------------- - - randomDrop: (modifiers, req) -> - {task} = modifiers - - # % chance of getting a drop - - chance = _.min([Math.abs(task.value - 21.27),37.5])/150+.02 # Base drop chance is a percentage based on task value. Typical fresh task: 15%. Very ripe task: 25%. Very blue task: 2%. - - chance *= - task.priority * # Task priority: +50% for Medium, +100% for Hard - (1 + (task.streak / 100 or 0)) * # Streak bonus: +1% per streak - (1 + (user._statsComputed.per / 100)) * # PERception: +1% per point - (1 + (user.contributor.level / 40 or 0)) * # Contrib levels: +2.5% per level - (1 + (user.achievements.rebirths / 20 or 0)) * # Rebirths: +5% per achievement - (1 + (user.achievements.streak / 200 or 0)) * # Streak achievements: +0.5% per achievement - (user._tmp.crit or 1) * # Use the crit multiplier if we got one - (1 + .5*(_.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),0) or 0)) # +50% per checklist item complete. TODO: make this into X individual drop chances instead - - chance = api.diminishingReturns(chance, 0.75) - - #console.log("Drop chance: " + chance) - - quest = content.quests[user.party.quest?.key] - if quest?.collect and user.fns.predictableRandom(user.stats.gp) < chance - dropK = user.fns.randomVal quest.collect, {key:true} - user.party.quest.progress.collect[dropK]++ - user.markModified? 'party.quest.progress' - #console.log {progress:user.party.quest.progress} - - dropMultiplier = if user.purchased?.plan?.customerId then 2 else 1 - return if (api.daysSince(user.items.lastDrop.date, user.preferences) is 0) and (user.items.lastDrop.count >= dropMultiplier * (5 + Math.floor(user._statsComputed.per / 25) + (user.contributor.level or 0))) - if user.flags?.dropsEnabled and user.fns.predictableRandom(user.stats.exp) < chance - - rarity = user.fns.predictableRandom(user.stats.gp) - - # Food: 40% chance - if rarity > .6 - drop = user.fns.randomVal _.where(content.food, {canDrop:true}) - user.items.food[drop.key] ?= 0 - user.items.food[drop.key]+= 1 - drop.type = 'Food' - drop.dialog = i18n.t('messageDropFood', {dropArticle: drop.article, dropText: drop.text(req.language), dropNotes: drop.notes(req.language)}, req.language) - - # Eggs: 30% chance - else if rarity > .3 - drop = user.fns.randomVal content.dropEggs - user.items.eggs[drop.key] ?= 0 - user.items.eggs[drop.key]++ - drop.type = 'Egg' - drop.dialog = i18n.t('messageDropEgg', {dropText: drop.text(req.language), dropNotes: drop.notes(req.language)}, req.language) - - # Hatching Potion, 30% chance - break down by rarity. - else - acceptableDrops = - # Very Rare: 10% (of 30%) - if rarity < .02 then ['Golden'] - # Rare: 20% (of 30%) - else if rarity < .09 then ['Zombie', 'CottonCandyPink', 'CottonCandyBlue'] - # Uncommon: 30% (of 30%) - else if rarity < .18 then ['Red', 'Shade', 'Skeleton'] - # Common: 40% (of 30%) - else ['Base', 'White', 'Desert'] - - # No Rarity (@see https://github.com/HabitRPG/habitrpg/issues/1048, we may want to remove rareness when we add mounts) - #drop = helpers.randomVal hatchingPotions - drop = user.fns.randomVal _.pick(content.hatchingPotions, ((v,k) -> k in acceptableDrops)) - - user.items.hatchingPotions[drop.key] ?= 0 - user.items.hatchingPotions[drop.key]++ - drop.type = 'HatchingPotion' - drop.dialog = i18n.t('messageDropPotion', {dropText: drop.text(req.language), dropNotes: drop.notes(req.language)}, req.language) - - # if they've dropped something, we want the consuming client to know so they can notify the user. See how the Derby - # app handles it for example. Would this be better handled as an emit() ? - user._tmp.drop = drop - - user.items.lastDrop.date = +new Date - user.items.lastDrop.count++ - - ### - Updates user stats with new stats. Handles death, leveling up, etc - {stats} new stats - {update} if aggregated changes, pass in userObj as update. otherwise commits will be made immediately - ### - autoAllocate: -> - user.stats[(-> - switch user.preferences.allocationMode - when "flat" - # Favor in order (right-to-left): INT, PER, STR, CON - stats = _.pick user.stats, $w 'con str per int' - _.invert(stats)[_.min stats] - when "classbased" - # Attributes get 3:2:1:1 per 7 levels. - lvlDiv7 = user.stats.lvl / 7 - ideal = [(lvlDiv7 * 3), (lvlDiv7 * 2), lvlDiv7, lvlDiv7] - # Primary, secondary etc. attributes aren't explicitly defined, so hardcode them. In order as above - preference = switch user.stats.class - when "wizard" then ["int", "per", "con", "str"] - when "rogue" then ["per", "str", "int", "con"] - when "healer" then ["con", "int", "str", "per"] - else ["str", "con", "per", "int"] - # Get the difference between the ideal attribute spread according to level, and the user's current spread. - diff = [(user.stats[preference[0]]-ideal[0]),(user.stats[preference[1]]-ideal[1]),(user.stats[preference[2]]-ideal[2]),(user.stats[preference[3]]-ideal[3])] - suggested = _.findIndex(diff, ((val) -> if val is _.min(diff) then true)) # Returns the index of the first attribute that's furthest behind the ideal - return if ~suggested then preference[suggested] else "str" # If _.findIndex failed, we'd get a -1... - when "taskbased" - suggested = _.invert(user.stats.training)[_.max user.stats.training] # Returns the stat that's been trained up the most this level - _.merge user.stats.training, {str:0,int:0,con:0,per:0} # Reset training for this level. - return suggested or "str" # Failed _.findkey gives undefined - else "str" # if all else fails, dump into STR - )()]++ - - updateStats: (stats, req, analytics) -> - # Game Over (death) - return user.stats.hp=0 if stats.hp <= 0 - - user.stats.hp = stats.hp - user.stats.gp = if stats.gp >= 0 then stats.gp else 0 - - tnl = api.tnl(user.stats.lvl) - - # level up & carry-over exp - if stats.exp >= tnl - #silent = true # push through the negative xp silently - user.stats.exp = stats.exp # push normal + notification - while stats.exp >= tnl # keep levelling up - stats.exp -= tnl - user.stats.lvl++ - tnl = api.tnl(user.stats.lvl) - - user.stats.hp = 50 - - continue if user.stats.lvl > api.maxLevel - - # Auto-allocate a point, or give them a new manual point - if user.preferences.automaticAllocation - user.fns.autoAllocate() - else - # add new allocatable points. We could do user.stats.points++, but this does a fail-safe just in case - user.stats.points = user.stats.lvl - (user.stats.con + user.stats.str + user.stats.per + user.stats.int) - if user.stats.points < 0 - user.stats.points = 0 - # This happens after dropping level with Fix Character Values and perhaps from other causes. - # TODO: Subtract points from attributes in the same manner as on death. - user.stats.exp = stats.exp - - # Set flags when they unlock features - user.flags ?= {} - if !user.flags.customizationsNotification and (user.stats.exp > 5 or user.stats.lvl > 1) - user.flags.customizationsNotification = true - if !user.flags.itemsEnabled and (user.stats.exp > 10 or user.stats.lvl > 1) - user.flags.itemsEnabled = true - if !user.flags.dropsEnabled and user.stats.lvl >= 3 - user.flags.dropsEnabled = true - if user.items.eggs["Wolf"] > 0 then user.items.eggs["Wolf"]++ else user.items.eggs["Wolf"] = 1 - if !user.flags.classSelected and user.stats.lvl >= 10 - user.flags.classSelected - # Level Drops - _.each {vice1:30, atom1:15, moonstone1:60, goldenknight1: 40}, (lvl,k)-> - if !user.flags.levelDrops?[k] and user.stats.lvl >= lvl - user.items.quests[k] ?= 0 - user.items.quests[k]++ - (user.flags.levelDrops ?= {})[k] = true - user.markModified? 'flags.levelDrops' - analyticsData = { - uuid: user._id, - itemKey: k, - acquireMethod: 'Level Drop', - category: 'behavior' - } - analytics?.track('acquire item', analyticsData) - user._tmp.drop = {type: 'Quest', key: k} - if !user.flags.rebirthEnabled and (user.stats.lvl >= 50 or user.achievements.beastMaster) - user.flags.rebirthEnabled = true - - ### - ------------------------------------------------------ - Cron - ------------------------------------------------------ - ### - - ### - At end of day, add value to all incomplete Daily & Todo tasks (further incentive) - For incomplete Dailys, deduct experience - Make sure to run this function once in a while as server will not take care of overnight calculations. - And you have to run it every time client connects. - {user} - ### - cron: (options={}) -> - now = +options.now || +new Date - - daysMissed = api.daysSince user.lastCron, _.defaults({now}, user.preferences) - return unless daysMissed > 0 - - user.auth.timestamps.loggedin = new Date() - - user.lastCron = now - - # Reset the lastDrop count to zero - if user.items.lastDrop.count > 0 - user.items.lastDrop.count = 0 - - # "Perfect Day" achievement for perfect-days - perfect = true - clearBuffs = {str:0,int:0,per:0,con:0,stealth:0,streaks:false} - - # end-of-month perks for subscribers - plan = user.purchased?.plan - if plan?.customerId - if moment(plan.dateUpdated).format('MMYYYY') != moment().format('MMYYYY') - plan.gemsBought = 0 # reset gem-cap - plan.dateUpdated = new Date() - # For every month, inc their "consecutive months" counter. Give perks based on consecutive blocks - # If they already got perks for those blocks (eg, 6mo subscription, subscription gifts, etc) - then dec the offset until it hits 0 - # TODO use month diff instead of ++ / --? - _.defaults plan.consecutive, {count:0, offset:0, trinkets:0, gemCapExtra:0} #fixme see https://github.com/HabitRPG/habitrpg/issues/4317 - plan.consecutive.count++ - if plan.consecutive.offset > 0 - plan.consecutive.offset-- - else if plan.consecutive.count%3==0 # every 3 months - plan.consecutive.trinkets++ - plan.consecutive.gemCapExtra+=5 - plan.consecutive.gemCapExtra=25 if plan.consecutive.gemCapExtra>25 # cap it at 50 (hard 25 limit + extra 25) - # If user cancelled subscription, we give them until 30day's end until it terminates - if plan.dateTerminated && moment(plan.dateTerminated).isBefore(+new Date) - _.merge plan, {planId:null, customerId:null, paymentMethod:null} - _.merge plan.consecutive, {count:0, offset:0, gemCapExtra:0} - user.markModified? 'purchased.plan' - - # User is resting at the inn. - # On cron, buffs are cleared and all dailies are reset without performing damage - if user.preferences.sleep is true - user.stats.buffs = clearBuffs - user.dailys.forEach (daily) -> - {completed, repeat} = daily - thatDay = moment(now).subtract({days: 1}) - - if api.shouldDo(thatDay.toDate(), daily, user.preferences) || completed - _.each daily.checklist, ((box)->box.completed=false;true) - daily.completed = false - return - - multiDaysCountAsOneDay = true - # If the user does not log in for two or more days, cron (mostly) acts as if it were only one day. - # When site-wide difficulty settings are introduced, this can be a user preference option. - - # Tally each task - todoTally = 0 - user.todos.forEach (task) -> # make uncompleted todos redder - return unless task - {id, completed} = task - delta = user.ops.score({params:{id:task.id, direction:'down'}, query:{times:(multiDaysCountAsOneDay ? 1 : daysMissed), cron:true}}) - absVal = if (completed) then Math.abs(task.value) else task.value - todoTally += absVal - - dailyChecked = 0 # how many dailies were checked? - dailyDueUnchecked = 0 # how many dailies were due but not checked? - user.party.quest.progress.down ?= 0 - user.dailys.forEach (task) -> - return unless task - {id, completed} = task - - # Deduct points for missed Daily tasks - EvadeTask = 0 - scheduleMisses = daysMissed - if completed - dailyChecked += 1 - else - # dailys repeat, so need to calculate how many they've missed according to their own schedule - scheduleMisses = 0 - for n in [0...daysMissed] - thatDay = moment(now).subtract({days: n + 1}) - if api.shouldDo(thatDay.toDate(), task, user.preferences) - scheduleMisses++ - if user.stats.buffs.stealth - user.stats.buffs.stealth-- - EvadeTask++ - if multiDaysCountAsOneDay - break - - if scheduleMisses > EvadeTask - perfect = false - if task.checklist?.length > 0 # Partially completed checklists dock fewer mana points - fractionChecked = _.reduce(task.checklist,((m,i)->m+(if i.completed then 1 else 0)),0) / task.checklist.length - dailyDueUnchecked += (1 - fractionChecked) - dailyChecked += fractionChecked - else - dailyDueUnchecked += 1 - delta = user.ops.score({params:{id:task.id, direction:'down'}, query:{times:(multiDaysCountAsOneDay ? 1 : (scheduleMisses-EvadeTask)), cron:true}}) - - # Apply damage from a boss, less damage for Trivial priority (difficulty) - user.party.quest.progress.down += delta * (if task.priority < 1 then task.priority else 1) - # NB: Medium and Hard priorities do not increase damage from boss. This was by accident - # initially, and when we realised, we could not fix it because users are used to - # their Medium and Hard Dailies doing an Easy amount of damage from boss. - # Easy is task.priority = 1. Anything < 1 will be Trivial (0.1) or any future - # setting between Trivial and Easy. - - (task.history ?= []).push({ date: +new Date, value: task.value }) - task.completed = false - if completed || (scheduleMisses > 0) - _.each task.checklist, ((i)->i.completed=false;true) # this should not happen for grey tasks unless they are completed - - user.habits.forEach (task) -> # slowly reset 'onlies' value to 0 - if task.up is false or task.down is false - if Math.abs(task.value) < 0.1 - task.value = 0 - else - task.value = task.value / 2 - - # Finished tallying - ((user.history ?= {}).todos ?= []).push { date: now, value: todoTally } - # tally experience - expTally = user.stats.exp - lvl = 0 #iterator - while lvl < (user.stats.lvl - 1) - lvl++ - expTally += api.tnl(lvl) - (user.history.exp ?= []).push { date: now, value: expTally } - - # premium subscribers can keep their full history. - # TODO figure out something performance-wise - unless user.purchased?.plan?.customerId - user.fns.preenUserHistory() - user.markModified? 'history' - user.markModified? 'dailys' # covers dailys.*.history - - user.stats.buffs = - if perfect - user.achievements.perfect ?= 0 - user.achievements.perfect++ - lvlDiv2 = Math.ceil(api.capByLevel(user.stats.lvl) / 2) - {str:lvlDiv2,int:lvlDiv2,per:lvlDiv2,con:lvlDiv2,stealth:0,streaks:false} - else clearBuffs - - # Add 10 MP, or 10% of max MP if that'd be more. Perform this after Perfect Day for maximum benefit - # Adjust for fraction of dailies completed - dailyChecked=1 if dailyDueUnchecked is 0 and dailyChecked is 0 - user.stats.mp += _.max([10,.1 * user._statsComputed.maxMP]) * dailyChecked / (dailyDueUnchecked + dailyChecked) - user.stats.mp = user._statsComputed.maxMP if user.stats.mp > user._statsComputed.maxMP - - # After all is said and done, progress up user's effect on quest, return those values & reset the user's - progress = user.party.quest.progress; _progress = _.cloneDeep progress - _.merge progress, {down:0,up:0} - progress.collect = _.transform progress.collect, ((m,v,k)->m[k]=0) - - # Analytics - user.flags.cronCount?=0 - user.flags.cronCount++ - - analyticsData = { - category: 'behavior', - gaLabel: 'Cron Count', - gaValue: user.flags.cronCount, - uuid: user._id, - user: user, - resting: user.preferences.sleep, - cronCount: user.flags.cronCount, - progressUp: _.min([_progress.up, 900]), - progressDown: _progress.down - } - options.analytics?.track('Cron', analyticsData) - - _progress - - # Registered users with some history - preenUserHistory: (minHistLen = 7) -> - _.each user.habits.concat(user.dailys), (task) -> - task.history = preenHistory(task.history) if task.history?.length > minHistLen - true - - _.defaults user.history, {todos:[], exp: []} - user.history.exp = preenHistory(user.history.exp) if user.history.exp.length > minHistLen - user.history.todos = preenHistory(user.history.todos) if user.history.todos.length > minHistLen - #user.markModified? 'history' - #user.markModified? 'habits' - #user.markModified? 'dailys' - - # ---------------------------------------------------------------------- - # Achievements - # ---------------------------------------------------------------------- - ultimateGear: -> - # on the server this is a Lodash transform, on the client its an object - owned = if window? then user.items.gear.owned else user.items.gear.owned.toObject() - user.achievements.ultimateGearSets ?= {healer: false, wizard: false, rogue: false, warrior: false} - content.classes.forEach (klass) -> - if user.achievements.ultimateGearSets[klass] isnt true - user.achievements.ultimateGearSets[klass] = _.reduce ['armor', 'shield', 'head', 'weapon'], (soFarGood, type) -> - found = _.find content.gear.tree[type][klass], {last:true} - soFarGood and (!found or owned[found.key]==true) #!found only true when weapon is two-handed (mages) - , true # start with true, else `and` will fail right away - user.markModified? 'achievements.ultimateGearSets' - if _.contains(user.achievements.ultimateGearSets, true) and user.flags.armoireEnabled != true - user.flags.armoireEnabled = true - user.markModified? 'flags' - - nullify: -> - user.ops = null - user.fns = null - user = null - - # ---------------------------------------------------------------------- - # Virtual Attributes - # ---------------------------------------------------------------------- - - # Aggregate all intrinsic stats, buffs, weapon, & armor into computed stats - Object.defineProperty user, '_statsComputed', - get: -> - computed = _.reduce ['per','con','str','int'], (m,stat) => - m[stat] = _.reduce $w('stats stats.buffs items.gear.equipped.weapon items.gear.equipped.armor items.gear.equipped.head items.gear.equipped.shield'), (m2,path) => - val = user.fns.dotGet(path) - m2 + - if ~path.indexOf('items.gear') - # get the gear stat, and multiply it by 1.5 if it's class-gear - item = content.gear.flat[val] - (+item?[stat] or 0) * (if item?.klass is user.stats.class || item?.specialClass is user.stats.class then 1.5 else 1) - else - +val[stat] or 0 - , 0 - m[stat] += Math.floor(api.capByLevel(user.stats.lvl) / 2) - m - , {} - computed.maxMP = computed.int*2 + 30 - computed - Object.defineProperty user, 'tasks', - get: -> - tasks = user.habits.concat(user.dailys).concat(user.todos).concat(user.rewards) - _.object(_.pluck(tasks, "id"), tasks) diff --git a/common/script/index.js b/common/script/index.js new file mode 100644 index 0000000000..6a3558f937 --- /dev/null +++ b/common/script/index.js @@ -0,0 +1,2864 @@ +var $w, _, api, content, i18n, moment, preenHistory, sanitizeOptions, sortOrder, + indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + +moment = require('moment'); + +_ = require('lodash'); + +content = require('./content/index'); + +i18n = require('./i18n'); + +api = module.exports = {}; + +api.i18n = i18n; + +$w = api.$w = function(s) { + return s.split(' '); +}; + +api.dotSet = function(obj, path, val) { + var arr; + arr = path.split('.'); + return _.reduce(arr, (function(_this) { + return function(curr, next, index) { + if ((arr.length - 1) === index) { + curr[next] = val; + } + return curr[next] != null ? curr[next] : curr[next] = {}; + }; + })(this), obj); +}; + +api.dotGet = function(obj, path) { + return _.reduce(path.split('.'), ((function(_this) { + return function(curr, next) { + return curr != null ? curr[next] : void 0; + }; + })(this)), obj); +}; + + +/* + Reflists are arrays, but stored as objects. Mongoose has a helluvatime working with arrays (the main problem for our + syncing issues) - so the goal is to move away from arrays to objects, since mongoose can reference elements by ID + no problem. To maintain sorting, we use these helper functions: + */ + +api.refPush = function(reflist, item, prune) { + if (prune == null) { + prune = 0; + } + item.sort = _.isEmpty(reflist) ? 0 : _.max(reflist, 'sort').sort + 1; + if (!(item.id && !reflist[item.id])) { + item.id = api.uuid(); + } + return reflist[item.id] = item; +}; + +api.planGemLimits = { + convRate: 20, + convCap: 25 +}; + + +/* + ------------------------------------------------------ + Time / Day + ------------------------------------------------------ + */ + + +/* + Each time we're performing date math (cron, task-due-days, etc), we need to take user preferences into consideration. + Specifically {dayStart} (custom day start) and {timezoneOffset}. This function sanitizes / defaults those values. + {now} is also passed in for various purposes, one example being the test scripts scripts testing different "now" times + */ + +sanitizeOptions = function(o) { + var dayStart, now, ref, timezoneOffset; + dayStart = !_.isNaN(+o.dayStart) && (0 <= (ref = +o.dayStart) && ref <= 24) ? +o.dayStart : 0; + timezoneOffset = o.timezoneOffset ? +o.timezoneOffset : +moment().zone(); + now = o.now ? moment(o.now).zone(timezoneOffset) : moment(+(new Date)).zone(timezoneOffset); + return { + dayStart: dayStart, + timezoneOffset: timezoneOffset, + now: now + }; +}; + +api.startOfWeek = api.startOfWeek = function(options) { + var o; + if (options == null) { + options = {}; + } + o = sanitizeOptions(options); + return moment(o.now).startOf('week'); +}; + +api.startOfDay = function(options) { + var dayStart, o; + if (options == null) { + options = {}; + } + o = sanitizeOptions(options); + dayStart = moment(o.now).startOf('day').add({ + hours: o.dayStart + }); + if (moment(o.now).hour() < o.dayStart) { + dayStart.subtract({ + days: 1 + }); + } + return dayStart; +}; + +api.dayMapping = { + 0: 'su', + 1: 'm', + 2: 't', + 3: 'w', + 4: 'th', + 5: 'f', + 6: 's' +}; + + +/* + Absolute diff from "yesterday" till now + */ + +api.daysSince = function(yesterday, options) { + var o; + if (options == null) { + options = {}; + } + o = sanitizeOptions(options); + return api.startOfDay(_.defaults({ + now: o.now + }, o)).diff(api.startOfDay(_.defaults({ + now: yesterday + }, o)), 'days'); +}; + + +/* + Should the user do this task on this date, given the task's repeat options and user.preferences.dayStart? + */ + +api.shouldDo = function(day, dailyTask, options) { + var dayOfWeekCheck, dayOfWeekNum, daysSinceTaskStart, everyXCheck, o, startOfDayWithCDSTime, taskStartDate; + if (options == null) { + options = {}; + } + if (dailyTask.type !== 'daily') { + return false; + } + o = sanitizeOptions(options); + startOfDayWithCDSTime = api.startOfDay(_.defaults({ + now: day + }, o)); + taskStartDate = moment(dailyTask.startDate).zone(o.timezoneOffset); + taskStartDate = moment(taskStartDate).startOf('day'); + if (taskStartDate > startOfDayWithCDSTime.startOf('day')) { + return false; + } + if (dailyTask.frequency === 'daily') { + if (!dailyTask.everyX) { + return false; + } + daysSinceTaskStart = startOfDayWithCDSTime.startOf('day').diff(taskStartDate, 'days'); + everyXCheck = daysSinceTaskStart % dailyTask.everyX === 0; + return everyXCheck; + } else if (dailyTask.frequency === 'weekly') { + if (!dailyTask.repeat) { + return false; + } + dayOfWeekNum = startOfDayWithCDSTime.day(); + dayOfWeekCheck = dailyTask.repeat[api.dayMapping[dayOfWeekNum]]; + return dayOfWeekCheck; + } else { + return false; + } +}; + + +/* + ------------------------------------------------------ + Level cap + ------------------------------------------------------ + */ + +api.maxLevel = 100; + +api.capByLevel = function(lvl) { + if (lvl > api.maxLevel) { + return api.maxLevel; + } else { + return lvl; + } +}; + + +/* + ------------------------------------------------------ + Health cap + ------------------------------------------------------ + */ + +api.maxHealth = 50; + + +/* + ------------------------------------------------------ + Scoring + ------------------------------------------------------ + */ + +api.tnl = function(lvl) { + return Math.round(((Math.pow(lvl, 2) * 0.25) + (10 * lvl) + 139.75) / 10) * 10; +}; + + +/* + A hyperbola function that creates diminishing returns, so you can't go to infinite (eg, with Exp gain). + {max} The asymptote + {bonus} All the numbers combined for your point bonus (eg, task.value * user.stats.int * critChance, etc) + {halfway} (optional) the point at which the graph starts bending + */ + +api.diminishingReturns = function(bonus, max, halfway) { + if (halfway == null) { + halfway = max / 2; + } + return max * (bonus / (bonus + halfway)); +}; + +api.monod = function(bonus, rateOfIncrease, max) { + return rateOfIncrease * max * bonus / (rateOfIncrease * bonus + max); +}; + + +/* +Preen history for users with > 7 history entries +This takes an infinite array of single day entries [day day day day day...], and turns it into a condensed array +of averages, condensing more the further back in time we go. Eg, 7 entries each for last 7 days; 1 entry each week +of this month; 1 entry for each month of this year; 1 entry per previous year: [day*7 week*4 month*12 year*infinite] + */ + +preenHistory = function(history) { + var newHistory, preen, thisMonth; + history = _.filter(history, function(h) { + return !!h; + }); + newHistory = []; + preen = function(amount, groupBy) { + var groups; + groups = _.chain(history).groupBy(function(h) { + return moment(h.date).format(groupBy); + }).sortBy(function(h, k) { + return k; + }).value(); + groups = groups.slice(-amount); + groups.pop(); + return _.each(groups, function(group) { + newHistory.push({ + date: moment(group[0].date).toDate(), + value: _.reduce(group, (function(m, obj) { + return m + obj.value; + }), 0) / group.length + }); + return true; + }); + }; + preen(50, "YYYY"); + preen(moment().format('MM'), "YYYYMM"); + thisMonth = moment().format('YYYYMM'); + newHistory = newHistory.concat(_.filter(history, function(h) { + return moment(h.date).format('YYYYMM') === thisMonth; + })); + return newHistory; +}; + + +/* + Preen 3-day past-completed To-Dos from Angular & mobile app + */ + +api.preenTodos = function(tasks) { + return _.where(tasks, function(t) { + return !t.completed || (t.challenge && t.challenge.id) || moment(t.dateCompleted).isAfter(moment().subtract({ + days: 3 + })); + }); +}; + + +/* + Update the in-browser store with new gear. FIXME this was in user.fns, but it was causing strange issues there + */ + +sortOrder = _.reduce(content.gearTypes, (function(m, v, k) { + m[v] = k; + return m; +}), {}); + +api.updateStore = function(user) { + var changes; + if (!user) { + return; + } + changes = []; + _.each(content.gearTypes, function(type) { + var found; + found = _.find(content.gear.tree[type][user.stats["class"]], function(item) { + return !user.items.gear.owned[item.key]; + }); + if (found) { + changes.push(found); + } + return true; + }); + changes = changes.concat(_.filter(content.gear.flat, function(v) { + var ref; + return ((ref = v.klass) === 'special' || ref === 'mystery' || ref === 'armoire') && !user.items.gear.owned[v.key] && (typeof v.canOwn === "function" ? v.canOwn(user) : void 0); + })); + return _.sortBy(changes, function(c) { + return sortOrder[c.type]; + }); +}; + + +/* +------------------------------------------------------ +Content +------------------------------------------------------ + */ + +api.content = content; + + +/* +------------------------------------------------------ +Misc Helpers +------------------------------------------------------ + */ + +api.uuid = function() { + return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) { + var r, v; + r = Math.random() * 16 | 0; + v = (c === "x" ? r : r & 0x3 | 0x8); + return v.toString(16); + }); +}; + +api.countExists = function(items) { + return _.reduce(items, (function(m, v) { + return m + (v ? 1 : 0); + }), 0); +}; + + +/* +Even though Mongoose handles task defaults, we want to make sure defaults are set on the client-side before +sending up to the server for performance + */ + +api.taskDefaults = function(task) { + var defaults, ref, ref1, ref2; + if (task == null) { + task = {}; + } + if (!(task.type && ((ref = task.type) === 'habit' || ref === 'daily' || ref === 'todo' || ref === 'reward'))) { + task.type = 'habit'; + } + defaults = { + id: api.uuid(), + text: task.id != null ? task.id : '', + notes: '', + priority: 1, + challenge: {}, + attribute: 'str', + dateCreated: new Date() + }; + _.defaults(task, defaults); + if (task.type === 'habit') { + _.defaults(task, { + up: true, + down: true + }); + } + if ((ref1 = task.type) === 'habit' || ref1 === 'daily') { + _.defaults(task, { + history: [] + }); + } + if ((ref2 = task.type) === 'daily' || ref2 === 'todo') { + _.defaults(task, { + completed: false + }); + } + if (task.type === 'daily') { + _.defaults(task, { + streak: 0, + repeat: { + su: true, + m: true, + t: true, + w: true, + th: true, + f: true, + s: true + } + }, { + startDate: new Date(), + everyX: 1, + frequency: 'weekly' + }); + } + task._id = task.id; + if (task.value == null) { + task.value = task.type === 'reward' ? 10 : 0; + } + if (!_.isNumber(task.priority)) { + task.priority = 1; + } + return task; +}; + +api.percent = function(x, y, dir) { + var roundFn; + switch (dir) { + case "up": + roundFn = Math.ceil; + break; + case "down": + roundFn = Math.floor; + break; + default: + roundFn = Math.round; + } + if (x === 0) { + x = 1; + } + return Math.max(0, roundFn(x / y * 100)); +}; + + +/* +Remove whitespace #FIXME are we using this anywwhere? Should we be? + */ + +api.removeWhitespace = function(str) { + if (!str) { + return ''; + } + return str.replace(/\s/g, ''); +}; + + +/* +Encode the download link for .ics iCal file + */ + +api.encodeiCalLink = function(uid, apiToken) { + var loc, ref; + loc = (typeof window !== "undefined" && window !== null ? window.location.host : void 0) || (typeof process !== "undefined" && process !== null ? (ref = process.env) != null ? ref.BASE_URL : void 0 : void 0) || ''; + return encodeURIComponent("http://" + loc + "/v1/users/" + uid + "/calendar.ics?apiToken=" + apiToken); +}; + + +/* +Gold amount from their money + */ + +api.gold = function(num) { + if (num) { + return Math.floor(num); + } else { + return "0"; + } +}; + + +/* +Silver amount from their money + */ + +api.silver = function(num) { + if (num) { + return ("0" + Math.floor((num - Math.floor(num)) * 100)).slice(-2); + } else { + return "00"; + } +}; + + +/* +Task classes given everything about the class + */ + +api.taskClasses = function(task, filters, dayStart, lastCron, showCompleted, main) { + var classes, completed, enabled, filter, priority, ref, repeat, type, value; + if (filters == null) { + filters = []; + } + if (dayStart == null) { + dayStart = 0; + } + if (lastCron == null) { + lastCron = +(new Date); + } + if (showCompleted == null) { + showCompleted = false; + } + if (main == null) { + main = false; + } + if (!task) { + return; + } + type = task.type, completed = task.completed, value = task.value, repeat = task.repeat, priority = task.priority; + if (main) { + if (!task._editing) { + for (filter in filters) { + enabled = filters[filter]; + if (enabled && !((ref = task.tags) != null ? ref[filter] : void 0)) { + return 'hidden'; + } + } + } + } + classes = type; + if (task._editing) { + classes += " beingEdited"; + } + if (type === 'todo' || type === 'daily') { + if (completed || (type === 'daily' && !api.shouldDo(+(new Date), task, { + dayStart: dayStart + }))) { + classes += " completed"; + } else { + classes += " uncompleted"; + } + } else if (type === 'habit') { + if (task.down && task.up) { + classes += ' habit-wide'; + } + if (!task.down && !task.up) { + classes += ' habit-narrow'; + } + } + if (priority === 0.1) { + classes += ' difficulty-trivial'; + } else if (priority === 1) { + classes += ' difficulty-easy'; + } else if (priority === 1.5) { + classes += ' difficulty-medium'; + } else if (priority === 2) { + classes += ' difficulty-hard'; + } + if (value < -20) { + classes += ' color-worst'; + } else if (value < -10) { + classes += ' color-worse'; + } else if (value < -1) { + classes += ' color-bad'; + } else if (value < 1) { + classes += ' color-neutral'; + } else if (value < 5) { + classes += ' color-good'; + } else if (value < 10) { + classes += ' color-better'; + } else { + classes += ' color-best'; + } + return classes; +}; + + +/* +Friendly timestamp + */ + +api.friendlyTimestamp = function(timestamp) { + return moment(timestamp).format('MM/DD h:mm:ss a'); +}; + + +/* +Does user have new chat messages? + */ + +api.newChatMessages = function(messages, lastMessageSeen) { + if (!((messages != null ? messages.length : void 0) > 0)) { + return false; + } + return (messages != null ? messages[0] : void 0) && (messages[0].id !== lastMessageSeen); +}; + + +/* +are any tags active? + */ + +api.noTags = function(tags) { + return _.isEmpty(tags) || _.isEmpty(_.filter(tags, function(t) { + return t; + })); +}; + + +/* +Are there tags applied? + */ + +api.appliedTags = function(userTags, taskTags) { + var arr; + arr = []; + _.each(userTags, function(t) { + if (t == null) { + return; + } + if (taskTags != null ? taskTags[t.id] : void 0) { + return arr.push(t.name); + } + }); + return arr.join(', '); +}; + + +/* +Various counting functions + */ + +api.count = require('./count'); + + +/* +------------------------------------------------------ +User (prototype wrapper to give it ops, helper funcs, and virtuals +------------------------------------------------------ + */ + + +/* +User is now wrapped (both on client and server), adding a few new properties: + * getters (_statsComputed, tasks, etc) + * user.fns, which is a bunch of helper functions + These were originally up above, but they make more sense belonging to the user object so we don't have to pass + the user object all over the place. In fact, we should pull in more functions such as cron(), updateStats(), etc. + * user.ops, which is super important: + +If a function is inside user.ops, it has magical properties. If you call it on the client it updates the user object in +the browser and when it's done it automatically POSTs to the server, calling src/controllers/user.js#OP_NAME (the exact same name +of the op function). The first argument req is {query, body, params}, it's what the express controller function +expects. This means we call our functions as if we were calling an Express route. Eg, instead of score(task, direction), +we call score({params:{id:task.id,direction:direction}}). This also forces us to think about our routes (whether to use +params, query, or body for variables). see http://stackoverflow.com/questions/4024271/rest-api-best-practices-where-to-put-parameters + +If `src/controllers/user.js#OP_NAME` doesn't exist on the server, it's automatically added. It runs the code in user.ops.OP_NAME +to update the user model server-side, then performs `user.save()`. You can see this in action for `user.ops.buy`. That +function doesn't exist on the server - so the client calls it, it updates user in the browser, auto-POSTs to server, server +handles it by calling `user.ops.buy` again (to update user on the server), and then saves. We can do this for +everything that doesn't need any code difference from what's in user.ops.OP_NAME for special-handling server-side. If we +*do* need special handling, just add `src/controllers/user.js#OP_NAME` to override the user.ops.OP_NAME, and be +sure to call user.ops.OP_NAME at some point within the overridden function. + +TODO + * Is this the best way to wrap the user object? I thought of using user.prototype, but user is an object not a Function. + user on the server is a Mongoose model, so we can use prototype - but to do it on the client, we'd probably have to + move to $resource for user + * Move to $resource! + */ + +api.wrap = function(user, main) { + if (main == null) { + main = true; + } + if (user._wrapped) { + return; + } + user._wrapped = true; + if (main) { + user.ops = { + update: function(req, cb) { + _.each(req.body, function(v, k) { + user.fns.dotSet(k, v); + return true; + }); + return typeof cb === "function" ? cb(null, user) : void 0; + }, + sleep: function(req, cb) { + user.preferences.sleep = !user.preferences.sleep; + return typeof cb === "function" ? cb(null, {}) : void 0; + }, + revive: function(req, cb, analytics) { + var analyticsData, base, cl, gearOwned, item, losableItems, lostItem, lostStat; + if (!(user.stats.hp <= 0)) { + return typeof cb === "function" ? cb({ + code: 400, + message: "Cannot revive if not dead" + }) : void 0; + } + _.merge(user.stats, { + hp: 50, + exp: 0, + gp: 0 + }); + if (user.stats.lvl > 1) { + user.stats.lvl--; + } + lostStat = user.fns.randomVal(_.reduce(['str', 'con', 'per', 'int'], (function(m, k) { + if (user.stats[k]) { + m[k] = k; + } + return m; + }), {})); + if (lostStat) { + user.stats[lostStat]--; + } + cl = user.stats["class"]; + gearOwned = (typeof (base = user.items.gear.owned).toObject === "function" ? base.toObject() : void 0) || user.items.gear.owned; + losableItems = {}; + _.each(gearOwned, function(v, k) { + var itm; + if (v) { + itm = content.gear.flat['' + k]; + if (itm) { + if ((itm.value > 0 || k === 'weapon_warrior_0') && (itm.klass === cl || (itm.klass === 'special' && (!itm.specialClass || itm.specialClass === cl)) || itm.klass === 'armoire')) { + return losableItems['' + k] = '' + k; + } + } + } + }); + lostItem = user.fns.randomVal(losableItems); + if (item = content.gear.flat[lostItem]) { + user.items.gear.owned[lostItem] = false; + if (user.items.gear.equipped[item.type] === lostItem) { + user.items.gear.equipped[item.type] = item.type + "_base_0"; + } + if (user.items.gear.costume[item.type] === lostItem) { + user.items.gear.costume[item.type] = item.type + "_base_0"; + } + } + if (typeof user.markModified === "function") { + user.markModified('items.gear'); + } + analyticsData = { + uuid: user._id, + lostItem: lostItem, + gaLabel: lostItem, + category: 'behavior' + }; + if (analytics != null) { + analytics.track('Death', analyticsData); + } + return typeof cb === "function" ? cb((item ? { + code: 200, + message: i18n.t('messageLostItem', { + itemText: item.text(req.language) + }, req.language) + } : null), user) : void 0; + }, + reset: function(req, cb) { + var gear; + user.habits = []; + user.dailys = []; + user.todos = []; + user.rewards = []; + user.stats.hp = 50; + user.stats.lvl = 1; + user.stats.gp = 0; + user.stats.exp = 0; + gear = user.items.gear; + _.each(['equipped', 'costume'], function(type) { + gear[type].armor = 'armor_base_0'; + gear[type].weapon = 'weapon_base_0'; + gear[type].head = 'head_base_0'; + return gear[type].shield = 'shield_base_0'; + }); + if (typeof gear.owned === 'undefined') { + gear.owned = {}; + } + _.each(gear.owned, function(v, k) { + if (gear.owned[k]) { + gear.owned[k] = false; + } + return true; + }); + gear.owned.weapon_warrior_0 = true; + if (typeof user.markModified === "function") { + user.markModified('items.gear.owned'); + } + user.preferences.costume = false; + return typeof cb === "function" ? cb(null, user) : void 0; + }, + reroll: function(req, cb, analytics) { + var analyticsData; + if (user.balance < 1) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('notEnoughGems', req.language) + }) : void 0; + } + user.balance--; + _.each(user.tasks, function(task) { + if (task.type !== 'reward') { + return task.value = 0; + } + }); + user.stats.hp = 50; + analyticsData = { + uuid: user._id, + acquireMethod: 'Gems', + gemCost: 4, + category: 'behavior' + }; + if (analytics != null) { + analytics.track('Fortify Potion', analyticsData); + } + return typeof cb === "function" ? cb(null, user) : void 0; + }, + rebirth: function(req, cb, analytics) { + var analyticsData, flags, gear, lvl, stats; + if (user.balance < 2 && user.stats.lvl < api.maxLevel) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('notEnoughGems', req.language) + }) : void 0; + } + analyticsData = { + uuid: user._id, + category: 'behavior' + }; + if (user.stats.lvl < api.maxLevel) { + user.balance -= 2; + analyticsData.acquireMethod = 'Gems'; + analyticsData.gemCost = 8; + } else { + analyticsData.gemCost = 0; + analyticsData.acquireMethod = '> 100'; + } + if (analytics != null) { + analytics.track('Rebirth', analyticsData); + } + lvl = api.capByLevel(user.stats.lvl); + _.each(user.tasks, function(task) { + if (task.type !== 'reward') { + task.value = 0; + } + if (task.type === 'daily') { + return task.streak = 0; + } + }); + stats = user.stats; + stats.buffs = {}; + stats.hp = 50; + stats.lvl = 1; + stats["class"] = 'warrior'; + _.each(['per', 'int', 'con', 'str', 'points', 'gp', 'exp', 'mp'], function(value) { + return stats[value] = 0; + }); + gear = user.items.gear; + _.each(['equipped', 'costume'], function(type) { + gear[type] = {}; + gear[type].armor = 'armor_base_0'; + gear[type].weapon = 'weapon_warrior_0'; + gear[type].head = 'head_base_0'; + return gear[type].shield = 'shield_base_0'; + }); + if (user.items.currentPet) { + user.ops.equip({ + params: { + type: 'pet', + key: user.items.currentPet + } + }); + } + if (user.items.currentMount) { + user.ops.equip({ + params: { + type: 'mount', + key: user.items.currentMount + } + }); + } + _.each(gear.owned, function(v, k) { + if (gear.owned[k] && content.gear.flat[k].value) { + gear.owned[k] = false; + return true; + } + }); + gear.owned.weapon_warrior_0 = true; + if (typeof user.markModified === "function") { + user.markModified('items.gear.owned'); + } + user.preferences.costume = false; + flags = user.flags; + if (!user.achievements.beastMaster) { + flags.rebirthEnabled = false; + } + flags.itemsEnabled = false; + flags.dropsEnabled = false; + flags.classSelected = false; + flags.levelDrops = {}; + if (!user.achievements.rebirths) { + user.achievements.rebirths = 1; + user.achievements.rebirthLevel = lvl; + } else if (lvl > user.achievements.rebirthLevel || lvl === 100) { + user.achievements.rebirths++; + user.achievements.rebirthLevel = lvl; + } + user.stats.buffs = {}; + return typeof cb === "function" ? cb(null, user) : void 0; + }, + allocateNow: function(req, cb) { + _.times(user.stats.points, user.fns.autoAllocate); + user.stats.points = 0; + if (typeof user.markModified === "function") { + user.markModified('stats'); + } + return typeof cb === "function" ? cb(null, user.stats) : void 0; + }, + clearCompleted: function(req, cb) { + _.remove(user.todos, function(t) { + var ref; + return t.completed && !((ref = t.challenge) != null ? ref.id : void 0); + }); + if (typeof user.markModified === "function") { + user.markModified('todos'); + } + return typeof cb === "function" ? cb(null, user.todos) : void 0; + }, + sortTask: function(req, cb) { + var from, id, movedTask, preenedTasks, ref, task, tasks, to; + id = req.params.id; + ref = req.query, to = ref.to, from = ref.from; + task = user.tasks[id]; + if (!task) { + return typeof cb === "function" ? cb({ + code: 404, + message: i18n.t('messageTaskNotFound', req.language) + }) : void 0; + } + if (!((to != null) && (from != null))) { + return typeof cb === "function" ? cb('?to=__&from=__ are required') : void 0; + } + tasks = user[task.type + "s"]; + if (task.type === 'todo' && tasks[from] !== task) { + preenedTasks = api.preenTodos(tasks); + if (to !== -1) { + to = tasks.indexOf(preenedTasks[to]); + } + from = tasks.indexOf(preenedTasks[from]); + } + if (tasks[from] !== task) { + return typeof cb === "function" ? cb({ + code: 404, + message: i18n.t('messageTaskNotFound', req.language) + }) : void 0; + } + movedTask = tasks.splice(from, 1)[0]; + if (to === -1) { + tasks.push(movedTask); + } else { + tasks.splice(to, 0, movedTask); + } + return typeof cb === "function" ? cb(null, tasks) : void 0; + }, + updateTask: function(req, cb) { + var ref, task; + if (!(task = user.tasks[(ref = req.params) != null ? ref.id : void 0])) { + return typeof cb === "function" ? cb({ + code: 404, + message: i18n.t('messageTaskNotFound', req.language) + }) : void 0; + } + _.merge(task, _.omit(req.body, ['checklist', 'id', 'type'])); + if (req.body.checklist) { + task.checklist = req.body.checklist; + } + if (typeof task.markModified === "function") { + task.markModified('tags'); + } + return typeof cb === "function" ? cb(null, task) : void 0; + }, + deleteTask: function(req, cb) { + var i, ref, task; + task = user.tasks[(ref = req.params) != null ? ref.id : void 0]; + if (!task) { + return typeof cb === "function" ? cb({ + code: 404, + message: i18n.t('messageTaskNotFound', req.language) + }) : void 0; + } + i = user[task.type + "s"].indexOf(task); + if (~i) { + user[task.type + "s"].splice(i, 1); + } + return typeof cb === "function" ? cb(null, {}) : void 0; + }, + addTask: function(req, cb) { + var task; + task = api.taskDefaults(req.body); + if (user.tasks[task.id] != null) { + return typeof cb === "function" ? cb({ + code: 409, + message: i18n.t('messageDuplicateTaskID', req.language) + }) : void 0; + } + user[task.type + "s"].unshift(task); + if (user.preferences.newTaskEdit) { + task._editing = true; + } + if (user.preferences.tagsCollapsed) { + task._tags = true; + } + if (!user.preferences.advancedCollapsed) { + task._advanced = true; + } + if (typeof cb === "function") { + cb(null, task); + } + return task; + }, + addTag: function(req, cb) { + if (user.tags == null) { + user.tags = []; + } + user.tags.push({ + name: req.body.name, + id: req.body.id || api.uuid() + }); + return typeof cb === "function" ? cb(null, user.tags) : void 0; + }, + sortTag: function(req, cb) { + var from, ref, to; + ref = req.query, to = ref.to, from = ref.from; + if (!((to != null) && (from != null))) { + return typeof cb === "function" ? cb('?to=__&from=__ are required') : void 0; + } + user.tags.splice(to, 0, user.tags.splice(from, 1)[0]); + return typeof cb === "function" ? cb(null, user.tags) : void 0; + }, + getTags: function(req, cb) { + return typeof cb === "function" ? cb(null, user.tags) : void 0; + }, + getTag: function(req, cb) { + var i, tid; + tid = req.params.id; + i = _.findIndex(user.tags, { + id: tid + }); + if (!~i) { + return typeof cb === "function" ? cb({ + code: 404, + message: i18n.t('messageTagNotFound', req.language) + }) : void 0; + } + return typeof cb === "function" ? cb(null, user.tags[i]) : void 0; + }, + updateTag: function(req, cb) { + var i, tid; + tid = req.params.id; + i = _.findIndex(user.tags, { + id: tid + }); + if (!~i) { + return typeof cb === "function" ? cb({ + code: 404, + message: i18n.t('messageTagNotFound', req.language) + }) : void 0; + } + user.tags[i].name = req.body.name; + return typeof cb === "function" ? cb(null, user.tags[i]) : void 0; + }, + deleteTag: function(req, cb) { + var i, tag, tid; + tid = req.params.id; + i = _.findIndex(user.tags, { + id: tid + }); + if (!~i) { + return typeof cb === "function" ? cb({ + code: 404, + message: i18n.t('messageTagNotFound', req.language) + }) : void 0; + } + tag = user.tags[i]; + delete user.filters[tag.id]; + user.tags.splice(i, 1); + _.each(user.tasks, function(task) { + return delete task.tags[tag.id]; + }); + _.each(['habits', 'dailys', 'todos', 'rewards'], function(type) { + return typeof user.markModified === "function" ? user.markModified(type) : void 0; + }); + return typeof cb === "function" ? cb(null, user.tags) : void 0; + }, + addWebhook: function(req, cb) { + var wh; + wh = user.preferences.webhooks; + api.refPush(wh, { + url: req.body.url, + enabled: req.body.enabled || true, + id: req.body.id + }); + if (typeof user.markModified === "function") { + user.markModified('preferences.webhooks'); + } + return typeof cb === "function" ? cb(null, user.preferences.webhooks) : void 0; + }, + updateWebhook: function(req, cb) { + _.merge(user.preferences.webhooks[req.params.id], req.body); + if (typeof user.markModified === "function") { + user.markModified('preferences.webhooks'); + } + return typeof cb === "function" ? cb(null, user.preferences.webhooks) : void 0; + }, + deleteWebhook: function(req, cb) { + delete user.preferences.webhooks[req.params.id]; + if (typeof user.markModified === "function") { + user.markModified('preferences.webhooks'); + } + return typeof cb === "function" ? cb(null, user.preferences.webhooks) : void 0; + }, + addPushDevice: function(req, cb) { + var i, item, pd; + if (!user.pushDevices) { + user.pushDevices = []; + } + pd = user.pushDevices; + item = { + regId: req.body.regId, + type: req.body.type + }; + i = _.findIndex(pd, { + regId: item.regId + }); + if (i === -1) { + pd.push(item); + } + return typeof cb === "function" ? cb(null, user.pushDevices) : void 0; + }, + clearPMs: function(req, cb) { + user.inbox.messages = {}; + if (typeof user.markModified === "function") { + user.markModified('inbox.messages'); + } + return typeof cb === "function" ? cb(null, user.inbox.messages) : void 0; + }, + deletePM: function(req, cb) { + delete user.inbox.messages[req.params.id]; + if (typeof user.markModified === "function") { + user.markModified('inbox.messages.' + req.params.id); + } + return typeof cb === "function" ? cb(null, user.inbox.messages) : void 0; + }, + blockUser: function(req, cb) { + var i; + i = user.inbox.blocks.indexOf(req.params.uuid); + if (~i) { + user.inbox.blocks.splice(i, 1); + } else { + user.inbox.blocks.push(req.params.uuid); + } + if (typeof user.markModified === "function") { + user.markModified('inbox.blocks'); + } + return typeof cb === "function" ? cb(null, user.inbox.blocks) : void 0; + }, + feed: function(req, cb) { + var egg, eggText, evolve, food, message, pet, petDisplayName, potion, potionText, ref, ref1, ref2, userPets; + ref = req.params, pet = ref.pet, food = ref.food; + food = content.food[food]; + ref1 = pet.split('-'), egg = ref1[0], potion = ref1[1]; + userPets = user.items.pets; + potionText = content.hatchingPotions[potion] ? content.hatchingPotions[potion].text() : potion; + eggText = content.eggs[egg] ? content.eggs[egg].text() : egg; + petDisplayName = i18n.t('petName', { + potion: potionText, + egg: eggText + }); + if (!userPets[pet]) { + return typeof cb === "function" ? cb({ + code: 404, + message: i18n.t('messagePetNotFound', req.language) + }) : void 0; + } + if (!((ref2 = user.items.food) != null ? ref2[food.key] : void 0)) { + return typeof cb === "function" ? cb({ + code: 404, + message: i18n.t('messageFoodNotFound', req.language) + }) : void 0; + } + if (content.specialPets[pet]) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('messageCannotFeedPet', req.language) + }) : void 0; + } + if (user.items.mounts[pet]) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('messageAlreadyMount', req.language) + }) : void 0; + } + message = ''; + evolve = function() { + userPets[pet] = -1; + user.items.mounts[pet] = true; + if (pet === user.items.currentPet) { + user.items.currentPet = ""; + } + return message = i18n.t('messageEvolve', { + egg: petDisplayName + }, req.language); + }; + if (food.key === 'Saddle') { + evolve(); + } else { + if (food.target === potion || content.hatchingPotions[potion].premium) { + userPets[pet] += 5; + message = i18n.t('messageLikesFood', { + egg: petDisplayName, + foodText: food.text(req.language) + }, req.language); + } else { + userPets[pet] += 2; + message = i18n.t('messageDontEnjoyFood', { + egg: petDisplayName, + foodText: food.text(req.language) + }, req.language); + } + if (userPets[pet] >= 50 && !user.items.mounts[pet]) { + evolve(); + } + } + user.items.food[food.key]--; + return typeof cb === "function" ? cb({ + code: 200, + message: message + }, { + value: userPets[pet] + }) : void 0; + }, + buySpecialSpell: function(req, cb) { + var base, item, key, message; + key = req.params.key; + item = content.special[key]; + if (user.stats.gp < item.value) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('messageNotEnoughGold', req.language) + }) : void 0; + } + user.stats.gp -= item.value; + if ((base = user.items.special)[key] == null) { + base[key] = 0; + } + user.items.special[key]++; + if (typeof user.markModified === "function") { + user.markModified('items.special'); + } + message = i18n.t('messageBought', { + itemText: item.text(req.language) + }, req.language); + return typeof cb === "function" ? cb({ + code: 200, + message: message + }, _.pick(user, $w('items stats'))) : void 0; + }, + purchase: function(req, cb, analytics) { + var analyticsData, convCap, convRate, item, key, price, ref, ref1, ref2, ref3, type; + ref = req.params, type = ref.type, key = ref.key; + if (type === 'gems' && key === 'gem') { + ref1 = api.planGemLimits, convRate = ref1.convRate, convCap = ref1.convCap; + convCap += user.purchased.plan.consecutive.gemCapExtra; + if (!((ref2 = user.purchased) != null ? (ref3 = ref2.plan) != null ? ref3.customerId : void 0 : void 0)) { + return typeof cb === "function" ? cb({ + code: 401, + message: "Must subscribe to purchase gems with GP" + }, req) : void 0; + } + if (!(user.stats.gp >= convRate)) { + return typeof cb === "function" ? cb({ + code: 401, + message: "Not enough Gold" + }) : void 0; + } + if (user.purchased.plan.gemsBought >= convCap) { + return typeof cb === "function" ? cb({ + code: 401, + message: "You've reached the Gold=>Gem conversion cap (" + convCap + ") for this month. We have this to prevent abuse / farming. The cap will reset within the first three days of next month." + }) : void 0; + } + user.balance += .25; + user.purchased.plan.gemsBought++; + user.stats.gp -= convRate; + analyticsData = { + uuid: user._id, + itemKey: key, + acquireMethod: 'Gold', + goldCost: convRate, + category: 'behavior' + }; + if (analytics != null) { + analytics.track('purchase gems', analyticsData); + } + return typeof cb === "function" ? cb({ + code: 200, + message: "+1 Gem" + }, _.pick(user, $w('stats balance'))) : void 0; + } + if (type !== 'eggs' && type !== 'hatchingPotions' && type !== 'food' && type !== 'quests' && type !== 'gear') { + return typeof cb === "function" ? cb({ + code: 404, + message: ":type must be in [eggs,hatchingPotions,food,quests,gear]" + }, req) : void 0; + } + if (type === 'gear') { + item = content.gear.flat[key]; + if (user.items.gear.owned[key]) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('alreadyHave', req.language) + }) : void 0; + } + price = (item.twoHanded || item.gearSet === 'animal' ? 2 : 1) / 4; + } else { + item = content[type][key]; + price = item.value / 4; + } + if (!item) { + return typeof cb === "function" ? cb({ + code: 404, + message: ":key not found for Content." + type + }, req) : void 0; + } + if (!item.canBuy(user)) { + return typeof cb === "function" ? cb({ + code: 403, + message: i18n.t('messageNotAvailable', req.language) + }) : void 0; + } + if ((user.balance < price) || !user.balance) { + return typeof cb === "function" ? cb({ + code: 403, + message: i18n.t('notEnoughGems', req.language) + }) : void 0; + } + user.balance -= price; + if (type === 'gear') { + user.items.gear.owned[key] = true; + } else { + if (!(user.items[type][key] > 0)) { + user.items[type][key] = 0; + } + user.items[type][key]++; + } + analyticsData = { + uuid: user._id, + itemKey: key, + itemType: 'Market', + acquireMethod: 'Gems', + gemCost: item.value, + category: 'behavior' + }; + if (analytics != null) { + analytics.track('acquire item', analyticsData); + } + return typeof cb === "function" ? cb(null, _.pick(user, $w('items balance'))) : void 0; + }, + releasePets: function(req, cb, analytics) { + var analyticsData, pet; + if (user.balance < 1) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('notEnoughGems', req.language) + }) : void 0; + } else { + user.balance -= 1; + for (pet in content.pets) { + user.items.pets[pet] = 0; + } + if (!user.achievements.beastMasterCount) { + user.achievements.beastMasterCount = 0; + } + user.achievements.beastMasterCount++; + user.items.currentPet = ""; + } + analyticsData = { + uuid: user._id, + acquireMethod: 'Gems', + gemCost: 4, + category: 'behavior' + }; + if (analytics != null) { + analytics.track('release pets', analyticsData); + } + return typeof cb === "function" ? cb(null, user) : void 0; + }, + releaseMounts: function(req, cb, analytics) { + var analyticsData, mount; + if (user.balance < 1) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('notEnoughGems', req.language) + }) : void 0; + } else { + user.balance -= 1; + user.items.currentMount = ""; + for (mount in content.pets) { + user.items.mounts[mount] = null; + } + if (!user.achievements.mountMasterCount) { + user.achievements.mountMasterCount = 0; + } + user.achievements.mountMasterCount++; + } + analyticsData = { + uuid: user._id, + acquireMethod: 'Gems', + gemCost: 4, + category: 'behavior' + }; + if (analytics != null) { + analytics.track('release mounts', analyticsData); + } + return typeof cb === "function" ? cb(null, user) : void 0; + }, + releaseBoth: function(req, cb) { + var analyticsData, animal, giveTriadBingo; + if (user.balance < 1.5 && !user.achievements.triadBingo) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('notEnoughGems', req.language) + }) : void 0; + } else { + giveTriadBingo = true; + if (!user.achievements.triadBingo) { + analyticsData = { + uuid: user._id, + acquireMethod: 'Gems', + gemCost: 6, + category: 'behavior' + }; + if (typeof analytics !== "undefined" && analytics !== null) { + analytics.track('release pets & mounts', analyticsData); + } + user.balance -= 1.5; + } + user.items.currentMount = ""; + user.items.currentPet = ""; + for (animal in content.pets) { + if (user.items.pets[animal] === -1) { + giveTriadBingo = false; + } + user.items.pets[animal] = 0; + user.items.mounts[animal] = null; + } + if (!user.achievements.beastMasterCount) { + user.achievements.beastMasterCount = 0; + } + user.achievements.beastMasterCount++; + if (!user.achievements.mountMasterCount) { + user.achievements.mountMasterCount = 0; + } + user.achievements.mountMasterCount++; + if (giveTriadBingo) { + if (!user.achievements.triadBingoCount) { + user.achievements.triadBingoCount = 0; + } + user.achievements.triadBingoCount++; + } + } + return typeof cb === "function" ? cb(null, user) : void 0; + }, + buy: function(req, cb, analytics) { + var analyticsData, armoireExp, armoireResp, armoireResult, base, buyResp, drop, eligibleEquipment, item, key, message, name; + key = req.params.key; + item = key === 'potion' ? content.potion : key === 'armoire' ? content.armoire : content.gear.flat[key]; + if (!item) { + return typeof cb === "function" ? cb({ + code: 404, + message: "Item '" + key + " not found (see https://github.com/HabitRPG/habitrpg/blob/develop/common/script/content/index.js)" + }) : void 0; + } + if (user.stats.gp < item.value) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('messageNotEnoughGold', req.language) + }) : void 0; + } + if ((item.canOwn != null) && !item.canOwn(user)) { + return typeof cb === "function" ? cb({ + code: 401, + message: "You can't buy this item" + }) : void 0; + } + armoireResp = void 0; + if (item.key === 'potion') { + user.stats.hp += 15; + if (user.stats.hp > 50) { + user.stats.hp = 50; + } + } else if (item.key === 'armoire') { + armoireResult = user.fns.predictableRandom(user.stats.gp); + eligibleEquipment = _.filter(content.gear.flat, (function(i) { + return i.klass === 'armoire' && !user.items.gear.owned[i.key]; + })); + if (!_.isEmpty(eligibleEquipment) && (armoireResult < .6 || !user.flags.armoireOpened)) { + eligibleEquipment.sort(); + drop = user.fns.randomVal(eligibleEquipment); + user.items.gear.owned[drop.key] = true; + user.flags.armoireOpened = true; + message = i18n.t('armoireEquipment', { + image: '', + dropText: drop.text(req.language) + }, req.language); + if (api.count.remainingGearInSet(user.items.gear.owned, 'armoire') === 0) { + user.flags.armoireEmpty = true; + } + armoireResp = { + type: "gear", + dropKey: drop.key, + dropText: drop.text(req.language) + }; + } else if ((!_.isEmpty(eligibleEquipment) && armoireResult < .8) || armoireResult < .5) { + drop = user.fns.randomVal(_.where(content.food, { + canDrop: true + })); + if ((base = user.items.food)[name = drop.key] == null) { + base[name] = 0; + } + user.items.food[drop.key] += 1; + message = i18n.t('armoireFood', { + image: '', + dropArticle: drop.article, + dropText: drop.text(req.language) + }, req.language); + armoireResp = { + type: "food", + dropKey: drop.key, + dropArticle: drop.article, + dropText: drop.text(req.language) + }; + } else { + armoireExp = Math.floor(user.fns.predictableRandom(user.stats.exp) * 40 + 10); + user.stats.exp += armoireExp; + message = i18n.t('armoireExp', req.language); + armoireResp = { + "type": "experience", + "value": armoireExp + }; + } + } else { + if (user.preferences.autoEquip) { + user.items.gear.equipped[item.type] = item.key; + } + user.items.gear.owned[item.key] = true; + message = user.fns.handleTwoHanded(item, null, req); + if (message == null) { + message = i18n.t('messageBought', { + itemText: item.text(req.language) + }, req.language); + } + if (item.last) { + user.fns.ultimateGear(); + } + } + user.stats.gp -= item.value; + analyticsData = { + uuid: user._id, + itemKey: key, + acquireMethod: 'Gold', + goldCost: item.value, + category: 'behavior' + }; + if (analytics != null) { + analytics.track('acquire item', analyticsData); + } + buyResp = _.pick(user, $w('items achievements stats flags')); + if (armoireResp) { + buyResp["armoire"] = armoireResp; + } + return typeof cb === "function" ? cb({ + code: 200, + message: message + }, buyResp) : void 0; + }, + buyQuest: function(req, cb, analytics) { + var analyticsData, base, item, key, message, name; + key = req.params.key; + item = content.quests[key]; + if (!item) { + return typeof cb === "function" ? cb({ + code: 404, + message: "Quest '" + key + " not found (see https://github.com/HabitRPG/habitrpg/blob/develop/common/script/content/index.js)" + }) : void 0; + } + if (!(item.category === 'gold' && item.goldValue)) { + return typeof cb === "function" ? cb({ + code: 404, + message: "Quest '" + key + " is not a Gold-purchasable quest (see https://github.com/HabitRPG/habitrpg/blob/develop/common/script/content/index.js)" + }) : void 0; + } + if (user.stats.gp < item.goldValue) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('messageNotEnoughGold', req.language) + }) : void 0; + } + message = i18n.t('messageBought', { + itemText: item.text(req.language) + }, req.language); + if ((base = user.items.quests)[name = item.key] == null) { + base[name] = 0; + } + user.items.quests[item.key] += 1; + user.stats.gp -= item.goldValue; + analyticsData = { + uuid: user._id, + itemKey: item.key, + itemType: 'Market', + goldCost: item.goldValue, + acquireMethod: 'Gold', + category: 'behavior' + }; + if (analytics != null) { + analytics.track('acquire item', analyticsData); + } + return typeof cb === "function" ? cb({ + code: 200, + message: message + }, user.items.quests) : void 0; + }, + buyMysterySet: function(req, cb, analytics) { + var mysterySet, ref; + if (!(user.purchased.plan.consecutive.trinkets > 0)) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('notEnoughHourglasses', req.language) + }) : void 0; + } + mysterySet = (ref = content.timeTravelerStore(user.items.gear.owned)) != null ? ref[req.params.key] : void 0; + if ((typeof window !== "undefined" && window !== null ? window.confirm : void 0) != null) { + if (!window.confirm(i18n.t('hourglassBuyEquipSetConfirm'))) { + return; + } + } + if (!mysterySet) { + return typeof cb === "function" ? cb({ + code: 404, + message: "Mystery set not found, or set already owned" + }) : void 0; + } + _.each(mysterySet.items, function(i) { + var analyticsData; + user.items.gear.owned[i.key] = true; + analyticsData = { + uuid: user._id, + itemKey: i.key, + itemType: 'Subscriber Gear', + acquireMethod: 'Hourglass', + category: 'behavior' + }; + return analytics != null ? analytics.track('acquire item', analyticsData) : void 0; + }); + user.purchased.plan.consecutive.trinkets--; + return typeof cb === "function" ? cb({ + code: 200, + message: i18n.t('hourglassPurchaseSet', req.language) + }, _.pick(user, $w('items purchased.plan.consecutive'))) : void 0; + }, + hourglassPurchase: function(req, cb, analytics) { + var analyticsData, key, ref, type; + ref = req.params, type = ref.type, key = ref.key; + if (!content.timeTravelStable[type]) { + return typeof cb === "function" ? cb({ + code: 403, + message: i18n.t('typeNotAllowedHourglass', req.language) + JSON.stringify(_.keys(content.timeTravelStable)) + }) : void 0; + } + if (!_.contains(_.keys(content.timeTravelStable[type]), key)) { + return typeof cb === "function" ? cb({ + code: 403, + message: i18n.t(type + 'NotAllowedHourglass', req.language) + }) : void 0; + } + if (user.items[type][key]) { + return typeof cb === "function" ? cb({ + code: 403, + message: i18n.t(type + 'AlreadyOwned', req.language) + }) : void 0; + } + if (!(user.purchased.plan.consecutive.trinkets > 0)) { + return typeof cb === "function" ? cb({ + code: 403, + message: i18n.t('notEnoughHourglasses', req.language) + }) : void 0; + } + user.purchased.plan.consecutive.trinkets--; + if (type === 'pets') { + user.items.pets[key] = 5; + } + if (type === 'mounts') { + user.items.mounts[key] = true; + } + analyticsData = { + uuid: user._id, + itemKey: key, + itemType: type, + acquireMethod: 'Hourglass', + category: 'behavior' + }; + if (analytics != null) { + analytics.track('acquire item', analyticsData); + } + return typeof cb === "function" ? cb({ + code: 200, + message: i18n.t('hourglassPurchase', req.language) + }, _.pick(user, $w('items purchased.plan.consecutive'))) : void 0; + }, + sell: function(req, cb) { + var key, ref, type; + ref = req.params, key = ref.key, type = ref.type; + if (type !== 'eggs' && type !== 'hatchingPotions' && type !== 'food') { + return typeof cb === "function" ? cb({ + code: 404, + message: ":type not found. Must bes in [eggs, hatchingPotions, food]" + }) : void 0; + } + if (!user.items[type][key]) { + return typeof cb === "function" ? cb({ + code: 404, + message: ":key not found for user.items." + type + }) : void 0; + } + user.items[type][key]--; + user.stats.gp += content[type][key].value; + return typeof cb === "function" ? cb(null, _.pick(user, $w('stats items'))) : void 0; + }, + equip: function(req, cb) { + var item, key, message, ref, type; + ref = [req.params.type || 'equipped', req.params.key], type = ref[0], key = ref[1]; + switch (type) { + case 'mount': + if (!user.items.mounts[key]) { + return typeof cb === "function" ? cb({ + code: 404, + message: ":You do not own this mount." + }) : void 0; + } + user.items.currentMount = user.items.currentMount === key ? '' : key; + break; + case 'pet': + if (!user.items.pets[key]) { + return typeof cb === "function" ? cb({ + code: 404, + message: ":You do not own this pet." + }) : void 0; + } + user.items.currentPet = user.items.currentPet === key ? '' : key; + break; + case 'costume': + case 'equipped': + item = content.gear.flat[key]; + if (!user.items.gear.owned[key]) { + return typeof cb === "function" ? cb({ + code: 404, + message: ":You do not own this gear." + }) : void 0; + } + if (user.items.gear[type][item.type] === key) { + user.items.gear[type][item.type] = item.type + "_base_0"; + message = i18n.t('messageUnEquipped', { + itemText: item.text(req.language) + }, req.language); + } else { + user.items.gear[type][item.type] = item.key; + message = user.fns.handleTwoHanded(item, type, req); + } + if (typeof user.markModified === "function") { + user.markModified("items.gear." + type); + } + } + return typeof cb === "function" ? cb((message ? { + code: 200, + message: message + } : null), user.items) : void 0; + }, + hatch: function(req, cb) { + var egg, hatchingPotion, pet, ref; + ref = req.params, egg = ref.egg, hatchingPotion = ref.hatchingPotion; + if (!(egg && hatchingPotion)) { + return typeof cb === "function" ? cb({ + code: 400, + message: "Please specify query.egg & query.hatchingPotion" + }) : void 0; + } + if (!(user.items.eggs[egg] > 0 && user.items.hatchingPotions[hatchingPotion] > 0)) { + return typeof cb === "function" ? cb({ + code: 403, + message: i18n.t('messageMissingEggPotion', req.language) + }) : void 0; + } + if (content.hatchingPotions[hatchingPotion].premium && !content.dropEggs[egg]) { + return typeof cb === "function" ? cb({ + code: 403, + message: i18n.t('messageInvalidEggPotionCombo', req.language) + }) : void 0; + } + pet = egg + "-" + hatchingPotion; + if (user.items.pets[pet] && user.items.pets[pet] > 0) { + return typeof cb === "function" ? cb({ + code: 403, + message: i18n.t('messageAlreadyPet', req.language) + }) : void 0; + } + user.items.pets[pet] = 5; + user.items.eggs[egg]--; + user.items.hatchingPotions[hatchingPotion]--; + return typeof cb === "function" ? cb({ + code: 200, + message: i18n.t('messageHatched', req.language) + }, user.items) : void 0; + }, + unlock: function(req, cb, analytics) { + var alreadyOwns, analyticsData, cost, fullSet, k, path, split, v; + path = req.query.path; + fullSet = ~path.indexOf(","); + cost = ~path.indexOf('background.') ? fullSet ? 3.75 : 1.75 : fullSet ? 1.25 : 0.5; + alreadyOwns = !fullSet && user.fns.dotGet("purchased." + path) === true; + if ((user.balance < cost || !user.balance) && !alreadyOwns) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('notEnoughGems', req.language) + }) : void 0; + } + if (fullSet) { + _.each(path.split(","), function(p) { + if (~path.indexOf('gear.')) { + user.fns.dotSet("" + p, true); + true; + } else { + + } + user.fns.dotSet("purchased." + p, true); + return true; + }); + } else { + if (alreadyOwns) { + split = path.split('.'); + v = split.pop(); + k = split.join('.'); + if (k === 'background' && v === user.preferences.background) { + v = ''; + } + user.fns.dotSet("preferences." + k, v); + return typeof cb === "function" ? cb(null, req) : void 0; + } + user.fns.dotSet("purchased." + path, true); + } + user.balance -= cost; + if (~path.indexOf('gear.')) { + if (typeof user.markModified === "function") { + user.markModified('gear.owned'); + } + } else { + if (typeof user.markModified === "function") { + user.markModified('purchased'); + } + } + analyticsData = { + uuid: user._id, + itemKey: path, + itemType: 'customization', + acquireMethod: 'Gems', + gemCost: cost / .25, + category: 'behavior' + }; + if (analytics != null) { + analytics.track('acquire item', analyticsData); + } + return typeof cb === "function" ? cb(null, _.pick(user, $w('purchased preferences items'))) : void 0; + }, + changeClass: function(req, cb, analytics) { + var analyticsData, klass, ref; + klass = (ref = req.query) != null ? ref["class"] : void 0; + if (klass === 'warrior' || klass === 'rogue' || klass === 'wizard' || klass === 'healer') { + analyticsData = { + uuid: user._id, + "class": klass, + acquireMethod: 'Gems', + gemCost: 3, + category: 'behavior' + }; + if (analytics != null) { + analytics.track('change class', analyticsData); + } + user.stats["class"] = klass; + user.flags.classSelected = true; + _.each(["weapon", "armor", "shield", "head"], function(type) { + var foundKey; + foundKey = false; + _.findLast(user.items.gear.owned, function(v, k) { + if (~k.indexOf(type + "_" + klass) && v === true) { + return foundKey = k; + } + }); + user.items.gear.equipped[type] = foundKey ? foundKey : type === "weapon" ? "weapon_" + klass + "_0" : type === "shield" && klass === "rogue" ? "shield_rogue_0" : type + "_base_0"; + if (type === "weapon" || (type === "shield" && klass === "rogue")) { + user.items.gear.owned[type + "_" + klass + "_0"] = true; + } + return true; + }); + } else { + if (user.preferences.disableClasses) { + user.preferences.disableClasses = false; + user.preferences.autoAllocate = false; + } else { + if (!(user.balance >= .75)) { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('notEnoughGems', req.language) + }) : void 0; + } + user.balance -= .75; + } + _.merge(user.stats, { + str: 0, + con: 0, + per: 0, + int: 0, + points: api.capByLevel(user.stats.lvl) + }); + user.flags.classSelected = false; + } + return typeof cb === "function" ? cb(null, _.pick(user, $w('stats flags items preferences'))) : void 0; + }, + disableClasses: function(req, cb) { + user.stats["class"] = 'warrior'; + user.flags.classSelected = true; + user.preferences.disableClasses = true; + user.preferences.autoAllocate = true; + user.stats.str = api.capByLevel(user.stats.lvl); + user.stats.points = 0; + return typeof cb === "function" ? cb(null, _.pick(user, $w('stats flags preferences'))) : void 0; + }, + allocate: function(req, cb) { + var stat; + stat = req.query.stat || 'str'; + if (user.stats.points > 0) { + user.stats[stat]++; + user.stats.points--; + if (stat === 'int') { + user.stats.mp++; + } + } + return typeof cb === "function" ? cb(null, _.pick(user, $w('stats'))) : void 0; + }, + readCard: function(req, cb) { + var cardType; + cardType = req.params.cardType; + user.items.special[cardType + "Received"].shift(); + if (typeof user.markModified === "function") { + user.markModified("items.special." + cardType + "Received"); + } + user.flags.cardReceived = false; + return typeof cb === "function" ? cb(null, 'items.special flags.cardReceived') : void 0; + }, + openMysteryItem: function(req, cb, analytics) { + var analyticsData, item, ref, ref1; + item = (ref = user.purchased.plan) != null ? (ref1 = ref.mysteryItems) != null ? ref1.shift() : void 0 : void 0; + if (!item) { + return typeof cb === "function" ? cb({ + code: 400, + message: "Empty" + }) : void 0; + } + item = content.gear.flat[item]; + user.items.gear.owned[item.key] = true; + if (typeof user.markModified === "function") { + user.markModified('purchased.plan.mysteryItems'); + } + item.notificationType = 'Mystery'; + analyticsData = { + uuid: user._id, + itemKey: item, + itemType: 'Subscriber Gear', + acquireMethod: 'Subscriber', + category: 'behavior' + }; + if (analytics != null) { + analytics.track('open mystery item', analyticsData); + } + if (typeof window !== 'undefined') { + (user._tmp != null ? user._tmp : user._tmp = {}).drop = item; + } + return typeof cb === "function" ? cb(null, user.items.gear.owned) : void 0; + }, + score: function(req, cb) { + var addPoints, calculateDelta, calculateReverseDelta, changeTaskValue, delta, direction, gainMP, id, multiplier, num, options, ref, stats, subtractPoints, task, th; + ref = req.params, id = ref.id, direction = ref.direction; + task = user.tasks[id]; + options = req.query || {}; + _.defaults(options, { + times: 1, + cron: false + }); + user._tmp = {}; + stats = { + gp: +user.stats.gp, + hp: +user.stats.hp, + exp: +user.stats.exp + }; + task.value = +task.value; + task.streak = ~~task.streak; + if (task.priority == null) { + task.priority = 1; + } + if (task.value > stats.gp && task.type === 'reward') { + return typeof cb === "function" ? cb({ + code: 401, + message: i18n.t('messageNotEnoughGold', req.language) + }) : void 0; + } + delta = 0; + calculateDelta = function() { + var currVal, nextDelta, ref1; + currVal = task.value < -47.27 ? -47.27 : task.value > 21.27 ? 21.27 : task.value; + nextDelta = Math.pow(0.9747, currVal) * (direction === 'down' ? -1 : 1); + if (((ref1 = task.checklist) != null ? ref1.length : void 0) > 0) { + if (direction === 'down' && task.type === 'daily' && options.cron) { + nextDelta *= 1 - _.reduce(task.checklist, (function(m, i) { + return m + (i.completed ? 1 : 0); + }), 0) / task.checklist.length; + } + if (task.type === 'todo') { + nextDelta *= 1 + _.reduce(task.checklist, (function(m, i) { + return m + (i.completed ? 1 : 0); + }), 0); + } + } + return nextDelta; + }; + calculateReverseDelta = function() { + var calc, closeEnough, currVal, diff, nextDelta, ref1, testVal; + currVal = task.value < -47.27 ? -47.27 : task.value > 21.27 ? 21.27 : task.value; + testVal = currVal + Math.pow(0.9747, currVal) * (direction === 'down' ? -1 : 1); + closeEnough = 0.00001; + while (true) { + calc = testVal + Math.pow(0.9747, testVal); + diff = currVal - calc; + if (Math.abs(diff) < closeEnough) { + break; + } + if (diff > 0) { + testVal -= diff; + } else { + testVal += diff; + } + } + nextDelta = testVal - currVal; + if (((ref1 = task.checklist) != null ? ref1.length : void 0) > 0) { + if (task.type === 'todo') { + nextDelta *= 1 + _.reduce(task.checklist, (function(m, i) { + return m + (i.completed ? 1 : 0); + }), 0); + } + } + return nextDelta; + }; + changeTaskValue = function() { + return _.times(options.times, function() { + var nextDelta, ref1; + nextDelta = !options.cron && direction === 'down' ? calculateReverseDelta() : calculateDelta(); + if (task.type !== 'reward') { + if (user.preferences.automaticAllocation === true && user.preferences.allocationMode === 'taskbased' && !(task.type === 'todo' && direction === 'down')) { + user.stats.training[task.attribute] += nextDelta; + } + if (direction === 'up') { + user.party.quest.progress.up = user.party.quest.progress.up || 0; + if ((ref1 = task.type) === 'daily' || ref1 === 'todo') { + user.party.quest.progress.up += nextDelta * (1 + (user._statsComputed.str / 200)); + } + if (task.type === 'habit') { + user.party.quest.progress.up += nextDelta * (0.5 + (user._statsComputed.str / 400)); + } + } + task.value += nextDelta; + } + return delta += nextDelta; + }); + }; + addPoints = function() { + var _crit, afterStreak, currStreak, gpMod, intBonus, perBonus, streakBonus; + _crit = (delta > 0 ? user.fns.crit() : 1); + if (_crit > 1) { + user._tmp.crit = _crit; + } + intBonus = 1 + (user._statsComputed.int * .025); + stats.exp += Math.round(delta * intBonus * task.priority * _crit * 6); + perBonus = 1 + user._statsComputed.per * .02; + gpMod = delta * task.priority * _crit * perBonus; + return stats.gp += task.streak ? (currStreak = direction === 'down' ? task.streak - 1 : task.streak, streakBonus = currStreak / 100 + 1, afterStreak = gpMod * streakBonus, currStreak > 0 ? gpMod > 0 ? user._tmp.streakBonus = afterStreak - gpMod : void 0 : void 0, afterStreak) : gpMod; + }; + subtractPoints = function() { + var conBonus, hpMod; + conBonus = 1 - (user._statsComputed.con / 250); + if (conBonus < .1) { + conBonus = 0.1; + } + hpMod = delta * conBonus * task.priority * 2; + return stats.hp += Math.round(hpMod * 10) / 10; + }; + gainMP = function(delta) { + delta *= user._tmp.crit || 1; + user.stats.mp += delta; + if (user.stats.mp >= user._statsComputed.maxMP) { + user.stats.mp = user._statsComputed.maxMP; + } + if (user.stats.mp < 0) { + return user.stats.mp = 0; + } + }; + switch (task.type) { + case 'habit': + changeTaskValue(); + if (delta > 0) { + addPoints(); + } else { + subtractPoints(); + } + gainMP(_.max([0.25, .0025 * user._statsComputed.maxMP]) * (direction === 'down' ? -1 : 1)); + th = (task.history != null ? task.history : task.history = []); + if (th[th.length - 1] && moment(th[th.length - 1].date).isSame(new Date, 'day')) { + th[th.length - 1].value = task.value; + } else { + th.push({ + date: +(new Date), + value: task.value + }); + } + if (typeof user.markModified === "function") { + user.markModified("habits." + (_.findIndex(user.habits, { + id: task.id + })) + ".history"); + } + break; + case 'daily': + if (options.cron) { + changeTaskValue(); + subtractPoints(); + if (!user.stats.buffs.streaks) { + task.streak = 0; + } + } else { + changeTaskValue(); + if (direction === 'down') { + delta = calculateDelta(); + } + addPoints(); + gainMP(_.max([1, .01 * user._statsComputed.maxMP]) * (direction === 'down' ? -1 : 1)); + if (direction === 'up') { + task.streak = task.streak ? task.streak + 1 : 1; + if ((task.streak % 21) === 0) { + user.achievements.streak = user.achievements.streak ? user.achievements.streak + 1 : 1; + } + } else { + if ((task.streak % 21) === 0) { + user.achievements.streak = user.achievements.streak ? user.achievements.streak - 1 : 0; + } + task.streak = task.streak ? task.streak - 1 : 0; + } + } + break; + case 'todo': + if (options.cron) { + changeTaskValue(); + } else { + task.dateCompleted = direction === 'up' ? new Date : void 0; + changeTaskValue(); + if (direction === 'down') { + delta = calculateDelta(); + } + addPoints(); + multiplier = _.max([ + _.reduce(task.checklist, (function(m, i) { + return m + (i.completed ? 1 : 0); + }), 1), 1 + ]); + gainMP(_.max([multiplier, .01 * user._statsComputed.maxMP * multiplier]) * (direction === 'down' ? -1 : 1)); + } + break; + case 'reward': + changeTaskValue(); + stats.gp -= Math.abs(task.value); + num = parseFloat(task.value).toFixed(2); + if (stats.gp < 0) { + stats.hp += stats.gp; + stats.gp = 0; + } + } + user.fns.updateStats(stats, req); + if (typeof window === 'undefined') { + if (direction === 'up') { + user.fns.randomDrop({ + task: task, + delta: delta + }, req); + } + } + if (typeof cb === "function") { + cb(null, user); + } + return delta; + } + }; + } + user.fns = { + getItem: function(type) { + var item; + item = content.gear.flat[user.items.gear.equipped[type]]; + if (!item) { + return content.gear.flat[type + "_base_0"]; + } + return item; + }, + handleTwoHanded: function(item, type, req) { + var message, ref, weapon; + if (type == null) { + type = 'equipped'; + } + if (item.type === "shield" && ((ref = (weapon = content.gear.flat[user.items.gear[type].weapon])) != null ? ref.twoHanded : void 0)) { + user.items.gear[type].weapon = 'weapon_base_0'; + message = i18n.t('messageTwoHandled', { + gearText: weapon.text(req.language) + }, req.language); + } + if (item.twoHanded) { + user.items.gear[type].shield = "shield_base_0"; + message = i18n.t('messageTwoHandled', { + gearText: item.text(req.language) + }, req.language); + } + return message; + }, + + /* + Because the same op needs to be performed on the client and the server (critical hits, item drops, etc), + we need things to be "random", but technically predictable so that they don't go out-of-sync + */ + predictableRandom: function(seed) { + var x; + if (!seed || seed === Math.PI) { + seed = _.reduce(user.stats, (function(m, v) { + if (_.isNumber(v)) { + return m + v; + } else { + return m; + } + }), 0); + } + x = Math.sin(seed++) * 10000; + return x - Math.floor(x); + }, + crit: function(stat, chance) { + var s; + if (stat == null) { + stat = 'str'; + } + if (chance == null) { + chance = .03; + } + s = user._statsComputed[stat]; + if (user.fns.predictableRandom() <= chance * (1 + s / 100)) { + return 1.5 + 4 * s / (s + 200); + } else { + return 1; + } + }, + + /* + Get a random property from an object + returns random property (the value) + */ + randomVal: function(obj, options) { + var array, rand; + array = (options != null ? options.key : void 0) ? _.keys(obj) : _.values(obj); + rand = user.fns.predictableRandom(options != null ? options.seed : void 0); + array.sort(); + return array[Math.floor(rand * array.length)]; + }, + + /* + This allows you to set object properties by dot-path. Eg, you can run pathSet('stats.hp',50,user) which is the same as + user.stats.hp = 50. This is useful because in our habitrpg-shared functions we're returning changesets as {path:value}, + so that different consumers can implement setters their own way. Derby needs model.set(path, value) for example, where + Angular sets object properties directly - in which case, this function will be used. + */ + dotSet: function(path, val) { + return api.dotSet(user, path, val); + }, + dotGet: function(path) { + return api.dotGet(user, path); + }, + randomDrop: function(modifiers, req) { + var acceptableDrops, base, base1, base2, chance, drop, dropK, dropMultiplier, name, name1, name2, quest, rarity, ref, ref1, ref2, ref3, task; + task = modifiers.task; + chance = _.min([Math.abs(task.value - 21.27), 37.5]) / 150 + .02; + chance *= task.priority * (1 + (task.streak / 100 || 0)) * (1 + (user._statsComputed.per / 100)) * (1 + (user.contributor.level / 40 || 0)) * (1 + (user.achievements.rebirths / 20 || 0)) * (1 + (user.achievements.streak / 200 || 0)) * (user._tmp.crit || 1) * (1 + .5 * (_.reduce(task.checklist, (function(m, i) { + return m + (i.completed ? 1 : 0); + }), 0) || 0)); + chance = api.diminishingReturns(chance, 0.75); + quest = content.quests[(ref = user.party.quest) != null ? ref.key : void 0]; + if ((quest != null ? quest.collect : void 0) && user.fns.predictableRandom(user.stats.gp) < chance) { + dropK = user.fns.randomVal(quest.collect, { + key: true + }); + user.party.quest.progress.collect[dropK]++; + if (typeof user.markModified === "function") { + user.markModified('party.quest.progress'); + } + } + dropMultiplier = ((ref1 = user.purchased) != null ? (ref2 = ref1.plan) != null ? ref2.customerId : void 0 : void 0) ? 2 : 1; + if ((api.daysSince(user.items.lastDrop.date, user.preferences) === 0) && (user.items.lastDrop.count >= dropMultiplier * (5 + Math.floor(user._statsComputed.per / 25) + (user.contributor.level || 0)))) { + return; + } + if (((ref3 = user.flags) != null ? ref3.dropsEnabled : void 0) && user.fns.predictableRandom(user.stats.exp) < chance) { + rarity = user.fns.predictableRandom(user.stats.gp); + if (rarity > .6) { + drop = user.fns.randomVal(_.where(content.food, { + canDrop: true + })); + if ((base = user.items.food)[name = drop.key] == null) { + base[name] = 0; + } + user.items.food[drop.key] += 1; + drop.type = 'Food'; + drop.dialog = i18n.t('messageDropFood', { + dropArticle: drop.article, + dropText: drop.text(req.language), + dropNotes: drop.notes(req.language) + }, req.language); + } else if (rarity > .3) { + drop = user.fns.randomVal(content.dropEggs); + if ((base1 = user.items.eggs)[name1 = drop.key] == null) { + base1[name1] = 0; + } + user.items.eggs[drop.key]++; + drop.type = 'Egg'; + drop.dialog = i18n.t('messageDropEgg', { + dropText: drop.text(req.language), + dropNotes: drop.notes(req.language) + }, req.language); + } else { + acceptableDrops = rarity < .02 ? ['Golden'] : rarity < .09 ? ['Zombie', 'CottonCandyPink', 'CottonCandyBlue'] : rarity < .18 ? ['Red', 'Shade', 'Skeleton'] : ['Base', 'White', 'Desert']; + drop = user.fns.randomVal(_.pick(content.hatchingPotions, (function(v, k) { + return indexOf.call(acceptableDrops, k) >= 0; + }))); + if ((base2 = user.items.hatchingPotions)[name2 = drop.key] == null) { + base2[name2] = 0; + } + user.items.hatchingPotions[drop.key]++; + drop.type = 'HatchingPotion'; + drop.dialog = i18n.t('messageDropPotion', { + dropText: drop.text(req.language), + dropNotes: drop.notes(req.language) + }, req.language); + } + user._tmp.drop = drop; + user.items.lastDrop.date = +(new Date); + return user.items.lastDrop.count++; + } + }, + + /* + Updates user stats with new stats. Handles death, leveling up, etc + {stats} new stats + {update} if aggregated changes, pass in userObj as update. otherwise commits will be made immediately + */ + autoAllocate: function() { + return user.stats[(function() { + var diff, ideal, lvlDiv7, preference, stats, suggested; + switch (user.preferences.allocationMode) { + case "flat": + stats = _.pick(user.stats, $w('con str per int')); + return _.invert(stats)[_.min(stats)]; + case "classbased": + lvlDiv7 = user.stats.lvl / 7; + ideal = [lvlDiv7 * 3, lvlDiv7 * 2, lvlDiv7, lvlDiv7]; + preference = (function() { + switch (user.stats["class"]) { + case "wizard": + return ["int", "per", "con", "str"]; + case "rogue": + return ["per", "str", "int", "con"]; + case "healer": + return ["con", "int", "str", "per"]; + default: + return ["str", "con", "per", "int"]; + } + })(); + diff = [user.stats[preference[0]] - ideal[0], user.stats[preference[1]] - ideal[1], user.stats[preference[2]] - ideal[2], user.stats[preference[3]] - ideal[3]]; + suggested = _.findIndex(diff, (function(val) { + if (val === _.min(diff)) { + return true; + } + })); + if (~suggested) { + return preference[suggested]; + } else { + return "str"; + } + case "taskbased": + suggested = _.invert(user.stats.training)[_.max(user.stats.training)]; + _.merge(user.stats.training, { + str: 0, + int: 0, + con: 0, + per: 0 + }); + return suggested || "str"; + default: + return "str"; + } + })()]++; + }, + updateStats: function(stats, req, analytics) { + var tnl; + if (stats.hp <= 0) { + return user.stats.hp = 0; + } + user.stats.hp = stats.hp; + user.stats.gp = stats.gp >= 0 ? stats.gp : 0; + tnl = api.tnl(user.stats.lvl); + if (stats.exp >= tnl) { + user.stats.exp = stats.exp; + while (stats.exp >= tnl) { + stats.exp -= tnl; + user.stats.lvl++; + tnl = api.tnl(user.stats.lvl); + user.stats.hp = 50; + if (user.stats.lvl > api.maxLevel) { + continue; + } + if (user.preferences.automaticAllocation) { + user.fns.autoAllocate(); + } else { + user.stats.points = user.stats.lvl - (user.stats.con + user.stats.str + user.stats.per + user.stats.int); + if (user.stats.points < 0) { + user.stats.points = 0; + } + } + } + } + user.stats.exp = stats.exp; + if (user.flags == null) { + user.flags = {}; + } + if (!user.flags.customizationsNotification && (user.stats.exp > 5 || user.stats.lvl > 1)) { + user.flags.customizationsNotification = true; + } + if (!user.flags.itemsEnabled && (user.stats.exp > 10 || user.stats.lvl > 1)) { + user.flags.itemsEnabled = true; + } + if (!user.flags.dropsEnabled && user.stats.lvl >= 3) { + user.flags.dropsEnabled = true; + if (user.items.eggs["Wolf"] > 0) { + user.items.eggs["Wolf"]++; + } else { + user.items.eggs["Wolf"] = 1; + } + } + if (!user.flags.classSelected && user.stats.lvl >= 10) { + user.flags.classSelected; + } + _.each({ + vice1: 30, + atom1: 15, + moonstone1: 60, + goldenknight1: 40 + }, function(lvl, k) { + var analyticsData, base, base1, ref; + if (!((ref = user.flags.levelDrops) != null ? ref[k] : void 0) && user.stats.lvl >= lvl) { + if ((base = user.items.quests)[k] == null) { + base[k] = 0; + } + user.items.quests[k]++; + ((base1 = user.flags).levelDrops != null ? base1.levelDrops : base1.levelDrops = {})[k] = true; + if (typeof user.markModified === "function") { + user.markModified('flags.levelDrops'); + } + analyticsData = { + uuid: user._id, + itemKey: k, + acquireMethod: 'Level Drop', + category: 'behavior' + }; + if (analytics != null) { + analytics.track('acquire item', analyticsData); + } + return user._tmp.drop = { + type: 'Quest', + key: k + }; + } + }); + if (!user.flags.rebirthEnabled && (user.stats.lvl >= 50 || user.achievements.beastMaster)) { + return user.flags.rebirthEnabled = true; + } + }, + + /* + ------------------------------------------------------ + Cron + ------------------------------------------------------ + */ + + /* + At end of day, add value to all incomplete Daily & Todo tasks (further incentive) + For incomplete Dailys, deduct experience + Make sure to run this function once in a while as server will not take care of overnight calculations. + And you have to run it every time client connects. + {user} + */ + cron: function(options) { + var _progress, analyticsData, base, base1, base2, base3, base4, clearBuffs, dailyChecked, dailyDueUnchecked, daysMissed, expTally, lvl, lvlDiv2, multiDaysCountAsOneDay, now, perfect, plan, progress, ref, ref1, ref2, ref3, todoTally; + if (options == null) { + options = {}; + } + now = +options.now || +(new Date); + daysMissed = api.daysSince(user.lastCron, _.defaults({ + now: now + }, user.preferences)); + if (!(daysMissed > 0)) { + return; + } + user.auth.timestamps.loggedin = new Date(); + user.lastCron = now; + if (user.items.lastDrop.count > 0) { + user.items.lastDrop.count = 0; + } + perfect = true; + clearBuffs = { + str: 0, + int: 0, + per: 0, + con: 0, + stealth: 0, + streaks: false + }; + plan = (ref = user.purchased) != null ? ref.plan : void 0; + if (plan != null ? plan.customerId : void 0) { + if (moment(plan.dateUpdated).format('MMYYYY') !== moment().format('MMYYYY')) { + plan.gemsBought = 0; + plan.dateUpdated = new Date(); + _.defaults(plan.consecutive, { + count: 0, + offset: 0, + trinkets: 0, + gemCapExtra: 0 + }); + plan.consecutive.count++; + if (plan.consecutive.offset > 0) { + plan.consecutive.offset--; + } else if (plan.consecutive.count % 3 === 0) { + plan.consecutive.trinkets++; + plan.consecutive.gemCapExtra += 5; + if (plan.consecutive.gemCapExtra > 25) { + plan.consecutive.gemCapExtra = 25; + } + } + } + if (plan.dateTerminated && moment(plan.dateTerminated).isBefore(+(new Date))) { + _.merge(plan, { + planId: null, + customerId: null, + paymentMethod: null + }); + _.merge(plan.consecutive, { + count: 0, + offset: 0, + gemCapExtra: 0 + }); + if (typeof user.markModified === "function") { + user.markModified('purchased.plan'); + } + } + } + if (user.preferences.sleep === true) { + user.stats.buffs = clearBuffs; + user.dailys.forEach(function(daily) { + var completed, repeat, thatDay; + completed = daily.completed, repeat = daily.repeat; + thatDay = moment(now).subtract({ + days: 1 + }); + if (api.shouldDo(thatDay.toDate(), daily, user.preferences) || completed) { + _.each(daily.checklist, (function(box) { + box.completed = false; + return true; + })); + } + return daily.completed = false; + }); + return; + } + multiDaysCountAsOneDay = true; + todoTally = 0; + user.todos.forEach(function(task) { + var absVal, completed, delta, id; + if (!task) { + return; + } + id = task.id, completed = task.completed; + delta = user.ops.score({ + params: { + id: task.id, + direction: 'down' + }, + query: { + times: multiDaysCountAsOneDay != null ? multiDaysCountAsOneDay : { + 1: daysMissed + }, + cron: true + } + }); + absVal = completed ? Math.abs(task.value) : task.value; + return todoTally += absVal; + }); + dailyChecked = 0; + dailyDueUnchecked = 0; + if ((base = user.party.quest.progress).down == null) { + base.down = 0; + } + user.dailys.forEach(function(task) { + var EvadeTask, completed, delta, fractionChecked, id, j, n, ref1, ref2, scheduleMisses, thatDay; + if (!task) { + return; + } + id = task.id, completed = task.completed; + EvadeTask = 0; + scheduleMisses = daysMissed; + if (completed) { + dailyChecked += 1; + } else { + scheduleMisses = 0; + for (n = j = 0, ref1 = daysMissed; 0 <= ref1 ? j < ref1 : j > ref1; n = 0 <= ref1 ? ++j : --j) { + thatDay = moment(now).subtract({ + days: n + 1 + }); + if (api.shouldDo(thatDay.toDate(), task, user.preferences)) { + scheduleMisses++; + if (user.stats.buffs.stealth) { + user.stats.buffs.stealth--; + EvadeTask++; + } + if (multiDaysCountAsOneDay) { + break; + } + } + } + if (scheduleMisses > EvadeTask) { + perfect = false; + if (((ref2 = task.checklist) != null ? ref2.length : void 0) > 0) { + fractionChecked = _.reduce(task.checklist, (function(m, i) { + return m + (i.completed ? 1 : 0); + }), 0) / task.checklist.length; + dailyDueUnchecked += 1 - fractionChecked; + dailyChecked += fractionChecked; + } else { + dailyDueUnchecked += 1; + } + delta = user.ops.score({ + params: { + id: task.id, + direction: 'down' + }, + query: { + times: multiDaysCountAsOneDay != null ? multiDaysCountAsOneDay : { + 1: scheduleMisses - EvadeTask + }, + cron: true + } + }); + user.party.quest.progress.down += delta * (task.priority < 1 ? task.priority : 1); + } + } + (task.history != null ? task.history : task.history = []).push({ + date: +(new Date), + value: task.value + }); + task.completed = false; + if (completed || (scheduleMisses > 0)) { + return _.each(task.checklist, (function(i) { + i.completed = false; + return true; + })); + } + }); + user.habits.forEach(function(task) { + if (task.up === false || task.down === false) { + if (Math.abs(task.value) < 0.1) { + return task.value = 0; + } else { + return task.value = task.value / 2; + } + } + }); + ((base1 = (user.history != null ? user.history : user.history = {})).todos != null ? base1.todos : base1.todos = []).push({ + date: now, + value: todoTally + }); + expTally = user.stats.exp; + lvl = 0; + while (lvl < (user.stats.lvl - 1)) { + lvl++; + expTally += api.tnl(lvl); + } + ((base2 = user.history).exp != null ? base2.exp : base2.exp = []).push({ + date: now, + value: expTally + }); + if (!((ref1 = user.purchased) != null ? (ref2 = ref1.plan) != null ? ref2.customerId : void 0 : void 0)) { + user.fns.preenUserHistory(); + if (typeof user.markModified === "function") { + user.markModified('history'); + } + if (typeof user.markModified === "function") { + user.markModified('dailys'); + } + } + user.stats.buffs = perfect ? ((base3 = user.achievements).perfect != null ? base3.perfect : base3.perfect = 0, user.achievements.perfect++, lvlDiv2 = Math.ceil(api.capByLevel(user.stats.lvl) / 2), { + str: lvlDiv2, + int: lvlDiv2, + per: lvlDiv2, + con: lvlDiv2, + stealth: 0, + streaks: false + }) : clearBuffs; + if (dailyDueUnchecked === 0 && dailyChecked === 0) { + dailyChecked = 1; + } + user.stats.mp += _.max([10, .1 * user._statsComputed.maxMP]) * dailyChecked / (dailyDueUnchecked + dailyChecked); + if (user.stats.mp > user._statsComputed.maxMP) { + user.stats.mp = user._statsComputed.maxMP; + } + progress = user.party.quest.progress; + _progress = _.cloneDeep(progress); + _.merge(progress, { + down: 0, + up: 0 + }); + progress.collect = _.transform(progress.collect, (function(m, v, k) { + return m[k] = 0; + })); + if ((base4 = user.flags).cronCount == null) { + base4.cronCount = 0; + } + user.flags.cronCount++; + analyticsData = { + category: 'behavior', + gaLabel: 'Cron Count', + gaValue: user.flags.cronCount, + uuid: user._id, + user: user, + resting: user.preferences.sleep, + cronCount: user.flags.cronCount, + progressUp: _.min([_progress.up, 900]), + progressDown: _progress.down + }; + if ((ref3 = options.analytics) != null) { + ref3.track('Cron', analyticsData); + } + return _progress; + }, + preenUserHistory: function(minHistLen) { + if (minHistLen == null) { + minHistLen = 7; + } + _.each(user.habits.concat(user.dailys), function(task) { + var ref; + if (((ref = task.history) != null ? ref.length : void 0) > minHistLen) { + task.history = preenHistory(task.history); + } + return true; + }); + _.defaults(user.history, { + todos: [], + exp: [] + }); + if (user.history.exp.length > minHistLen) { + user.history.exp = preenHistory(user.history.exp); + } + if (user.history.todos.length > minHistLen) { + return user.history.todos = preenHistory(user.history.todos); + } + }, + ultimateGear: function() { + var base, owned; + owned = typeof window !== "undefined" && window !== null ? user.items.gear.owned : user.items.gear.owned.toObject(); + if ((base = user.achievements).ultimateGearSets == null) { + base.ultimateGearSets = { + healer: false, + wizard: false, + rogue: false, + warrior: false + }; + } + content.classes.forEach(function(klass) { + if (user.achievements.ultimateGearSets[klass] !== true) { + return user.achievements.ultimateGearSets[klass] = _.reduce(['armor', 'shield', 'head', 'weapon'], function(soFarGood, type) { + var found; + found = _.find(content.gear.tree[type][klass], { + last: true + }); + return soFarGood && (!found || owned[found.key] === true); + }, true); + } + }); + if (typeof user.markModified === "function") { + user.markModified('achievements.ultimateGearSets'); + } + if (_.contains(user.achievements.ultimateGearSets, true) && user.flags.armoireEnabled !== true) { + user.flags.armoireEnabled = true; + return typeof user.markModified === "function" ? user.markModified('flags') : void 0; + } + }, + nullify: function() { + user.ops = null; + user.fns = null; + return user = null; + } + }; + Object.defineProperty(user, '_statsComputed', { + get: function() { + var computed; + computed = _.reduce(['per', 'con', 'str', 'int'], (function(_this) { + return function(m, stat) { + m[stat] = _.reduce($w('stats stats.buffs items.gear.equipped.weapon items.gear.equipped.armor items.gear.equipped.head items.gear.equipped.shield'), function(m2, path) { + var item, val; + val = user.fns.dotGet(path); + return m2 + (~path.indexOf('items.gear') ? (item = content.gear.flat[val], (+(item != null ? item[stat] : void 0) || 0) * ((item != null ? item.klass : void 0) === user.stats["class"] || (item != null ? item.specialClass : void 0) === user.stats["class"] ? 1.5 : 1)) : +val[stat] || 0); + }, 0); + m[stat] += Math.floor(api.capByLevel(user.stats.lvl) / 2); + return m; + }; + })(this), {}); + computed.maxMP = computed.int * 2 + 30; + return computed; + } + }); + return Object.defineProperty(user, 'tasks', { + get: function() { + var tasks; + tasks = user.habits.concat(user.dailys).concat(user.todos).concat(user.rewards); + return _.object(_.pluck(tasks, "id"), tasks); + } + }); +}; diff --git a/package.json b/package.json index 3117ca87b9..40c04bdfbb 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,12 @@ "async": "^1.5.0", "aws-sdk": "^2.0.25", "babel": "^5.5.4", + "babelify": "^7.2.0", "body-parser": "^1.14.1", + "compression": "^1.6.0", "bower": "~1.3.12", "browserify": "~12.0.1", "coffee-script": "1.6.x", - "coffeeify": "0.6.0", - "compression": "^1.6.0", "connect-ratelimit": "0.0.7", "cookie-parser": "^1.4.0", "cookie-session": "^1.2.0", @@ -29,7 +29,6 @@ "firebase-token-generator": "^2.0.0", "glob": "^4.3.5", "grunt": "~0.4.1", - "grunt-browserify": "^3.3.0", "grunt-cli": "~0.1.9", "grunt-contrib-clean": "~0.6.0", "grunt-contrib-copy": "~0.6.0", @@ -45,6 +44,8 @@ "gulp-grunt": "^0.5.2", "gulp-imagemin": "^2.3.0", "gulp-nodemon": "^2.0.4", + "gulp-sourcemaps": "^1.6.0", + "gulp-uglify": "^1.4.2", "gulp.spritesmith": "^4.1.0", "icalendar": "lefnire/node-icalendar#e06da0e55901f0ba940dfadc42c158ed0b1fead9", "image-size": "~0.3.2", @@ -81,6 +82,8 @@ "swagger-node-express": "lefnire/swagger-node-express#habitrpg", "universal-analytics": "~0.3.2", "validator": "~4.2.1", + "vinyl-buffer": "^1.0.0", + "vinyl-source-stream": "^1.1.0", "winston": "^2.1.0" }, "private": true, @@ -98,7 +101,6 @@ "devDependencies": { "chai": "^3.4.0", "chai-as-promised": "^5.1.0", - "coffee-coverage": "~0.4.2", "coveralls": "^2.11.2", "csv": "~0.3.6", "deep-diff": "~0.1.4", diff --git a/register-handlers.js b/register-handlers.js deleted file mode 100644 index 7a6c57a91a..0000000000 --- a/register-handlers.js +++ /dev/null @@ -1,7 +0,0 @@ -if(process.env.COVERAGE) { - require('coffee-coverage').register({ - path: 'abbr', - basePath: __dirname + '/common/script', - initAll: true, - }); -} diff --git a/tasks/gulp-babelify.js b/tasks/gulp-babelify.js index a77be47ecc..a5bd7af203 100644 --- a/tasks/gulp-babelify.js +++ b/tasks/gulp-babelify.js @@ -1,16 +1,31 @@ import gulp from 'gulp'; -import babel from 'gulp-babel'; +import browserify from 'browserify'; +import source from 'vinyl-source-stream'; +import buffer from 'vinyl-buffer'; +import uglify from 'gulp-uglify'; +import sourcemaps from 'gulp-sourcemaps'; +import babel from 'babelify'; -const ES2015_SOURCE = 'common/script/src/**/*.js'; -const ES2015_DIST = 'common/dist/scripts/'; +gulp.task('browserify', function () { + let bundler = browserify({ + entries: './common/index.js', + debug: true, + transform: [[babel, { compact: false }]] + }); -gulp.task('babel:common', () => { - return gulp.src(ES2015_SOURCE) - .pipe(babel()) - .pipe(gulp.dest(ES2015_DIST)); + return bundler.bundle() + .pipe(source('habitrpg-shared.js')) + .pipe(buffer()) + .pipe(sourcemaps.init({loadMaps: true})) + .pipe(uglify()) + .on('error', function (err) { + console.error(err); + this.emit('end'); + }) + .pipe(sourcemaps.write('./')) + .pipe(gulp.dest('./common/dist/scripts/')); }); -gulp.task('babel:common:watch', () => { - gulp.watch([ES2015_SOURCE], ['babel:common']); +gulp.task('browserify:watch', () => { + gulp.watch('./common/script/**/*.js', ['browserify']); }); - diff --git a/tasks/gulp-build.js b/tasks/gulp-build.js index 8b0b752ca2..599d577b10 100644 --- a/tasks/gulp-build.js +++ b/tasks/gulp-build.js @@ -9,7 +9,7 @@ gulp.task('build', () => { } }); -gulp.task('build:dev', ['babel:common', 'prepare:staticNewStuff'], (done) => { +gulp.task('build:dev', ['browserify', 'prepare:staticNewStuff'], (done) => { gulp.start('grunt-build:dev', done); }); @@ -17,6 +17,6 @@ gulp.task('build:dev:watch', ['build:dev'], () => { gulp.watch(['website/public/**/*.styl', 'common/script/*']); }); -gulp.task('build:prod', ['babel:common', 'prepare:staticNewStuff'], (done) => { +gulp.task('build:prod', ['browserify', 'prepare:staticNewStuff'], (done) => { gulp.start('grunt-build:prod', done); }); diff --git a/tasks/gulp-console.js b/tasks/gulp-console.js index 768df81e3b..84c389578b 100644 --- a/tasks/gulp-console.js +++ b/tasks/gulp-console.js @@ -1,5 +1,3 @@ -import 'coffee-script'; - import mongoose from 'mongoose'; import autoinc from 'mongoose-id-autoinc'; import logging from '../website/src/libs/api-v2/logging'; diff --git a/tasks/gulp-eslint.js b/tasks/gulp-eslint.js index 6b1306049c..403dc517f3 100644 --- a/tasks/gulp-eslint.js +++ b/tasks/gulp-eslint.js @@ -7,7 +7,6 @@ import eslint from 'gulp-eslint'; // TODO what about prefer-const rule? // TODO remove estraverse dependency once https://github.com/adametry/gulp-eslint/issues/117 sorted out gulp.task('lint:server', () => { - // Ignore .coffee files return gulp .src([ './website/src/**/api-v3/**/*.js', @@ -19,4 +18,4 @@ gulp.task('lint:server', () => { .pipe(eslint.failAfterError()); }); -gulp.task('lint', ['lint:server']); \ No newline at end of file +gulp.task('lint', ['lint:server']); diff --git a/test/api-legacy/api-helper.js b/test/api-legacy/api-helper.js index b74e004847..e972a0cc34 100644 --- a/test/api-legacy/api-helper.js +++ b/test/api-legacy/api-helper.js @@ -1,4 +1,3 @@ -require('coffee-script'); require('babel/register'); var path, superagentDefaults; diff --git a/test/archive/README.md b/test/archive/README.md deleted file mode 100644 index 27eaee4c77..0000000000 --- a/test/archive/README.md +++ /dev/null @@ -1,3 +0,0 @@ -These are tests which are no longer used. While we could delete them and depend on git history for later lookup, -I think it's important these are visible to developers since they may have valuable tests which haven't been ported -to our new setup. Once a file is ported or determined useless, feel free to delete. \ No newline at end of file diff --git a/test/archive/api.mocha.coffee b/test/archive/api.mocha.coffee deleted file mode 100644 index cf9d276f03..0000000000 --- a/test/archive/api.mocha.coffee +++ /dev/null @@ -1,656 +0,0 @@ -_ = require 'lodash' -expect = require 'expect.js' -require 'coffee-script' -async = require 'async' -superagentDefaults = require 'superagent-defaults' - -request = superagentDefaults() - -conf = require("nconf") -conf.argv().env().file({file: __dirname + '../config.json'}).defaults -conf.set('port','1337') - -# Override normal ENV values with nconf ENV values (ENV values are used the same way without nconf) -#FIXME can't get nconf file above to load... -process.env.BASE_URL = conf.get("BASE_URL") -process.env.FACEBOOK_KEY = conf.get("FACEBOOK_KEY") -process.env.FACEBOOK_SECRET = conf.get("FACEBOOK_SECRET") -process.env.NODE_DB_URI = 'mongodb://localhost/habitrpg' - -User = require('../../src/models/user').model -Group = require('../../src/models/group').model -Challenge = require('../../src/models/challenge').model - -app = require '../../src/server' - -## monkey-patch expect.js for better diffs on mocha -## see: https://github.com/LearnBoost/expect.js/pull/34 -#origBe = expect.Assertion::be -#expect.Assertion::be = expect.Assertion::equal = (obj) -> -# @_expected = obj -# origBe.call this, obj - -# Custom modules -shared = require 'habitrpg-shared' - -###### Helpers & Variables ###### - -model = null -uuid = null -taskPath = null -baseURL = 'http://localhost:3000/api/v2' - -### - expect().eql expects object keys to be in the correct order, this sorts that out -### - -expectUserEqual = (u1, u2) -> - [u1, u2] = _.map [u1, u2], (obj) -> - 'update__ stats.toNextLevel stats.maxHealth __v'.split(' ').forEach (path) -> - helpers.dotSet path, null, obj - sorted = {} - _.each _.keys(obj).sort(), (k) -> sorted[k] = obj[k] - sorted.tasks = _.sortBy sorted.tasks, 'id' - sorted -# console.log {u1, u2} - expect(u1).to.eql(u2) - -expectSameValues = (obj1, obj2, paths) -> - _.each paths, (k) -> - expect(helpers.dotGet(k,obj1)).to.eql helpers.dotGet(k,obj2) - -expectCode = (res, code) -> - expect(res.body.err).to.be undefined if code is 200 - expect(res.statusCode).to.be code - -###### Specs ###### - -describe 'API', -> - user = null - _id = null - apiToken = null - username = null - password = null - - registerNewUser = (cb, main=true)-> - randomID = shared.uuid() - [username,password] = [randomID,randomID] if main - request.post("#{baseURL}/register") - .set('Accept', 'application/json') - .send({ - username: randomID - password: randomID - confirmPassword: randomID - email: "#{randomID}@gmail.com" - }) - .end (res) -> - return cb(null,res.body) unless main - {_id,apiToken} = res.body - console.log {_id,apiToken} - User.findOne {_id, apiToken}, (err, _user) -> - expect(err).to.not.be.ok - user = _user - request - .set('Accept', 'application/json') - .set('X-API-User', _id) - .set('X-API-Key', apiToken) - cb null, res.body - - before (done)-> - require '../../src/server' #start the server - # then wait for it to do it's thing. TODO make a cb-compatible export of server - setTimeout done, 2000 - - describe 'Without token or user id', -> - it '/api/v2/status', (done) -> - request.get("#{baseURL}/status") - .set('Accept', 'application/json') - .end (res) -> - expect(res.statusCode).to.be 200 - expect(res.body.status).to.be 'up' - done() - - it '/api/v2/user', (done) -> - request.get("#{baseURL}/user") - .set('Accept', 'application/json') - .end (res) -> - expect(res.statusCode).to.be 401 - expect(res.body.err).to.be 'You must include a token and uid (user id) in your request' - done() - - describe 'With token and user id', -> - currentUser = null - - before (done) -> - registerNewUser(done,true) - - beforeEach (done) -> - User.findById _id, (err,_user) -> - currentUser = _user - done() - - ############ - # Groups - ############ - - describe 'Groups', -> - group = undefined - - before (done) -> - request.post("#{baseURL}/groups") - .send({name:"TestGroup", type:"party"}) - .end (res) -> - expectCode res, 200 - group = res.body - expect(group.members.length).to.be 1 - expect(group.leader).to.be user._id - done() - - describe 'Challenges', -> - challenge = undefined - updateTodo = undefined - - it 'Creates a challenge', (done) -> - request.post("#{baseURL}/challenges") - .send({ - group:group._id - dailys: [{type:'daily',text:'Challenge Daily'}] - todos: [{type:'todo', text:'Challenge Todo', notes:'Challenge Notes'}] - rewards: [] - habits: [] - official: true - }) - .end (res) -> - expectCode res, 200 - async.parallel [ - (cb) -> User.findById _id, cb - (cb) -> Challenge.findById res.body._id, cb - ], (err, results) -> - [_user,challenge] = [results[0],results[1]] - expect(_user.dailys[_user.dailys.length-1].text).to.be('Challenge Daily') - updateTodo = _user.todos[_user.todos.length-1] - expect(updateTodo.text).to.be('Challenge Todo') - expect(challenge.official).to.be false - done() - - it 'User updates challenge notes', (done) -> - updateTodo.notes = "User overriden notes" - request.put("#{baseURL}/user/tasks/#{updateTodo.id}") - .send(updateTodo) - .end (res) -> - done() #we'll do the check down below - - it 'Change challenge daily', (done) -> - challenge.dailys[0].text = 'Updated Daily' - challenge.todos[0].notes = 'Challenge Updated Todo Notes' - request.post("#{baseURL}/challenges/#{challenge._id}") - .send(challenge) - .end (res) -> - setTimeout -> - User.findById _id, (err,_user) -> - expectCode res, 200 - expect(_user.dailys[_user.dailys.length-1].text).to.be('Updated Daily') - expect(res.body.todos[0].notes).to.be('Challenge Updated Todo Notes') - expect(_user.todos[_user.todos.length-1].notes).to.be('User overriden notes') - currentUser = _user - done() - , 500 # we have to wait a while for users' tasks to be updated, called async on server - - it 'Shows user notes on challenge page', (done) -> - request.get("#{baseURL}/challenges/#{challenge._id}/member/#{_id}") - .end (res) -> - expect(res.body.todos[res.body.todos.length-1].notes).to.be('User overriden notes') - done() - - it 'Complete To-Dos', (done) -> - u = currentUser - request.post("#{baseURL}/user/tasks/#{u.todos[0].id}/up").end (res) -> - request.post("#{baseURL}/user/tasks/#{u.todos[1].id}/up").end (res) -> - request.post("#{baseURL}/user/tasks/").send({type:'todo'}).end (res) -> - request.post("#{baseURL}/user/tasks/clear-completed").end (res) -> - expect(_.size res.body).to.be 2 - done() - - it 'Admin creates a challenge', (done) -> - User.findByIdAndUpdate _id, {$set:{'contributor.admin':true}}, (err,_user) -> - expect(err).to.not.be.ok - - async.parallel [ - (cb)-> - request.post("#{baseURL}/challenges") - .send({group:group._id, dailys: [], todos: [], rewards: [], habits: [], official: false}).end (res) -> - expect(res.body.official).to.be false - cb() - (cb)-> - request.post("#{baseURL}/challenges") - .send({group:group._id, dailys: [], todos: [], rewards: [], habits: [], official: true}).end (res) -> - expect(res.body.official).to.be true - cb() - ], done - - - describe 'Quests', -> - party = undefined - participating = [] - notParticipating = [] - - it 'Invites some members', (done) -> - async.waterfall [ - - # Register new users - (cb) -> - async.parallel [ - (cb2) -> registerNewUser(cb2,false) - (cb2) -> registerNewUser(cb2,false) - (cb2) -> registerNewUser(cb2,false) - ], cb - - # Send them invitations - (_party, cb) -> - party = _party - async.parallel [ - (cb2) -> request.post("#{baseURL}/groups/#{group._id}/invite?uuid=#{party[0]._id}").end (-> cb2()) - (cb2) -> request.post("#{baseURL}/groups/#{group._id}/invite?uuid=#{party[1]._id}").end (-> cb2()) - (cb2) -> request.post("#{baseURL}/groups/#{group._id}/invite?uuid=#{party[2]._id}").end (-> cb2()) - ], cb - - # Accept / Reject - (results, cb) -> - #series since they'll be modifying the same group record - async.series (_.reduce party, (m,v,i) -> - m.push (cb2) -> - request.post("#{baseURL}/groups/#{group._id}/join") - .set('X-API-User', party[i]._id) - .set('X-API-Key', party[i].apiToken) - .end (res) -> cb2() - m - , []), cb - - # Make sure the invites stuck - (whatever, cb) -> - Group.findById group._id, (err, g) -> - expect(g.members.length).to.be 4 - cb() - - ], (err, results) -> - expect(err).to.be.ok - done() - - it 'Starts a quest', (done) -> - async.waterfall [ - (cb)-> - request.post("#{baseURL}/groups/#{group._id}/questAccept?key=evilsanta") - .end (res) -> - expectCode(res, 401) - User.findByIdAndUpdate _id, {$set:'items.quests.evilsanta':1}, cb - (_user,cb)-> - request.post("#{baseURL}/groups/#{group._id}/questAccept?key=evilsanta") - .end (res) -> - expectCode(res, 200) - Group.findById group._id,cb - (_group,cb)-> - group = _group #refresh local group - expect(group.quest.key).to.be 'evilsanta' - - async.series (_.reduce party, (m,v,i) -> - m.push (cb2) -> - request.post("#{baseURL}/groups/#{group._id}/questAccept") - .set('X-API-User', party[i]._id) - .set('X-API-Key', party[i].apiToken) - .end (res) -> cb2() - m - , []), cb - - ], done - - it "Doesn't include people who aren't participating" - - -# ############ -# # Batch Update -# ############ -# -# describe 'Batch Update', -> -# -# it 'POST /api/v1/batch-update', (done) -> -# userBefore = _.cloneDeep(currentUser) -# -# ops = [ -# # Good scores -# op: 'score', params: {id:user.habits[0].id, direction: 'up'} -# op: 'score', params: {id:user.habits[1].id, direction: 'down'} -# op: 'score', params: {id:user.dailys[0].id, direction: 'up'} -# op: 'score', params: {id:user.todos[0].id, direction: 'up'} -# ] -# -# request.post("#{baseURL}/user/batch-update") -# .send(ops) -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 200 -# #expectUserEqual(userBefore, res.body) -# done() -# -# -# ############ -# # To Be Updated (these are old v1 tests which haven't been touched in over 6 months, need to be portd to new API tests or deleted) -# ############ -# -# it.skip 'POST /api/v2/batch-update (handles corrupt values)', (done) -> -# registerNewUser (_res) -> -# # corrupt the tasks, and let's see how the server handles this -# ids = _res.dailyIds -# _res.tasks[ids[0]].value = NaN -# _res.tasks[ids[1]].value = undefined -# _res.tasks[ids[2]] = {} -# _res.tasks["undefined"] = {} -# -# _res.stats.hp = _res.stats.gp = NaN -# -# _res.lastCron = +new Date('08/13/2013') -# -# ops = [ -# op: 'score', task: _res.tasks[ids[0]], dir: 'up' -# ] -# -# model.set "users.#{_res.id}", _res, -> -# request.post("#{baseURL}/user/batch-update") -# .set('Accept', 'application/json') -# .set('X-API-User', _res.id) -# .set('X-API-Key', _res.apiToken) -# .send(ops) -# .end (res) -> -# expect(res.statusCode).to.be 200 -# console.log {stats:res.body.stats, tasks:res.body.tasks} -# done() -# -# -# #FIXME figure out how to compare the objects -# it.skip 'GET /api/v1/user', (done) -> -# request.get("#{baseURL}/user") -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 200 -# expect(res.body.id).not.to.be.empty() -# self = _.clone(currentUser) -# delete self.apiToken -# self.stats.toNextLevel = 150 -# self.stats.maxHealth = 50 -# -# expectUserEqual(res.body, self) -# done() -# -# it.skip 'GET /api/v1/user/task/:id', (done) -> -# tid = _.pluck(currentUser.tasks, 'id')[0] -# request.get("#{baseURL}/user/task/#{tid}") -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 200 -# expect(res.body).to.eql currentUser.tasks[tid] -# done() -# -# it.skip 'POST /api/v1/user/task', (done) -> -# request.post("#{baseURL}/user/task") -# .send({title: 'Title', text: 'Text', type: 'habit'}) -# .end (res) -> -# query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken) -# query.fetch (err, user) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 201 -# expect(res.body.id).not.to.be.empty() -# # Ensure that user owns the newly created object -# saved = user.get("tasks.#{res.body.id}") -# expect(saved).to.be.an('object') -# done() -# -# it.skip 'POST /api/v1/user/task (without type)', (done) -> -# request.post("#{baseURL}/user/task") -# .send({}) -# .end (res) -> -# expect(res.body.err).to.be 'type must be habit, todo, daily, or reward' -# expect(res.statusCode).to.be 400 -# done() -# -# it.skip 'POST /api/v1/user/task (only type)', (done) -> -# request.post("#{baseURL}/user/task") -# .send(type: 'habit') -# .end (res) -> -# query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken) -# query.fetch (err, user) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 201 -# expect(res.body.id).not.to.be.empty() -# # Ensure that user owns the newly created object -# expect(user.get().tasks[res.body.id]).to.be.an('object') -# # Ensure that value gets set to 0 since not otherwise specified -# expect(user.get().tasks[res.body.id].value).to.be.equal(0) -# done() -# -# it.skip 'PUT /api/v1/user/task/:id', (done) -> -# tid = _.pluck(currentUser.tasks, 'id')[0] -# request.put("#{baseURL}/user/task/#{tid}") -# .send(text: 'bye') -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 200 -# currentUser.tasks[tid].text = 'bye' -# expectSameValues res.body, currentUser.tasks[tid], ['id','type','text'] -# #expect(res.body).to.eql currentUser.tasks[tid] -# done() -# -# it.skip 'PUT /api/v1/user/task/:id (shouldnt update type)', (done) -> -# tid = _.pluck(currentUser.tasks, 'id')[1] -# type = if currentUser.tasks[tid].type is 'habit' then 'daily' else 'habit' -# request.put("#{baseURL}/user/task/#{tid}") -# .send(type: type, text: 'fishman') -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 200 -# currentUser.tasks[tid].text = 'fishman' -# expect(res.body).to.eql currentUser.tasks[tid] -# done() -# -# it.skip 'PUT /api/v1/user/task/:id (update notes)', (done) -> -# tid = _.pluck(currentUser.tasks, 'id')[2] -# request.put("#{baseURL}/user/task/#{tid}") -# .send(text: 'hi',notes:'foobar matey') -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 200 -# currentUser.tasks[tid].text = 'hi' -# currentUser.tasks[tid].notes = 'foobar matey' -# expect(res.body).to.eql currentUser.tasks[tid] -# done() -# -# it.skip 'GET /api/v1/user/tasks', (done) -> -# request.get("#{baseURL}/user/tasks") -# .end (res) -> -# query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken) -# query.fetch (err, user) -> -# expect(res.body.err).to.be undefined -# expect(user.get()).to.be.ok() -# expect(res.statusCode).to.be 200 -# model.ref '_user', user -# tasks = [] -# for type in ['habit','todo','daily','reward'] -# model.refList "_#{type}List", "_user.tasks", "_user.#{type}Ids" -# tasks = tasks.concat model.get("_#{type}List") -# # Ensure that user owns the tasks -# expect(res.body.length).to.equal tasks.length -# # Ensure that the two sets are equal -# expect(_.difference(_.pluck(res.body,'id'), _.pluck(tasks,'id')).length).to.equal 0 -# done() -# -# it.skip 'GET /api/v1/user/tasks (todos)', (done) -> -# request.get("#{baseURL}/user/tasks") -# .query(type:'todo') -# .end (res) -> -# query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken) -# query.fetch (err, user) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 200 -# model.ref '_user', user -# model.refList "_todoList", "_user.tasks", "_user.todoIds" -# tasks = model.get("_todoList") -# # Ensure that user owns the tasks -# expect(res.body.length).to.equal tasks.length -# # Ensure that the two sets are equal -# expect(_.difference(_.pluck(res.body,'id'), _.pluck(tasks,'id')).length).to.equal 0 -# done() -# -# it.skip 'DELETE /api/v1/user/task/:id', (done) -> -# tid = currentUser.habitIds[2] -# request.del("#{baseURL}/user/task/#{tid}") -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 204 -# query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken) -# query.fetch (err, user) -> -# expect(user.get('habitIds').indexOf(tid)).to.be -1 -# expect(user.get("tasks.#{tid}")).to.be undefined -# done() -# -# it.skip 'DELETE /api/v1/user/task/:id (no task found)', (done) -> -# tid = "adsfasdfjunkshouldntbeatask" -# request.del("#{baseURL}/user/task/#{tid}") -# .end (res) -> -# expect(res.statusCode).to.be 400 -# expect(res.body.err).to.be 'No task found.' -# done() -# -# it.skip 'POST /api/v1/user/task/:id/up (habit)', (done) -> -# tid = currentUser.habitIds[0] -# request.post("#{baseURL}/user/task/#{tid}/up") -# .send({}) -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 200 -# expect(res.body).to.eql { gp: 1, exp: 7.5, lvl: 1, hp: 50, delta: 1 } -# done() -# -# it.skip 'POST /api/v1/user/task/:id/up (daily)', (done) -> -# tid = currentUser.dailyIds[0] -# request.post("#{baseURL}/user/task/#{tid}/up") -# .send({}) -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 200 -# expect(res.body).to.eql { gp: 2, exp: 15, lvl: 1, hp: 50, delta: 1 } -# query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken) -# query.fetch (err, user) -> -# expect(user.get("tasks.#{tid}.completed")).to.be true -# done() -# -# it.skip 'POST /api/v1/user/task (array)', (done) -> -# habitId = currentUser.habitIds[0] -# dailyId = currentUser.dailyIds[0] -# arr = [{ -# id: habitId -# text: 'hello' -# notes: 'note' -# },{ -# text: 'new task' -# notes: 'notes!' -# },{ -# id: dailyId -# del: true -# }] -# -# request.post("#{baseURL}/user/tasks") -# .send(arr) -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 201 -# -# expectSameValues res.body[0], {id: habitId,text: 'hello',notes: 'note'}, ['id','text','notes'] -# expect(res.body[1].id).to.be.a 'string' -# expect(res.body[1].text).to.be 'new task' -# expect(res.body[1].notes).to.be 'notes!' -# expect(res.body[2]).to.eql deleted: true -# -# query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken) -# query.fetch (err, user) -> -# expectSameValues user.get("tasks.#{habitId}"), {id: habitId,text: 'hello',notes: 'note'}, ['id','text','notes'] -# expect(user.get("tasks.#{dailyId}")).to.be undefined -# expectSameValues user.get("tasks.#{res.body[1].id}"), {id: res.body[1].id, text: 'new task', notes: 'notes!'}, ['id','text','notes'] -# done() -# -# it.skip 'PUT /api/v1/user (bad path)', (done) -> -# # These updates should not save, as per the API changes -# userUpdates = -# stats: hp: 30 -# flags: itemsEnabled: true -# tasks: [{ -# text: 'hello2' -# notes: 'note2' -# }] -# -# request.put("#{baseURL}/user") -# .send(userUpdates) -# .end (res) -> -# expect(res.body.err).to.be.ok() -# expect(res.statusCode).to.be 500 -# done() -# -# it.skip 'PUT /api/v1/user', (done) -> -# userBefore = {} -# query = model.query('users').withIdAndToken(currentUser.id, currentUser.apiToken) -# query.fetch (err, user) -> -# userBefore = user.get() -# -# habitId = currentUser.habitIds[0] -# dailyId = currentUser.dailyIds[0] -# updates = {} -# updates['stats.hp'] = 30 -# updates['flags.itemsEnabled'] = true -# updates["tasks.#{habitId}.text"] = 'hello2' -# updates["tasks.#{habitId}.notes"] = 'note2' -# -# request.put("#{baseURL}/user") -# .send(updates) -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 200 -# changesWereMade = (obj) -> -# expect(obj.stats.hp).to.be 30 -# expect(obj.flags.itemsEnabled).to.be true -# expectSameValues _.find(obj.tasks,{id:habitId}), {id: habitId,text: 'hello2',notes: 'note2'}, ['id','text','notes'] -# changesWereMade res.body -# query.fetch (err, user) -> -# changesWereMade user.get() -# done() -# -# it.skip 'POST /api/v1/user/auth/local', (done) -> -# userAuth = {username, password} -# request.post("#{baseURL}/user/auth/local") -# .set('Accept', 'application/json') -# .send(userAuth) -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 200 -# expect(res.body.id).to.be currentUser.id -# expect(res.body.token).to.be currentUser.apiToken -# done() -# -# it.skip 'POST /api/v1/user/auth/facebook', (done) -> -# id = shared.uuid() -# userAuth = facebook_id: 12345, name: 'Tyler Renelle', email: 'x@y.com' -# newUser = helpers.newUser(true) -# newUser.id = id -# newUser.auth = facebook: -# id: userAuth.facebook_id -# name: userAuth.name -# email: userAuth.email -# model.set "users.#{id}", newUser, -> -# -# request.post("#{baseURL}/user/auth/facebook") -# .set('Accept', 'application/json') -# .send(userAuth) -# .end (res) -> -# expect(res.body.err).to.be undefined -# expect(res.statusCode).to.be 200 -# expect(res.body.id).to.be newUser.id -# #expect(res.body.token).to.be newUser.apiToken -# done() -# -# diff --git a/test/archive/casper/dailies.casper.coffee b/test/archive/casper/dailies.casper.coffee deleted file mode 100644 index 3730b91ad9..0000000000 --- a/test/archive/casper/dailies.casper.coffee +++ /dev/null @@ -1,45 +0,0 @@ -helpers = new require('./test/casper/helpers')() -casper = helpers.casper -utils = helpers.utils -url = helpers.playUrl - -casper.start url - -# ---------- Daily ------------ -casper.then -> - helpers.reset() - helpers.addTasks(['daily']) - -# Gained exp on +daily -casper.then -> - helpers.modelBeforeAfter (-> casper.click '.dailys input[type="checkbox"]'), (model) -> - casper.test.assertEquals model.before._user.stats.hp, model.after._user.stats.hp, '+daily =hp' - casper.test.assert model.before._user.stats.exp < model.after._user.stats.exp, '+daily +exp' - casper.test.assert model.before._user.stats.gp < model.after._user.stats.gp, '+daily +gp' - -# -daily acts as undo -casper.then -> - helpers.modelBeforeAfter (-> casper.click '.dailys input[type="checkbox"]'), (model) -> - casper.test.assertEquals model.before._user.stats.hp, model.after._user.stats.hp, '-daily =hp' - casper.test.assert model.before._user.stats.exp > model.after._user.stats.exp, '-daily -exp' - casper.test.assert model.before._user.stats.gp > model.after._user.stats.gp, '-daily -gp' - -# ---------- Cron ------------ -casper.then -> - helpers.reset() - helpers.addTasks(['daily']) - -casper.then -> - helpers.cronBeforeAfter (model) -> - casper.then -> - casper.test.assert model.before._user.stats.hp > model.after._user.stats.hp, 'daily:cron:hp lost value' - - # Go through all the dailys, all of them are uncompleted, so should all get a negative value - casper.echo "Testing all uncompleted dailys after cron" - for id in model.before._user.dailyIds - casper.test.assertEquals model.before._user.tasks[id].value, 0, "daily:cron:daily value before was 0" - casper.test.assert model.after._user.tasks[id].value < 0, "daily:cron:daily value after is negative" - -# ---------- Run ------------ -casper.run -> - casper.test.renderResults true \ No newline at end of file diff --git a/test/archive/casper/general.casper.coffee b/test/archive/casper/general.casper.coffee deleted file mode 100644 index 8ce7280ab8..0000000000 --- a/test/archive/casper/general.casper.coffee +++ /dev/null @@ -1,38 +0,0 @@ -helpers = new require('./test/casper/helpers')() -casper = helpers.casper -utils = helpers.utils -url = helpers.playUrl - -# ---------- Basic Reset Test ------------ - -casper.start url, -> - casper.test.assertTitle 'HabitRPG | Gamify Your Life', 'Page Title' - -# Gain some GP and lose some HP -casper.then -> - casper.repeat 5, -> casper.click '.habits a[data-direction="down"]' - casper.repeat 5, -> casper.click '.habits a[data-direction="up"]' - -# Reset -casper.then -> - helpers.reset() - -# Test that reset worked -casper.then -> - model = helpers.getModelDelayed (model) -> - casper.echo 'testing user after reset' - casper.test.assertEqual model._user.tasks, {}, 'no tasks' - casper.test.assertEqual model._user.stats, {hp:50, gp:0, exp:0, lvl:1}, 'stats' - - -# ---------- Misc Pages ------------ - -casper.thenOpen "#{helpers.baseUrl}/terms", -> - casper.test.assertTitle "Terms Of Use", "terms page works" - -casper.thenOpen "#{helpers.baseUrl}/privacy", -> - casper.test.assertTitle "Privacy Policy", "privacy page works" - -# ---------- Run ------------ -casper.run -> - casper.test.renderResults true \ No newline at end of file diff --git a/test/archive/casper/habits.casper.coffee b/test/archive/casper/habits.casper.coffee deleted file mode 100644 index 075b2ba434..0000000000 --- a/test/archive/casper/habits.casper.coffee +++ /dev/null @@ -1,40 +0,0 @@ -helpers = new require('./test/casper/helpers')() -casper = helpers.casper -utils = helpers.utils -url = helpers.playUrl - -casper.start url - -# # ---------- Register ------------ -# casper.then -> helpers.register() -# casper.then -> user = helpers.getUser() - -# ---------- Habits ------------ -casper.then -> - helpers.reset() - helpers.addTasks(['habit']) - -casper.then -> - helpers.modelBeforeAfter (-> casper.click '.habits a[data-direction="down"]'), (model) -> - casper.test.assert model.before._user.stats.hp > model.after._user.stats.hp, '-habit -hp' - casper.test.assertEquals model.before._user.stats.exp, model.after._user.stats.exp, '-habit =exp' - casper.test.assertEquals model.before._user.stats.gp, model.after._user.stats.gp, '-habit =gp' - -casper.then -> - helpers.modelBeforeAfter (-> casper.click '.habits a[data-direction="up"]'), (model) -> - casper.test.assert model.before._user.stats.exp < model.after._user.stats.exp, '+habit +exp' - casper.test.assert model.before._user.stats.gp < model.after._user.stats.gp, '+habit +gp' - casper.test.assertEquals model.before._user.stats.hp, model.after._user.stats.hp, '+habit =hp' - -# Test Death -casper.then -> - casper.repeat 50, (-> casper.click '.habits a[data-direction="down"]') - casper.then -> - helpers.getModelDelayed (model) -> - casper.test.assertEquals model._user.stats.hp, 0, 'hp==0 (death by habits)' - casper.test.assertEquals model._user.stats.lvl, 0, 'lvl==0 (death by habits)' - casper.test.assertVisible '#dead-modal', 'Revive Modal Visible' - -# ---------- Run ------------ -casper.run -> - casper.test.renderResults true \ No newline at end of file diff --git a/test/archive/casper/helpers.coffee b/test/archive/casper/helpers.coffee deleted file mode 100644 index 138da7d03f..0000000000 --- a/test/archive/casper/helpers.coffee +++ /dev/null @@ -1,106 +0,0 @@ -utils = require('utils') - -module.exports = -> - - SYNC_WAIT_TIME = 40 - - baseUrl = 'http://localhost:3000' - - random = Math.random().toString(36).substring(7) - - casper = require("casper").create - clientScripts: 'test/includes/lodash.min.js' - - getModel = -> - casper.evaluate -> - model = window.DERBY.app.model - { - _userId: model.get('_userId') - _user: model.get('_user') - _todoList: model.get('_todoList') - _dailyList: model.get('_dailyList') - _rewardList: model.get('_rewardList') - _habitList: model.get('_habitList') - } - - { - casper: casper - - baseUrl: baseUrl - playUrl: baseUrl + '/?play=1' - - utils: utils - - addTasks: (types = 'all', num = 5)-> - if types == 'all' - types = ['habit', 'daily', 'todo', 'reward'] - types.forEach (type) -> - i = 0 - casper.repeat num, -> - casper.fill "form#new-#{type}", {'new-task': "#{type}-#{i}"} # why can't I use true here? - casper.click "form#new-#{type} input[type=submit]" - - reset: -> - casper.evaluate -> window.DERBY.app.reset() - - getModelDelayed: (cb) -> - # This time is needed for derby to have enough time to update all it's data. - # It still happens sometimes that the retrieved model does not contain any - # data. It might be worth to do some basic checks on the model here, and if - # it doesn't look OK, wait a bit longer and get it again. - casper.wait SYNC_WAIT_TIME, -> - cb(getModel()) - - modelBeforeAfter: (between_cb, done_cb) -> - that = @ - model = {} - @getModelDelayed (before) -> - model.before = before - casper.then -> - between_cb() - that.getModelDelayed (after) -> - model.after = after - casper.then -> done_cb(model) - - runCron: -> - casper.evaluate -> - yesterday = new Date() - yesterday.setDate(yesterday.getDate() - 1); - window.DERBY.app.model.set('_user.lastCron', yesterday) - casper.then -> casper.reload() - - cronBeforeAfter: (cb) -> - that = @ - model = {} - @getModelDelayed (before) -> - model.before = before - casper.then -> that.runCron() - casper.then -> - casper.wait 1100, -> # user's hp is updated after 1s for animation - model.after = getModel() - casper.then -> - casper.test.assertEqual model.before._user.id, model.after._user.id, 'user id equal after cron' - casper.test.assertEqual model.before._user.tasks.length, model.after._user.tasks.length, "Didn't lose anything on cron" - cb(model) - - register: -> - casper.fill 'form#derby-auth-register', - username: random - email: random + '@example.com' - password: random - 'password-confirmation': random - , true - - login: -> - casper.fill 'form#derby-auth-login', - username: random - password: random - , true - - deleteOne: (list, typeSelector) -> - selector = "#{typeSelector} a[data-original-title=\"Delete\"]" - @modelBeforeAfter (-> casper.click selector), (model) -> - casper.test.assertEquals Object.keys(model.before._user.tasks).length - 1, Object.keys(model.after._user.tasks).length, "1 #{typeSelector} deleted from user.tasks" - casper.test.assertEquals model.before._user["#{list}Ids"].length - 1, model.after._user["#{list}Ids"].length, "1 #{typeSelector} deleted from user._typeIds" - casper.test.assertEquals model.before["_#{list}List"].length - 1, model.after["_#{list}List"].length, "1 #{typeSelector} deleted from _typeList" - } diff --git a/test/archive/casper/items.casper.coffee b/test/archive/casper/items.casper.coffee deleted file mode 100644 index 853aa3f127..0000000000 --- a/test/archive/casper/items.casper.coffee +++ /dev/null @@ -1,22 +0,0 @@ -helpers = new require('./test/casper/helpers')() -casper = helpers.casper -utils = helpers.utils -url = helpers.playUrl - -casper.start url - -# ---------- Items (in-game rewards) ------------ -casper.then -> - helpers.reset() - helpers.addTasks(['habit'], 1) - -casper.then -> casper.test.assertDoesntExist 'ul.items', 'no items after reset' -casper.then -> casper.repeat 70, -> - casper.click '.habits a[data-direction="up"]' -casper.then -> - casper.test.assertVisible '.item-store-popover', 'store popover visible' - casper.test.assertExists 'ul.items', 'items appear after lvl up' - -# ---------- Run ------------ -casper.run -> - casper.test.renderResults true \ No newline at end of file diff --git a/test/archive/casper/memoryleak.casper.coffee b/test/archive/casper/memoryleak.casper.coffee deleted file mode 100644 index ff5357a90f..0000000000 --- a/test/archive/casper/memoryleak.casper.coffee +++ /dev/null @@ -1,12 +0,0 @@ -helpers = new require('./test/casper/helpers')() -casper = helpers.casper -utils = helpers.utils -url = helpers.playUrl - -casper.start url - -casper.repeat 100, -> - casper.reload() - -casper.run -> - casper.test.renderResults true \ No newline at end of file diff --git a/test/archive/casper/registration.casper.coffee b/test/archive/casper/registration.casper.coffee deleted file mode 100644 index e3e1a53574..0000000000 --- a/test/archive/casper/registration.casper.coffee +++ /dev/null @@ -1,35 +0,0 @@ -helpers = new require('./test/casper/helpers')() -casper = helpers.casper -utils = helpers.utils -url = helpers.playUrl - -casper.start url - -# ---------- Register ------------ -registeredUser = undefined -casper.then -> helpers.register() -casper.then -> - helpers.getModelDelayed (model) -> - registeredUser = model - -casper.then -> casper.reload() -casper.then -> - helpers.getModelDelayed (nowModel) -> - casper.test.assertEqual registeredUser._userId, nowModel._userId, 'user registered and maintained session' - -# ---------- Log Out ------------ -casper.thenOpen helpers.baseUrl + '/logout' -casper.thenOpen helpers.playUrl -casper.then -> - helpers.getModelDelayed (nowModel) -> - casper.test.assertNotEquals registeredUser._userId, nowModel._userId, 'user logged out' - -# ---------- Login ------------ -casper.then -> helpers.login() -casper.then -> - helpers.getModelDelayed (nowModel) -> - casper.test.assertEqual registeredUser._userId, nowModel._userId, 'user logged out' - -# ---------- Run ------------ -casper.run -> - casper.test.renderResults true \ No newline at end of file diff --git a/test/archive/casper/rest.casper.coffee b/test/archive/casper/rest.casper.coffee deleted file mode 100644 index 767d93489e..0000000000 --- a/test/archive/casper/rest.casper.coffee +++ /dev/null @@ -1,74 +0,0 @@ -url = 'http://localhost:3000' -utils = require('utils') -casper = require("casper").create() - -user1 = {} -user2 = {} - -# ---------- Main Stuff ------------ - -casper.start "#{url}/?play=1", -> - user1 = casper.evaluate -> window.DERBY.app.model.get("_user") - @fill 'form#derby-auth-register', - username: user1.id - email: "{user1.id}@gmail.com" - password: 'habitrpg123' - 'password-confirmation': "habitrpg123" - , true -casper.thenOpen "#{url}/logout" -casper.thenOpen "#{url}/?play=1", -> - user2 = @evaluate -> window.DERBY.app.model.get("_user") - casper.then -> @test.assertNotEquals user1.id, user2.id, '2 new users created' - - - # ---------- REST API ------------ - - # casper.thenOpen "#{url}/users/#{user.id}" - # casper.thenOpen "#{url}/users/#{user.id}/tasks" - # casper.thenOpen "#{url}/users/#{user.id}/tasks/{taskId}" - - taskId = 'productivity' - pomodoro = { - 'title': 'Stay Focused', - 'service': 'pomodoro', - 'icon': 'http://www.veryicon.com/icon/16/Food%20%26%20Drinks/Paradise%20Fruits/Tomato.png' - } - - # ---------- v1 ------------ - - @thenOpen "#{url}/users/#{user2.id}/tasks/#{taskId}/up", { - method: 'post', - data: pomodoro - }, -> - result = JSON.parse @getPageContent() - @test.assertEqual user2.stats.hp, result.hp, 'REST +habit =hp' - @test.assert user2.stats.exp < result.exp, 'REST +habit +exp' - @test.assert user2.stats.money < result.money, 'REST +habit +money' - utils.dump result - - @thenOpen "#{url}/users/#{user1.id}/tasks/#{taskId}/down", { - method: 'post', - data: pomodoro - }, -> - result = JSON.parse @getPageContent() - @test.assert user1.stats.hp > result.hp, 'REST -habit -hp' - @test.assertEqual user1.stats.exp, result.exp, 'REST -habit =exp' - @test.assertEqual user1.stats.money, result.money, 'REST -habit =money' - utils.dump result - -casper.thenOpen "#{url}/?play=1", -> - # User2 is logged in by now. Make sure we don't get logged in as user1 since that was the last REST call - current = casper.evaluate -> window.DERBY.app.model.get('_user') - casper.then -> casper.test.assertEqual current.id, user2.id, "session remains user2's" - - # ---------- v2 ------------ - -# @thenOpen "#{url}/v2/users/#{uid}/tasks/#{taskId}/down", { -# method: 'post', -# data: pomodoro -# } - -# ---------- Run ------------ - -casper.run -> - @test.renderResults true \ No newline at end of file diff --git a/test/archive/casper/todos.casper.coffee b/test/archive/casper/todos.casper.coffee deleted file mode 100644 index f898f68b12..0000000000 --- a/test/archive/casper/todos.casper.coffee +++ /dev/null @@ -1,59 +0,0 @@ -helpers = new require('./test/casper/helpers')() -casper = helpers.casper -utils = helpers.utils -url = helpers.playUrl - -casper.start url - -# ---------- Todos ------------ -casper.then -> - helpers.reset() - helpers.addTasks(['todo']) - -# Completing todo gives exp and gp -casper.then -> - helpers.modelBeforeAfter (-> casper.click '.todos .uncompleted input[type="checkbox"]'), (model) -> - casper.test.assertEquals model.before._user.stats.hp, 50, 'todo:hp starts at 50' - casper.test.assertEquals model.before._user.stats.hp, model.after._user.stats.hp, '+todo =hp' - casper.test.assertEquals model.after._user.stats.exp, 1, '+todo exp=1' - casper.test.assertEquals model.after._user.stats.gp, 1, '+todo gp=1' - - casper.test.assert model.before._user.stats.exp < model.after._user.stats.exp, '+todo +exp' - casper.test.assert model.before._user.stats.gp < model.after._user.stats.gp, '+todo +gp' - -# Can delete completed -casper.then -> helpers.deleteOne('todo', '.todos .completed') - -# Can delete uncompleted -casper.then -> helpers.deleteOne('todo', '.todos .uncompleted') - -# Uncompleting subtracts exp and gp -casper.then -> - casper.click '.todos .uncompleted input[type="checkbox"]' - helpers.modelBeforeAfter (-> casper.click '.todos .completed input[type="checkbox"]'), (model) -> - casper.test.assertEquals model.before._user.stats.hp, model.after._user.stats.hp, '-todo =hp' - casper.test.assert model.before._user.stats.exp > model.after._user.stats.exp, '-todo -exp' - casper.test.assert model.before._user.stats.gp > model.after._user.stats.gp, '-todo -gp' - - - -# ---------- Cron ------------ -casper.then -> - helpers.reset() - helpers.addTasks(['todo']) - -casper.then -> - helpers.cronBeforeAfter (model) -> - casper.then -> - casper.test.assertEqual model.before._user.stats.hp, model.after._user.stats.hp, 'todo:cron:hp no change' - - # Go through all the todos, all of them are uncompleted, so should all get a negative value - casper.echo "Testing all uncompleted todos after cron" - for id in model.before._user.todoIds - casper.test.assertEquals model.before._user.tasks[id].value, 0, "todo:cron:todo value before was 0" - casper.test.assert model.after._user.tasks[id].value < 0, "todo:cron:todo value after is negative" - - -# ---------- Run ------------ -casper.run -> - casper.test.renderResults true \ No newline at end of file diff --git a/test/archive/test2/casper/add.items.coffee b/test/archive/test2/casper/add.items.coffee deleted file mode 100644 index 9094b67c77..0000000000 --- a/test/archive/test2/casper/add.items.coffee +++ /dev/null @@ -1,40 +0,0 @@ -helpers = casper.helpers -uid = helpers.uid -# test creation of Todos, Rewards, Habits, etc - -casper.start helpers.playUrl, -> - casper.test.assert(true,'true==true') -# helpers.getModel (err, model) -> -# tasksCount=0 -# for own key,value of model.user.tasks -# tasksCount++ -# utils.dump model.user.tasks -# casper.fill "form[data-task-type='habit']", { -# 'new-task': 'Habit' + uid -# }, true -# helpers.getModel (err, model) -> -# newTasksCount=0 -# for own key,value of model.user.tasks -# newTasksCount++ -# casper.echo "Tasks new: " + tasksCount -# casper.test.assert(newTasksCount>tasksCount,"Task list increases in length after new habit form submitted") -# -# -##casper.then -> -## helpers.getModel (err, model) -> -## casper.test.assertEquals(typeof model.user.stats.exp, "number", 'XP is number') -## casper.test.assertEquals(model.user.stats.exp, 0, 'XP == 0') -## casper.click '.habits a[data-direction="up"]' -## helpers.getModel (err, newModel) -> -## casper.test.assert(newModel.user.stats.exp > model.user.stats.exp, 'XP has increased after clicking habits "+"') -## casper.test.assert(newModel.user.stats.gp > model.user.stats.gp, 'GP has increased after clicking habits "+"') - - -# ---------- finish tests ------------ -casper.then -> - casper.test.done() - - -# ---------- Run ------------ -casper.run -> - casper.test.renderResults true diff --git a/test/archive/test2/casper/stats.coffee b/test/archive/test2/casper/stats.coffee deleted file mode 100644 index d134f518ee..0000000000 --- a/test/archive/test2/casper/stats.coffee +++ /dev/null @@ -1,103 +0,0 @@ -#helpers = new require('./lib/helpers')() -#casper = helpers.casper -helpers = casper.helpers -eTest = helpers.evalTest -getModel = helpers.getModel -# ---------- Checks if clicking on the buttons changes stats and in right direction ------------ - - -casper.start helpers.playUrl, -> - test = 'EXP and GP increasing after clicking habits "+"' - getModel (err, model) -> - casper.test.assertEquals(typeof model.user.stats.exp, "number", 'XP is number') - casper.test.assertEquals(model.user.stats.exp, 0, 'XP == 0') - casper.click '.habits a[data-direction="up"]' - eTest( - (oldStats)-> - stats = window.DERBY.app.model.get '_user.stats' - console.log "Was:" + oldStats.exp + "Is: " + stats.exp - console.log "Was:" + oldStats.gp + "Is: " + stats.gp - (stats.exp > oldStats.exp && stats.gp > oldStats.gp) - test - model.user.stats - ) - - -casper.then -> - test = 'HP decreasing after clicking habits "-"' - getModel (err, model) -> - casper.click '.habits a[data-direction="down"]' - eTest( - (oldStats)-> - stats = window.DERBY.app.model.get '_user.stats' - console.log "Was:" + oldStats.hp + "Is: " + stats.hp - (stats.hp < oldStats.hp) - test - model.user.stats - ) - -casper.then -> - test = 'EXP and GP increasing after clicking .todo.uncompleted' - getModel (err, model) -> - casper.click '.task.todo.uncompleted input[type=checkbox]' - eTest( - (oldStats)-> - stats = window.DERBY.app.model.get '_user.stats' - console.log "Was:" + oldStats.exp + "Is: " + stats.exp - console.log "Was:" + oldStats.gp + "Is: " + stats.gp - (stats.exp > oldStats.exp && stats.gp > oldStats.gp) - test - model.user.stats - ) - -casper.then -> - test = 'EXP and GP decreasing after clicking .todo.completed' - getModel (err, model) -> - casper.click '.task.todo.completed input[type=checkbox]' - eTest( - (oldStats)-> - stats = window.DERBY.app.model.get '_user.stats' - console.log "Was:" + oldStats.exp + "Is: " + stats.exp - console.log "Was:" + oldStats.gp + "Is: " + stats.gp - (stats.exp < oldStats.exp && stats.gp < oldStats.gp) - test - model.user.stats - ) - -casper.then -> - test = 'EXP and GP increasing after clicking .daily.uncompleted' - getModel (err, model) -> - casper.click '.task.daily.uncompleted input[type=checkbox]' - eTest( - (oldStats)-> - stats = window.DERBY.app.model.get '_user.stats' - console.log "Was:" + oldStats.exp + "Is: " + stats.exp - console.log "Was:" + oldStats.gp + "Is: " + stats.gp - (stats.exp > oldStats.exp && stats.gp > oldStats.gp) - test - model.user.stats - ) - -casper.then -> - test = 'EXP and GP decreasing after clicking .daily.completed' - getModel (err, model) -> - casper.click '.task.daily.completed input[type=checkbox]' - eTest( - (oldStats)-> - stats = window.DERBY.app.model.get '_user.stats' - console.log "Was:" + oldStats.exp + "Is: " + stats.exp - console.log "Was:" + oldStats.gp + "Is: " + stats.gp - (stats.exp < oldStats.exp && stats.gp < oldStats.gp) - test - model.user.stats - ) - - -# ---------- finish tests ------------ -casper.then -> - casper.test.done() - - -# ---------- Run ------------ -casper.run -> - casper.test.renderResults true \ No newline at end of file diff --git a/test/archive/test2/readme.md b/test/archive/test2/readme.md deleted file mode 100644 index a0567235cb..0000000000 --- a/test/archive/test2/readme.md +++ /dev/null @@ -1,9 +0,0 @@ -1) It is a bit verbose -2) It needs to be refactored using "async" library. Somehow casper.then() is introducing bugs so I'm not going to use it until I figure out why exactly. Leave it as it is, I'll refactor as it grows. -3) It does not use any timeouts along the way, which is a good thing. -4) It runs consistently on my side (i.e. always passes). -5) So far phantomJS is given new userID every time so app.reset,app.revive is not necessary. I'll add it later. - -To run the tests run from terminal: -cd test/test2 -casperjs test ./casper/ --includes=./lib/helpers.coffee \ No newline at end of file diff --git a/test/common/algos.mocha.coffee b/test/common/algos.mocha.coffee index b413c3e000..4e911ca06d 100644 --- a/test/common/algos.mocha.coffee +++ b/test/common/algos.mocha.coffee @@ -2,7 +2,7 @@ _ = require 'lodash' expect = require 'expect.js' sinon = require 'sinon' moment = require 'moment' -shared = require '../../common/script/index.coffee' +shared = require '../../common/script/index.js' shared.i18n.translations = require('../../website/src/libs/i18n.js').translations test_helper = require './test_helper' test_helper.addCustomMatchers() diff --git a/test/common/count.js b/test/common/count.js index b9040a71f1..86d746d3ff 100644 --- a/test/common/count.js +++ b/test/common/count.js @@ -3,7 +3,6 @@ var chai = require("chai") chai.use(require("sinon-chai")) var expect = chai.expect -require('coffee-script'); var count = require('../../common/script/count'); describe('count', function() { @@ -27,9 +26,9 @@ describe('count', function() { }); it('does not count pets hatched with premium potions', function() { - var pets = { - "Wolf-Spooky": 5, - "Dragon-Spooky": 5, + var pets = { + "Wolf-Spooky": 5, + "Dragon-Spooky": 5, "FlyingPig-Base": 5 } var beastMasterTotal = count.beastMasterProgress(pets); diff --git a/test/common/dailies.coffee b/test/common/dailies.coffee index e5e3fad81a..71729ff77c 100644 --- a/test/common/dailies.coffee +++ b/test/common/dailies.coffee @@ -2,7 +2,7 @@ _ = require 'lodash' expect = require 'expect.js' sinon = require 'sinon' moment = require 'moment' -shared = require '../../common/script/index.coffee' +shared = require '../../common/script/index.js' shared.i18n.translations = require('../../website/src/libs/i18n.js').translations repeatWithoutLastWeekday = ()-> diff --git a/test/common/simulations/autoAllocate.coffee b/test/common/simulations/autoAllocate.coffee index 6b21b9ca9d..fec7ccbb31 100644 --- a/test/common/simulations/autoAllocate.coffee +++ b/test/common/simulations/autoAllocate.coffee @@ -6,7 +6,7 @@ Current results at https://gist.github.com/lefnire/8049676 ### -shared = require '../../../common/script/index.coffee' +shared = require '../../../common/script/index.js' _ = require 'lodash' $w = (s)->s.split(' ') diff --git a/test/common/simulations/passive_active_attrs.coffee b/test/common/simulations/passive_active_attrs.coffee index 11646ae933..0788488ec2 100644 --- a/test/common/simulations/passive_active_attrs.coffee +++ b/test/common/simulations/passive_active_attrs.coffee @@ -6,7 +6,7 @@ Current results at https://gist.github.com/lefnire/8049676 ### -shared = require '../../../common/script/index.coffee' +shared = require '../../../common/script/index.js' _ = require 'lodash' id = shared.uuid() diff --git a/test/common/user.fns.buy.test.js b/test/common/user.fns.buy.test.js index 3eb91dcf0b..f7e91ffab9 100644 --- a/test/common/user.fns.buy.test.js +++ b/test/common/user.fns.buy.test.js @@ -4,8 +4,7 @@ chai.use(require("sinon-chai")) var expect = chai.expect var _ = require('lodash'); -require('coffee-script'); -var shared = require('../../common/script/index.coffee'); +var shared = require('../../common/script/index.js'); describe('user.fns.buy', function() { var user; diff --git a/test/common/user.fns.ultimateGear.test.js b/test/common/user.fns.ultimateGear.test.js index d2b82f43e8..988313d5cc 100644 --- a/test/common/user.fns.ultimateGear.test.js +++ b/test/common/user.fns.ultimateGear.test.js @@ -1,6 +1,6 @@ 'use strict'; -var shared = require('../../common/script/index.coffee'); +var shared = require('../../common/script/index.js'); shared.i18n.translations = require('../../website/src/libs/i18n.js').translations require('./test_helper'); diff --git a/test/common/user.ops.buyMysterySet.test.js b/test/common/user.ops.buyMysterySet.test.js index f0a4a7b2f8..1f88b45802 100644 --- a/test/common/user.ops.buyMysterySet.test.js +++ b/test/common/user.ops.buyMysterySet.test.js @@ -3,9 +3,8 @@ var chai = require("chai") chai.use(require("sinon-chai")) var expect = chai.expect -require('coffee-script'); -var shared = require('../../common/script/index.coffee'); -var Content = require('../../common/script/content/index.coffee'); +var shared = require('../../common/script/index.js'); +var Content = require('../../common/script/content/index.js'); describe('user.ops.buyMysterySet', function() { var user; @@ -51,7 +50,7 @@ describe('user.ops.buyMysterySet', function() { armor_mystery_301404: true, head_mystery_301404: true, eyewear_mystery_301404: true - }; + }; user.ops.buyMysterySet({params:{key:'301404'}}, function(response) { expect(response.message).to.eql("Mystery set not found, or set already owned"); diff --git a/test/common/user.ops.hatch.js b/test/common/user.ops.hatch.js index 2ec1d627d3..b5cf174ff9 100644 --- a/test/common/user.ops.hatch.js +++ b/test/common/user.ops.hatch.js @@ -3,9 +3,8 @@ var chai = require('chai'); chai.use(require('sinon-chai')) var expect = chai.expect -require('coffee-script'); -var shared = require('../../common/script/index.coffee'); -var content = require('../../common/script/content/index.coffee'); +var shared = require('../../common/script/index.js'); +var content = require('../../common/script/content/index.js'); describe('user.ops.hatch', function() { var user; diff --git a/test/common/user.ops.hourglassPurchase.test.js b/test/common/user.ops.hourglassPurchase.test.js index 458029c6df..76e3f98c9c 100644 --- a/test/common/user.ops.hourglassPurchase.test.js +++ b/test/common/user.ops.hourglassPurchase.test.js @@ -3,9 +3,8 @@ var chai = require("chai") chai.use(require("sinon-chai")) var expect = chai.expect -require('coffee-script'); -var shared = require('../../common/script/index.coffee'); -var Content = require('../../common/script/content/index.coffee'); +var shared = require('../../common/script/index.js'); +var Content = require('../../common/script/content/index.js'); describe('user.ops.hourglassPurchase', function() { var user; diff --git a/test/common/user.ops.test.js b/test/common/user.ops.test.js index 6e26d5430a..aee5b795f7 100644 --- a/test/common/user.ops.test.js +++ b/test/common/user.ops.test.js @@ -4,8 +4,7 @@ chai.use(require("sinon-chai")) var expect = chai.expect var _ = require('lodash'); -require('coffee-script'); -var shared = require('../../common/script/index.coffee'); +var shared = require('../../common/script/index.js'); describe('user.ops', function() { var user; diff --git a/test/helpers/api-integration.helper.js b/test/helpers/api-integration.helper.js index 1ddaa75b0d..3e1ae734cc 100644 --- a/test/helpers/api-integration.helper.js +++ b/test/helpers/api-integration.helper.js @@ -8,7 +8,6 @@ import {MongoClient as mongo} from 'mongodb'; import {v4 as generateUUID} from 'uuid'; import superagent from 'superagent'; import i18n from '../../common/script/src/i18n'; -require('coffee-script'); i18n.translations = require('../../website/src/libs/i18n.js').translations; const API_TEST_SERVER_PORT = 3003; diff --git a/test/helpers/content.helper.js b/test/helpers/content.helper.js index c54a62d508..db95a1f0b3 100644 --- a/test/helpers/content.helper.js +++ b/test/helpers/content.helper.js @@ -2,7 +2,6 @@ require('./globals.helper'); import {each} from 'lodash'; import i18n from '../../common/script/src/i18n'; -require('coffee-script'); i18n.translations = require('../../website/src/libs/i18n.js').translations; export const STRING_ERROR_MSG = 'Error processing the string. Please see Help > Report a Bug.'; diff --git a/website/public/css/tasks.styl b/website/public/css/tasks.styl index 3baa99bf48..0318d9b5c8 100644 --- a/website/public/css/tasks.styl +++ b/website/public/css/tasks.styl @@ -196,6 +196,8 @@ for $stage in $stages // ------------------------ .dailiesRestingInInn clear: both + button + margin-top 10px // an individual task entry // ------------------------ diff --git a/website/public/js/app.js b/website/public/js/app.js index d0caf41c2b..acda8479f7 100644 --- a/website/public/js/app.js +++ b/website/public/js/app.js @@ -255,4 +255,6 @@ window.habitrpg = angular.module('habitrpg', $httpProvider.defaults.headers.common['x-api-user'] = settings.auth.apiId; $httpProvider.defaults.headers.common['x-api-key'] = settings.auth.apiToken; } + + $httpProvider.defaults.headers.common['x-client'] = 'habitica-web'; }]); diff --git a/website/public/js/controllers/authCtrl.js b/website/public/js/controllers/authCtrl.js index 0a262fc141..7dced7ce00 100644 --- a/website/public/js/controllers/authCtrl.js +++ b/website/public/js/controllers/authCtrl.js @@ -9,8 +9,6 @@ angular.module('habitrpg') function($scope, $rootScope, User, $http, $location, $window, ApiUrl, $modal, Analytics) { $scope.Analytics = Analytics; - $http.defaults.headers.common['x-client'] = 'habitica-web'; - $scope.logout = function() { localStorage.clear(); window.location.href = '/logout'; diff --git a/website/public/js/controllers/rootCtrl.js b/website/public/js/controllers/rootCtrl.js index 506a779444..0e6fd743c7 100644 --- a/website/public/js/controllers/rootCtrl.js +++ b/website/public/js/controllers/rootCtrl.js @@ -36,8 +36,6 @@ habitrpg.controller("RootCtrl", ['$scope', '$rootScope', '$location', 'User', '$ $rootScope.toJson = angular.toJson; $rootScope.Payments = Payments; - $http.defaults.headers.common['x-client'] = 'habitica-web'; - // Angular UI Router $rootScope.$state = $state; $rootScope.$stateParams = $stateParams; diff --git a/website/public/js/static.js b/website/public/js/static.js index e87368cdd8..67a07df815 100644 --- a/website/public/js/static.js +++ b/website/public/js/static.js @@ -19,6 +19,8 @@ window.habitrpg = angular.module('habitrpg', ['chieffancypants.loadingBar', 'ui. }); }) } + + $http.defaults.headers.common['x-client'] = 'habitica-web'; }]) .controller("PlansCtrl", ['$rootScope','Analytics', @@ -56,4 +58,4 @@ window.habitrpg = angular.module('habitrpg', ['chieffancypants.loadingBar', 'ui. $(document).ready(function(){ openHashAccordion(); }); -}) +}) diff --git a/website/src/controllers/api-v2/auth.js b/website/src/controllers/api-v2/auth.js index b01e1aba3d..73a8a8e38d 100644 --- a/website/src/controllers/api-v2/auth.js +++ b/website/src/controllers/api-v2/auth.js @@ -109,6 +109,7 @@ api.registerUser = function(req, res, next) { // existing user, allow them to add local authentication if (data.findFacebook) { data.findFacebook.auth.local = newUser.auth.local; + data.findFacebook.registeredThrough = newUser.registeredThrough; data.findFacebook.save(cb); // new user, register them } else { @@ -116,6 +117,7 @@ api.registerUser = function(req, res, next) { newUser.preferences.language = req.language; // User language detected from browser, not saved var user = new User(newUser); + user.registeredThrough = req.headers['x-client']; var analyticsData = { category: 'acquisition', type: 'local', @@ -124,8 +126,6 @@ api.registerUser = function(req, res, next) { }; analytics.track('register', analyticsData) - user.registeredThrough = req.headers['x-client'] - user.save(function(err, savedUser){ // Clean previous email preferences // TODO when emails added to EmailUnsubcription they should use lowercase version @@ -203,6 +203,8 @@ api.loginSocial = function(req, res, next) { }; user.auth[network] = prof; user = new User(user); + user.registeredThrough = req.headers['x-client']; + user.save(function(err, savedUser){ // Clean previous email preferences if(savedUser.auth.facebook.emails && savedUser.auth.facebook.emails[0] && savedUser.auth.facebook.emails[0].value){ diff --git a/website/src/controllers/api-v2/groups.js b/website/src/controllers/api-v2/groups.js index 8832c5e501..0fc969c3af 100644 --- a/website/src/controllers/api-v2/groups.js +++ b/website/src/controllers/api-v2/groups.js @@ -684,7 +684,7 @@ var inviteByEmails = function(invites, group, req, res, next){ // Send only status code down the line because it doesn't need // info on invited users since they are not yet registered - res.send(200); + res.json(200, {}); } }); }; diff --git a/website/src/controllers/api-v2/user.js b/website/src/controllers/api-v2/user.js index ed8aa05f25..cd747e7d5c 100644 --- a/website/src/controllers/api-v2/user.js +++ b/website/src/controllers/api-v2/user.js @@ -1,5 +1,3 @@ -/* @see ./routes.coffee for routing*/ - var url = require('url'); var ipn = require('paypal-ipn'); var _ = require('lodash'); @@ -65,10 +63,6 @@ var findTask = function(req, res) { --------------- */ -/** - This is called form deprecated.coffee's score function, and the req.headers are setup properly to handle the login - Export it also so we can call it from deprecated.coffee -*/ api.score = function(req, res, next) { var id = req.params.id, direction = req.params.direction, @@ -545,7 +539,7 @@ api.sessionPartyInvite = function(req,res,next){ } /** - * All other user.ops which can easily be mapped to habitrpg-shared/index.coffee, not requiring custom API-wrapping + * All other user.ops which can easily be mapped to common/script/index.js, not requiring custom API-wrapping */ _.each(shared.wrap({}).ops, function(op,k){ if (!api[k]) { diff --git a/website/src/controllers/payments/index.js b/website/src/controllers/payments/index.js index cf6d0dae90..866c33381b 100644 --- a/website/src/controllers/payments/index.js +++ b/website/src/controllers/payments/index.js @@ -1,4 +1,3 @@ -/* @see ./routes.coffee for routing*/ var _ = require('lodash'); var shared = require('../../../../common'); var nconf = require('nconf'); diff --git a/website/src/controllers/payments/paypalBillingSetup.js b/website/src/controllers/payments/paypalBillingSetup.js index ce238338f1..8130de99cc 100644 --- a/website/src/controllers/payments/paypalBillingSetup.js +++ b/website/src/controllers/payments/paypalBillingSetup.js @@ -2,7 +2,6 @@ // payment plan definitions, instead you have to create it via their REST SDK and keep it updated the same way. So this // file will be used once for initing your billing plan (then you get the resultant plan.id to store in config.json), // and once for any time you need to edit the plan thereafter -require('coffee-script'); var path = require('path'); var nconf = require('nconf'); _ = require('lodash'); @@ -90,4 +89,4 @@ switch(OP) { }); break; case "remove": break; -} \ No newline at end of file +} diff --git a/website/src/index.js b/website/src/index.js index 9454b0c46b..aa72ec1a27 100644 --- a/website/src/index.js +++ b/website/src/index.js @@ -1,9 +1,6 @@ // Register babel hook so we can write the real entry file (server.js) in ES6 require('babel/register'); -// TODO remove this once we've fully converted over -require('coffee-script'); - // Only do the minimal amount of work before forking just in case of a dyno restart var cluster = require('cluster'); var nconf = require('nconf'); diff --git a/website/src/libs/api-v2/analytics.js b/website/src/libs/api-v2/analytics.js index 315dc4b618..dffa7c2a9b 100644 --- a/website/src/libs/api-v2/analytics.js +++ b/website/src/libs/api-v2/analytics.js @@ -1,4 +1,3 @@ -require('coffee-script'); require('./i18n'); var _ = require('lodash'); diff --git a/website/src/models/user.js b/website/src/models/user.js index 1cb1684360..96df847024 100644 --- a/website/src/models/user.js +++ b/website/src/models/user.js @@ -157,6 +157,7 @@ export let schema = new Schema({ tavern: {type: Boolean, default: false}, equipment: {type: Boolean, default: false}, items: {type: Boolean, default: false}, + inviteParty: {type: Boolean, default: false}, }, ios: { addTask: {type: Boolean, default: false}, @@ -541,6 +542,7 @@ function _populateDefaultsForNewUser (user) { 'tavern', 'equipment', 'items', + 'inviteParty', ]; _.each(tutorialCommonSections, (section) => { diff --git a/website/src/routes/api-v2/swagger.js b/website/src/routes/api-v2/swagger.js index d93cfe6271..a1500ac39a 100644 --- a/website/src/routes/api-v2/swagger.js +++ b/website/src/routes/api-v2/swagger.js @@ -2,13 +2,11 @@ ---------- /api/v2 API ------------ see https://github.com/wordnik/swagger-node-express Every url added to router is prefaced by /api/v2 -Note: Many user-route ops exist in ../../common/script/index.coffee#user.ops, so that they can (1) be called both +Note: Many user-route ops exist in ../../common/script/index.js#user.ops, so that they can (1) be called both client and server. v1 user. Requires x-api-user (user id) and x-api-key (api key) headers, Test with: -$ mocha test/user.mocha.coffee */ -require('coffee-script'); var user = require("../../controllers/api-v2/user"); var groups = require("../../controllers/api-v2/groups"); var members = require("../../controllers/api-v2/members"); @@ -295,7 +293,7 @@ module.exports = function(swagger, v2) { spec: { method: 'POST', description: "Casts a spell on a target.", - parameters: [path('spell', "The key of the spell to cast (see ../../common#content/index.coffee)", 'string'), query('targetType', "The type of object you're targeting", 'string', ['party', 'self', 'user', 'task']), query('targetId', "The ID of the object you're targeting", 'string')] + parameters: [path('spell', "The key of the spell to cast (see ../../common#content/index.js)", 'string'), query('targetType', "The type of object you're targeting", 'string', ['party', 'self', 'user', 'task']), query('targetId', "The ID of the object you're targeting", 'string')] }, action: user.cast }, @@ -772,6 +770,6 @@ module.exports = function(swagger, v2) { swagger["add" + route.spec.method](route); return true; }); - + return swagger.configure((nconf.get('BASE_URL')) + "/api/v2", "2"); }; diff --git a/website/views/shared/tasks/index.jade b/website/views/shared/tasks/index.jade index 79ab99d11b..5cc8d27f89 100644 --- a/website/views/shared/tasks/index.jade +++ b/website/views/shared/tasks/index.jade @@ -22,6 +22,9 @@ script(id='templates/habitrpg-tasks.html', type="text/ng-template") alert.alert-warning.dailiesRestingInInn(ng-if='list.type == "daily" && user.preferences.sleep && !$state.includes("options.social.challenges")') i.glyphicon.glyphicon-warning-sign   =env.t('dailiesRestingInInn') + + button.btn-block.btn.btn-lg.btn-success(ng-click='User.user.ops.sleep({})') + | {{env.t('innCheckOut')}} +taskColumnTabs('top') diff --git a/website/views/social/landing-page.jade b/website/views/social/landing-page.jade index 50667a38bc..c2e9c935c9 100644 --- a/website/views/social/landing-page.jade +++ b/website/views/social/landing-page.jade @@ -4,7 +4,7 @@ ul.lead li=env.t('landingCopy1') li=env.t('landingCopy2') - li=env.t('landingCopy3') + li=env.t('landingCopy3', {userCount:'900,000'}) .mobile-container .row .col-md-6 diff --git a/website/views/static/front.jade b/website/views/static/front.jade index 63009af221..35531a67cf 100644 --- a/website/views/static/front.jade +++ b/website/views/static/front.jade @@ -74,7 +74,7 @@ html(ng-app='habitrpg', ng-controller='RootCtrl') img.img-rendering-auto.center-block.img-responsive(src='https://d2afqr2xdmyzvu.cloudfront.net/front/images/intro.png') // insert intro images .introcall.bg-success - h4= env.t('joinOthers') + h4= env.t('joinOthers', {userCount:'900,000'}) small button#play-btn.btn.btn-primary.btn-lg.gamifybutton(ng-click='playButtonClick()')= env.t('free') .presslogos.text-center