Compare commits

..

490 Commits

Author SHA1 Message Date
Matteo Pagliazzi 23906d8f94 4.174.0 2020-12-14 16:01:14 +01:00
Matteo Pagliazzi 2d091fc667 Stripe: upgrade module and API, switch to Checkout (#12785)
* upgrade stripe module

* switch stripe api to latest version

* fix api version in tests

* start upgrading client and server

* client: switch to redirect

* implement checkout session creation for gems, start implementing webhooks

* stripe: start refactoring one time payments

* working gems and gift payments

* start adding support for subscriptions

* stripe: migrate subscriptions and fix cancelling sub

* allow upgrading group plans

* remove console.log statements

* group plans: upgrade from static page / create new one

* fix #11885, correct group plan modal title

* silence more stripe webhooks

* fix group plans redirects

* implement editing payment method

* start cleaning up code

* fix(stripe): update in-code docs, fix eslint issues

* subscriptions tests

* remove and skip old tests

* skip integration tests

* fix client build

* stripe webhooks: throw error if request fails

* subscriptions: correctly pass groupId

* remove console.log

* stripe: add unit tests for one time payments

* wip: stripe checkout tests

* stripe createCheckoutSession unit tests

* stripe createCheckoutSession unit tests

* stripe createCheckoutSession unit tests (editing card)

* fix existing webhooks tests

* add new webhooks tests

* add more webhooks tests

* fix lint

* stripe integration tests

* better error handling when retrieving customer from stripe

* client: remove unused strings and improve error handling

* payments: limit gift message length (server)

* payments: limit gift message length (client)

* fix redirects when payment is cancelled

* add back "subUpdateCard" string

* fix redirects when editing a sub card, use proper names for products, check subs when gifting
2020-12-14 16:01:07 +01:00
Sabe Jones 5daf96bbf5 4.173.0 2020-12-08 11:13:03 -06:00
Alys 62498ab646 remove links to Moderator Contact Form
This is a temporary measure until we can get the form working again.

This has NOT been approved by any of Habitica's staff.
It's just being proposed for consideration.

The changes are:

- remove link from Help menu
- replace link in Contacts page with mailto admin@habitica.com without changing the visible text of the link
- replace link in Tavern sidebar with mailto admin@habitica.com using the visible text from the Contacts page
2020-12-07 15:48:45 -06:00
Sabe Jones cf435ad007 chore(sprites): compile 2020-12-07 15:40:32 -06:00
Sabe Jones 55f4b8ae87 feat(content): Armoire items and backgrounds for Dec 2020 2020-12-07 15:40:24 -06:00
Sabe Jones 8434d727bd fix(Docker): use new Node base image 2020-12-04 13:18:45 -06:00
Sabe Jones c055d43895 4.172.1 2020-12-04 13:12:39 -06:00
Melior f0123a1571 Merge branch 'origin/develop' into Weblate. 2020-11-30 22:03:24 +01:00
Melior e4e200c32c Translated using Weblate (English (Pirate))
Currently translated at 100.0% (54 of 54 strings)

Translation: Habitica/Defaulttasks
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/en@pirate/

Translated using Weblate (English)

Currently translated at 14.4% (16 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/en@lolcat/

Translated using Weblate (English)

Currently translated at 20.4% (37 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/en@lolcat/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 91.3% (95 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant_HK/

Translated using Weblate (English)

Currently translated at 100.0% (365 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/en@lolcat/

Translated using Weblate (Japanese)

Currently translated at 100.0% (111 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ja/

Translated using Weblate (Japanese)

Currently translated at 94.1% (2065 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (102 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/pt_BR/

Translated using Weblate (Russian)

Currently translated at 100.0% (104 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ru/

Translated using Weblate (English (Pirate))

Currently translated at 75.8% (138 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 90.6% (1988 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 80.3% (45 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 97.9% (709 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (123 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (102 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/en@pirate/

Translated using Weblate (Korean)

Currently translated at 15.8% (52 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/ko/

Translated using Weblate (English (Pirate))

Currently translated at 82.1% (46 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/en@pirate/

Translated using Weblate (Spanish (Latin America))

Currently translated at 86.7% (628 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 95.3% (2090 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (102 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 93.9% (2060 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (English (Pirate))

Currently translated at 90.6% (1987 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 97.3% (705 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 93.2% (675 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/en@pirate/

Translated using Weblate (Japanese)

Currently translated at 93.7% (2056 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (English (Pirate))

Currently translated at 92.8% (672 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/en@pirate/

Translated using Weblate (Spanish (Latin America))

Currently translated at 95.0% (2084 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Japanese)

Currently translated at 93.6% (2053 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (English (Pirate))

Currently translated at 98.3% (358 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/en@pirate/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt_BR/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (724 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hans/

Translated using Weblate (Turkish)

Currently translated at 79.1% (452 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/tr/

Translated using Weblate (Japanese)

Currently translated at 100.0% (203 of 203 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/ja/

Translated using Weblate (Vietnamese)

Currently translated at 83.9% (47 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/vi/

Translated using Weblate (Tagalog)

Currently translated at 62.5% (35 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/tl/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 78.5% (44 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/nb_NO/

Translated using Weblate (Galician)

Currently translated at 62.5% (35 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/gl/

Translated using Weblate (Vietnamese)

Currently translated at 100.0% (187 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/vi/

Translated using Weblate (Vietnamese)

Currently translated at 92.8% (169 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/vi/

Translated using Weblate (Galician)

Currently translated at 64.8% (118 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/gl/

Translated using Weblate (Persian)

Currently translated at 64.8% (118 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fa/

Translated using Weblate (Tagalog)

Currently translated at 84.6% (11 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/tl/

Translated using Weblate (Croatian)

Currently translated at 84.6% (11 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/hr/

Translated using Weblate (Greek)

Currently translated at 84.6% (11 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/el/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/zh_Hant_HK/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/nb_NO/

Translated using Weblate (Arabic)

Currently translated at 75.0% (6 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/ar/

Translated using Weblate (English)

Currently translated at 39.4% (41 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en@lolcat/

Translated using Weblate (Latvian)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/lv/

Translated using Weblate (Lithuanian)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/lt/

Translated using Weblate (Lingala)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ln/

Translated using Weblate (Latin)

Currently translated at 90.1% (330 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/la/

Translated using Weblate (Hindi)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/hi/

Translated using Weblate (Hawaiian)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/haw/

Translated using Weblate (Frisian)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/fy/

Translated using Weblate (Filipino)

Currently translated at 94.5% (346 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/fil/

Translated using Weblate (Finnish)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/fi/

Translated using Weblate (Bosnian)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/bs/

Translated using Weblate (Bengali)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/bn/

Translated using Weblate (Hindi)

Currently translated at 99.1% (122 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/hi/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 91.6% (165 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/zh_Hant_HK/

Translated using Weblate (Klingon)

Currently translated at 91.6% (165 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/tlh/

Translated using Weblate (Tamil)

Currently translated at 91.6% (165 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ta/

Translated using Weblate (Malay)

Currently translated at 91.6% (165 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ms/

Translated using Weblate (Latin)

Currently translated at 93.3% (168 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/la/

Translated using Weblate (Lojban)

Currently translated at 92.2% (166 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/jbo/

Translated using Weblate (Irish)

Currently translated at 91.6% (165 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ga/

Translated using Weblate (Slovak)

Currently translated at 90.9% (101 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/sk/

Translated using Weblate (Portuguese)

Currently translated at 89.1% (99 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/pt/

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/zh_Hant/

Translated using Weblate (Ukrainian)

Currently translated at 87.5% (7 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/uk/

Translated using Weblate (Swedish)

Currently translated at 75.0% (6 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/sv/

Translated using Weblate (Romanian)

Currently translated at 87.5% (7 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/ro/

Translated using Weblate (Dutch)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/nl/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/es_419/

Translated using Weblate (Hebrew)

Currently translated at 87.4% (320 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/he/

Translated using Weblate (Bulgarian)

Currently translated at 94.8% (347 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/bg/

Translated using Weblate (Portuguese)

Currently translated at 97.7% (177 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/pt/

Translated using Weblate (Hungarian)

Currently translated at 96.1% (174 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/hu/

Translated using Weblate (Chinese (Traditional))

Currently translated at 91.0% (51 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/zh_Hant/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/zh_Hans/

Translated using Weblate (Ukrainian)

Currently translated at 64.2% (36 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/uk/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt_BR/

Translated using Weblate (Portuguese)

Currently translated at 64.2% (36 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt/

Translated using Weblate (Polish)

Currently translated at 96.4% (54 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pl/

Translated using Weblate (Dutch)

Currently translated at 85.7% (48 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/nl/

Translated using Weblate (Italian)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/it/

Translated using Weblate (Indonesian)

Currently translated at 62.5% (35 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/id/

Translated using Weblate (Hebrew)

Currently translated at 62.5% (35 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/he/

Translated using Weblate (Danish)

Currently translated at 62.5% (35 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/da/

Translated using Weblate (Czech)

Currently translated at 78.5% (44 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/cs/

Translated using Weblate (Bulgarian)

Currently translated at 64.2% (36 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/bg/

Translated using Weblate (Dutch)

Currently translated at 100.0% (187 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/nl/

Translated using Weblate (Czech)

Currently translated at 88.4% (92 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/cs/

Translated using Weblate (Macedonian)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/mk/

Translated using Weblate (Kurdish)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ku_IQ/

Translated using Weblate (Icelandic)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/is/

Translated using Weblate (Galician)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/gl/

Translated using Weblate (Irish)

Currently translated at 90.1% (330 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ga/

Translated using Weblate (Persian)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/fa/

Translated using Weblate (Estonian)

Currently translated at 90.1% (330 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/et/

Translated using Weblate (Greek)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/el/

Translated using Weblate (Catalan)

Currently translated at 89.6% (328 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ca/

Translated using Weblate (Belarusian)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/be/

Translated using Weblate (Indonesian)

Currently translated at 87.1% (319 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/id/

Translated using Weblate (Hungarian)

Currently translated at 87.1% (319 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/hu/

Translated using Weblate (Mongolian)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/mn/

Translated using Weblate (Malayalam)

Currently translated at 90.1% (330 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ml/

Translated using Weblate (Lithuanian)

Currently translated at 64.2% (36 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/lt/

Translated using Weblate (Korean)

Currently translated at 64.2% (36 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ko/

Translated using Weblate (Greek)

Currently translated at 64.2% (36 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/el/

Translated using Weblate (Tagalog)

Currently translated at 86.0% (623 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/tl/

Translated using Weblate (Korean)

Currently translated at 86.0% (623 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ko/

Translated using Weblate (Arabic)

Currently translated at 86.1% (624 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ar/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 89.8% (329 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/zh_Hant_HK/

Translated using Weblate (Vietnamese)

Currently translated at 98.6% (361 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/vi/

Translated using Weblate (Urdu (Pakistan))

Currently translated at 92.0% (337 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ur_PK/

Translated using Weblate (Klingon)

Currently translated at 91.8% (336 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/tlh/

Translated using Weblate (Tagalog)

Currently translated at 89.6% (328 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/tl/

Translated using Weblate (Thai)

Currently translated at 89.6% (328 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/th/

Translated using Weblate (Tamil)

Currently translated at 92.8% (340 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ta/

Translated using Weblate (Swahili)

Currently translated at 92.3% (338 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/sw/

Translated using Weblate (Sundanese)

Currently translated at 92.3% (338 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/su/

Translated using Weblate (Slovenian)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/sl/

Translated using Weblate (Sinhala)

Currently translated at 92.3% (338 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/si/

Translated using Weblate (Scots)

Currently translated at 92.3% (338 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/sco/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 99.4% (364 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/nb_NO/

Translated using Weblate (Norwegian Nynorsk)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/nn/

Translated using Weblate (Malay)

Currently translated at 92.0% (337 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ms/

Translated using Weblate (Marathi)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/mr/

Translated using Weblate (Korean)

Currently translated at 90.7% (332 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ko/

Translated using Weblate (Javanese)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/jv/

Translated using Weblate (Lojban)

Currently translated at 89.8% (329 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/jbo/

Translated using Weblate (Esperanto)

Currently translated at 89.6% (328 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/eo/

Translated using Weblate (English)

Currently translated at 91.5% (335 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/en@lolcat/

Translated using Weblate (Arabic)

Currently translated at 91.8% (336 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ar/

Translated using Weblate (Afrikaans)

Currently translated at 90.4% (331 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/af/

Translated using Weblate (Acholi)

Currently translated at 90.1% (330 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ach/

Translated using Weblate (Turkish)

Currently translated at 87.5% (7 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/tr/

Translated using Weblate (Dutch)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/nl/

Translated using Weblate (Indonesian)

Currently translated at 87.5% (7 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/id/

Translated using Weblate (Czech)

Currently translated at 87.5% (7 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/cs/

Translated using Weblate (Ukrainian)

Currently translated at 87.1% (319 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/uk/

Translated using Weblate (Turkish)

Currently translated at 92.0% (337 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/tr/

Translated using Weblate (Serbian)

Currently translated at 87.4% (320 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/sr/

Translated using Weblate (Slovak)

Currently translated at 87.4% (320 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/sk/

Translated using Weblate (Romanian)

Currently translated at 96.1% (352 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ro/

Translated using Weblate (Dutch)

Currently translated at 95.0% (348 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/nl/

Translated using Weblate (English (Pirate))

Currently translated at 90.2% (1979 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (Ukrainian)

Currently translated at 64.2% (36 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/uk/

Translated using Weblate (Portuguese)

Currently translated at 64.2% (36 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt/

Translated using Weblate (Polish)

Currently translated at 96.4% (54 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pl/

Translated using Weblate (Bulgarian)

Currently translated at 64.2% (36 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/bg/

Translated using Weblate (Swedish)

Currently translated at 86.0% (623 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/sv/

Translated using Weblate (Portuguese)

Currently translated at 84.6% (613 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt/

Translated using Weblate (Dutch)

Currently translated at 95.1% (689 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/nl/

Translated using Weblate (Indonesian)

Currently translated at 78.5% (569 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/id/

Translated using Weblate (Czech)

Currently translated at 83.9% (608 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/cs/

Translated using Weblate (Ukrainian)

Currently translated at 87.5% (7 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/uk/

Translated using Weblate (English (Pirate))

Currently translated at 89.1% (1955 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 88.6% (1944 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (Swahili)

Currently translated at 97.0% (99 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/sw/

Translated using Weblate (Persian)

Currently translated at 97.0% (99 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/fa/

Translated using Weblate (Afrikaans)

Currently translated at 97.0% (99 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/af/

Translated using Weblate (Icelandic)

Currently translated at 8.6% (9 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/is/

Translated using Weblate (Korean)

Currently translated at 93.9% (343 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/ko/

Translated using Weblate (Korean)

Currently translated at 98.3% (121 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/ko/

Translated using Weblate (Basque)

Currently translated at 6.5% (8 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/eu/

Translated using Weblate (Persian)

Currently translated at 91.6% (165 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/fa/

Translated using Weblate (Portuguese)

Currently translated at 88.0% (118 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/pt/

Translated using Weblate (Swedish)

Currently translated at 79.6% (145 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/sv/

Translated using Weblate (Portuguese)

Currently translated at 96.4% (54 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/pt/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (111 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/pt_BR/

Translated using Weblate (Turkish)

Currently translated at 78.1% (1714 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/tr/

Translated using Weblate (Dutch)

Currently translated at 97.6% (2141 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/

Translated using Weblate (Hungarian)

Currently translated at 77.7% (1704 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/hu/

Translated using Weblate (English (Pirate))

Currently translated at 87.9% (1929 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (Portuguese)

Currently translated at 97.7% (177 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/pt/

Translated using Weblate (Bulgarian)

Currently translated at 98.8% (179 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/bg/

Translated using Weblate (Serbian)

Currently translated at 15.3% (16 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/sr/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/en@pirate/

Translated using Weblate (Spanish (Latin America))

Currently translated at 95.0% (2084 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Korean)

Currently translated at 69.2% (72 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ko/

Translated using Weblate (Japanese)

Currently translated at 93.5% (2052 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (104 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ja/

Translated using Weblate (Turkish)

Currently translated at 78.1% (1714 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/tr/

Translated using Weblate (English (Pirate))

Currently translated at 86.6% (1901 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (Turkish)

Currently translated at 99.0% (101 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/tr/

Translated using Weblate (French)

Currently translated at 100.0% (104 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/fr/

Translated using Weblate (English)

Currently translated at 98.3% (359 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/en@lolcat/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/en@pirate/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (366 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pt_BR/

Translated using Weblate (English (Pirate))

Currently translated at 91.9% (666 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 99.1% (122 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/en@pirate/

Translated using Weblate (English)

Currently translated at 98.3% (359 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/en@lolcat/

Translated using Weblate (Japanese)

Currently translated at 93.3% (2048 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (123 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/pt_BR/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 98.0% (357 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 84.4% (1851 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 91.2% (661 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (187 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/en@pirate/

Translated using Weblate (English)

Currently translated at 13.5% (15 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/en@lolcat/

Translated using Weblate (Latin)

Currently translated at 99.4% (186 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/la/

Translated using Weblate (Catalan)

Currently translated at 97.0% (99 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/ca/

Translated using Weblate (Latvian)

Currently translated at 84.6% (11 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/lv/

Translated using Weblate (Korean)

Currently translated at 83.5% (71 of 85 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/ko/

Translated using Weblate (Latin)

Currently translated at 88.4% (92 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/la/

Translated using Weblate (English)

Currently translated at 39.4% (41 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en@lolcat/

Translated using Weblate (Vietnamese)

Currently translated at 90.1% (55 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/vi/

Translated using Weblate (English)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/en@lolcat/

Translated using Weblate (Korean)

Currently translated at 94.0% (191 of 203 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/ko/

Translated using Weblate (Tagalog)

Currently translated at 77.5% (1701 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/tl/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 77.6% (1703 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nb_NO/

Translated using Weblate (Lithuanian)

Currently translated at 77.5% (1701 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/lt/

Translated using Weblate (Malay)

Currently translated at 83.8% (306 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/ms/

Translated using Weblate (English)

Currently translated at 98.3% (359 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/en@lolcat/

Translated using Weblate (Vietnamese)

Currently translated at 98.8% (178 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/vi/

Translated using Weblate (Spanish (Latin America))

Currently translated at 86.0% (623 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 95.0% (2084 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Czech)

Currently translated at 97.8% (182 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/cs/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/

Translated using Weblate (Swedish)

Currently translated at 81.9% (1797 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/sv/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Portuguese)

Currently translated at 79.2% (1739 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt/

Translated using Weblate (Italian)

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/

Translated using Weblate (Indonesian)

Currently translated at 77.6% (1703 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/id/

Translated using Weblate (Spanish)

Currently translated at 88.0% (1932 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish)

Currently translated at 88.0% (1932 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (365 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/zh_Hans/

Translated using Weblate (Czech)

Currently translated at 100.0% (187 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/cs/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (104 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en@pirate/

Translated using Weblate (German)

Currently translated at 100.0% (104 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/de/

Translated using Weblate (Dutch)

Currently translated at 99.4% (179 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/nl/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (186 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 83.9% (1840 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (104 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en@pirate/

Translated using Weblate (Spanish)

Currently translated at 87.9% (1928 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (104 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Spanish)

Currently translated at 97.1% (101 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Spanish)

Currently translated at 96.1% (100 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Spanish)

Currently translated at 95.1% (99 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Spanish)

Currently translated at 90.3% (94 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Spanish)

Currently translated at 87.8% (1927 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish)

Currently translated at 89.4% (93 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Spanish)

Currently translated at 87.8% (1927 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish)

Currently translated at 87.8% (1927 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish)

Currently translated at 87.8% (1927 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Italian)

Currently translated at 100.0% (104 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/it/

Translated using Weblate (Spanish)

Currently translated at 87.8% (1927 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Italian)

Currently translated at 97.1% (101 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/it/

Translated using Weblate (Spanish)

Currently translated at 100.0% (182 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (186 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (186 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/en@pirate/

Translated using Weblate (Spanish)

Currently translated at 87.8% (1927 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish)

Currently translated at 87.8% (1927 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (123 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (English (Pirate))

Currently translated at 89.7% (167 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 89.7% (167 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/en@pirate/

Translated using Weblate (Spanish (Latin America))

Currently translated at 95.0% (2084 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (104 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es_419/

Translated using Weblate (English (Pirate))

Currently translated at 96.8% (553 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/en@pirate/

Translated using Weblate (Japanese)

Currently translated at 99.0% (103 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ja/

Translated using Weblate (Hindi)

Currently translated at 100.0% (13 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/hi/

Translated using Weblate (German)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/de/

Translated using Weblate (Japanese)

Currently translated at 100.0% (724 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/

Translated using Weblate (English (Pirate))

Currently translated at 83.7% (1836 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (German)

Currently translated at 100.0% (104 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/de/

Translated using Weblate (English)

Currently translated at 0.5% (3 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/en@lolcat/

Translated using Weblate (English (Pirate))

Currently translated at 83.6% (1834 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (724 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hans/

Translated using Weblate (English (Pirate))

Currently translated at 98.9% (185 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/en@pirate/

Translated using Weblate (Chinese (Traditional))

Currently translated at 98.0% (102 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (104 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt_BR/

Translated using Weblate (German)

Currently translated at 99.0% (103 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/de/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 70.1% (73 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant_HK/

Translated using Weblate (English (Pirate))

Currently translated at 93.2% (125 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (13 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 83.5% (1832 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 76.7% (43 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/en@pirate/

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.5% (721 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (104 of 104 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hans/

Translated using Weblate (English (Pirate))

Currently translated at 83.2% (1826 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/
2020-11-30 22:03:01 +01:00
Sabe Jones 637048af0b Merge branch 'release' into develop 2020-11-30 15:01:07 -06:00
Sabe Jones d6be92b346 4.172.0 2020-11-30 14:59:50 -06:00
Sabe Jones 2ed15f58e9 chore(sprites): compile 2020-11-30 14:59:36 -06:00
Sabe Jones 42de4397a1 feat(content): December Mystery Items 2020-11-30 14:59:30 -06:00
RaitheOfDureya 661c7b23a1 Removed duplicates I18N strings (related to issue #9210) (#12679)
* Removed duplicated string from `generic.json`

* Removed duplicated string from `npc.json`
2020-11-30 21:44:01 +01:00
jbusa22 f077e40c4c use or clause for display name and username search (#12820)
* use or clause for display name and username search

* update styling

* More style fix

* update comment and regex
2020-11-30 20:05:58 +01:00
Denys Dorokhov 3ce182d0dc Feature/enhance get memebers for a challenge fixes #12481 (#12716)
* refactor(api-members): separate handler for the GET /challenges/:challengeId/members route

* refactor(api-members): challenges-related code removed from _getMembersForItem handler function

* feat(api-members): added support to the new includeTasks query parameter for the GET /challenges/:challengeId/members route

* fix(api-members): adjustments to the GET /challenges/:challengeId/members route

* fix(api-members): merge of _getMembersTasksFromChallenge and additional check for a test suite

* refactor(api-members): includeAllMembers query parameter got removed from the GET /challenges/:challengeId/members route

* GET-challenges_challengeId_members.test.js: use _id

* members.js: use _id instead of id

* use id instead of _id

* _id instead of id

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-11-30 20:04:17 +01:00
Matteo Pagliazzi 6a658c45b5 Upgrade some deps: helmet, slack, amplitude and short-uuid (#12817)
* upgrade helmet to version 4

* deps(short-uuid): upgrade to version 4, closes #12573

* deps(slack): upgrade to version 4

* deps(slack): upgrade to version 5, closes #11442

* deps(amplitude): upgrade to latest version use api v2

* fix tests

* slack tests: return promise

* refactor slack setup for tests

* fix slack unit tests
2020-11-30 20:03:04 +01:00
Matteo Pagliazzi 7057797ed3 Node 14 (#12715)
* node 14

* restore package-lock.json from develop

* remove old heroku buildpack
2020-11-30 20:02:06 +01:00
negue d3eb9fe230 Apply Dropdown Styles to various parts (#12814)
* membersModal use the new select component instead of html select

* update dropdown styles on challengeDetail (add task) and on inventory unequip

* change the width to "min-width"
2020-11-30 20:01:22 +01:00
Matteo Pagliazzi 51b50bfa3c Upgrade APN module (#12818)
* switch apn module to up to date version @parse/apn

* remove old module

* fix unit tests
2020-11-30 20:00:57 +01:00
dependabot-preview[bot] 8c953ea8cb build(deps): bump core-js from 3.7.0 to 3.8.0 in /website/client (#12833)
Bumps [core-js](https://github.com/zloirock/core-js) from 3.7.0 to 3.8.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.7.0...v3.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-30 11:52:58 +01:00
dependabot-preview[bot] c5b644b892 build(deps): bump mongoose from 5.10.15 to 5.10.18 (#12826)
Bumps [mongoose](https://github.com/Automattic/mongoose) from 5.10.15 to 5.10.18.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/History.md)
- [Commits](https://github.com/Automattic/mongoose/compare/5.10.15...5.10.18)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-30 11:52:49 +01:00
dependabot-preview[bot] e65bd4164d build(deps): bump @babel/core from 7.12.7 to 7.12.9 (#12825)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.12.7 to 7.12.9.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.12.9/packages/babel-core)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-30 11:52:39 +01:00
dependabot-preview[bot] c9ef21aa7e build(deps): bump nconf from 0.10.0 to 0.11.0 (#12821)
Bumps [nconf](https://github.com/flatiron/nconf) from 0.10.0 to 0.11.0.
- [Release notes](https://github.com/flatiron/nconf/releases)
- [Changelog](https://github.com/indexzero/nconf/blob/master/CHANGELOG.md)
- [Commits](https://github.com/flatiron/nconf/compare/0.10.0...v0.11.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-30 11:52:15 +01:00
dependabot-preview[bot] f41eae3bf3 build(deps): bump nconf from 0.10.0 to 0.11.0 in /website/client (#12829)
Bumps [nconf](https://github.com/flatiron/nconf) from 0.10.0 to 0.11.0.
- [Release notes](https://github.com/flatiron/nconf/releases)
- [Changelog](https://github.com/indexzero/nconf/blob/master/CHANGELOG.md)
- [Commits](https://github.com/flatiron/nconf/compare/0.10.0...v0.11.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-30 11:52:07 +01:00
dependabot-preview[bot] c984c04e46 build(deps-dev): bump run-rs from 0.6.2 to 0.7.3 (#12822)
Bumps [run-rs](https://github.com/vkarpov15/run-rs) from 0.6.2 to 0.7.3.
- [Release notes](https://github.com/vkarpov15/run-rs/releases)
- [Changelog](https://github.com/vkarpov15/run-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vkarpov15/run-rs/compare/0.6.2...0.7.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-30 11:51:52 +01:00
Matteo Pagliazzi 4e9a2de527 fix(analytics): fix tests and add new ones for getServiceByEnvironment 2020-11-30 11:39:39 +01:00
Matteo Pagliazzi 7745a0e65a fix(analytics): always use mock service in development 2020-11-29 23:15:26 +01:00
Matteo Pagliazzi 6b3a6eb59f fix(analytics): allow tracking static pages events when the user is not authenticated 2020-11-29 20:15:12 +01:00
Matteo Pagliazzi 103b4cb8a8 docs(get user challenges): document all query parameters for the GET /challenges/user API route 2020-11-28 19:32:08 +01:00
Sabe Jones de5473c71e 4.171.1 2020-11-26 14:01:31 -06:00
Sabe Jones f31370d7ba chore(event): NPCs and auto award turkey 2020-11-26 14:01:23 -06:00
Sabe Jones 3b7bf5de75 chore(event): yearly harvest feasting 2020-11-26 13:39:07 -06:00
Melior 496950e97d Merge branch 'origin/develop' into Weblate. 2020-11-25 01:00:01 +01:00
Sabe Jones 281d7b4fe2 Merge branch 'release' into develop 2020-11-24 17:57:24 -06:00
Sabe Jones 8d2ecaffb0 4.171.0 2020-11-24 17:56:54 -06:00
Sabe Jones 00f66b3824 chore(sprites): compile 2020-11-24 17:53:23 -06:00
Sabe Jones c4f6644c3a feat(content): Red Pet Achievement 2020-11-24 17:53:15 -06:00
Melior 58b5af0d4c Translated using Weblate (English (Pirate))
Currently translated at 100.0% (13 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 76.7% (43 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/en@pirate/

Translated using Weblate (Spanish (Latin America))

Currently translated at 86.0% (623 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (English (Pirate))

Currently translated at 69.6% (39 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/en@pirate/

Translated using Weblate (Korean)

Currently translated at 16.1% (53 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/ko/

Translated using Weblate (Dutch)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/nl/

Translated using Weblate (Spanish (Latin America))

Currently translated at 94.2% (2066 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 93.2% (2044 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Spanish)

Currently translated at 87.8% (1926 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (English (Pirate))

Currently translated at 83.2% (1825 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (Dutch)

Currently translated at 85.7% (48 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/nl/

Translated using Weblate (English (Pirate))

Currently translated at 67.8% (38 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/en@pirate/

Translated using Weblate (Spanish)

Currently translated at 87.8% (1926 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish)

Currently translated at 87.8% (1926 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Hindi)

Currently translated at 46.8% (52 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/hi/

Translated using Weblate (Malay)

Currently translated at 3.8% (7 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/ms/

Translated using Weblate (Hindi)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/hi/

Translated using Weblate (Hindi)

Currently translated at 97.5% (121 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/hi/

Translated using Weblate (Galician)

Currently translated at 85.9% (622 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/gl/

Translated using Weblate (Hindi)

Currently translated at 91.8% (90 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/hi/

Translated using Weblate (English (Pirate))

Currently translated at 92.5% (124 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/en@pirate/

Translated using Weblate (Dutch)

Currently translated at 98.8% (84 of 85 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/nl/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (186 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/zh_Hans/

Translated using Weblate (Danish)

Currently translated at 87.4% (320 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/da/

Translated using Weblate (English (Pirate))

Currently translated at 82.7% (1815 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 67.8% (38 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/en@pirate/

Translated using Weblate (Chinese (Traditional))

Currently translated at 96.9% (702 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hant/

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.4% (720 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hans/

Translated using Weblate (Italian)

Currently translated at 100.0% (724 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/

Translated using Weblate (Spanish)

Currently translated at 95.7% (693 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es/

Translated using Weblate (German)

Currently translated at 100.0% (724 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (365 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/zh_Hans/

Translated using Weblate (English (Pirate))

Currently translated at 98.9% (97 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en@pirate/

Translated using Weblate (Spanish (Latin America))

Currently translated at 85.4% (619 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/pt_BR/

Translated using Weblate (Spanish (Latin America))

Currently translated at 94.1% (2065 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish)

Currently translated at 94.7% (686 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es/

Translated using Weblate (Latin)

Currently translated at 99.4% (186 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/la/

Translated using Weblate (Latin)

Currently translated at 93.8% (92 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/la/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 99.4% (364 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/nb_NO/

Translated using Weblate (Danish)

Currently translated at 88.0% (118 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/da/

Translated using Weblate (Dutch)

Currently translated at 90.3% (168 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/nl/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Dutch)

Currently translated at 97.6% (2141 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/

Translated using Weblate (Japanese)

Currently translated at 93.0% (2040 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Spanish)

Currently translated at 87.4% (1918 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Italian)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/it/

Translated using Weblate (Spanish)

Currently translated at 93.3% (676 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es/

Translated using Weblate (Korean)

Currently translated at 98.3% (184 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/ko/

Translated using Weblate (Russian)

Currently translated at 96.9% (702 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ru/

Translated using Weblate (Russian)

Currently translated at 99.7% (364 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/ru/

Translated using Weblate (Russian)

Currently translated at 97.8% (182 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ru/

Translated using Weblate (Spanish)

Currently translated at 100.0% (186 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/es/

Translated using Weblate (Spanish)

Currently translated at 93.2% (675 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (123 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (365 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/es/

Translated using Weblate (Russian)

Currently translated at 99.0% (101 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/ru/

Translated using Weblate (Portuguese)

Currently translated at 81.6% (80 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt/

Translated using Weblate (Spanish (Latin America))

Currently translated at 93.8% (2058 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Japanese)

Currently translated at 92.8% (2036 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (724 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (724 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (German)

Currently translated at 100.0% (724 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/

Translated using Weblate (Spanish (Latin America))

Currently translated at 93.7% (2056 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 93.2% (2045 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (723 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (723 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.7% (722 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.5% (721 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.5% (721 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.4% (720 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Italian)

Currently translated at 100.0% (724 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/

Translated using Weblate (Japanese)

Currently translated at 92.6% (2032 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Spanish (Latin America))

Currently translated at 92.6% (2032 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 92.4% (2028 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Japanese)

Currently translated at 92.4% (2028 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 92.4% (2028 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 92.3% (2025 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 48.9% (48 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant_HK/

Translated using Weblate (German)

Currently translated at 100.0% (186 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/de/

Translated using Weblate (German)

Currently translated at 100.0% (724 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/

Translated using Weblate (German)

Currently translated at 100.0% (365 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/de/

Translated using Weblate (French)

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/fr/

Translated using Weblate (Spanish (Latin America))

Currently translated at 92.4% (2028 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (186 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 92.3% (2025 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (365 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/es_419/

Translated using Weblate (Italian)

Currently translated at 99.8% (723 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (186 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 100.0% (186 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ja/

Translated using Weblate (Italian)

Currently translated at 100.0% (186 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/it/

Translated using Weblate (Japanese)

Currently translated at 100.0% (724 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/

Translated using Weblate (Italian)

Currently translated at 99.4% (720 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/

Translated using Weblate (German)

Currently translated at 99.4% (720 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (365 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 100.0% (365 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/ja/

Translated using Weblate (Spanish)

Currently translated at 100.0% (102 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/es/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.3% (719 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (French)

Currently translated at 100.0% (724 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/

Translated using Weblate (Dutch)

Currently translated at 100.0% (123 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/nl/

Translated using Weblate (French)

Currently translated at 100.0% (365 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/fr/

Translated using Weblate (French)

Currently translated at 100.0% (186 of 186 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/fr/

Translated using Weblate (Dutch)

Currently translated at 83.9% (47 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/nl/

Translated using Weblate (Italian)

Currently translated at 100.0% (365 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/it/

Translated using Weblate (French)

Currently translated at 99.7% (364 of 365 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/fr/

Translated using Weblate (Spanish (Latin America))

Currently translated at 85.4% (619 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 85.4% (619 of 724 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/
2020-11-25 00:14:39 +01:00
Alys 9b76f9831e Miscellaneous lint fixes: move watch & mounted properties; apply automatic fixes (#12791)
* commit lint's automatic fixes

* move watch and mounted properties as advised in lint warnings
2020-11-23 22:14:14 +01:00
Lio 8bd2e09bde Bugfix in ko/front.json (#12790)
In weblate we have the allert:
Weblate could not parse the translation files while updating the translations.

The following occurrences were found:
Filename	Error
website/common/locales/ko/front.json	JSONDecodeError('Expecting property name enclosed in double quotes: line 19 column 1 (char 805)',)

I deleted the trailing comma (so that no further entry is expected).
2020-11-23 21:53:58 +01:00
dependabot-preview[bot] 670843c395 build(deps): bump @vue/cli-plugin-unit-mocha in /website/client (#12810)
Bumps [@vue/cli-plugin-unit-mocha](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-unit-mocha) from 4.5.8 to 4.5.9.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/v4.5.9/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.9/packages/@vue/cli-plugin-unit-mocha)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-23 11:31:20 +01:00
dependabot-preview[bot] a81e6932fb build(deps): bump @vue/cli-plugin-eslint in /website/client (#12806)
Bumps [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-eslint) from 4.5.8 to 4.5.9.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/v4.5.9/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.9/packages/@vue/cli-plugin-eslint)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-23 11:31:00 +01:00
dependabot-preview[bot] 4219bcbffa build(deps): bump @babel/core from 7.12.3 to 7.12.7 (#12799)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.12.3 to 7.12.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.12.7/packages/babel-core)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-23 11:28:01 +01:00
dependabot-preview[bot] e499666f64 build(deps): bump @vue/cli-plugin-router in /website/client (#12807)
Bumps [@vue/cli-plugin-router](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-router) from 4.5.8 to 4.5.9.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/v4.5.9/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.9/packages/@vue/cli-plugin-router)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-23 11:25:34 +01:00
dependabot-preview[bot] b5a25d74df build(deps): bump @vue/cli-plugin-babel in /website/client (#12811)
Bumps [@vue/cli-plugin-babel](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-babel) from 4.5.8 to 4.5.9.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/v4.5.9/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.9/packages/@vue/cli-plugin-babel)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-23 11:25:21 +01:00
dependabot-preview[bot] d5408b89b2 build(deps): bump @vue/cli-service in /website/client (#12805)
Bumps [@vue/cli-service](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-service) from 4.5.8 to 4.5.9.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/v4.5.9/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.9/packages/@vue/cli-service)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-23 11:24:59 +01:00
dependabot-preview[bot] 4c69bf2090 build(deps): bump @babel/preset-env from 7.12.1 to 7.12.7 (#12804)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.12.1 to 7.12.7.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.12.7/packages/babel-preset-env)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-23 11:24:47 +01:00
dependabot-preview[bot] 54e2874990 build(deps): bump csv-stringify from 5.5.1 to 5.5.3 (#12801)
Bumps [csv-stringify](https://github.com/adaltas/node-csv-stringify) from 5.5.1 to 5.5.3.
- [Release notes](https://github.com/adaltas/node-csv-stringify/releases)
- [Changelog](https://github.com/adaltas/node-csv-stringify/blob/master/CHANGELOG.md)
- [Commits](https://github.com/adaltas/node-csv-stringify/compare/v5.5.1...v5.5.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-23 11:24:07 +01:00
dependabot-preview[bot] 278ed4d2df build(deps): bump mongoose from 5.10.14 to 5.10.15 (#12798)
Bumps [mongoose](https://github.com/Automattic/mongoose) from 5.10.14 to 5.10.15.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/History.md)
- [Commits](https://github.com/Automattic/mongoose/compare/5.10.14...5.10.15)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-23 11:23:50 +01:00
Matteo Pagliazzi f7b4d25657 update apidoc 2020-11-20 09:18:16 +01:00
Sabe Jones f44b331680 4.170.1 2020-11-19 16:19:24 -06:00
Matteo Pagliazzi 284cfde935 Mandatory pagination for GET /challenges/user (#12792)
* BREAKING: require pagination for GET /challenges/user

* fix tests

* remove unused test
2020-11-19 16:18:11 -06:00
Melior c19c39d72d Translated using Weblate (Spanish (Latin America))
Currently translated at 91.1% (1998 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Italian)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/it/

Translated using Weblate (Japanese)

Currently translated at 92.2% (2024 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Dutch)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/nl/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/en_GB/

Translated using Weblate (Dutch)

Currently translated at 99.4% (179 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/nl/

Translated using Weblate (Dutch)

Currently translated at 99.4% (179 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/nl/

Translated using Weblate (Italian)

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/it/

Translated using Weblate (Japanese)

Currently translated at 92.1% (2021 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (German)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/de/

Translated using Weblate (Chinese (Traditional))

Currently translated at 99.2% (567 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/zh_Hant/

Translated using Weblate (German)

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/

Translated using Weblate (German)

Currently translated at 100.0% (203 of 203 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/de/

Translated using Weblate (German)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/de/

Translated using Weblate (German)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/de/

Translated using Weblate (German)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/de/

Translated using Weblate (Chinese (Traditional))

Currently translated at 97.9% (96 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant/

Translated using Weblate (Chinese (Traditional))

Currently translated at 99.4% (179 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/zh_Hant/

Translated using Weblate (German)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/de/

Translated using Weblate (German)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/de/

Translated using Weblate (German)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/de/

Translated using Weblate (German)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/de/

Translated using Weblate (German)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/de/

Translated using Weblate (German)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/de/

Translated using Weblate (Japanese)

Currently translated at 92.1% (2020 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (54 of 54 strings)

Translation: Habitica/Defaulttasks
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/pt_BR/

Translated using Weblate (Korean)

Currently translated at 98.1% (109 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ko/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 35.7% (35 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant_HK/

Translated using Weblate (Korean)

Currently translated at 98.1% (109 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ko/

Translated using Weblate (Korean)

Currently translated at 98.1% (109 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ko/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (47 of 47 strings)

Translation: Habitica/Contrib
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/pt_BR/

Translated using Weblate (Spanish (Latin America))

Currently translated at 90.2% (1980 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/zh_Hans/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (47 of 47 strings)

Translation: Habitica/Contrib
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 91.9% (2016 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 91.8% (2014 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (23 of 23 strings)

Translation: Habitica/Loginincentives
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 91.7% (2012 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (German)

Currently translated at 100.0% (102 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/de/

Translated using Weblate (Spanish (Latin America))

Currently translated at 88.6% (1944 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (102 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/zh_Hans/

Translated using Weblate (Spanish (Latin America))

Currently translated at 88.6% (1944 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (102 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/es_419/

Translated using Weblate (Japanese)

Currently translated at 91.5% (2008 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (102 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 91.5% (2007 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (102 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/ja/

Translated using Weblate (Italian)

Currently translated at 100.0% (102 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/it/

Translated using Weblate (French)

Currently translated at 100.0% (102 of 102 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/fr/
2020-11-18 21:11:25 +01:00
Sabe Jones 809398f607 Merge branch 'release' into develop 2020-11-18 13:53:50 -06:00
Sabe Jones 5791e87132 4.170.0 2020-11-18 13:53:30 -06:00
Sabe Jones 4a93201f50 chore(analytics): track Challenge prizes 2020-11-17 15:50:44 -06:00
Sabe Jones a8ac927030 chore(sprites): compile 2020-11-16 15:52:13 -06:00
Sabe Jones 5327827ef7 feat(content): Black Pearl Hatching Potions + quest 2020-11-16 15:52:06 -06:00
Matteo Pagliazzi df1e4af7fc fix(profile): correctly change page title when closing profile modal, fixes #12760, thanks @aevix 2020-11-16 11:30:06 +01:00
dependabot-preview[bot] d0c9c2917f build(deps): bump mongoose from 5.10.13 to 5.10.14 (#12786)
Bumps [mongoose](https://github.com/Automattic/mongoose) from 5.10.13 to 5.10.14.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/History.md)
- [Commits](https://github.com/Automattic/mongoose/compare/5.10.13...5.10.14)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-16 11:16:51 +01:00
dependabot-preview[bot] 50e009efff build(deps): bump amplitude-js from 7.3.2 to 7.3.3 in /website/client (#12789)
Bumps [amplitude-js](https://github.com/amplitude/amplitude-javascript) from 7.3.2 to 7.3.3.
- [Release notes](https://github.com/amplitude/amplitude-javascript/releases)
- [Changelog](https://github.com/amplitude/Amplitude-JavaScript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/amplitude/amplitude-javascript/compare/v7.3.2...v7.3.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-16 11:16:05 +01:00
Shadow 8c98b7127e make guilds not display group plans as title section (#12761)
* make guilds not display group plans as title section

* fix for parties as well

* task board for group plans now says group plans

* fix party title

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-11-14 19:35:09 +01:00
Melior cb96ff84d1 Merge branch 'origin/develop' into Weblate. 2020-11-13 21:34:10 +01:00
Sabe Jones 705ae93292 4.169.2 2020-11-13 14:32:48 -06:00
Sabe Jones 1c089c33a0 Merge branch 'develop' into release 2020-11-13 14:31:50 -06:00
Melior 4481217b90 Translated using Weblate (Spanish (Latin America))
Currently translated at 87.5% (1920 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Italian)

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/

Translated using Weblate (Italian)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/it/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (23 of 23 strings)

Translation: Habitica/Loginincentives
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 91.4% (2006 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Czech)

Currently translated at 87.5% (1921 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/cs/

Translated using Weblate (Czech)

Currently translated at 87.5% (1921 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/cs/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (111 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/nb_NO/

Translated using Weblate (Hindi)

Currently translated at 46.8% (52 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/hi/

Translated using Weblate (Latin)

Currently translated at 98.9% (185 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/la/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/nb_NO/

Translated using Weblate (Irish)

Currently translated at 84.6% (11 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/ga/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/nb_NO/

Translated using Weblate (Hindi)

Currently translated at 91.8% (90 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/hi/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 90.1% (55 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/nb_NO/

Translated using Weblate (Hindi)

Currently translated at 96.0% (195 of 203 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/hi/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 77.6% (1703 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nb_NO/

Translated using Weblate (Irish)

Currently translated at 77.5% (1701 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ga/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 92.4% (196 of 212 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/nb_NO/

Translated using Weblate (Spanish (Latin America))

Currently translated at 86.9% (1907 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Dutch)

Currently translated at 97.6% (2141 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/

Translated using Weblate (Spanish)

Currently translated at 87.4% (1918 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Czech)

Currently translated at 87.5% (1921 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/cs/

Translated using Weblate (Romanian)

Currently translated at 100.0% (187 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/ro/

Translated using Weblate (Bulgarian)

Currently translated at 100.0% (187 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/bg/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (23 of 23 strings)

Translation: Habitica/Loginincentives
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 91.2% (2002 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Spanish)

Currently translated at 87.4% (1918 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Japanese)

Currently translated at 91.1% (1998 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (15 of 15 strings)

Translation: Habitica/Death
Translate-URL: https://translate.habitica.com/projects/habitica/death/pt_BR/

Translated using Weblate (French)

Currently translated at 100.0% (98 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/fr/

Translated using Weblate (French)

Currently translated at 100.0% (98 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/fr/
2020-11-13 20:34:14 +01:00
Matteo Pagliazzi d3ba0346af Move more analytics to server (#12782)
* track events on the client by default, remove unused ones

* fix lint, remove some calls to updateUser

* remove dead code from guide.js
2020-11-13 15:42:46 +01:00
Matteo Pagliazzi 41de90e578 fix: make sure world state is not loaded every time a modal is opened, fix dev server caching on safari 2020-11-13 14:33:59 +01:00
Sabe Jones a863e79214 fix(teams): allow dismissal of approval requests, again 2020-11-10 15:25:12 -06:00
Sabe Jones 6ed1353e31 4.169.1 2020-11-10 14:49:14 -06:00
Sabe Jones c748477546 chore(shops): featured items update 2020-11-10 14:49:00 -06:00
Melior 365f9c0aa7 Merge branch 'origin/develop' into Weblate. 2020-11-10 21:12:30 +01:00
Melior 23e717353d Translated using Weblate (Spanish (Latin America))
Currently translated at 86.9% (1907 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 90.9% (1994 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Spanish (Latin America))

Currently translated at 86.5% (1897 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Swedish)

Currently translated at 98.3% (178 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/sv/

Translated using Weblate (Russian)

Currently translated at 85.7% (48 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ru/

Translated using Weblate (Japanese)

Currently translated at 90.7% (1990 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Czech)

Currently translated at 98.7% (564 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/cs/

Translated using Weblate (Czech)

Currently translated at 98.7% (564 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/cs/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 26.5% (26 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant_HK/

Translated using Weblate (Portuguese)

Currently translated at 99.4% (361 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/pt/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (13 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/pt_BR/

Translated using Weblate (Spanish (Latin America))

Currently translated at 86.1% (1890 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Portuguese)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/pt/

Translated using Weblate (Portuguese)

Currently translated at 96.5% (196 of 203 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/pt/

Translated using Weblate (Portuguese)

Currently translated at 96.1% (349 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/pt/

Translated using Weblate (Portuguese)

Currently translated at 78.5% (77 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/pt_BR/

Translated using Weblate (Spanish (Latin America))

Currently translated at 84.6% (1856 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish)

Currently translated at 100.0% (182 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (Spanish (Latin America))

Currently translated at 84.3% (1849 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish)

Currently translated at 100.0% (366 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/

Translated using Weblate (Japanese)

Currently translated at 90.5% (1986 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Spanish)

Currently translated at 87.4% (1918 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Swedish)

Currently translated at 71.4% (40 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/sv/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/zh_Hans/

Translated using Weblate (Ukrainian)

Currently translated at 51.6% (48 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Swedish)

Currently translated at 70.4% (69 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/sv/

Translated using Weblate (Spanish (Latin America))

Currently translated at 82.5% (1810 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Japanese)

Currently translated at 90.3% (1982 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hans/

Translated using Weblate (Japanese)

Currently translated at 90.2% (1979 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Spanish)

Currently translated at 100.0% (182 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (111 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (185 of 185 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (23 of 23 strings)

Translation: Habitica/Loginincentives
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (366 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/

Translated using Weblate (Spanish)

Currently translated at 87.4% (1918 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/es/

Translated using Weblate (Spanish)

Currently translated at 93.1% (669 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (47 of 47 strings)

Translation: Habitica/Contrib
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (187 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/es/

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.9% (2192 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/

Translated using Weblate (Russian)

Currently translated at 88.4% (161 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ru/

Translated using Weblate (Russian)

Currently translated at 97.8% (559 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ru/

Translated using Weblate (Russian)

Currently translated at 97.8% (559 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ru/

Translated using Weblate (Russian)

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/ru/

Translated using Weblate (Russian)

Currently translated at 97.8% (181 of 185 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ru/

Translated using Weblate (Russian)

Currently translated at 96.7% (354 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ru/

Translated using Weblate (Russian)

Currently translated at 100.0% (100 of 100 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/ru/

Translated using Weblate (Russian)

Currently translated at 100.0% (98 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ru/

Translated using Weblate (Russian)

Currently translated at 95.0% (58 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/ru/

Translated using Weblate (Russian)

Currently translated at 93.4% (57 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/ru/

Translated using Weblate (Russian)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/ru/

Translated using Weblate (Swedish)

Currently translated at 100.0% (187 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/sv/

Translated using Weblate (Polish)

Currently translated at 94.8% (93 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/

Translated using Weblate (Czech)

Currently translated at 87.5% (1921 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/cs/

Translated using Weblate (Japanese)

Currently translated at 90.1% (1978 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Spanish (Latin America))

Currently translated at 86.2% (619 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/
2020-11-10 21:12:21 +01:00
Sabe Jones d5517ffc5f 4.169.0 2020-11-10 14:06:56 -06:00
Sabe Jones 7b6f63958a fix(pets): better marshmallow positioning
Fixes #12630
2020-11-10 14:06:47 -06:00
Matteo Pagliazzi b5d8bcc0fe fix(categories): correct z-index, fix #12777 2020-11-10 19:10:39 +01:00
Matteo Pagliazzi 181b33101e Challenge Won Notification improvements (#12762)
* challenge won notification: add more info

* update tests

* use new notification on web, fixes #7716

* wip design

* finalize design

* fix markdown rendering
2020-11-10 18:47:13 +01:00
negue 4319bd5ad1 Update sidebar styles (#12744)
* update sidebars to the filter-sidebar components

* update sidebars to the filter-sidebar components

* use object v-for instead of Object.keys
2020-11-09 23:00:57 +01:00
negue f2c6838e95 update dropdowns to use the updated / styled components (#12758)
* update dropdowns to use the updated / styled components

* update colors / behavior for colors

* remove class binding
2020-11-09 22:26:21 +01:00
Sabe Jones a2cd79f20e chore(sprites): compile 2020-11-09 15:07:05 -06:00
Sabe Jones 6a367d3697 feat(content): Autumn Leaf and Frost Hatching Potions 2020-11-09 15:06:56 -06:00
Sabe Jones ef0b19f17e fix(backgrounds): corrected icon 2020-11-09 14:35:30 -06:00
Matteo Pagliazzi 27129754cd gems-promo: comment unused code 2020-11-09 16:34:52 +01:00
jbusa22 983aae7f87 Fixes #12730 - Tag filter not always cleared correctly when deleting active tag (#12737)
* Update title for tabs not including challenges, guild and team

* add section titles to challenges, guilds, and groups

* Update dynamic title to use vuex action

* Remove duplicate key

* Actually remove duplicate key

* Fix section sub section in group

* Add note to implement setTitle when adding a page

* Add missing sections to dynamic title

* Features string not translated

* Use onGroupUpdate to update group titles

* Add watcher to challenges for dynamic title updates

* Small fixes

* Add register and login to title, remove duplicate keys

* Add home page dynamic title functionality

* Minor name changes

* Fix tag filtering on deletion

* Remove debuggers

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-11-09 12:25:22 +01:00
Matteo Pagliazzi 174ac6d7e3 Revert "Revert "fix(banned words): fix partial matching of words containing diacritic… (#12444)""
This reverts commit 5362058f35.
2020-11-09 11:34:28 +01:00
Matteo Pagliazzi 2e59260149 Revert "Revert "Analytics: track generic events through the server (#12735)""
This reverts commit 9d6fb2ca26.
2020-11-09 11:34:20 +01:00
Matteo Pagliazzi 997cc9f3c5 Merge branch 'release' into develop 2020-11-09 11:33:53 +01:00
dependabot-preview[bot] 8a7b4db5ee build(deps): bump amplitude-js from 7.3.1 to 7.3.2 in /website/client (#12771)
Bumps [amplitude-js](https://github.com/amplitude/amplitude-javascript) from 7.3.1 to 7.3.2.
- [Release notes](https://github.com/amplitude/amplitude-javascript/releases)
- [Changelog](https://github.com/amplitude/Amplitude-JavaScript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/amplitude/amplitude-javascript/compare/v7.3.1...v7.3.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-09 10:50:39 +01:00
dependabot-preview[bot] 7adb33887e build(deps): bump bootstrap-vue from 2.18.1 to 2.19.0 in /website/client (#12772)
Bumps [bootstrap-vue](https://github.com/bootstrap-vue/bootstrap-vue) from 2.18.1 to 2.19.0.
- [Release notes](https://github.com/bootstrap-vue/bootstrap-vue/releases)
- [Changelog](https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/bootstrap-vue/bootstrap-vue/compare/v2.18.1...v2.19.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-09 10:50:30 +01:00
dependabot-preview[bot] 85d2e21510 build(deps): bump core-js from 3.6.5 to 3.7.0 in /website/client (#12770)
Bumps [core-js](https://github.com/zloirock/core-js) from 3.6.5 to 3.7.0.
- [Release notes](https://github.com/zloirock/core-js/releases)
- [Changelog](https://github.com/zloirock/core-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/zloirock/core-js/compare/v3.6.5...v3.7.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-09 10:50:11 +01:00
dependabot-preview[bot] 868a8a4e77 build(deps): bump sass from 1.28.0 to 1.29.0 in /website/client (#12769)
Bumps [sass](https://github.com/sass/dart-sass) from 1.28.0 to 1.29.0.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.28.0...1.29.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-09 10:50:05 +01:00
dependabot-preview[bot] b61425078a build(deps): bump mongoose from 5.10.11 to 5.10.13 (#12768)
Bumps [mongoose](https://github.com/Automattic/mongoose) from 5.10.11 to 5.10.13.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/History.md)
- [Commits](https://github.com/Automattic/mongoose/compare/5.10.11...5.10.13)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-09 10:49:53 +01:00
dependabot-preview[bot] 03876b86bb build(deps): bump vue-router from 3.4.8 to 3.4.9 in /website/client (#12773)
Bumps [vue-router](https://github.com/vuejs/vue-router) from 3.4.8 to 3.4.9.
- [Release notes](https://github.com/vuejs/vue-router/releases)
- [Changelog](https://github.com/vuejs/vue-router/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-router/compare/v3.4.8...v3.4.9)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-09 10:45:58 +01:00
Melior 8ac48406e9 Translated using Weblate (Spanish (Latin America))
Currently translated at 86.2% (619 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 86.2% (619 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (182 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es_419/

Translated using Weblate (Spanish)

Currently translated at 100.0% (182 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (13 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/pt_BR/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (366 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 82.3% (1806 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (98 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es_419/

Translated using Weblate (Japanese)

Currently translated at 90.0% (1974 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/ja/

Translated using Weblate (Spanish)

Currently translated at 100.0% (100 of 100 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/es/

Translated using Weblate (Japanese)

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ja/

Translated using Weblate (Spanish)

Currently translated at 99.2% (567 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (Hindi)

Currently translated at 99.1% (122 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/hi/

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.7% (2187 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 16.3% (16 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant_HK/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 15.3% (15 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant_HK/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (98 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt_BR/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (100 of 100 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/es_419/

Translated using Weblate (Spanish)

Currently translated at 99.1% (566 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (Spanish (Latin America))

Currently translated at 86.2% (619 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (182 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 96.9% (95 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es_419/

Translated using Weblate (Ukrainian)

Currently translated at 87.1% (319 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/uk/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 89.9% (1972 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (German)

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/

Translated using Weblate (German)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/de/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 99.6% (569 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ja/

Translated using Weblate (German)

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/de/

Translated using Weblate (Hindi)

Currently translated at 97.5% (121 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/hi/

Translated using Weblate (Italian)

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/

Translated using Weblate (Italian)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/it/

Translated using Weblate (Italian)

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/it/

Translated using Weblate (Hindi)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/hi/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/zh_Hans/

Translated using Weblate (French)

Currently translated at 100.0% (366 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/fr/

Translated using Weblate (French)

Currently translated at 100.0% (2193 of 2193 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/zh_Hans/

Translated using Weblate (French)

Currently translated at 100.0% (571 of 571 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/fr/

Translated using Weblate (French)

Currently translated at 100.0% (182 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fr/

Translated using Weblate (French)

Currently translated at 100.0% (185 of 185 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/fr/

Translated using Weblate (French)

Currently translated at 99.7% (365 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/fr/

Translated using Weblate (French)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/fr/

Translated using Weblate (French)

Currently translated at 100.0% (100 of 100 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/fr/
2020-11-05 22:49:10 +01:00
Sabe Jones a6e96f7ad9 4.168.3 2020-11-05 15:45:54 -06:00
Sabe Jones 43b8368f42 Merge branch 'develop' into release 2020-11-05 15:45:44 -06:00
Sabe Jones 5362058f35 Revert "fix(banned words): fix partial matching of words containing diacritic… (#12444)"
This reverts commit f2bcdd21de.
2020-11-05 15:44:59 -06:00
Sabe Jones 9d6fb2ca26 Revert "Analytics: track generic events through the server (#12735)"
This reverts commit 48dbe547c0.
2020-11-05 15:44:30 -06:00
jbusa22 9213ee92de Group title on route fix (#12743)
* Update title for tabs not including challenges, guild and team

* add section titles to challenges, guilds, and groups

* Update dynamic title to use vuex action

* Remove duplicate key

* Actually remove duplicate key

* Fix section sub section in group

* Add note to implement setTitle when adding a page

* Add missing sections to dynamic title

* Features string not translated

* Use onGroupUpdate to update group titles

* Add watcher to challenges for dynamic title updates

* Small fixes

* Add register and login to title, remove duplicate keys

* Add home page dynamic title functionality

* Minor name changes

* remove wrong i18n strings from front.js

* refactor router note

* 4.166.1

* build(deps): bump got from 11.7.0 to 11.8.0

Bumps [got](https://github.com/sindresorhus/got) from 11.7.0 to 11.8.0.
- [Release notes](https://github.com/sindresorhus/got/releases)
- [Commits](https://github.com/sindresorhus/got/compare/v11.7.0...v11.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

* build(deps): bump rate-limiter-flexible from 2.1.10 to 2.1.13 (#12709)

Bumps [rate-limiter-flexible](https://github.com/animir/node-rate-limiter-flexible) from 2.1.10 to 2.1.13.
- [Release notes](https://github.com/animir/node-rate-limiter-flexible/releases)
- [Commits](https://github.com/animir/node-rate-limiter-flexible/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* build(deps): bump image-size from 0.9.1 to 0.9.2 (#12711)

Bumps [image-size](https://github.com/image-size/image-size) from 0.9.1 to 0.9.2.
- [Release notes](https://github.com/image-size/image-size/releases)
- [Commits](https://github.com/image-size/image-size/compare/v0.9.1...v0.9.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* build(deps): bump mongoose from 5.10.9 to 5.10.10 (#12706)

Bumps [mongoose](https://github.com/Automattic/mongoose) from 5.10.9 to 5.10.10.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/History.md)
- [Commits](https://github.com/Automattic/mongoose/compare/5.10.9...5.10.10)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* build(deps-dev): bump axios from 0.19.2 to 0.21.0 (#12708)

Bumps [axios](https://github.com/axios/axios) from 0.19.2 to 0.21.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.19.2...v0.21.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* build(deps): bump axios from 0.19.2 to 0.21.0 in /website/client (#12712)

Bumps [axios](https://github.com/axios/axios) from 0.19.2 to 0.21.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.19.2...v0.21.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* build(deps): bump jwks-rsa from 1.10.1 to 1.11.0 (#12707)

Bumps [jwks-rsa](https://github.com/auth0/node-jwks-rsa) from 1.10.1 to 1.11.0.
- [Release notes](https://github.com/auth0/node-jwks-rsa/releases)
- [Changelog](https://github.com/auth0/node-jwks-rsa/blob/master/CHANGELOG.md)
- [Commits](https://github.com/auth0/node-jwks-rsa/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* Prevent the removal of a quest owner from a group, take 2 (#12695)

* add cannotRemoveQuestLeader string

* throw error when member is quest leader

* add the new apidoc error

* change i18n key name

* fix apidoc formatting and change key in throw()

* add test for preventing removing quest owner

* patch(groups): change error codes

* Merge #12654
Fixes #12417
Squashed commit of the following:

commit 1f074175c480a638cf61e2c72ca57cdc6f8699b6
Author: Matteo Pagliazzi <matteopagliazzi@gmail.com>
Date:   Mon Oct 26 10:57:23 2020 +0100

    fix(i18n): remove unused string questLevelTooHigh

commit 12cc74002ec87c14cc000b008454f34475fd3636
Merge: 4fc260e552 ad9b551de3
Author: Matteo Pagliazzi <matteopagliazzi@gmail.com>
Date:   Mon Oct 26 10:50:39 2020 +0100

    Merge branch 'feature/level-locked-quests-should-be-used-at-any-level' of https://github.com/hamboomger/habitica into hamboomger-feature/level-locked-quests-should-be-used-at-any-level

commit ad9b551de3
Author: hamboomger <hamboomger@gmail.com>
Date:   Thu Oct 8 13:34:19 2020 +0300

    fix(quests): Quests that are level-locked for purchase can now be used at any level

* fix(banned words): fix partial matching of words containing diacritic… (#12444)

* fix(banned words): fix partial matching of words containing diacritics against banned words list (#12309)

* lint: remove whitespace to fix error

* test: add test to prevent partial matching of words containing diacritics against banned words list (#12309)

* doc: add link to Unicode table of diacritical marks (#12309)

* fix Arabic punctuation & alignment (#12655)

* fix Arabic punctuation & alignment

* fix Arabic punctuation & alignment - 2

* add rtl support for all rtl languages

* add auto direction to chat cards

* fix alignment: use automatic alignment based on dir attribute

* restore package-lock.json

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>

* Fix keyboard inaccessible accordion in guild/party page fixes #12653 (#12656)

* fix: replace clickable div with button

improve accessibility for keyboard users

* refactor: extract sidebar button to own component

* refactor: button to div

* fix: lint, update sidebarSection test

* build(deps): bump vuedraggable from 2.24.2 to 2.24.3 in /website/client (#12727)

Bumps [vuedraggable](https://github.com/SortableJS/Vue.Draggable) from 2.24.2 to 2.24.3.
- [Release notes](https://github.com/SortableJS/Vue.Draggable/releases)
- [Commits](https://github.com/SortableJS/Vue.Draggable/compare/v2.24.2...v2.24.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* build(deps): bump @vue/cli-plugin-eslint in /website/client (#12719)

Bumps [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-eslint) from 4.5.7 to 4.5.8.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.8/packages/@vue/cli-plugin-eslint)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* build(deps): bump bootstrap-vue from 2.18.0 to 2.18.1 in /website/client (#12725)

Bumps [bootstrap-vue](https://github.com/bootstrap-vue/bootstrap-vue) from 2.18.0 to 2.18.1.
- [Release notes](https://github.com/bootstrap-vue/bootstrap-vue/releases)
- [Changelog](https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/bootstrap-vue/bootstrap-vue/compare/v2.18.0...v2.18.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* build(deps): bump @vue/cli-plugin-unit-mocha in /website/client (#12721)

Bumps [@vue/cli-plugin-unit-mocha](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-unit-mocha) from 4.5.7 to 4.5.8.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.8/packages/@vue/cli-plugin-unit-mocha)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* build(deps): bump vue-router from 3.4.7 to 3.4.8 in /website/client (#12720)

Bumps [vue-router](https://github.com/vuejs/vue-router) from 3.4.7 to 3.4.8.
- [Release notes](https://github.com/vuejs/vue-router/releases)
- [Changelog](https://github.com/vuejs/vue-router/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-router/compare/v3.4.7...v3.4.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* build(deps): bump @vue/cli-plugin-router in /website/client (#12718)

Bumps [@vue/cli-plugin-router](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-router) from 4.5.7 to 4.5.8.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.8/packages/@vue/cli-plugin-router)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* build(deps): bump @vue/cli-plugin-babel in /website/client (#12717)

Bumps [@vue/cli-plugin-babel](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-babel) from 4.5.7 to 4.5.8.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.8/packages/@vue/cli-plugin-babel)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* build(deps): bump @vue/cli-service in /website/client (#12726)

Bumps [@vue/cli-service](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-service) from 4.5.7 to 4.5.8.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.8/packages/@vue/cli-service)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>

* feat(content): Mystery Items and Habitoween pet

* fix(content): shield not weapon

* fix(event): goodies for newbies

* Loggly-only user support events (#12676)

* feat(analytics): Loggly-only user support events

* fix(analytics): clean up more Unknowns

* 4.166.2

* Analytics: track generic events through the server (#12735)

* Loggly-only user support events (#12676)

* feat(analytics): Loggly-only user support events

* fix(analytics): clean up more Unknowns

* wip: allow tracking events from the server

* analytics: allow tracking generic events on the server

* remove console.logs

* remove console.log (client)

* add integration test

Co-authored-by: Sabe Jones <sabrecat@gmail.com>

* 4.166.3

* fix erranous upgrade

* 4.166.2

* 4.167.0

* Translated using Weblate (Korean)

Currently translated at 98.1% (109 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ko/

Translated using Weblate (Korean)

Currently translated at 98.3% (121 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/ko/

Translated using Weblate (Japanese)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Japanese)

Currently translated at 89.0% (1944 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ja/

Translated using Weblate (Korean)

Currently translated at 65.7% (73 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ko/

Translated using Weblate (Korean)

Currently translated at 77.4% (72 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ko/

Translated using Weblate (Japanese)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Japanese)

Currently translated at 88.9% (1941 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Korean)

Currently translated at 73.1% (68 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ko/

Translated using Weblate (English (Pirate))

Currently translated at 97.8% (356 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/en@pirate/

Translated using Weblate (Japanese)

Currently translated at 88.8% (1940 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (French)

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/fr/

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/uk/

Translated using Weblate (Japanese)

Currently translated at 88.7% (1938 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Ukrainian)

Currently translated at 45.1% (42 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Ukrainian)

Currently translated at 45.1% (42 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Ukrainian)

Currently translated at 92.2% (166 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/uk/

Translated using Weblate (Japanese)

Currently translated at 88.7% (1937 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Basque)

Currently translated at 100.0% (1 of 1 strings)

Translation: Habitica/Merch
Translate-URL: https://translate.habitica.com/projects/habitica/merch/eu/

Translated using Weblate (Basque)

Currently translated at 100.0% (13 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/eu/

Translated using Weblate (Basque)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/eu/

Translated using Weblate (Basque)

Currently translated at 6.5% (8 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/eu/

Translated using Weblate (Spanish)

Currently translated at 100.0% (364 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (364 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (123 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (Spanish)

Currently translated at 97.2% (354 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/es/

Translated using Weblate (Spanish)

Currently translated at 99.8% (563 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (23 of 23 strings)

Translation: Habitica/Loginincentives
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/es/

Translated using Weblate (Spanish)

Currently translated at 87.8% (1917 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/es/

Translated using Weblate (Spanish)

Currently translated at 95.3% (538 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Japanese)

Currently translated at 88.6% (1935 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Italian)

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/it/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (203 of 203 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/pt_BR/

Translated using Weblate (Spanish (Latin America))

Currently translated at 81.4% (1779 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Czech)

Currently translated at 98.9% (182 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/cs/

Translated using Weblate (Japanese)

Currently translated at 88.5% (1933 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 96.4% (54 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/

Translated using Weblate (Czech)

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/cs/

Translated using Weblate (Japanese)

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ja/

Translated using Weblate (Japanese)

Currently translated at 88.4% (1931 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 96.4% (54 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/

Translated using Weblate (Japanese)

Currently translated at 89.2% (50 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/

Translated using Weblate (Japanese)

Currently translated at 97.7% (177 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/ja/

Translated using Weblate (Polish)

Currently translated at 98.2% (55 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pl/

Translated using Weblate (Japanese)

Currently translated at 87.5% (49 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/

Translated using Weblate (Polish)

Currently translated at 96.4% (54 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (364 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/pl/

Translated using Weblate (Polish)

Currently translated at 89.2% (50 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pl/

Translated using Weblate (Japanese)

Currently translated at 95.0% (58 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/ja/

Translated using Weblate (Japanese)

Currently translated at 99.4% (183 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ja/

Translated using Weblate (Spanish (Latin America))

Currently translated at 85.3% (613 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

* fix(event): Habitoween NPC sprites

* Fix Tasks styles (#12700)

* re-add previous markdown h3/h4 styles - remove double transition properties

* fix more heading styles

* fix markdown h3 / tasktitle h3

* Add title update to fetchguilds to catch router.push page changes

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
Co-authored-by: Sabe Jones <sabrecat@gmail.com>
Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
Co-authored-by: Shadow <william.shadow@outlook.com>
Co-authored-by: Carlton McFarlane <carlton@ilicmcfarlane.io>
Co-authored-by: Mario Yonan <62141485+mario130@users.noreply.github.com>
Co-authored-by: J Sanderson <julia@parentscheme.com>
Co-authored-by: Melior <admin@habitica.com>
Co-authored-by: negue <negue@users.noreply.github.com>
2020-11-03 23:28:27 +01:00
Melior 3a80875505 Merge branch 'origin/develop' into Weblate. 2020-11-03 22:39:06 +01:00
Melior 2d6802ae87 Translated using Weblate (French)
Currently translated at 100.0% (98 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/fr/

Merge branch 'origin/develop' into Weblate.

Translated using Weblate (Spanish (Latin America))

Currently translated at 85.3% (613 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 81.3% (1779 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Czech)

Currently translated at 87.8% (1921 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/cs/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (185 of 185 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (366 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pt_BR/

Translated using Weblate (Czech)

Currently translated at 87.8% (1921 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/cs/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (100 of 100 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/pt_BR/

Translated using Weblate (Czech)

Currently translated at 100.0% (100 of 100 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/cs/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (98 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt_BR/

Translated using Weblate (Czech)

Currently translated at 87.8% (1921 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/cs/

Translated using Weblate (Czech)

Currently translated at 87.8% (1921 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/cs/

Translated using Weblate (Hindi)

Currently translated at 16.5% (30 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/hi/

Translated using Weblate (Hindi)

Currently translated at 100.0% (100 of 100 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/hi/

Translated using Weblate (Hindi)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/hi/

Translated using Weblate (Hindi)

Currently translated at 98.3% (121 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/hi/

Translated using Weblate (Japanese)

Currently translated at 90.0% (1970 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Dutch)

Currently translated at 95.9% (689 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/nl/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.4% (364 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pt_BR/

Translated using Weblate (Italian)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/it/

Translated using Weblate (Japanese)

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/

Translated using Weblate (Portuguese)

Currently translated at 77.5% (76 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt/

Translated using Weblate (Japanese)

Currently translated at 100.0% (182 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Japanese)

Currently translated at 89.8% (1966 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/zh_Hant_HK/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/zh_Hant_HK/

Translated using Weblate (Japanese)

Currently translated at 99.4% (181 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (English (United Kingdom))

Currently translated at 97.7% (702 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/en_GB/

Translated using Weblate (English (Pirate))

Currently translated at 93.4% (527 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 93.4% (527 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 98.9% (97 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/en@pirate/

Translated using Weblate (English (Pirate))

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/en@pirate/

Translated using Weblate (Japanese)

Currently translated at 89.7% (1962 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (366 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/

Translated using Weblate (Japanese)

Currently translated at 89.3% (1955 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/ja/

Translated using Weblate (Japanese)

Currently translated at 99.5% (715 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/

Translated using Weblate (Japanese)

Currently translated at 99.5% (715 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/

Translated using Weblate (Japanese)

Currently translated at 99.5% (715 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (98 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ja/

Translated using Weblate (Japanese)

Currently translated at 98.0% (704 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 99.1% (559 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (182 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (185 of 185 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (366 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (2187 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en_GB/

Translated using Weblate (Japanese)

Currently translated at 96.3% (692 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (100 of 100 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (98 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 95.0% (173 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/en_GB/

Translated using Weblate (German)

Currently translated at 100.0% (182 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/de/

Translated using Weblate (German)

Currently translated at 100.0% (185 of 185 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/de/

Translated using Weblate (German)

Currently translated at 100.0% (366 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/de/

Translated using Weblate (German)

Currently translated at 100.0% (2187 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/

Translated using Weblate (English (Pirate))

Currently translated at 98.9% (185 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/en@pirate/

Translated using Weblate (German)

Currently translated at 100.0% (100 of 100 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/de/

Translated using Weblate (German)

Currently translated at 100.0% (98 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/de/

Translated using Weblate (English (Pirate))

Currently translated at 98.9% (185 of 187 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/en@pirate/

Translated using Weblate (Italian)

Currently translated at 100.0% (182 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/it/

Translated using Weblate (Japanese)

Currently translated at 100.0% (185 of 185 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ja/

Translated using Weblate (Japanese)

Currently translated at 99.7% (365 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/

Translated using Weblate (Italian)

Currently translated at 100.0% (366 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/it/

Translated using Weblate (Italian)

Currently translated at 100.0% (2187 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/

Translated using Weblate (Japanese)

Currently translated at 95.9% (689 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/

Translated using Weblate (Japanese)

Currently translated at 96.9% (95 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ja/

Translated using Weblate (Italian)

Currently translated at 100.0% (98 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/it/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (182 of 182 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (185 of 185 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (366 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2187 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/

Translated using Weblate (Swedish)

Currently translated at 67.8% (38 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/sv/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (100 of 100 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/zh_Hans/

Translated using Weblate (Japanese)

Currently translated at 100.0% (100 of 100 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/ja/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (98 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hans/

Translated using Weblate (Spanish (Latin America))

Currently translated at 85.3% (613 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (185 of 185 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 81.3% (1779 of 2187 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 96.9% (95 of 98 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es_419/

Translated using Weblate (Italian)

Currently translated at 100.0% (185 of 185 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/it/

Translated using Weblate (Spanish)

Currently translated at 99.7% (365 of 366 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es/

Translated using Weblate (Italian)

Currently translated at 100.0% (100 of 100 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/it/

Translated using Weblate (English (Pirate))

Currently translated at 99.5% (202 of 203 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/en@pirate/
2020-11-03 22:39:00 +01:00
Sabe Jones 497c023995 Merge branch 'release' into develop 2020-11-03 15:20:20 -06:00
Sabe Jones b97d514c68 4.168.2 2020-11-03 15:20:01 -06:00
Sabe Jones 142fdfe743 fix(events): handle new spacer 2020-11-03 15:19:54 -06:00
Sabe Jones ee5a2b0e36 Merge branch 'release' into develop 2020-11-03 15:14:42 -06:00
Sabe Jones 9455f996ef 4.168.1 2020-11-03 15:14:23 -06:00
Sabe Jones 5cc3f6e8aa fix(mobile): empty event in world state 2020-11-03 15:14:17 -06:00
Sabe Jones 8bad3d1184 Merge branch 'release' into develop 2020-11-03 14:57:00 -06:00
Sabe Jones 3f65353974 4.168.0 2020-11-03 14:56:16 -06:00
Sabe Jones ab7c4015a2 chore(sprites): compile 2020-11-03 14:55:59 -06:00
Sabe Jones 6d509ae1f8 feat(content): Armoire and Backgrounds 2020-11-03 14:55:51 -06:00
Matteo Pagliazzi 6375bc1d59 drop cap ab test: add migration to enroll all web users 2020-11-03 21:30:50 +01:00
Matteo Pagliazzi 14714f9e1c Drop Cap A/B Tests: v2 (#12759)
* drop cap ab test: enroll all web users, 50/50

* update tests

* fix lint
2020-11-03 14:19:09 -06:00
Sara Olson 60b3f2b860 Update faq.json (#12757)
Changed android faq to properly explain where user can choose their class after opting out
2020-11-02 18:12:21 +01:00
Matteo Pagliazzi 965df326ed fix(hall): correctly set page title 2020-11-02 17:33:10 +01:00
agarwalvaibhav0211 3c49db9bfe Nested Spans Withing li tags (#12732) 2020-11-02 17:28:23 +01:00
Matteo Pagliazzi 72bd104567 migration: add migration to fix items.pets.JackOLantern-Base for new users 2020-11-02 13:31:40 +01:00
Matteo Pagliazzi 2cbd376cf6 fix(new users): use correct numeric value for JackOLantern-Base pet 2020-11-02 13:20:20 +01:00
Sabe Jones a7477e137e fix(teams): preserve original subscription start date (#12742) 2020-11-02 11:42:09 +01:00
dependabot-preview[bot] f6cb57c22f build(deps): bump image-size from 0.9.2 to 0.9.3 (#12747)
Bumps [image-size](https://github.com/image-size/image-size) from 0.9.2 to 0.9.3.
- [Release notes](https://github.com/image-size/image-size/releases)
- [Commits](https://github.com/image-size/image-size/compare/v0.9.2...v0.9.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-02 10:57:47 +01:00
dependabot-preview[bot] 76fa4dfd7f build(deps-dev): bump sinon from 9.2.0 to 9.2.1 (#12745)
Bumps [sinon](https://github.com/sinonjs/sinon) from 9.2.0 to 9.2.1.
- [Release notes](https://github.com/sinonjs/sinon/releases)
- [Changelog](https://github.com/sinonjs/sinon/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sinonjs/sinon/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-02 10:57:37 +01:00
dependabot-preview[bot] aceaeacbf0 build(deps): bump amplitude-js from 7.3.0 to 7.3.1 in /website/client (#12752)
Bumps [amplitude-js](https://github.com/amplitude/amplitude-javascript) from 7.3.0 to 7.3.1.
- [Release notes](https://github.com/amplitude/amplitude-javascript/releases)
- [Changelog](https://github.com/amplitude/Amplitude-JavaScript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/amplitude/amplitude-javascript/compare/v7.3.0...v7.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-02 10:57:30 +01:00
dependabot-preview[bot] b2cb5f83de build(deps): bump mongoose from 5.10.10 to 5.10.11 (#12749)
Bumps [mongoose](https://github.com/Automattic/mongoose) from 5.10.10 to 5.10.11.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/History.md)
- [Commits](https://github.com/Automattic/mongoose/compare/5.10.10...5.10.11)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-02 10:57:07 +01:00
dependabot-preview[bot] d09dea5185 build(deps): bump sass from 1.27.0 to 1.28.0 in /website/client (#12753)
Bumps [sass](https://github.com/sass/dart-sass) from 1.27.0 to 1.28.0.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.27.0...1.28.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-11-02 10:52:50 +01:00
Sabe Jones 6fa7fbce3f Merge branch 'release' into develop 2020-11-01 22:03:42 -06:00
Sabe Jones b17c9a33a5 4.167.2 2020-11-01 22:02:49 -06:00
Sabe Jones 31d0cb5a91 chore(event): conclude
and fix rotten potatoe
2020-11-01 22:02:39 -06:00
negue d678eb920f Fix Tasks styles (#12700)
* re-add previous markdown h3/h4 styles - remove double transition properties

* fix more heading styles

* fix markdown h3 / tasktitle h3
2020-10-29 23:50:29 +01:00
Sabe Jones 163eb55dbb 4.167.1 2020-10-29 12:31:30 -05:00
Sabe Jones 8661716c23 fix(event): Habitoween NPC sprites 2020-10-29 12:31:26 -05:00
Sabe Jones ea11e302c6 fix(event): Habitoween NPC sprites 2020-10-29 11:58:31 -05:00
Melior afdd5af7a9 Merge branch 'origin/develop' into Weblate. 2020-10-29 16:36:52 +01:00
Melior a09e56048e Translated using Weblate (Korean)
Currently translated at 98.1% (109 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ko/

Translated using Weblate (Korean)

Currently translated at 98.3% (121 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/ko/

Translated using Weblate (Japanese)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Japanese)

Currently translated at 89.0% (1944 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ja/

Translated using Weblate (Korean)

Currently translated at 65.7% (73 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ko/

Translated using Weblate (Korean)

Currently translated at 77.4% (72 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ko/

Translated using Weblate (Japanese)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Japanese)

Currently translated at 88.9% (1941 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Korean)

Currently translated at 73.1% (68 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ko/

Translated using Weblate (English (Pirate))

Currently translated at 97.8% (356 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/en@pirate/

Translated using Weblate (Japanese)

Currently translated at 88.8% (1940 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (French)

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/fr/

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/uk/

Translated using Weblate (Japanese)

Currently translated at 88.7% (1938 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Ukrainian)

Currently translated at 45.1% (42 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Ukrainian)

Currently translated at 45.1% (42 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Ukrainian)

Currently translated at 92.2% (166 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/uk/

Translated using Weblate (Japanese)

Currently translated at 88.7% (1937 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Basque)

Currently translated at 100.0% (1 of 1 strings)

Translation: Habitica/Merch
Translate-URL: https://translate.habitica.com/projects/habitica/merch/eu/

Translated using Weblate (Basque)

Currently translated at 100.0% (13 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/eu/

Translated using Weblate (Basque)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/eu/

Translated using Weblate (Basque)

Currently translated at 6.5% (8 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/eu/

Translated using Weblate (Spanish)

Currently translated at 100.0% (364 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (364 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (123 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (Spanish)

Currently translated at 97.2% (354 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/es/

Translated using Weblate (Spanish)

Currently translated at 99.8% (563 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (23 of 23 strings)

Translation: Habitica/Loginincentives
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/es/

Translated using Weblate (Spanish)

Currently translated at 87.8% (1917 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/es/

Translated using Weblate (Spanish)

Currently translated at 95.3% (538 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Japanese)

Currently translated at 88.6% (1935 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Italian)

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/it/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (203 of 203 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/pt_BR/

Translated using Weblate (Spanish (Latin America))

Currently translated at 81.4% (1779 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Japanese)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Czech)

Currently translated at 98.9% (182 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/cs/

Translated using Weblate (Japanese)

Currently translated at 88.5% (1933 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 96.4% (54 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/

Translated using Weblate (Czech)

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/cs/

Translated using Weblate (Japanese)

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ja/

Translated using Weblate (Japanese)

Currently translated at 88.4% (1931 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 96.4% (54 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/

Translated using Weblate (Japanese)

Currently translated at 89.2% (50 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/

Translated using Weblate (Japanese)

Currently translated at 97.7% (177 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/ja/

Translated using Weblate (Polish)

Currently translated at 98.2% (55 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pl/

Translated using Weblate (Japanese)

Currently translated at 87.5% (49 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/

Translated using Weblate (Polish)

Currently translated at 96.4% (54 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (364 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/pl/

Translated using Weblate (Polish)

Currently translated at 89.2% (50 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pl/

Translated using Weblate (Japanese)

Currently translated at 95.0% (58 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/ja/

Translated using Weblate (Japanese)

Currently translated at 99.4% (183 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ja/

Translated using Weblate (Spanish (Latin America))

Currently translated at 85.3% (613 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/
2020-10-29 16:36:33 +01:00
Sabe Jones fd37ee90da 4.167.0 2020-10-29 10:25:35 -05:00
Sabe Jones a4cfb97dbf Merge branch 'sabrecat/prebuild-202010' into develop 2020-10-29 10:25:06 -05:00
Matteo Pagliazzi ea766251c2 Merge branch 'release' into develop 2020-10-28 23:24:42 +01:00
Matteo Pagliazzi f196ff2e24 4.166.2 2020-10-28 22:43:39 +01:00
Matteo Pagliazzi cc901fe085 fix erranous upgrade 2020-10-28 22:43:32 +01:00
Matteo Pagliazzi f257488b39 4.166.3 2020-10-28 22:39:55 +01:00
Matteo Pagliazzi 48dbe547c0 Analytics: track generic events through the server (#12735)
* Loggly-only user support events (#12676)

* feat(analytics): Loggly-only user support events

* fix(analytics): clean up more Unknowns

* wip: allow tracking events from the server

* analytics: allow tracking generic events on the server

* remove console.logs

* remove console.log (client)

* add integration test

Co-authored-by: Sabe Jones <sabrecat@gmail.com>
2020-10-28 22:39:19 +01:00
Matteo Pagliazzi b15462596b 4.166.2 2020-10-28 22:38:59 +01:00
Sabe Jones 2a98b5b7bf Loggly-only user support events (#12676)
* feat(analytics): Loggly-only user support events

* fix(analytics): clean up more Unknowns
2020-10-28 17:05:54 +01:00
Sabe Jones f7667fcf79 fix(event): goodies for newbies 2020-10-27 16:39:38 -05:00
Sabe Jones 05aaad8743 fix(content): shield not weapon 2020-10-27 16:33:45 -05:00
Sabe Jones 5e1f2c16f8 feat(content): Mystery Items and Habitoween pet 2020-10-27 16:19:36 -05:00
dependabot-preview[bot] 82b6a14d5b build(deps): bump @vue/cli-service in /website/client (#12726)
Bumps [@vue/cli-service](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-service) from 4.5.7 to 4.5.8.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.8/packages/@vue/cli-service)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-27 11:36:02 +01:00
dependabot-preview[bot] f9cfd9fb5e build(deps): bump @vue/cli-plugin-babel in /website/client (#12717)
Bumps [@vue/cli-plugin-babel](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-babel) from 4.5.7 to 4.5.8.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.8/packages/@vue/cli-plugin-babel)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-27 11:35:25 +01:00
dependabot-preview[bot] 60bef56577 build(deps): bump @vue/cli-plugin-router in /website/client (#12718)
Bumps [@vue/cli-plugin-router](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-router) from 4.5.7 to 4.5.8.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.8/packages/@vue/cli-plugin-router)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-27 11:34:53 +01:00
dependabot-preview[bot] af87185bfa build(deps): bump vue-router from 3.4.7 to 3.4.8 in /website/client (#12720)
Bumps [vue-router](https://github.com/vuejs/vue-router) from 3.4.7 to 3.4.8.
- [Release notes](https://github.com/vuejs/vue-router/releases)
- [Changelog](https://github.com/vuejs/vue-router/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-router/compare/v3.4.7...v3.4.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-27 11:31:00 +01:00
dependabot-preview[bot] f8c8be4f4c build(deps): bump @vue/cli-plugin-unit-mocha in /website/client (#12721)
Bumps [@vue/cli-plugin-unit-mocha](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-unit-mocha) from 4.5.7 to 4.5.8.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.8/packages/@vue/cli-plugin-unit-mocha)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-27 11:30:54 +01:00
dependabot-preview[bot] 5d220544e0 build(deps): bump bootstrap-vue from 2.18.0 to 2.18.1 in /website/client (#12725)
Bumps [bootstrap-vue](https://github.com/bootstrap-vue/bootstrap-vue) from 2.18.0 to 2.18.1.
- [Release notes](https://github.com/bootstrap-vue/bootstrap-vue/releases)
- [Changelog](https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/bootstrap-vue/bootstrap-vue/compare/v2.18.0...v2.18.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-27 11:30:46 +01:00
dependabot-preview[bot] c4fd9daa90 build(deps): bump @vue/cli-plugin-eslint in /website/client (#12719)
Bumps [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-eslint) from 4.5.7 to 4.5.8.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.8/packages/@vue/cli-plugin-eslint)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-27 11:30:33 +01:00
dependabot-preview[bot] fc8f9cbaa0 build(deps): bump vuedraggable from 2.24.2 to 2.24.3 in /website/client (#12727)
Bumps [vuedraggable](https://github.com/SortableJS/Vue.Draggable) from 2.24.2 to 2.24.3.
- [Release notes](https://github.com/SortableJS/Vue.Draggable/releases)
- [Commits](https://github.com/SortableJS/Vue.Draggable/compare/v2.24.2...v2.24.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-27 11:30:14 +01:00
J Sanderson e39d3e52e2 Fix keyboard inaccessible accordion in guild/party page fixes #12653 (#12656)
* fix: replace clickable div with button

improve accessibility for keyboard users

* refactor: extract sidebar button to own component

* refactor: button to div

* fix: lint, update sidebarSection test
2020-10-26 15:41:40 +01:00
Mario Yonan 625b4a4ad7 fix Arabic punctuation & alignment (#12655)
* fix Arabic punctuation & alignment

* fix Arabic punctuation & alignment - 2

* add rtl support for all rtl languages

* add auto direction to chat cards

* fix alignment: use automatic alignment based on dir attribute

* restore package-lock.json

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-10-26 15:32:07 +01:00
Carlton McFarlane f2bcdd21de fix(banned words): fix partial matching of words containing diacritic… (#12444)
* fix(banned words): fix partial matching of words containing diacritics against banned words list (#12309)

* lint: remove whitespace to fix error

* test: add test to prevent partial matching of words containing diacritics against banned words list (#12309)

* doc: add link to Unicode table of diacritical marks (#12309)
2020-10-26 12:14:04 +01:00
jbusa22 ad51675ac6 Fixes Issue #12421 - Change page title based on the site section being viewed (#12627)
* Update title for tabs not including challenges, guild and team

* add section titles to challenges, guilds, and groups

* Update dynamic title to use vuex action

* Remove duplicate key

* Actually remove duplicate key

* Fix section sub section in group

* Add note to implement setTitle when adding a page

* Add missing sections to dynamic title

* Features string not translated

* Use onGroupUpdate to update group titles

* Add watcher to challenges for dynamic title updates

* Small fixes

* Add register and login to title, remove duplicate keys

* Add home page dynamic title functionality

* Minor name changes

* remove wrong i18n strings from front.js

* refactor router note

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-10-26 11:22:46 +01:00
Matteo Pagliazzi 869d2df4fa Merge #12654
Fixes #12417
Squashed commit of the following:

commit 1f074175c480a638cf61e2c72ca57cdc6f8699b6
Author: Matteo Pagliazzi <matteopagliazzi@gmail.com>
Date:   Mon Oct 26 10:57:23 2020 +0100

    fix(i18n): remove unused string questLevelTooHigh

commit 12cc74002ec87c14cc000b008454f34475fd3636
Merge: 4fc260e552 ad9b551de3
Author: Matteo Pagliazzi <matteopagliazzi@gmail.com>
Date:   Mon Oct 26 10:50:39 2020 +0100

    Merge branch 'feature/level-locked-quests-should-be-used-at-any-level' of https://github.com/hamboomger/habitica into hamboomger-feature/level-locked-quests-should-be-used-at-any-level

commit ad9b551de3
Author: hamboomger <hamboomger@gmail.com>
Date:   Thu Oct 8 13:34:19 2020 +0300

    fix(quests): Quests that are level-locked for purchase can now be used at any level
2020-10-26 10:58:50 +01:00
Shadow 734e997345 Prevent the removal of a quest owner from a group, take 2 (#12695)
* add cannotRemoveQuestLeader string

* throw error when member is quest leader

* add the new apidoc error

* change i18n key name

* fix apidoc formatting and change key in throw()

* add test for preventing removing quest owner

* patch(groups): change error codes
2020-10-26 10:46:43 +01:00
dependabot-preview[bot] 4fc260e552 build(deps): bump jwks-rsa from 1.10.1 to 1.11.0 (#12707)
Bumps [jwks-rsa](https://github.com/auth0/node-jwks-rsa) from 1.10.1 to 1.11.0.
- [Release notes](https://github.com/auth0/node-jwks-rsa/releases)
- [Changelog](https://github.com/auth0/node-jwks-rsa/blob/master/CHANGELOG.md)
- [Commits](https://github.com/auth0/node-jwks-rsa/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-26 10:43:16 +01:00
dependabot-preview[bot] fa22a47b7a build(deps): bump axios from 0.19.2 to 0.21.0 in /website/client (#12712)
Bumps [axios](https://github.com/axios/axios) from 0.19.2 to 0.21.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.19.2...v0.21.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-26 10:33:19 +01:00
dependabot-preview[bot] 0366245fab build(deps-dev): bump axios from 0.19.2 to 0.21.0 (#12708)
Bumps [axios](https://github.com/axios/axios) from 0.19.2 to 0.21.0.
- [Release notes](https://github.com/axios/axios/releases)
- [Changelog](https://github.com/axios/axios/blob/master/CHANGELOG.md)
- [Commits](https://github.com/axios/axios/compare/v0.19.2...v0.21.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-26 10:28:16 +01:00
dependabot-preview[bot] f342eff70b build(deps): bump mongoose from 5.10.9 to 5.10.10 (#12706)
Bumps [mongoose](https://github.com/Automattic/mongoose) from 5.10.9 to 5.10.10.
- [Release notes](https://github.com/Automattic/mongoose/releases)
- [Changelog](https://github.com/Automattic/mongoose/blob/master/History.md)
- [Commits](https://github.com/Automattic/mongoose/compare/5.10.9...5.10.10)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-26 10:20:46 +01:00
dependabot-preview[bot] 84eb39fde2 build(deps): bump image-size from 0.9.1 to 0.9.2 (#12711)
Bumps [image-size](https://github.com/image-size/image-size) from 0.9.1 to 0.9.2.
- [Release notes](https://github.com/image-size/image-size/releases)
- [Commits](https://github.com/image-size/image-size/compare/v0.9.1...v0.9.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-26 10:20:06 +01:00
Matteo Pagliazzi d6fe2c76e2 build(deps): bump got from 11.7.0 to 11.8.0 (#12710)
Bumps [got](https://github.com/sindresorhus/got) from 11.7.0 to 11.8.0.
- [Release notes](https://github.com/sindresorhus/got/releases)
- [Commits](https://github.com/sindresorhus/got/compare/v11.7.0...v11.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-26 10:19:47 +01:00
dependabot-preview[bot] f19e9dd57e build(deps): bump rate-limiter-flexible from 2.1.10 to 2.1.13 (#12709)
Bumps [rate-limiter-flexible](https://github.com/animir/node-rate-limiter-flexible) from 2.1.10 to 2.1.13.
- [Release notes](https://github.com/animir/node-rate-limiter-flexible/releases)
- [Commits](https://github.com/animir/node-rate-limiter-flexible/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-26 10:19:33 +01:00
dependabot-preview[bot] 13566e8a39 build(deps): bump got from 11.7.0 to 11.8.0
Bumps [got](https://github.com/sindresorhus/got) from 11.7.0 to 11.8.0.
- [Release notes](https://github.com/sindresorhus/got/releases)
- [Commits](https://github.com/sindresorhus/got/compare/v11.7.0...v11.8.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-26 07:27:39 +00:00
Melior 7d3dd9f157 Translated using Weblate (Spanish (Latin America))
Currently translated at 85.3% (613 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Czech)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/cs/

Translated using Weblate (Czech)

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/cs/

Translated using Weblate (Hindi)

Currently translated at 46.8% (52 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/hi/

Translated using Weblate (Polish)

Currently translated at 97.0% (130 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/pl/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/pt_BR/

Translated using Weblate (Hindi)

Currently translated at 40.5% (45 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/hi/

Translated using Weblate (Italian)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/it/

Translated using Weblate (French)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fr/

Translated using Weblate (Italian)

Currently translated at 100.0% (111 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/it/

Translated using Weblate (Italian)

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/it/

Translated using Weblate (French)

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/fr/

Translated using Weblate (Italian)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/it/

Translated using Weblate (French)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/fr/

Translated using Weblate (Italian)

Currently translated at 100.0% (203 of 203 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/it/

Translated using Weblate (Italian)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/it/

Translated using Weblate (German)

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/

Translated using Weblate (Italian)

Currently translated at 100.0% (230 of 230 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/it/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/zh_Hans/

Translated using Weblate (German)

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/de/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/zh_Hans/

Translated using Weblate (German)

Currently translated at 100.0% (61 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/de/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/zh_Hans/

Translated using Weblate (Japanese)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/ja/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (181 of 181 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 98.3% (60 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/pt_BR/

Translated using Weblate (German)

Currently translated at 96.7% (59 of 61 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/de/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/pt_BR/

Translated using Weblate (German)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/de/

Translated using Weblate (English (Pirate))

Currently translated at 81.9% (1788 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/en@pirate/
2020-10-22 20:50:10 +02:00
Sabe Jones 92f283f6a2 4.166.1 2020-10-22 13:42:55 -05:00
Melior 5d24d584d4 Merge branch 'develop' of github.com:HabitRPG/habitica into develop 2020-10-20 21:28:02 +02:00
Sabe Jones 0320827f7e Merge branch 'release' into develop 2020-10-20 14:13:00 -05:00
Sabe Jones 79c1a5d9c1 4.166.0 2020-10-20 14:12:23 -05:00
Yowi faa49b1412 Translated using Weblate (Spanish (Latin America))
Currently translated at 85.3% (613 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/
2020-10-20 15:42:19 +02:00
Atticus c3decc3951 Translated using Weblate (Swedish)
Currently translated at 81.8% (144 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/sv/
2020-10-20 15:42:16 +02:00
blacksheep47 084adf8b0d Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (13 of 13 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/zh_Hans/
2020-10-20 15:42:16 +02:00
Atticus 04574dad69 Translated using Weblate (Swedish)
Currently translated at 91.8% (518 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/sv/
2020-10-20 15:42:15 +02:00
Atticus 6526a6317e Translated using Weblate (Swedish)
Currently translated at 93.3% (168 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/sv/
2020-10-20 15:42:14 +02:00
Andrew Webb c778e5e84e Translated using Weblate (English (Pirate))
Currently translated at 100.0% (111 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/en@pirate/
2020-10-20 03:22:16 +02:00
Quartz Fox b5dacdf9ea Translated using Weblate (English (Pirate))
Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/en@pirate/
2020-10-20 03:22:15 +02:00
Lio Zam e05d1dae43 Translated using Weblate (German)
Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/
2020-10-20 03:22:15 +02:00
Quartz Fox 864db644e3 Translated using Weblate (English (Pirate))
Currently translated at 97.8% (91 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en@pirate/
2020-10-20 03:22:11 +02:00
Andrew Webb 5ddd4ec564 Translated using Weblate (English (Pirate))
Currently translated at 97.8% (91 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en@pirate/
2020-10-20 03:22:11 +02:00
Anonymous 2d7d4af2b8 Translated using Weblate (English (Pirate))
Currently translated at 97.8% (91 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en@pirate/
2020-10-20 03:22:11 +02:00
negue bad3f82dfb Inventory: fixes / layout (#11948)
Co-authored-by: Sabe Jones <sabrecat@gmail.com>
2020-10-19 23:54:51 +02:00
Atticus 8595641d12 Translated using Weblate (Swedish)
Currently translated at 78.9% (139 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/sv/
2020-10-19 23:20:45 +02:00
Lio Zam 9bb3e17995 Translated using Weblate (Swedish)
Currently translated at 98.3% (121 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/sv/
2020-10-19 23:20:44 +02:00
Sabe Jones 8b955e2c5e feat(content): Skeleton Achievements 2020-10-19 15:38:12 -05:00
Atticus 1d7e02428b Translated using Weblate (Swedish)
Currently translated at 78.9% (139 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/sv/
2020-10-19 21:35:14 +02:00
Atticus eee04255f8 Translated using Weblate (Swedish)
Currently translated at 85.8% (158 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/sv/
2020-10-19 21:35:13 +02:00
Atticus 7f30385c09 Translated using Weblate (Swedish)
Currently translated at 78.9% (139 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/sv/
2020-10-19 20:21:27 +02:00
Atticus 5b6eeef290 Translated using Weblate (Swedish)
Currently translated at 91.1% (113 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/sv/
2020-10-19 20:21:27 +02:00
Atticus 9953c9346d Translated using Weblate (Swedish)
Currently translated at 73.1% (68 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/sv/
2020-10-19 20:21:26 +02:00
Matteo Pagliazzi d62930b9da Merge branch 'release' into develop 2020-10-19 16:54:35 +02:00
Matteo Pagliazzi 67c607216f 4.165.3 2020-10-19 16:54:20 +02:00
Matteo Pagliazzi 672fd43ad0 user dropdown: restore backgrounds 2020-10-19 16:54:15 +02:00
Matteo Pagliazzi 69281f80ea drop cap ab test: misc fixes (#12694) 2020-10-19 16:53:28 +02:00
Atticus 093bcbb715 Translated using Weblate (Swedish)
Currently translated at 78.4% (138 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/sv/
2020-10-19 16:38:44 +02:00
Atticus 1f5992ccc5 Translated using Weblate (Swedish)
Currently translated at 67.9% (125 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/sv/
2020-10-19 16:38:44 +02:00
Atticus 2d598c9933 Translated using Weblate (Swedish)
Currently translated at 82.2% (1796 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/sv/
2020-10-19 16:38:43 +02:00
Atticus b4be8286e2 Translated using Weblate (Swedish)
Currently translated at 91.1% (514 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/sv/
2020-10-19 16:38:40 +02:00
Yowi 96b985a191 Translated using Weblate (Spanish (Latin America))
Currently translated at 85.3% (613 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/
2020-10-19 13:51:18 +02:00
sou osu a196a0cae2 Translated using Weblate (Japanese)
Currently translated at 95.9% (689 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/
2020-10-19 13:51:17 +02:00
Tereza F 8f9043e4f1 Translated using Weblate (Czech)
Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/cs/
2020-10-19 13:51:12 +02:00
Matteo Pagliazzi 1cace198a1 Merge branch 'release' into develop 2020-10-19 12:30:52 +02:00
Matteo Pagliazzi ec0e5024a7 new users: do not show bailey news (#12693) 2020-10-19 12:30:41 +02:00
Matteo Pagliazzi 0275636f46 new users: do not show bailey news (#12693) 2020-10-19 12:13:31 +02:00
dependabot-preview[bot] ea7ae4bb2f build(deps): bump bootstrap-vue from 2.17.3 to 2.18.0 in /website/client (#12691)
Bumps [bootstrap-vue](https://github.com/bootstrap-vue/bootstrap-vue) from 2.17.3 to 2.18.0.
- [Release notes](https://github.com/bootstrap-vue/bootstrap-vue/releases)
- [Changelog](https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/bootstrap-vue/bootstrap-vue/compare/v2.17.3...v2.18.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-19 12:09:48 +02:00
dependabot-preview[bot] 9f32a879e3 build(deps): bump @babel/preset-env from 7.11.5 to 7.12.1 (#12684)
Bumps [@babel/preset-env](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-env) from 7.11.5 to 7.12.1.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.12.1/packages/babel-preset-env)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-19 12:07:46 +02:00
dependabot-preview[bot] 665200b49d build(deps): bump vue-router from 3.4.6 to 3.4.7 in /website/client (#12692)
Bumps [vue-router](https://github.com/vuejs/vue-router) from 3.4.6 to 3.4.7.
- [Release notes](https://github.com/vuejs/vue-router/releases)
- [Changelog](https://github.com/vuejs/vue-router/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-router/compare/v3.4.6...v3.4.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-19 12:06:45 +02:00
dependabot-preview[bot] c63e92c8f2 build(deps): bump bootstrap from 4.5.2 to 4.5.3 in /website/client (#12689)
Bumps [bootstrap](https://github.com/twbs/bootstrap) from 4.5.2 to 4.5.3.
- [Release notes](https://github.com/twbs/bootstrap/releases)
- [Commits](https://github.com/twbs/bootstrap/compare/v4.5.2...v4.5.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-19 12:06:11 +02:00
dependabot-preview[bot] ba5b79855f build(deps): bump vuedraggable from 2.24.1 to 2.24.2 in /website/client (#12686)
Bumps [vuedraggable](https://github.com/SortableJS/Vue.Draggable) from 2.24.1 to 2.24.2.
- [Release notes](https://github.com/SortableJS/Vue.Draggable/releases)
- [Commits](https://github.com/SortableJS/Vue.Draggable/commits/v2.24.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-19 12:05:51 +02:00
dependabot-preview[bot] 97051bb3ae build(deps): bump amplitude-js from 7.2.2 to 7.3.0 in /website/client (#12687)
Bumps [amplitude-js](https://github.com/amplitude/amplitude-javascript) from 7.2.2 to 7.3.0.
- [Release notes](https://github.com/amplitude/amplitude-javascript/releases)
- [Changelog](https://github.com/amplitude/Amplitude-JavaScript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/amplitude/amplitude-javascript/compare/v7.2.2...v7.3.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-19 12:04:59 +02:00
dependabot-preview[bot] 29e3cae0a6 build(deps): bump @babel/register from 7.11.5 to 7.12.1 (#12683)
Bumps [@babel/register](https://github.com/babel/babel/tree/HEAD/packages/babel-register) from 7.11.5 to 7.12.1.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.12.1/packages/babel-register)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-19 12:04:44 +02:00
dependabot-preview[bot] 274c582af8 build(deps): bump @babel/core from 7.11.6 to 7.12.3 (#12681)
Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.11.6 to 7.12.3.
- [Release notes](https://github.com/babel/babel/releases)
- [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel/commits/v7.12.3/packages/babel-core)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-19 12:04:33 +02:00
sou osu 4a7f40ea37 Translated using Weblate (Japanese)
Currently translated at 95.6% (687 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/
2020-10-19 11:09:21 +02:00
Lio Zam 97ad0fae26 Translated using Weblate (German)
Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/
2020-10-19 11:09:19 +02:00
Tereza F b7b91caef1 Translated using Weblate (Czech)
Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/cs/
2020-10-19 11:09:16 +02:00
Matteo Pagliazzi daa3458760 Merge branch 'release' into develop 2020-10-19 01:30:00 +02:00
Matteo Pagliazzi 8e6ce39d64 4.165.2 2020-10-19 01:11:20 +02:00
Matteo Pagliazzi 617832f02d fix(i18n): restore missing strings 2020-10-19 01:11:00 +02:00
Matteo Pagliazzi 2cfc765e39 Merge branch 'release' into develop 2020-10-18 19:16:25 +02:00
Matteo Pagliazzi 43efe2d6d6 4.165.1 2020-10-18 19:16:02 +02:00
Matteo Pagliazzi 9474a44df3 fix(ab test): enroll more users 2020-10-18 19:15:50 +02:00
sou osu 7cd9f800cc Translated using Weblate (Japanese)
Currently translated at 95.4% (685 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/
2020-10-18 14:19:17 +02:00
Lio Zam 9a1cadd49f Translated using Weblate (German)
Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/de/
2020-10-18 14:19:14 +02:00
Melior b3285db5b0 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (364 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (Spanish)

Currently translated at 86.8% (1896 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish)

Currently translated at 93.1% (669 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/es/

Translated using Weblate (Spanish (Latin America))

Currently translated at 98.6% (359 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt_BR/

Translated using Weblate (Spanish)

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (176 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (86 of 86 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (111 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/es/

Translated using Weblate (Japanese)

Currently translated at 88.3% (1929 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Spanish)

Currently translated at 100.0% (298 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (328 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/es/

Translated using Weblate (German)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/de/

Translated using Weblate (Spanish)

Currently translated at 93.0% (668 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (123 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (47 of 47 strings)

Translation: Habitica/Contrib
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/es/

Translated using Weblate (Czech)

Currently translated at 97.1% (548 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/cs/

Translated using Weblate (Spanish)

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/
2020-10-18 00:26:47 +02:00
Alys 8b1c009990 fix "push to bottom" for user tasks in API (#12659)
Also:
- Fix the test for this which has been equally broken.
- Simplify apidoc position info and make consistent in similar routes.
- Replace non-ascii characters in apidoc comment.
2020-10-17 17:58:48 +02:00
RaitheOfDureya 9061a59fc2 Removed unused I18N strings from the challenges.json files (related to issue #9957) (#12639)
* Removed unused I18N strings from the `challenges.json` file (locales\en)

* Removed unused I18N `challenge.json` strings from all other languages

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-10-17 17:40:57 +02:00
RaitheOfDureya cbfed9c0d3 Removed unused I18N strings from the character.json files (related to issue #9957) (#12635)
* Removed unused I18N strings from the `character.json` file (locales\en)

* Removed unused I18N `character.json` strings from the other languages

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-10-17 17:40:24 +02:00
RaitheOfDureya 77447f7096 Removed unused I18N strings from the achievements.json files (related to issue #9957) (#12658)
* Removed unused I18N string from the `achievements.json` file (locales\en)

* Removed unused I18N `achievements.json` strings from the other languages
2020-10-17 17:39:33 +02:00
RaitheOfDureya 361bb92b3b Removed unused I18N front.json strings from all the languages (#12604) 2020-10-17 17:39:13 +02:00
RaitheOfDureya e50d5f514c Removed unused I18N strings from the generic.json files (related to issue #9957) (#12590)
* Removed unused I18N strings from the `generic.json` file (locales\en)

* Removed unused I18N `generic.json` strings from all the other languages

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-10-17 17:38:21 +02:00
Matteo Pagliazzi a7ac4633a8 Merge branch 'release' into develop 2020-10-16 19:58:24 +02:00
Matteo Pagliazzi 6a27feb3f9 4.165.0 2020-10-16 19:57:57 +02:00
Matteo Pagliazzi 31b53fd6ed Merge branch 'release' into develop 2020-10-16 19:51:54 +02:00
Matteo Pagliazzi e04d4e8bea Drop Cap Notification, Modal and A/B Test (#12651)
* add drop cap notification

* add drop cap notification

* add dismissible notification

* fix(notification): correct remove icon positioning

* track events

* add modal

* add back files

* fix links and add missing analytics

* fix rounded borders and hide sub info for subscribers

* a/b test

* fix comparison

* Translated using Weblate (Spanish)

Currently translated at 98.2% (55 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/es/

Translated using Weblate (Spanish)

Currently translated at 99.4% (179 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/es/

Merge branch 'origin/develop' into Weblate.

Translated using Weblate (Spanish)

Currently translated at 99.4% (175 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (Spanish (Latin America))

Currently translated at 98.6% (359 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (Spanish)

Currently translated at 85.7% (151 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (Spanish)

Currently translated at 95.3% (538 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (Spanish (Latin America))

Currently translated at 98.6% (359 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (French)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/fr/

Translated using Weblate (German)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/de/

Translated using Weblate (French)

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/

Translated using Weblate (German)

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/

Translated using Weblate (Czech)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/cs/

Translated using Weblate (Japanese)

Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Italian)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/it/

Translated using Weblate (Italian)

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/

Translated using Weblate (Czech)

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/cs/

Translated using Weblate (Basque)

Currently translated at 100.0% (2 of 2 strings)

Translation: Habitica/Noscript
Translate-URL: https://translate.habitica.com/projects/habitica/noscript/eu/

Translated using Weblate (Basque)

Currently translated at 6.5% (8 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/eu/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/zh_Hans/

Translated using Weblate (Japanese)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/ja/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hans/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (717 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

* clarify a/b test values

* add tests

* refactor user dropdown

* fix hover state

* fix user dropdown

* fix user menu hierarchy

* restore i18n files to release version

Co-authored-by: Melior <admin@habitica.com>
2020-10-16 19:50:54 +02:00
Melior 3e31223812 Translated using Weblate (Spanish)
Currently translated at 98.2% (55 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/es/

Translated using Weblate (Spanish)

Currently translated at 99.4% (179 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/es/

Merge branch 'origin/develop' into Weblate.

Translated using Weblate (Spanish)

Currently translated at 99.4% (175 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (Spanish (Latin America))

Currently translated at 98.6% (359 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (Spanish)

Currently translated at 85.7% (151 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/

Translated using Weblate (Spanish)

Currently translated at 95.3% (538 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/

Translated using Weblate (Spanish (Latin America))

Currently translated at 98.6% (359 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (French)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/fr/

Translated using Weblate (German)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/de/

Translated using Weblate (French)

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/

Translated using Weblate (German)

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/

Translated using Weblate (Czech)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/cs/

Translated using Weblate (Japanese)

Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Italian)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/it/

Translated using Weblate (Italian)

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/

Translated using Weblate (Czech)

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/cs/

Translated using Weblate (Basque)

Currently translated at 100.0% (2 of 2 strings)

Translation: Habitica/Noscript
Translate-URL: https://translate.habitica.com/projects/habitica/noscript/eu/

Translated using Weblate (Basque)

Currently translated at 6.5% (8 of 123 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/eu/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/zh_Hans/

Translated using Weblate (Japanese)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/ja/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hans/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (718 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (717 of 718 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/
2020-10-15 22:29:31 +02:00
Sabe Jones 2832226539 4.164.0 2020-10-15 15:14:59 -05:00
Matteo Pagliazzi dcbc5da2ba fix(news): use correct date for posts 2020-10-15 17:32:26 +02:00
Matteo Pagliazzi 1d44bfe0cd fix(profile): correct formatting, fixes #12677 2020-10-15 12:54:52 +02:00
Melior 6553118636 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/pt_BR/

Merge branch 'origin/develop' into Weblate.

Translated using Weblate (Arabic)

Currently translated at 1.8% (2 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ar/

Translated using Weblate (Japanese)

Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Spanish (Latin America))

Currently translated at 98.6% (359 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (Japanese)

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ja/

Translated using Weblate (Japanese)

Currently translated at 88.1% (1925 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Japanese)

Currently translated at 97.7% (171 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (364 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/

Translated using Weblate (Italian)

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/

Translated using Weblate (Japanese)

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ja/

Translated using Weblate (Italian)

Currently translated at 100.0% (176 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/it/

Translated using Weblate (Hindi)

Currently translated at 31.5% (35 of 111 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/hi/

Translated using Weblate (Hindi)

Currently translated at 100.0% (15 of 15 strings)

Translation: Habitica/Death
Translate-URL: https://translate.habitica.com/projects/habitica/death/hi/

Translated using Weblate (Japanese)

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ja/

Translated using Weblate (Spanish)

Currently translated at 100.0% (15 of 15 strings)

Translation: Habitica/Death
Translate-URL: https://translate.habitica.com/projects/habitica/death/es/

Translated using Weblate (Spanish)

Currently translated at 100.0% (15 of 15 strings)

Translation: Habitica/Death
Translate-URL: https://translate.habitica.com/projects/habitica/death/es/

Translated using Weblate (Japanese)

Currently translated at 99.8% (563 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ja/

Translated using Weblate (Spanish (Latin America))

Currently translated at 85.6% (613 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 86.0% (74 of 86 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (23 of 23 strings)

Translation: Habitica/Loginincentives
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (364 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/nb_NO/

Translated using Weblate (Polish)

Currently translated at 79.3% (1733 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pl/

Translated using Weblate (Spanish (Latin America))

Currently translated at 85.6% (613 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 98.3% (358 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 81.4% (1779 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 95.5% (539 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es_419/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/

Translated using Weblate (Portuguese)

Currently translated at 81.7% (76 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt/

Translated using Weblate (Spanish (Latin America))

Currently translated at 98.0% (357 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 96.7% (352 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 94.7% (345 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (Japanese)

Currently translated at 98.6% (359 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/

Translated using Weblate (Japanese)

Currently translated at 88.0% (1923 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ja/

Translated using Weblate (Italian)

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/

Translated using Weblate (Japanese)

Currently translated at 98.8% (178 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ja/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (55 of 55 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/en_GB/

Translated using Weblate (English (United Kingdom))

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/en_GB/

Translated using Weblate (German)

Currently translated at 100.0% (176 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/de/

Translated using Weblate (Spanish (Latin America))

Currently translated at 92.5% (337 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/es_419/

Translated using Weblate (German)

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/de/

Translated using Weblate (French)

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (German)

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/

Translated using Weblate (Czech)

Currently translated at 87.6% (1913 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/cs/

Translated using Weblate (French)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/fr/

Translated using Weblate (French)

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/fr/

Translated using Weblate (German)

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/de/

Translated using Weblate (French)

Currently translated at 99.9% (2182 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 99.9% (2182 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 99.8% (2180 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 99.8% (2180 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 99.7% (2178 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 99.7% (2178 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 99.7% (2177 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 99.7% (2177 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 99.6% (2176 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/fr/

Translated using Weblate (French)

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/fr/

Translated using Weblate (French)

Currently translated at 98.9% (558 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/fr/

Translated using Weblate (Japanese)

Currently translated at 96.0% (168 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (French)

Currently translated at 100.0% (176 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fr/

Translated using Weblate (Japanese)

Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/ja/

Translated using Weblate (Japanese)

Currently translated at 96.7% (178 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ja/

Translated using Weblate (Japanese)

Currently translated at 98.6% (359 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/

Translated using Weblate (Slovak)

Currently translated at 29.0% (27 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/sk/

Translated using Weblate (Japanese)

Currently translated at 98.8% (178 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ja/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (176 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (364 of 364 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2183 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (German)

Currently translated at 99.5% (2174 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/

Translated using Weblate (Italian)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/it/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/zh_Hans/

Translated using Weblate (Italian)

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/it/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (2179 of 2183 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Russian)

Currently translated at 98.4% (555 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ru/

Translated using Weblate (German)

Currently translated at 99.2% (560 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/de/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (176 of 176 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (564 of 564 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/pt_BR/
2020-10-13 22:09:31 +02:00
Sabe Jones a238b264e5 Merge branch 'release' into develop 2020-10-13 14:38:39 -05:00
Sabe Jones 4696237b21 4.163.0 2020-10-13 14:37:40 -05:00
Sabe Jones b7956a82ee feat(content): Pet Quest Bundle 2020-10-13 14:36:38 -05:00
Sabe Jones a5babc493f fix(tests): update analytics expectations 2020-10-13 11:08:35 -05:00
Sabe Jones 708bd4a292 chore(analytics): track first-time-purchase info 2020-10-13 10:35:44 -05:00
Phillip Thelen d9e774dd77 Implement Bailey CMS API (#10739)
* Begin refactoring news API to return individual markdown posts

* Implement simple bailey CMS

* Prevented users with lvl less than 10 from seeing mana

* Added in class checks and notification tests

* Added getter use

* Fixed class check

* chore(i18n): update locales

* 4.60.2

* remove tests that are no longer needed because we won't be purging private messages (#10670)

Ref: this comment from paglias: https://github.com/HabitRPG/habitica/issues/7940#issuecomment-406489506

* remove .only

* allow challenge leader/owner to view/join/modify challenge in private group they've left - fixes #9753 (#10606)

* rename hasAccess to canJoin for challenges

This is so the function won't be used accidentally for other
purposes, since hasAccess could be misinterpretted.

* add isLeader function for challenges

* allow challenge leader to join/modify/end challenge when they're not in the private group it's in

* delete duplicate test

* clarify title of existing tests

* add tests and adjust existing tests to reduce privileges of test users

* fix lint errors

* remove pointless isLeader check (it's checked in canJoin)

* Correct Challenges tooltip in Guild view (#10667)

* Fix new party member cannot join pending quest (#10648)

* Saved sort selection into local storage for later use - fixes #10432 (#10655)

* Saved sort selection into local storage for later use

* Updated code to use userLocalManager module

* Fix initial position item info when selecting one item after another (fixes #10077) (#10661)

* Update lastMouseMoveEvent even when dragging an egg or potion.

* Update lastMouseMoveEvent even when dragging a food item.

* Refactor/market vue (#10601)

* extract inventoryDrawer from market

* show scrollbar only if needed

* extract featuredItemsHeader / pinUtils

* extract pageLayout

* extract layoutSection / filterDropdown - fix sortByNumber

* rollback sortByNumber order-fix

* move equipment lists out of the layout-section (for now)

* refactor sellModal

* extract checkbox

* extract equipment section

* extract category row

* revert scroll - remove sellModal item template

* fix(lint): commas and semis

* Created category item component (#10613)

* extract filter sidebar

* fix gemCount - fix raising the item count if the item wasn't previously owned

* fixes #10659

* remove unneeded method

* fix typo when importing component

* feat(content): Forest Friends Quest Bundle

* chore(sprites): compile

* chore(i18n): update locales

* 4.60.3

* fix(bcrypt): install fork compatible with Node 8

* chore(i18n): update locales

* 4.60.4

* add swear words - TRIGGER / CONTENT WARNING: assault, slurs, swearwords, etc

* add pinUtils-mixin   - fixes #10682 (#10683)

* chore(news): Bailey

* chore(i18n): update locales

* 4.60.5

* Improve rendering banner about sleeping in the inn

See #10695

* Display settings in one column

* Small Updates (#10701)

* small updates

* fix client unit test

* fix uuid validation

* Revert "Small Updates (#10701)" (#10702)

This reverts commit dd7fa73961.

* feat(event): Fall Festival 2018

* chore(sprites): compile

* chore(i18n): update locales

* 4.61.0

* Move inbox to its own model (#10428)

* shared model for chat and inbox

* disable inbox schema

* inbox: use separate model

* remove old code that used group.chat

* add back chat field (not used) and remove old tests

* remove inbox exclusions when loading user

* add GET /api/v3/inbox/messages

* add comment

* implement DELETE /inbox/messages/:messageid in v4

* implement GET /inbox/messages in v4 and update tests

* implement DELETE /api/v4/inbox/clear

* fix url

* fix doc

* update /export/inbox.html

* update other data exports

* add back messages in user schema

* add user.toJSONWithInbox

* add compativility until migration is done

* more compatibility

* fix tojson called twice

* add compatibility methods

* fix common tests

* fix v4 integration tests

* v3 get user -> with inbox

* start to fix tests

* fix v3 integration tests

* wip

* wip, client use new route

* update tests for members/send-private-message

* tests for get user in v4

* add tests for DELETE /inbox/messages/:messageId

* add tests for DELETE /inbox/clear in v4

* update docs

* fix tests

* initial migration

* fix migration

* fix migration

* migration fixes

* migrate api.enterCouponCode

* migrate api.castSpell

* migrate reset, reroll, rebirth

* add routes to v4 version

* fix tests

* fixes

* api.updateUser

* remove .only

* get user -> userLib

* refactor inbox.vue to work with new data model

* fix return message when messaging yourself

* wip fix bug with new conversation

* wip

* fix remaining ui issues

* move api.registerLocal, fixes

* keep only v3 version of GET /inbox/messages

* Fix API early Stat Point allocation (#10680)

* Refactor hasClass check to common so it can be used in shared & server-side code

* Check that user has selected class before allocating stat points

* chore(event): end Ember Hatching Potions

* chore(analytics): reenable navigation tracking

* update bcrypt

* Point achievement modal links to main site (#10709)

* Animal ears after death (#10691)

* Animal Ears purchasable with Gold if lost in Death

* remove ears from pinned items when set is bought

* standardise css and error handling for gems and coins

* revert accidental new line

* fix client tests

* Reduce margin-bottom of checklist-item from 10px to -3px. (#10684)

* chore(i18n): update locales

* 4.61.1

* Position inn banner when window is resized

* feat(content): Subscriber Items and Magic Potions

* chore(sprites): compile

* chore(i18n): update locales

* 4.62.0

* Update inn banner handling

* Fix banner offset on initial load

* Fix minor issues.

* Issue: 10660 - Fixed. Changed default to Please Enter A Value (#10718)

* Issue: 10660 - Fixed. Changed default to Please Enter A Value

* Issue: 10660 - Fixed/revision 2 Changed default to Enter A Value

* chore(news): Bailey announcements

* chore(i18n): update locales

* 4.62.1

* adjust wiki link for usernameInfo string

https://github.com/HabitRPG/habitica-private/issues/7#issuecomment-425405425

* raise coverage for tasks api calls (#10029)

* - updates a group task - approval is required
- updates a group task with checklist

* add expect to test the new checklist length

* - moves tasks to a specified position out of length

* remove unused line

* website getter tasks tests

* re-add sanitizeUserChallengeTask

* change config.json.example variable to be a string not a boolean

* fix tests - pick the text / up/down props too

* fix test - remove changes on text/up/down - revert sanitize condition - revert sanitization props

* chore(i18n): update locales

* 4.62.2

* chore(news): Bailey

* chore(i18n): update locales

* 4.62.3

* inbox: fix avatar display and order

* Username announcement (#10729)

* Change update username API call

The call no longer requires a password and also validates the username.

* Implement API call to verify username without setting it

* Improve coding style

* Apply username verification to registration

* Update error messages

* Validate display names.

* Fix API early Stat Point allocation (#10680)

* Refactor hasClass check to common so it can be used in shared & server-side code

* Check that user has selected class before allocating stat points

* chore(event): end Ember Hatching Potions

* chore(analytics): reenable navigation tracking

* update bcrypt

* Point achievement modal links to main site (#10709)

* Animal ears after death (#10691)

* Animal Ears purchasable with Gold if lost in Death

* remove ears from pinned items when set is bought

* standardise css and error handling for gems and coins

* revert accidental new line

* fix client tests

* Reduce margin-bottom of checklist-item from 10px to -3px. (#10684)

* chore(i18n): update locales

* 4.61.1

* feat(content): Subscriber Items and Magic Potions

* chore(sprites): compile

* chore(i18n): update locales

* 4.62.0

* Display notification for users to confirm their username

* fix typo

* WIP(usernames): Changes to address #10694

* WIP(usernames): Further changes for #10694

* fix(usernames): don't show spurious headings

* Change verify username notification to new version

* Improve feedback for invalid usernames

* Allow user to set their username again to confirm it

* Improve validation display for usernames

* Temporarily move display name validation outside of schema

* Improve rendering banner about sleeping in the inn

See #10695

* Display settings in one column

* Position inn banner when window is resized

* Update inn banner handling

* Fix banner offset on initial load

* Fix minor issues.

* Issue: 10660 - Fixed. Changed default to Please Enter A Value (#10718)

* Issue: 10660 - Fixed. Changed default to Please Enter A Value

* Issue: 10660 - Fixed/revision 2 Changed default to Enter A Value

* chore(news): Bailey announcements

* chore(i18n): update locales

* 4.62.1

* adjust wiki link for usernameInfo string

https://github.com/HabitRPG/habitica-private/issues/7#issuecomment-425405425

* raise coverage for tasks api calls (#10029)

* - updates a group task - approval is required
- updates a group task with checklist

* add expect to test the new checklist length

* - moves tasks to a specified position out of length

* remove unused line

* website getter tasks tests

* re-add sanitizeUserChallengeTask

* change config.json.example variable to be a string not a boolean

* fix tests - pick the text / up/down props too

* fix test - remove changes on text/up/down - revert sanitize condition - revert sanitization props

* Change update username API call

The call no longer requires a password and also validates the username.

* feat(content): Subscriber Items and Magic Potions

* Re-add register call

* Fix merge issue

* Fix issue with setting username

* Implement new alert style

* Display username confirmation status in settings

* Add disclaimer to change username field

* validate username in settings

* Allow specific fields to be focused when opening site settings

* Implement requested changes.

* Fix merge issue

* Fix failing tests

* verify username when users register with username and password

* Set ID for change username notification

* Disable submit button if username is invalid

* Improve username confirmation handling

* refactor(settings): address remaining code comments on auth form

* Revert "refactor(settings): address remaining code comments on auth form"

This reverts commit 9b6609ad64.

* Social user username (#10620)

* Refactored private functions to library

* Refactored social login code

* Added username to social registration

* Changed id library

* Added new local auth check

* Fixed export error. Fixed password check error

* fix(settings): password not available on client

* refactor(settings): more sensible placement of methods

* chore(migration): script to hand out procgen usernames

* fix(migration): don't give EVERYONE new names you doofus

* fix(migration): limit data retrieved, be extra careful about updates

* fix(migration): use missing field, not migration tag, for query

* fix(migration): unused var

* fix(usernames): only generate 20 characters

* fix(migration): set lowerCaseUsername

* fix(lint): comma

* fix(lint): comma spacing

* chore(i18n): update locales

* 4.63.0

* chore(news): Bailey

* chore(i18n): update locales

* 4.63.1

* fix(usernames): various
Reword invalid characters error
Correct typo in slur error
Remove extraneous Confirm button
Reset username field if empty on blur
Restore ability to add local auth to social login

* fix(auth): account for new username paradigm in add-local flow

* fix(auth): alert on successful addLocal

* chore(i18n): update locales

* 4.63.2

* fix(auth): Don't try to check existing username on new reg

* 4.63.3

* feat(content): Armoire and BGs 2018/10

* chore(sprites): compile

* fix(passport): use graph API v2.8

* chore(i18n): update locales

* 4.64.0

* Begin refactoring news API to return individual markdown posts

* Implement simple bailey CMS

* remove old news markdown

* Correctly display images in bailey modal

* Remove need for newStuff migration

* Add basic tests

* Fix authentication issue

* Fix tests

* Update news model

* add API route to get single post

* remove news admin frontend code

* fix lint error

* Fix merge mixups

* Fix lint errors

* fix api call

* fix lint error

* Fix issues caused by merging

* remove console log

* Improve news display

* Correctly update users notifications

* Fix date display for news posts

* Fix tests

* remove old cache file

* correctly create date

* correctly create promise

* Better check for existance.

* Improve docs

* Fix minor issues

* Add method to get latest post

* fix lint errors

* use correct call for 404

* add comment about old newStuff field

* paginate news

* Fix lint errors

* Remove unnecessary await

* Fix broken tests

* ...

* correct existence check

* fix database queries

* change approach to cached news posts

* fix tests

* Change how news posts are cached

* Fetch last news post at an interval

* Fix typos and other small things

* add new permission for modifying bailey posts

* add test for ensureNewsPoster

* return last news post with legacy api

* Fix test

* Hopefully fix test

* change fields to _id

* Fixes

* Fixes

* fix test

* Fixes

* make all tests pass

* fix lint

* id -> _id

* _id -> id

* remove identical tell me later route from api v4

* fix lint

* user model: fix issues with newStuff

* improve user#toJSONTransform

* fix typo

* improve newsPost.js

* fix(integration tests): do not return flags.newStuff if it was not selected

* fix news controller

* server side fixes, start refactoring client

* more client fixes

* automatically set author

* new stuff: show one post per user + drafts

* change default border radius for modals to 8px

* required fields and defaults

* slit news into its own component and fix static page

* noNewsPoster: move from i18n to apiError

* remove unused strings

* fix unit tests

* update apidocs

* add backward comparibility for flags.newStuff in api v3

* fix integration tests

* POST news: make integration test independent of number of posts

* api v3 news: render markdown

* static new-stuff: add padding and fix when user not logged in

* test flags.newStuff

* api v3: test setting flags.newStuff on PUT /user

* refactor news post cache and add tests

* remove new locales file

* more resilient tests

* more resilient tests

* refactor tests for NewsPost.updateLastNewsPost

* api v4: fix tests

* api v3: fix tests

* can set flags.newStuff in api v4

Co-authored-by: Keith Holliday <keithrholliday@gmail.com>
Co-authored-by: Sabe Jones <sabrecat@gmail.com>
Co-authored-by: Alys <Alys@users.noreply.github.com>
Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
Co-authored-by: Carl Vuorinen <carl.vuorinen@gmail.com>
Co-authored-by: Rene Cordier <rene.cordier@gmail.com>
Co-authored-by: Forrest Hatfield <github@forresthatfield.com>
Co-authored-by: lucubro <88whacko@gmail.com>
Co-authored-by: negue <negue@users.noreply.github.com>
Co-authored-by: Alys <alice.harris@oldgods.net>
Co-authored-by: J.D. Sandifer <sandifer.jd@gmail.com>
Co-authored-by: Kirsty <kirsty-tortoise@users.noreply.github.com>
Co-authored-by: beatscribe <rattjp@gmail.com>
Co-authored-by: Phillip Thelen <phillip@habitica.com>
2020-10-13 10:15:52 -05:00
dependabot-preview[bot] 97ef3b1d4b build(deps): bump @vue/cli-plugin-babel in /website/client (#12665)
Bumps [@vue/cli-plugin-babel](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-babel) from 4.5.6 to 4.5.7.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.7/packages/@vue/cli-plugin-babel)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-12 13:31:33 +02:00
dependabot-preview[bot] 8e3ac280b0 build(deps): bump moment from 2.29.0 to 2.29.1 (#12663)
Bumps [moment](https://github.com/moment/moment) from 2.29.0 to 2.29.1.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.29.0...2.29.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-12 13:31:14 +02:00
Matteo Pagliazzi 7fedbdde03 build(deps): bump @vue/cli-service in /website/client (#12669)
Bumps [@vue/cli-service](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-service) from 4.5.6 to 4.5.7.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.7/packages/@vue/cli-service)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-12 13:30:50 +02:00
dependabot-preview[bot] 6ad808f717 build(deps): bump moment from 2.29.0 to 2.29.1 in /website/client (#12666)
Bumps [moment](https://github.com/moment/moment) from 2.29.0 to 2.29.1.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.29.0...2.29.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-12 13:30:40 +02:00
dependabot-preview[bot] c6541399bb build(deps): bump @vue/cli-plugin-router in /website/client (#12667)
Bumps [@vue/cli-plugin-router](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-router) from 4.5.6 to 4.5.7.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.7/packages/@vue/cli-plugin-router)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-12 13:30:10 +02:00
dependabot-preview[bot] 81028893b2 build(deps): bump @vue/cli-service in /website/client
Bumps [@vue/cli-service](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-service) from 4.5.6 to 4.5.7.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.7/packages/@vue/cli-service)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-12 11:26:59 +00:00
dependabot-preview[bot] 943862c0ea build(deps-dev): bump sinon from 9.1.0 to 9.2.0 (#12661)
Bumps [sinon](https://github.com/sinonjs/sinon) from 9.1.0 to 9.2.0.
- [Release notes](https://github.com/sinonjs/sinon/releases)
- [Changelog](https://github.com/sinonjs/sinon/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sinonjs/sinon/compare/v9.1.0...v9.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-12 13:24:50 +02:00
dependabot-preview[bot] 43511aacb9 build(deps): bump @vue/cli-plugin-unit-mocha in /website/client (#12673)
Bumps [@vue/cli-plugin-unit-mocha](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-unit-mocha) from 4.5.6 to 4.5.7.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.7/packages/@vue/cli-plugin-unit-mocha)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-12 13:24:06 +02:00
dependabot-preview[bot] ce68e2f855 build(deps): bump hellojs from 1.18.4 to 1.18.6 in /website/client (#12670)
Bumps [hellojs](https://github.com/MrSwitch/hello.js) from 1.18.4 to 1.18.6.
- [Release notes](https://github.com/MrSwitch/hello.js/releases)
- [Commits](https://github.com/MrSwitch/hello.js/compare/v1.18.4...v1.18.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-12 13:23:55 +02:00
dependabot-preview[bot] ec06faef32 build(deps): bump @vue/cli-plugin-eslint in /website/client (#12671)
Bumps [@vue/cli-plugin-eslint](https://github.com/vuejs/vue-cli/tree/HEAD/packages/@vue/cli-plugin-eslint) from 4.5.6 to 4.5.7.
- [Release notes](https://github.com/vuejs/vue-cli/releases)
- [Changelog](https://github.com/vuejs/vue-cli/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-cli/commits/v4.5.7/packages/@vue/cli-plugin-eslint)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-12 13:23:48 +02:00
dependabot-preview[bot] cfac54d44c build(deps): bump vue-router from 3.4.5 to 3.4.6 in /website/client (#12672)
Bumps [vue-router](https://github.com/vuejs/vue-router) from 3.4.5 to 3.4.6.
- [Release notes](https://github.com/vuejs/vue-router/releases)
- [Changelog](https://github.com/vuejs/vue-router/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-router/compare/v3.4.5...v3.4.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-12 13:23:21 +02:00
dependabot-preview[bot] f4b41bd958 build(deps): bump sass from 1.26.11 to 1.27.0 in /website/client (#12674)
Bumps [sass](https://github.com/sass/dart-sass) from 1.26.11 to 1.27.0.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.26.11...1.27.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-12 13:23:04 +02:00
Alys 7d7d71e95f move comment to just above the code it refers to
Also adds "promotion" to the comment to help when we're grepping
for info about promos.
2020-10-12 12:54:34 +10:00
J Sanderson 2b21c2a28e Fix overflow in guild member text and keyboard inaccessible member/bank lists fixes #11067 (#12637)
* fix: guild member list overflow

* feat: make member/bank divs tabbable

* fix: bank button calls correct modal on keypress

* fix: review suggestions

* fix: svg size on firefox, row spacing
2020-10-10 10:34:59 +02:00
Matteo Pagliazzi dfa8725c55 upgrade mongoose and fix tests (#12657) 2020-10-10 10:31:42 +02:00
Matteo Pagliazzi 1d8880c04d fix(run-rs): downgrade to working version 2020-10-08 12:45:42 +02:00
Melior 07fd3cef4c Merge branch 'develop' of github.com:HabitRPG/habitica into develop 2020-10-06 23:09:10 +02:00
Benoit Hetru b58443140a Translated using Weblate (French)
Currently translated at 100.0% (716 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/
2020-10-06 22:52:10 +02:00
Sabe Jones a0b93d57e4 Merge branch 'release' into develop 2020-10-06 15:50:05 -05:00
Sabe Jones 7cac574c31 4.162.0 2020-10-06 15:49:26 -05:00
Sabe Jones 86619a2ac9 chore(sprites): compile 2020-10-06 15:49:18 -05:00
Sabe Jones 058c1464d3 feat(content): Armoire and BGs 2020/10 2020-10-06 15:49:09 -05:00
Yowi 70e747c131 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/es_419/
2020-10-06 16:32:13 +02:00
Yowi 8869d3ebf0 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es_419/
2020-10-06 15:46:44 +02:00
Yowi d82f4f5c91 Translated using Weblate (Spanish (Latin America))
Currently translated at 98.3% (122 of 124 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/es_419/
2020-10-06 15:46:44 +02:00
Yowi d9a6120cfe Translated using Weblate (Spanish (Latin America))
Currently translated at 91.4% (160 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es_419/
2020-10-06 13:53:12 +02:00
Yowi 5c7ad58ce4 Translated using Weblate (Spanish (Latin America))
Currently translated at 81.4% (1771 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/
2020-10-06 13:53:10 +02:00
Yowi 284510d0a3 Translated using Weblate (Spanish (Latin America))
Currently translated at 70.2% (123 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es_419/
2020-10-06 13:15:15 +02:00
そら 0791848fa3 Translated using Weblate (Japanese)
Currently translated at 96.7% (178 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ja/
2020-10-06 09:55:44 +02:00
そら 466f109edb Translated using Weblate (Japanese)
Currently translated at 99.0% (499 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/
2020-10-06 09:55:43 +02:00
Geist Mann 87fe4aa28e Translated using Weblate (Latin)
Currently translated at 98.2% (55 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/la/
2020-10-05 19:17:44 +02:00
Geist Mann baa86bab88 Translated using Weblate (Latin)
Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/la/
2020-10-05 19:17:44 +02:00
Atticus 17cbe16773 Translated using Weblate (English (United Kingdom))
Currently translated at 97.8% (180 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/en_GB/
2020-10-05 19:17:43 +02:00
Matteo Pagliazzi 660f3635aa fix(habit): correct icon positions 2020-10-05 17:13:35 +02:00
RaitheOfDureya 10a28a9161 Removed unused I18N strings from the communityGuidelines.json files (related to issue #9957) (#12633)
* Remove `iAcceptCommunityGuidelines` from `communityGuidelines.json`

The string currently in use is `acceptCommunityGuidelines` located in 
`website/common/locales/en/npc.json`

* Removed unused `communityGuidelines.json` strings from other languages
2020-10-05 16:37:26 +02:00
RaitheOfDureya 2964eff298 Removed duplicated I18N strings from the content.json file (locales/en) (#12628) 2020-10-05 16:36:34 +02:00
RaitheOfDureya 7119763c1e Removed unused I18N strings from the defaultTasks.json files (related to issue #9957) (#12608)
* Removed unused I18N strings from `defaultTasks.json` file (locales\en)

* Removed unused I18N `defaultTasks.json` strings from all the other languages
2020-10-05 16:35:34 +02:00
Bart Enkelaar 12bd10a095 fix(task) - 11139 use start-from hours in due date calculation (#12609)
* fix(task) - 11139 use start-from hours in due date calculation

* fix(task) - 11139 - Initial setup of Task unit test

* Add more unit tests for formatDueDate
2020-10-05 16:19:47 +02:00
dependabot-preview[bot] 221c95eb14 build(deps): bump uuid from 8.3.0 to 8.3.1 in /website/client (#12647)
Bumps [uuid](https://github.com/uuidjs/uuid) from 8.3.0 to 8.3.1.
- [Release notes](https://github.com/uuidjs/uuid/releases)
- [Changelog](https://github.com/uuidjs/uuid/blob/master/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v8.3.0...v8.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-05 12:35:26 +02:00
そら 7815d501fa Translated using Weblate (Japanese)
Currently translated at 96.0% (168 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/
2020-10-05 11:51:47 +02:00
そら 9dec717e10 Translated using Weblate (Japanese)
Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/ja/
2020-10-05 11:51:46 +02:00
そら d23368a826 Translated using Weblate (Japanese)
Currently translated at 87.5% (49 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/
2020-10-05 11:51:46 +02:00
そら 33913743e9 Translated using Weblate (Japanese)
Currently translated at 98.8% (178 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ja/
2020-10-05 11:51:44 +02:00
dependabot-preview[bot] d92b344e91 build(deps-dev): bump run-rs from 0.6.2 to 0.7.0 (#12618)
Bumps [run-rs](https://github.com/vkarpov15/run-rs) from 0.6.2 to 0.7.0.
- [Release notes](https://github.com/vkarpov15/run-rs/releases)
- [Changelog](https://github.com/vkarpov15/run-rs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/vkarpov15/run-rs/compare/0.6.2...0.7.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-05 10:12:36 +02:00
dependabot-preview[bot] def065d86a build(deps-dev): bump sinon from 9.0.3 to 9.1.0 (#12641)
Bumps [sinon](https://github.com/sinonjs/sinon) from 9.0.3 to 9.1.0.
- [Release notes](https://github.com/sinonjs/sinon/releases)
- [Changelog](https://github.com/sinonjs/sinon/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sinonjs/sinon/compare/v9.0.3...v9.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-05 09:48:15 +02:00
dependabot-preview[bot] 5b50761d9f build(deps): bump uuid from 8.3.0 to 8.3.1 (#12642)
Bumps [uuid](https://github.com/uuidjs/uuid) from 8.3.0 to 8.3.1.
- [Release notes](https://github.com/uuidjs/uuid/releases)
- [Changelog](https://github.com/uuidjs/uuid/blob/master/CHANGELOG.md)
- [Commits](https://github.com/uuidjs/uuid/compare/v8.3.0...v8.3.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-10-05 09:48:03 +02:00
blacksheep47 30a52e2bb8 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (2175 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/
2020-10-05 01:15:37 +02:00
mario yonan b361e3fc82 Translated using Weblate (Arabic)
Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/ar/
2020-10-04 17:53:05 +02:00
mario yonan 7419e8a926 Translated using Weblate (Arabic)
Currently translated at 13.9% (13 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ar/
2020-10-04 17:53:05 +02:00
そら 0d04509a97 Translated using Weblate (Japanese)
Currently translated at 99.0% (499 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/
2020-10-04 17:53:04 +02:00
Anonymous 4950ceb814 Translated using Weblate (Czech)
Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/cs/
2020-10-04 16:28:12 +02:00
Anonymous 218d186969 Translated using Weblate (Czech)
Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/cs/
2020-10-04 16:25:37 +02:00
Anonymous 4f6306e748 Translated using Weblate (Czech)
Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/cs/
2020-10-04 16:25:23 +02:00
Anonymous 334478f3d4 Translated using Weblate (Czech)
Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/cs/
2020-10-04 16:24:42 +02:00
Tereza F fd4c50083c Translated using Weblate (Czech)
Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/cs/
2020-10-04 16:24:38 +02:00
Martin Bartak 435471a48c Translated using Weblate (Czech)
Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/cs/
2020-10-04 16:23:40 +02:00
Tereza F be96e2c3a4 Translated using Weblate (Czech)
Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/cs/
2020-10-04 16:23:23 +02:00
Madalena MJ d018401f96 Translated using Weblate (Portuguese)
Currently translated at 98.7% (550 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/pt/
2020-10-04 09:07:21 +02:00
Madalena MJ 63bb9b8e68 Translated using Weblate (Portuguese)
Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/pt/
2020-10-04 07:57:03 +02:00
Lio Zam 682f559762 Translated using Weblate (German)
Currently translated at 99.8% (2172 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/
2020-10-03 23:43:40 +02:00
mattya 226 aa39af5ab4 Translated using Weblate (Japanese)
Currently translated at 95.2% (682 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ja/
2020-10-03 19:34:58 +02:00
mattya 226 d9503ef35a Translated using Weblate (Japanese)
Currently translated at 98.9% (551 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ja/
2020-10-03 19:34:54 +02:00
Matteo Pagliazzi 322a826576 Merge branch 'release' into develop 2020-10-03 16:56:19 +02:00
Matteo Pagliazzi 362dea6c5c fix(shopItem): correct syntax for popover triggers, fix #12638 2020-10-03 16:55:34 +02:00
Lio Zam f74e908bd5 Translated using Weblate (German)
Currently translated at 99.8% (2171 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/
2020-10-03 13:48:57 +02:00
Anonymous d4c11ff798 Translated using Weblate (German)
Currently translated at 99.8% (2171 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/
2020-10-03 13:21:13 +02:00
Lio Zam 24bc3822b6 Translated using Weblate (German)
Currently translated at 99.8% (2171 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/
2020-10-03 13:21:11 +02:00
Kitty Kat 4fc796b177 Translated using Weblate (Hindi)
Currently translated at 87.0% (316 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/hi/
2020-10-03 12:01:53 +02:00
そら c099242cb7 Translated using Weblate (Japanese)
Currently translated at 96.0% (168 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/
2020-10-03 12:01:53 +02:00
そら f7142b6f55 Translated using Weblate (Japanese)
Currently translated at 99.0% (499 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/
2020-10-03 12:01:53 +02:00
そら c0be28072b Translated using Weblate (Japanese)
Currently translated at 85.7% (48 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/
2020-10-03 12:01:52 +02:00
Kitty Kat a218f9ef25 Translated using Weblate (Hindi)
Currently translated at 86.7% (315 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/hi/
2020-10-03 07:54:12 +02:00
blacksheep47 65e881fa5a Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (2175 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/
2020-10-03 07:54:11 +02:00
Sabe Jones 2c34972629 4.161.4 2020-10-02 15:08:26 -05:00
Sabe Jones 9bd07034a5 fix(events): make sure we don't create "fall interim" gear 2020-10-02 15:08:13 -05:00
Melior 285507d68a Translated using Weblate (German)
Currently translated at 99.6% (2168 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/

Translated using Weblate (Spanish)

Currently translated at 86.9% (1892 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (328 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/es_419/

Translated using Weblate (Japanese)

Currently translated at 98.3% (548 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ja/

Translated using Weblate (Japanese)

Currently translated at 99.0% (499 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (298 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/ja/

Translated using Weblate (Japanese)

Currently translated at 83.9% (47 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ja/

Translated using Weblate (Czech)

Currently translated at 100.0% (504 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/cs/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (67 of 67 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/es_419/

Translated using Weblate (Polish)

Currently translated at 91.0% (122 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/pl/

Translated using Weblate (Spanish (Latin America))

Currently translated at 94.6% (477 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (328 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (15 of 15 strings)

Translation: Habitica/Death
Translate-URL: https://translate.habitica.com/projects/habitica/death/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (362 of 362 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (230 of 230 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/es_419/

Translated using Weblate (Polish)

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/pl/

Translated using Weblate (Japanese)

Currently translated at 99.0% (499 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/

Translated using Weblate (Polish)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/pl/

Translated using Weblate (Polish)

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/pl/

Translated using Weblate (French)

Currently translated at 100.0% (2175 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 100.0% (716 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/

Translated using Weblate (French)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/fr/

Translated using Weblate (Russian)

Currently translated at 94.5% (2056 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ru/

Translated using Weblate (German)

Currently translated at 99.5% (2166 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/

Translated using Weblate (Russian)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/ru/

Translated using Weblate (Japanese)

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/ja/

Translated using Weblate (Japanese)

Currently translated at 96.0% (168 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/ja/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (184 of 184 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (298 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/es_419/

Translated using Weblate (Japanese)

Currently translated at 99.0% (499 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (298 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/ja/

Translated using Weblate (Japanese)

Currently translated at 100.0% (328 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/ja/

Translated using Weblate (Japanese)

Currently translated at 98.8% (178 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ja/

Translated using Weblate (Italian)

Currently translated at 100.0% (2175 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2175 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2175 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2175 of 2175 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/zh_Hans/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/pt_BR/

Translated using Weblate (German)

Currently translated at 100.0% (363 of 363 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/de/
2020-10-02 22:07:43 +02:00
Sabe Jones 5c7227fc02 4.161.3 2020-10-02 14:36:25 -05:00
Sabe Jones 4a99fc5a74 fix(mobile): provide interim event 2020-10-02 14:36:15 -05:00
RaitheOfDureya 0a2e50ce76 Removed unused I18N strings from the contrib.json files (related to issue #9957) (#12589)
* Removed unused I18N strings from the `contrib.json` file (locales\en)

* Removed unused I18N `contrib.json` strings from all the other languages

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-10-02 19:06:12 +02:00
Matteo Pagliazzi 49d8c739c0 Merge PR #12588
Squashed commit of the following:

commit 87211e0d4b591cdd80492cfe67c5af7cadfaf1c6
Merge: 2c01e6347d 254e6b47de
Author: Matteo Pagliazzi <matteopagliazzi@gmail.com>
Date:   Fri Oct 2 19:00:56 2020 +0200

    Merge branch 'remove-unused-groups' of https://github.com/RaitheOfDureya/habitica into RaitheOfDureya-remove-unused-groups

commit 254e6b47de
Author: Raithe Of Dureya <raitheofdureya@gmail.com>
Date:   Wed Sep 23 00:56:19 2020 +0200

    Removed unused I18N `groups.json` strings from all the other languages

commit 7b4f2c3398
Author: Raithe Of Dureya <raitheofdureya@gmail.com>
Date:   Wed Sep 23 00:41:53 2020 +0200

    Removed unused I18N strings from the `groups.json` file (locales\en)
2020-10-02 19:01:27 +02:00
Matteo Pagliazzi 2c01e6347d fixed header bug (#12632)
Co-authored-by: Shamika Kumar <shamika_kumar@Shamikas-MacBook-Pro.local>
2020-10-02 18:56:01 +02:00
projectormato d050ef4779 Add aria-label to header (#12584)
* Add aria-label to classBadge.

* Add aria-label to the logo in the top left.

* Revert "Add aria-label to the logo in the top left."

This reverts commit f1e6a35cf1.
2020-10-02 18:53:46 +02:00
Sabe Jones 21d008aaee 4.161.2 2020-10-01 17:08:04 -05:00
Sabe Jones 0d4ed102a0 chore(news): Bailey 2020-10-01 17:07:51 -05:00
Sabe Jones 83bcfcde06 Merge branch 'develop' into release 2020-10-01 16:52:42 -05:00
Bart Enkelaar 32ac00b417 Fix vue test stacktraces (#12612)
* Issue 10786 - Add unit test for Home component

* Issue 10786 - Improve test setup and test invite parameter variations

* Issue 10786 - Improve Vue.js test isolation by adding async keyword to dispatch function

* Issue 10786 - Missing action does not need to be awaited

* fix(vuejs-unit-tests): Fewer stacktraces in avatar.spec.js

* No more stacktraces in avatar.spec.js

* Register dummy directive in chatCard.spec.js

* Resolve stacktraces in column.spec.js

* Resolve stacktrace in notifications.spec.js

* Resolve warnings in user.spec.js

* Resolve asynchronous stacktrace from home.spec.js

* Remove unnecessary mount call.

* Clear up some let clutter in column.spec.js
2020-10-01 19:08:34 +02:00
Sabe Jones 2a00aefdd6 4.161.1 2020-10-01 11:24:41 -05:00
Sabe Jones 679d615224 Squashed commit of the following:
commit dd4d53a68ccf547857c05402cdb569460589a223
Author: Sabe Jones <sabrecat@gmail.com>
Date:   Thu Oct 1 11:17:04 2020 -0500

    refactor(event): needless event thing

commit d1254af5218f6ae85bc64b45c55aea46388b665b
Author: Sabe Jones <sabrecat@gmail.com>
Date:   Thu Oct 1 10:56:06 2020 -0500

    fix(event): clone, not reassign

commit 50bd3199dc35ff215f7cb80b8e5db6770e7f436a
Author: Sabe Jones <sabrecat@gmail.com>
Date:   Thu Oct 1 10:36:39 2020 -0500

    fix(event): create interim period and handle it in gear generation
2020-10-01 11:24:31 -05:00
Shamika Kumar e4e980a6e3 fixed header bug 2020-09-30 12:41:13 +05:30
Melior 73c5764d63 Merge branch 'develop' of github.com:HabitRPG/habitica into develop 2020-09-29 21:54:24 +02:00
Sabe Jones 205d2758de Merge branch 'release' into develop 2020-09-29 14:19:29 -05:00
Sabe Jones efe7ea52bc 4.161.0 2020-09-29 14:16:38 -05:00
Sabe Jones 938152edea chore(news): Bailey 2020-09-29 14:16:25 -05:00
Jostein Skjånes 3e1e9b6d56 Translated using Weblate (Norwegian Bokmål)
Currently translated at 71.4% (125 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/nb_NO/
2020-09-29 18:02:36 +02:00
Jostein Skjånes 8b01d1a88c Translated using Weblate (Norwegian Bokmål)
Currently translated at 92.4% (196 of 212 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/nb_NO/
2020-09-29 18:02:36 +02:00
Kitty Kat 9910fb7b99 Translated using Weblate (Hindi)
Currently translated at 13.1% (43 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/hi/
2020-09-29 15:01:40 +02:00
Yowi a91d639606 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/es_419/
2020-09-29 15:01:39 +02:00
そら eaeb942ad8 Translated using Weblate (Japanese)
Currently translated at 96.0% (168 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/
2020-09-29 15:01:38 +02:00
Yowi c509d0edbd Translated using Weblate (Spanish (Latin America))
Currently translated at 87.0% (108 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/es_419/
2020-09-29 15:01:37 +02:00
Yowi 59566d9d65 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (70 of 70 strings)

Translation: Habitica/Contrib
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/es_419/
2020-09-29 15:01:37 +02:00
Yowi e457b8ddc0 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (230 of 230 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/es_419/
2020-09-29 15:01:36 +02:00
Yowi a43f7734dc Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/es_419/
2020-09-29 15:01:36 +02:00
Yowi 2618825ce2 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/es_419/
2020-09-29 15:01:35 +02:00
そら af35cbb743 Translated using Weblate (Japanese)
Currently translated at 98.8% (178 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ja/
2020-09-29 15:01:34 +02:00
Yıldıray 989361bb46 Translated using Weblate (Turkish)
Currently translated at 97.9% (292 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/tr/
2020-09-29 05:42:40 +02:00
Yıldıray b18225561e Translated using Weblate (Turkish)
Currently translated at 94.4% (170 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/tr/
2020-09-29 05:42:39 +02:00
そら a500119879 Translated using Weblate (Japanese)
Currently translated at 96.0% (168 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/
2020-09-28 21:28:48 +02:00
Yowi 4d2a738748 Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (140 of 140 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/es_419/
2020-09-28 21:28:47 +02:00
Yowi 38047b9d5c Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (230 of 230 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/es_419/
2020-09-28 21:28:46 +02:00
そら 035a6be8b7 Translated using Weblate (Japanese)
Currently translated at 99.0% (499 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/
2020-09-28 21:28:45 +02:00
Chalda Pnuzig e3bc4a5fc7 Translated using Weblate (Italian)
Currently translated at 100.0% (716 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/
2020-09-28 21:28:44 +02:00
そら d8d825c6b0 Translated using Weblate (Japanese)
Currently translated at 98.8% (178 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ja/
2020-09-28 21:28:41 +02:00
Sabe Jones f47c243cb0 fix(potions): previously-available text 2020-09-28 09:52:49 -05:00
dependabot-preview[bot] 8c31f944fa build(deps): bump vue-router from 3.4.3 to 3.4.5 in /website/client (#12622)
Bumps [vue-router](https://github.com/vuejs/vue-router) from 3.4.3 to 3.4.5.
- [Release notes](https://github.com/vuejs/vue-router/releases)
- [Changelog](https://github.com/vuejs/vue-router/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/vuejs/vue-router/compare/v3.4.3...v3.4.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-09-28 11:03:22 +02:00
dependabot-preview[bot] 931403ef0b build(deps): bump amplitude-js from 7.1.1 to 7.2.2 in /website/client (#12626)
Bumps [amplitude-js](https://github.com/amplitude/amplitude-javascript) from 7.1.1 to 7.2.2.
- [Release notes](https://github.com/amplitude/amplitude-javascript/releases)
- [Changelog](https://github.com/amplitude/Amplitude-JavaScript/blob/master/CHANGELOG.md)
- [Commits](https://github.com/amplitude/amplitude-javascript/compare/v7.1.1...v7.2.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-09-28 11:03:06 +02:00
dependabot-preview[bot] 17ff5f4640 build(deps): bump moment from 2.28.0 to 2.29.0 in /website/client (#12620)
Bumps [moment](https://github.com/moment/moment) from 2.28.0 to 2.29.0.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.28.0...2.29.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-09-28 11:02:52 +02:00
dependabot-preview[bot] ea590307c9 build(deps): bump moment from 2.28.0 to 2.29.0 (#12619)
Bumps [moment](https://github.com/moment/moment) from 2.28.0 to 2.29.0.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.28.0...2.29.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-09-28 11:02:45 +02:00
dependabot-preview[bot] e12597b330 build(deps): bump jwks-rsa from 1.9.0 to 1.10.1 (#12616)
Bumps [jwks-rsa](https://github.com/auth0/node-jwks-rsa) from 1.9.0 to 1.10.1.
- [Release notes](https://github.com/auth0/node-jwks-rsa/releases)
- [Changelog](https://github.com/auth0/node-jwks-rsa/blob/master/CHANGELOG.md)
- [Commits](https://github.com/auth0/node-jwks-rsa/compare/v1.9.0...v1.10.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-09-28 11:02:30 +02:00
Dennis Spaag dd92b20ef5 Translated using Weblate (Latin)
Currently translated at 78.7% (1710 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/la/
2020-09-28 08:05:16 +02:00
blacksheep47 fd0365eec9 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/
2020-09-28 08:05:12 +02:00
blacksheep47 cdeefcf4e9 Translated using Weblate (Chinese (Simplified))
Currently translated at 99.0% (2150 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/
2020-09-28 03:13:28 +02:00
blacksheep47 5d799546ff Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/zh_Hans/
2020-09-28 02:30:53 +02:00
Yowi 931bd33a9f Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (328 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/es_419/
2020-09-28 02:30:53 +02:00
Yowi 0b07aae1bb Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (362 of 362 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/es_419/
2020-09-28 02:30:52 +02:00
blacksheep47 4ff769db0c Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (189 of 189 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/zh_Hans/
2020-09-28 02:30:51 +02:00
blacksheep47 5456cc2348 Translated using Weblate (Chinese (Simplified))
Currently translated at 98.7% (2143 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/
2020-09-28 02:30:50 +02:00
blacksheep47 97baa69a8d Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/zh_Hans/
2020-09-28 02:30:46 +02:00
そら 66644b7369 Translated using Weblate (Japanese)
Currently translated at 96.0% (168 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/
2020-09-27 17:15:38 +02:00
Chalda Pnuzig 4dcac53d6d Translated using Weblate (Italian)
Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/it/
2020-09-27 17:15:37 +02:00
Chalda Pnuzig ead1c1b851 Translated using Weblate (Italian)
Currently translated at 100.0% (146 of 146 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/it/
2020-09-27 17:15:37 +02:00
Chalda Pnuzig f3a1ac425f Translated using Weblate (Italian)
Currently translated at 100.0% (504 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/it/
2020-09-27 17:15:36 +02:00
Chalda Pnuzig e450e7d975 Translated using Weblate (Italian)
Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/
2020-09-27 17:15:35 +02:00
そら 4984f99de0 Translated using Weblate (Japanese)
Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/ja/
2020-09-27 17:15:31 +02:00
Chalda Pnuzig 3ae6bfcb57 Translated using Weblate (Italian)
Currently translated at 100.0% (362 of 362 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/it/
2020-09-27 17:15:30 +02:00
Koldo Almandoz Forcen 5c6f727c4b Translated using Weblate (Basque)
Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/eu/
2020-09-27 01:40:50 +02:00
Anonymous 4bbb75a6a3 Translated using Weblate (Basque)
Currently translated at 37.6% (35 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/eu/
2020-09-27 01:40:50 +02:00
Koldo Almandoz Forcen a2dee15289 Translated using Weblate (Basque)
Currently translated at 37.6% (35 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/eu/
2020-09-27 01:40:50 +02:00
Koldo Almandoz Forcen db59a4b925 Translated using Weblate (Spanish)
Currently translated at 82.2% (144 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/es/
2020-09-27 01:40:49 +02:00
@ALESTHETIC 96aaa6f0e3 Translated using Weblate (Spanish)
Currently translated at 96.4% (537 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/
2020-09-27 01:40:49 +02:00
Koldo Almandoz Forcen 9eb7654a3c Translated using Weblate (Spanish)
Currently translated at 96.4% (537 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/
2020-09-27 01:40:48 +02:00
Anonymous d2902910bd Translated using Weblate (Turkish)
Currently translated at 61.2% (57 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/tr/
2020-09-27 01:40:47 +02:00
Ahmet Burak Baraklı 3a7c9b1c1f Translated using Weblate (Turkish)
Currently translated at 61.2% (57 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/tr/
2020-09-27 01:40:47 +02:00
@ALESTHETIC 6c214df289 Translated using Weblate (Spanish)
Currently translated at 95.8% (534 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/
2020-09-26 23:52:17 +02:00
Koldo Almandoz Forcen c2fe33650c Translated using Weblate (Spanish)
Currently translated at 95.8% (534 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/
2020-09-26 23:52:14 +02:00
Anonymous 53748d62f6 Translated using Weblate (Spanish)
Currently translated at 95.5% (532 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/
2020-09-26 23:48:10 +02:00
Anonymous c0364c0e00 Translated using Weblate (Basque)
Currently translated at 15.0% (14 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/eu/
2020-09-26 22:40:48 +02:00
Koldo Almandoz Forcen 2ccaa02e7e Translated using Weblate (Basque)
Currently translated at 15.0% (14 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/eu/
2020-09-26 22:40:45 +02:00
Anonymous 943bf1442d Translated using Weblate (Basque)
Currently translated at 7.5% (7 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/eu/
2020-09-26 22:36:47 +02:00
Koldo Almandoz Forcen 76f13abee1 Translated using Weblate (Basque)
Currently translated at 7.5% (7 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/eu/
2020-09-26 22:36:45 +02:00
Anonymous 06a0147a97 Translated using Weblate (Basque)
Currently translated at 6.4% (6 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/eu/
2020-09-26 22:35:23 +02:00
そら 03984df562 Translated using Weblate (Japanese)
Currently translated at 96.0% (168 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/
2020-09-26 09:52:29 +02:00
Yowi f95ad1201d Translated using Weblate (Spanish (Latin America))
Currently translated at 85.3% (611 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/es_419/
2020-09-26 05:40:00 +02:00
Yowi 91e311284a Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (1 of 1 strings)

Translation: Habitica/Merch
Translate-URL: https://translate.habitica.com/projects/habitica/merch/es_419/
2020-09-26 05:39:56 +02:00
Benoit Hetru ab554320f3 Translated using Weblate (French)
Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fr/
2020-09-26 05:39:56 +02:00
Bénédicte Botelle e5afb89706 Translated using Weblate (French)
Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/fr/
2020-09-26 05:39:55 +02:00
Yowi 0c1d78acdb Translated using Weblate (Spanish (Latin America))
Currently translated at 100.0% (146 of 146 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/es_419/
2020-09-26 05:39:55 +02:00
Bénédicte Botelle 3361ed1f2d Translated using Weblate (French)
Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/fr/
2020-09-26 05:39:54 +02:00
Benoit Hetru 4d7d8e84c5 Translated using Weblate (French)
Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/fr/
2020-09-26 05:39:53 +02:00
Benoit Hetru 28d3611c4a Translated using Weblate (French)
Currently translated at 100.0% (189 of 189 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/fr/
2020-09-26 05:39:53 +02:00
Benoit Hetru fbb758fa89 Translated using Weblate (French)
Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/
2020-09-26 05:39:52 +02:00
Bénédicte Botelle 40f9651378 Translated using Weblate (French)
Currently translated at 100.0% (557 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/fr/
2020-09-26 05:39:48 +02:00
Benoit Hetru e90041976b Translated using Weblate (French)
Currently translated at 100.0% (557 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/fr/
2020-09-26 05:39:48 +02:00
Sabe Jones 6d737330f2 chore(sprites): compile 2020-09-25 16:06:45 -05:00
Sabe Jones 910c49df4f feat(content): Mystery Items and avatar customizations 2020-09-25 16:06:37 -05:00
Melior 1a46fac7bf Translated using Weblate (French)
Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/fr/

Translated using Weblate (French)

Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/

Translated using Weblate (French)

Currently translated at 100.0% (189 of 189 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/fr/

Translated using Weblate (Japanese)

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/ja/

Translated using Weblate (Japanese)

Currently translated at 96.0% (168 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (146 of 146 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 81.5% (1771 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/
2020-09-25 22:38:13 +02:00
Sabe Jones 6bbdd74927 Merge branch 'release' into develop 2020-09-25 14:47:10 -05:00
Sabe Jones dd4c9c2536 4.160.1 2020-09-25 14:46:14 -05:00
Sabe Jones 0a6b22fdd9 fix(potions): erroneous Ghost overbuy warnings 2020-09-25 14:45:56 -05:00
RaitheOfDureya d940066ea2 Removed unused I18N strings from the pets.json files (related to issue #9957) (#12559)
* Removed unused I18N strings from the `pets.json` file (locales\en)

* Removed unused I18N strings from the `pets.json` file in all the languages

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-09-25 11:49:13 +02:00
RaitheOfDureya 7be3143e55 Removed unused I18N strings from the messages.json files (related to issue #9957) (#12563)
* Removed unused I18N strings from the `messages.json` file (locales\en)

* Removed unused I18N `messages.json` strings from all the other languages

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-09-25 11:47:36 +02:00
RaitheOfDureya b42875e2e1 Removed unused I18N strings from the quests.json files (related to issue #9957) (#12558)
* Removed unused I18N strings from the `quests.json` file (locales/en)

* Remove whereAreMyQuests, yourQuests and getMoreQuests (locales/en)

* Removed unused I18N `quests.json` strings from all the others languages

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-09-25 11:47:17 +02:00
Matteo Pagliazzi 6c6e8f0001 Merge branch 'benkelaar-12482-xml-export' into develop 2020-09-25 11:21:35 +02:00
Matteo Pagliazzi 8219dfd9e6 fix(integration tests): remove duplicate test file 2020-09-25 11:21:24 +02:00
Matteo Pagliazzi 025b994224 Merge branch '12482-xml-export' of https://github.com/benkelaar/habitica into benkelaar-12482-xml-export 2020-09-25 11:20:11 +02:00
Alexandrea Beh b056763f09 Issue 11450 Adding keyboard accessibility to task board controls and purchases (#12363)
* intial draft adding keyboard accessibility to task board controls

* cleanup

* finish adding keyboard accessibility for task dropdown, rewards

* add notEnough conditions to disable purchase button

* fix(lint): remove console.log from buy modal

* add missing comma, use focus-within instead of focus-visible

* missed one more focus visible

* override browser default focus styling

* move focus styling to tasks only

* add rounded border

* fix element height on focus, rounded borders

* fix dropdown margin to avoid element resizing

* styling updates on focus

* fix spacing around task checklist

* fix border around dropdown item

* remove spacing that made tasks with notes jump

* keep disabled habit control styling when not focused

* revert unintended spacing

Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-09-25 10:29:13 +02:00
Bart Enkelaar 6e91326648 fix(dataexport) - 12482 - Extract xml marshalling into library
- Add integration test on dataexport endpoint
- Add library with unit test for xml marshalling
2020-09-25 08:57:05 +02:00
Bart Enkelaar 8b9c76a2b7 fix(12842) - Remove duplication in gulp-tests.js 2020-09-25 08:57:05 +02:00
Bart Enkelaar c4fc2d825d fix(export) - Issue 12482 - Fix messages in xml export. 2020-09-25 08:57:05 +02:00
Melior 411ac94986 Merge branch 'develop' of github.com:HabitRPG/habitica into develop 2020-09-24 21:34:24 +02:00
Jostein Skjånes 8b952a6caf Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (173 of 173 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/nb_NO/
2020-09-24 21:21:28 +02:00
Jostein Skjånes b21bf0d428 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/nb_NO/
2020-09-24 21:21:26 +02:00
Jostein Skjånes 1b5134c0bc Translated using Weblate (Norwegian Bokmål)
Currently translated at 88.5% (124 of 140 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/nb_NO/
2020-09-24 21:21:26 +02:00
Sabe Jones 54ffe1d3b6 4.160.0 2020-09-24 14:13:36 -05:00
Sabe Jones ff77455b00 Merge branch 'sabrecat/vampotions' into release 2020-09-24 14:13:29 -05:00
Jostein Skjånes 22eaefb3b2 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (173 of 173 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/nb_NO/
2020-09-24 15:42:24 +02:00
Anas HARNOUCH b9710c4180 Translated using Weblate (French)
Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fr/
2020-09-24 15:42:23 +02:00
blacksheep47 919b30c237 Translated using Weblate (Chinese (Simplified))
Currently translated at 97.8% (185 of 189 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/zh_Hans/
2020-09-24 15:42:22 +02:00
Anas HARNOUCH 9a51d200f7 Translated using Weblate (French)
Currently translated at 100.0% (189 of 189 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/fr/
2020-09-24 15:42:22 +02:00
Bénédicte Botelle 170df77c3d Translated using Weblate (French)
Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/
2020-09-24 15:42:21 +02:00
Anas HARNOUCH 043f34d619 Translated using Weblate (French)
Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/
2020-09-24 15:42:21 +02:00
Kitty Kat 0b20f8a980 Translated using Weblate (Hindi)
Currently translated at 75.7% (422 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/hi/
2020-09-24 06:30:57 +02:00
そら 7f208eb141 Translated using Weblate (Japanese)
Currently translated at 96.0% (168 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ja/
2020-09-24 06:30:56 +02:00
Melior 75a196dd3b Translated using Weblate (Hindi)
Currently translated at 11.8% (39 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/hi/

Translated using Weblate (Chinese (Hong Kong))

Currently translated at 100.0% (15 of 15 strings)

Translation: Habitica/Death
Translate-URL: https://translate.habitica.com/projects/habitica/death/zh_Hant_HK/

Translated using Weblate (Hungarian)

Currently translated at 31.1% (29 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/hu/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (146 of 146 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (173 of 173 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 67.4% (118 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (28 of 28 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 86.8% (622 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (27 of 27 strings)

Translation: Habitica/Loginincentives
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (70 of 70 strings)

Translation: Habitica/Contrib
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (362 of 362 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/nb_NO/

Translated using Weblate (Dutch)

Currently translated at 98.6% (2141 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 36.3% (53 of 146 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 2.4% (8 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 80.3% (45 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 78.2% (436 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (67 of 67 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (27 of 27 strings)

Translation: Habitica/Loginincentives
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (189 of 189 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 78.4% (1703 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (63 of 63 strings)

Translation: Habitica/Defaulttasks
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (4 of 4 strings)

Translation: Habitica/Noscript
Translate-URL: https://translate.habitica.com/projects/habitica/noscript/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 75.5% (421 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (189 of 189 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (6 of 6 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 78.4% (1703 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (15 of 15 strings)

Translation: Habitica/Death
Translate-URL: https://translate.habitica.com/projects/habitica/death/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (70 of 70 strings)

Translation: Habitica/Contrib
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/nb_NO/

Translated using Weblate (Spanish (Latin America))

Currently translated at 81.5% (1771 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Japanese)

Currently translated at 99.0% (499 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ja/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 75.5% (421 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 75.5% (421 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/nb_NO/

Translated using Weblate (Italian)

Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/it/

Translated using Weblate (French)

Currently translated at 98.8% (173 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fr/

Translated using Weblate (Italian)

Currently translated at 100.0% (189 of 189 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/it/

Translated using Weblate (Italian)

Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/

Translated using Weblate (Italian)

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/it/

Translated using Weblate (Hindi)

Currently translated at 11.8% (39 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/hi/

Translated using Weblate (Russian)

Currently translated at 91.4% (160 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ru/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/

Translated using Weblate (German)

Currently translated at 100.0% (175 of 175 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/de/

Translated using Weblate (Spanish (Latin America))

Currently translated at 81.5% (1771 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Russian)

Currently translated at 98.4% (186 of 189 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ru/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (189 of 189 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/pt_BR/

Translated using Weblate (German)

Currently translated at 100.0% (189 of 189 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/de/

Translated using Weblate (Russian)

Currently translated at 94.6% (2054 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ru/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2171 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/

Translated using Weblate (German)

Currently translated at 99.5% (2162 of 2171 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/

Translated using Weblate (Russian)

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ru/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/pt_BR/

Translated using Weblate (French)

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/fr/

Translated using Weblate (German)

Currently translated at 100.0% (180 of 180 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/de/
2020-09-24 02:59:26 +02:00
Sabe Jones 701a6170a3 chore(sprites): compile 2020-09-23 14:09:49 -05:00
Sabe Jones ee70ed6146 feat(content): Vampire Hatching Potions 2020-09-23 14:09:38 -05:00
RaitheOfDureya d45a6f260d Removed unused I18N loginIncentives.json strings from all languages (#12566) 2020-09-23 17:44:39 +02:00
RaitheOfDureya de09e56f67 Removed unused I18N strings from all limited.json files (#12567)
Co-authored-by: Matteo Pagliazzi <matteopagliazzi@gmail.com>
2020-09-22 22:14:49 +02:00
Matteo Pagliazzi 17b520de12 Merge branch 'RaitheOfDureya-remove-unused-maintenance' into develop 2020-09-22 21:56:32 +02:00
Matteo Pagliazzi 0655e2e0a0 Merge branch 'remove-unused-maintenance' of https://github.com/RaitheOfDureya/habitica into RaitheOfDureya-remove-unused-maintenance 2020-09-22 21:56:20 +02:00
RaitheOfDureya bcf489f847 Removed unused I18N strings from the merch.json files (related to issue #9957) (#12564)
* Removed unused I18N strings from the `merch.json` file (locales\en)

* Removed unused I18N `merch.json` strings from all the other languages
2020-09-22 20:05:58 +02:00
RaitheOfDureya adc2207249 Removed unused I18N strings from the noscript.json files (related to issue #9957) (#12562)
* Removed unused I18N strings from the `nostring.json` file (locales\en)

* Removed unused I18N `noscript.json` strings from all the others languages
2020-09-22 20:03:41 +02:00
Matteo Pagliazzi 1c205a96fb Merge branch 'RaitheOfDureya-remove-unused-npc' into develop 2020-09-22 20:01:01 +02:00
Matteo Pagliazzi 8e2bbbd570 Merge branch 'remove-unused-npc' of https://github.com/RaitheOfDureya/habitica into RaitheOfDureya-remove-unused-npc 2020-09-22 20:00:51 +02:00
Matteo Pagliazzi 13d1f1b48b Merge #12553 - Removed unused I18N strings from the rebirth.json files
Squashed commit of the following:

commit 9de806e00296e9e8659ccde25085eb3b8a6639c4
Merge: 7c4faf8b7a 7361029289
Author: Matteo Pagliazzi <matteopagliazzi@gmail.com>
Date:   Tue Sep 22 19:52:09 2020 +0200

    Merge branch 'remove-unused-rebirth' of https://github.com/RaitheOfDureya/habitica into RaitheOfDureya-remove-unused-rebirth

commit 7361029289
Author: Raithe Of Dureya <raitheofdureya@gmail.com>
Date:   Fri Sep 11 13:43:59 2020 +0200

    Removed `rebirth.json`'s unused I18N strings from other languages

commit acd7786580
Author: Raithe Of Dureya <raitheofdureya@gmail.com>
Date:   Tue Sep 8 20:47:59 2020 +0200

    Removed unused I18N strings from the `rebirth.json` file (locales/en)
2020-09-22 19:52:55 +02:00
Bart Enkelaar 7c4faf8b7a fix(chat) - issue 12586 - can't put links without titles in message boxes (#12594) 2020-09-22 19:28:37 +02:00
Melior 82be621850 Merge branch 'origin/develop' into Weblate. 2020-09-22 17:07:35 +02:00
Sabe Jones 265fb7c5f6 Merge branch 'release' into develop 2020-09-22 09:49:49 -05:00
Sabe Jones cfa4d03e45 4.159.1 2020-09-22 09:49:16 -05:00
Sabe Jones f28c5a563a fix(news): missing Bailey paragraph 2020-09-22 09:48:58 -05:00
Matteo Pagliazzi 0455f08ec5 fix(gem icon): update gem icon 2020-09-22 16:46:27 +02:00
Matteo Pagliazzi 48193dce59 Revert "Revert "fix(gem icon in menu): add hover animation""
This reverts commit ffe8d34acb.
2020-09-22 16:39:01 +02:00
Matteo Pagliazzi ffe8d34acb Revert "fix(gem icon in menu): add hover animation"
This reverts commit 74428d0727.
2020-09-22 16:35:47 +02:00
Melior 29a278d0bc Merge branch 'origin/develop' into Weblate. 2020-09-22 16:17:25 +02:00
Melior 2fb9dfe909 Translated using Weblate (Norwegian Bokmål)
Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 78.5% (44 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (362 of 362 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/nb_NO/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/zh_Hans/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 98.2% (55 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 71.4% (40 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 86.8% (622 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (173 of 173 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (230 of 230 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 88.0% (118 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (28 of 28 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 86.8% (622 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (67 of 67 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (31 of 31 strings)

Translation: Habitica/Maintenance
Translate-URL: https://translate.habitica.com/projects/habitica/maintenance/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (185 of 185 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (6 of 6 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (63 of 63 strings)

Translation: Habitica/Defaulttasks
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (15 of 15 strings)

Translation: Habitica/Death
Translate-URL: https://translate.habitica.com/projects/habitica/death/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 84.8% (307 of 362 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 91.5% (194 of 212 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 93.0% (161 of 173 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 67.8% (38 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 86.8% (622 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 7.5% (11 of 146 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 90.7% (157 of 173 strings)

Translation: Habitica/Npc
Translate-URL: https://translate.habitica.com/projects/habitica/npc/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 64.2% (36 of 56 strings)

Translation: Habitica/Faq
Translate-URL: https://translate.habitica.com/projects/habitica/faq/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (230 of 230 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 88.0% (118 of 134 strings)

Translation: Habitica/Tasks
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 86.8% (622 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 86.4% (121 of 140 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (8 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (67 of 67 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (27 of 27 strings)

Translation: Habitica/Loginincentives
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 83.3% (5 of 6 strings)

Translation: Habitica/Inventory
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 99.8% (500 of 501 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (298 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 79.5% (1703 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nb_NO/

Translated using Weblate (Norwegian Bokmål)

Currently translated at 100.0% (124 of 124 strings)

Translation: Habitica/Communityguidelines
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/nb_NO/

Translated using Weblate (Spanish (Latin America))

Currently translated at 87.5% (7 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (28 of 28 strings)

Translation: Habitica/Rebirth
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 82.7% (1771 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (362 of 362 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/zh_Hans/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (716 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hans/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (56 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (146 of 146 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 87.5% (7 of 8 strings)

Translation: Habitica/Overview
Translate-URL: https://translate.habitica.com/projects/habitica/overview/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 82.7% (1771 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Korean)

Currently translated at 73.1% (68 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ko/

Translated using Weblate (Korean)

Currently translated at 73.1% (68 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ko/

Translated using Weblate (Spanish (Latin America))

Currently translated at 82.7% (1771 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Korean)

Currently translated at 95.3% (284 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/ko/

Translated using Weblate (Korean)

Currently translated at 95.3% (284 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/ko/

Translated using Weblate (Korean)

Currently translated at 97.3% (224 of 230 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/ko/

Translated using Weblate (Korean)

Currently translated at 96.3% (287 of 298 strings)

Translation: Habitica/Generic
Translate-URL: https://translate.habitica.com/projects/habitica/generic/ko/

Translated using Weblate (Korean)

Currently translated at 52.7% (77 of 146 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ko/

Translated using Weblate (Korean)

Currently translated at 100.0% (230 of 230 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/ko/

Translated using Weblate (Korean)

Currently translated at 100.0% (134 of 134 strings)

Translation: Habitica/Challenge
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/ko/

Translated using Weblate (Korean)

Currently translated at 67.7% (63 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ko/

Translated using Weblate (Spanish (Latin America))

Currently translated at 82.7% (1771 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 82.7% (1771 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (French)

Currently translated at 100.0% (557 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/fr/

Translated using Weblate (Swedish)

Currently translated at 66.4% (123 of 185 strings)

Translation: Habitica/Limited
Translate-URL: https://translate.habitica.com/projects/habitica/limited/sv/

Translated using Weblate (Swedish)

Currently translated at 83.6% (1792 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/sv/

Translated using Weblate (Swedish)

Currently translated at 92.1% (513 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/sv/

Translated using Weblate (Spanish (Latin America))

Currently translated at 82.7% (1771 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (230 of 230 strings)

Translation: Habitica/Character
Translate-URL: https://translate.habitica.com/projects/habitica/character/es_419/

Translated using Weblate (Hindi)

Currently translated at 97.8% (91 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/hi/
2020-09-22 16:12:26 +02:00
Sabe Jones 8ca369f937 Merge branch 'release' into develop 2020-09-22 09:10:11 -05:00
Sabe Jones 12c7fb7b27 4.159.0 2020-09-22 09:09:51 -05:00
Sabe Jones 2428347836 chore(news): Bailey 2020-09-22 09:09:43 -05:00
Sabe Jones 5aab13b28b Merge branch 'sabrecat/fall-2020' into release 2020-09-22 09:00:21 -05:00
Matteo Pagliazzi caa02141b8 Merge branch 'release' into develop 2020-09-22 15:53:28 +02:00
Matteo Pagliazzi 74428d0727 fix(gem icon in menu): add hover animation 2020-09-22 15:53:05 +02:00
Sabe Jones 0a15c0f1d8 fix(event): various content corrections 2020-09-21 19:59:13 -05:00
Sabe Jones 3aa58398b7 chore(sprites): compile 2020-09-21 14:34:45 -05:00
Sabe Jones 9450f9ee1d feat(event): Fall Festival 2020 2020-09-21 14:34:38 -05:00
dependabot-preview[bot] a1cea3b584 build(deps): bump @google-cloud/trace-agent from 5.1.0 to 5.1.1 (#12595)
Bumps [@google-cloud/trace-agent](https://github.com/googleapis/cloud-trace-nodejs) from 5.1.0 to 5.1.1.
- [Release notes](https://github.com/googleapis/cloud-trace-nodejs/releases)
- [Changelog](https://github.com/googleapis/cloud-trace-nodejs/blob/master/CHANGELOG.md)
- [Commits](https://github.com/googleapis/cloud-trace-nodejs/compare/v5.1.0...v5.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-09-21 17:19:12 +02:00
dependabot-preview[bot] 1b260aee52 build(deps): bump got from 11.6.2 to 11.7.0 (#12597)
Bumps [got](https://github.com/sindresorhus/got) from 11.6.2 to 11.7.0.
- [Release notes](https://github.com/sindresorhus/got/releases)
- [Commits](https://github.com/sindresorhus/got/compare/v11.6.2...v11.7.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-09-21 17:19:04 +02:00
dependabot-preview[bot] f2182428e5 build(deps): bump validator from 13.1.1 to 13.1.17 (#12598)
Bumps [validator](https://github.com/chriso/validator.js) from 13.1.1 to 13.1.17.
- [Release notes](https://github.com/chriso/validator.js/releases)
- [Changelog](https://github.com/validatorjs/validator.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/chriso/validator.js/compare/13.1.1...13.1.17)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-09-21 17:18:46 +02:00
dependabot-preview[bot] 996b8f67c5 build(deps): bump sass from 1.26.10 to 1.26.11 in /website/client (#12600)
Bumps [sass](https://github.com/sass/dart-sass) from 1.26.10 to 1.26.11.
- [Release notes](https://github.com/sass/dart-sass/releases)
- [Changelog](https://github.com/sass/dart-sass/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sass/dart-sass/compare/1.26.10...1.26.11)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-09-21 17:18:38 +02:00
dependabot-preview[bot] b297b2a48a build(deps): bump validator from 13.1.1 to 13.1.17 in /website/client (#12601)
Bumps [validator](https://github.com/chriso/validator.js) from 13.1.1 to 13.1.17.
- [Release notes](https://github.com/chriso/validator.js/releases)
- [Changelog](https://github.com/validatorjs/validator.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/chriso/validator.js/compare/13.1.1...13.1.17)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>

Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com>
2020-09-21 17:18:24 +02:00
Matteo Pagliazzi 74eab5bba9 Merge pull request #12603 from HabitRPG/dependabot/npm_and_yarn/website/client/bootstrap-vue-2.17.3
build(deps): bump bootstrap-vue from 2.17.0 to 2.17.3 in /website/client
2020-09-21 17:17:59 +02:00
Matteo Pagliazzi 87504f4d76 Merge pull request #12602 from HabitRPG/dependabot/npm_and_yarn/website/client/webpack-4.44.2
build(deps): bump webpack from 4.44.1 to 4.44.2 in /website/client
2020-09-21 17:17:49 +02:00
Matteo Pagliazzi 58a73dd62a 4.158.0 2020-09-21 16:27:24 +02:00
Matteo Pagliazzi 83aca20ce5 Fall Festival Gem Promo (#138)
* content: add gems blocks

* gemsBlocks: include ios and android identifiers

* wip: promo code

* split common constants into multiple files

* add second promo part

* geCurrentEvent, refactor promo

* fix lint

* fix exports, use world state api

* start adding world state tests

* remove console.log

* use gems block for purchases

* remove comments

* fix most unit tests

* restore comment

* fix lint

* prevent apple/google gift tests from breaking other tests when stub is not reset

* fix unit tests, clarify tests names

* iap: use gift object when gifting gems

* allow gift object with less data

* fix iap tests, remove findById stubs

* iap: require less data from the mobile apps

* apply discounts

* add missing worldState file

* fix lint

* add test event

* start removing 20 gems option for web

* start adding support for all gems packages on web

* fix unit tests for apple, stripe and google

* amazon: support all gems blocks

* paypal: support all gems blocks

* fix payments unit tests, add tests for getGemsBlock

* web: add gems plans with discounts, update stripe

* fix amazon and paypal clients, payments success modals

* amazon pay: disabled state

* update icons, start abstracting payments buttons

* begin redesign

* redesign gems modal

* fix buttons

* fix hover color for gems modal close icon

* add key to world state current event

* extend test event length

* implement gems modals designs

* early test fall2020

* fix header banner position

* add missing files

* use iso 8601 for dates, minor ui fixes

* fix time zones

* events: fix ISO8601 format

* fix css indentation

* start abstracting banners

* refactor payments buttons

* test spooky, fix group plans box

* implement gems promo banners, refactor banners, fixes

* fix lint

* fix dates

* remove unused i18n strings

* fix stripe integration test

* fix world state integration tests

* the current active event

* add missing unit tests

* add storybook story for payments buttons component

* fix typo

* fix(stripe): correct label when gifting subscriptions
2020-09-21 16:22:13 +02:00
dependabot-preview[bot] cd11d4c179 build(deps): bump bootstrap-vue from 2.17.0 to 2.17.3 in /website/client
Bumps [bootstrap-vue](https://github.com/bootstrap-vue/bootstrap-vue) from 2.17.0 to 2.17.3.
- [Release notes](https://github.com/bootstrap-vue/bootstrap-vue/releases)
- [Changelog](https://github.com/bootstrap-vue/bootstrap-vue/blob/dev/CHANGELOG.md)
- [Commits](https://github.com/bootstrap-vue/bootstrap-vue/compare/v2.17.0...v2.17.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-21 08:25:12 +00:00
dependabot-preview[bot] e821fab4a3 build(deps): bump webpack from 4.44.1 to 4.44.2 in /website/client
Bumps [webpack](https://github.com/webpack/webpack) from 4.44.1 to 4.44.2.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v4.44.1...v4.44.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-21 08:24:14 +00:00
Matteo Pagliazzi 82e6d544c8 fix(i18n) restore missing strings 2020-09-21 09:42:18 +02:00
Matteo Pagliazzi 70661da94d fix(settings.json): add back resetAccount string 2020-09-19 15:45:23 +02:00
Melior 069a133546 Merge branch 'origin/develop' into Weblate. 2020-09-17 22:40:48 +02:00
Melior 1aca81d15d Translated using Weblate (Dutch)
Currently translated at 100.0% (2141 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/

Translated using Weblate (Czech)

Currently translated at 89.3% (1913 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/cs/

Translated using Weblate (Hindi)

Currently translated at 11.5% (38 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/hi/

Translated using Weblate (Hindi)

Currently translated at 98.2% (55 of 56 strings)

Translation: Habitica/Spells
Translate-URL: https://translate.habitica.com/projects/habitica/spells/hi/

Translated using Weblate (Hindi)

Currently translated at 85.9% (311 of 362 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/hi/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (67 of 67 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (146 of 146 strings)

Translation: Habitica/Pets
Translate-URL: https://translate.habitica.com/projects/habitica/pets/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (63 of 63 strings)

Translation: Habitica/Defaulttasks
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (63 of 63 strings)

Translation: Habitica/Defaulttasks
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 96.5% (538 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 93.6% (59 of 63 strings)

Translation: Habitica/Defaulttasks
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 93.6% (59 of 63 strings)

Translation: Habitica/Defaulttasks
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 74.6% (47 of 63 strings)

Translation: Habitica/Defaulttasks
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 74.6% (47 of 63 strings)

Translation: Habitica/Defaulttasks
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (67 of 67 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/es_419/

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (67 of 67 strings)

Translation: Habitica/Messages
Translate-URL: https://translate.habitica.com/projects/habitica/messages/es_419/

Translated using Weblate (Hindi)

Currently translated at 10.9% (36 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/hi/

Translated using Weblate (Hindi)

Currently translated at 10.3% (34 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/hi/

Translated using Weblate (French)

Currently translated at 100.0% (173 of 173 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fr/

Translated using Weblate (French)

Currently translated at 100.0% (504 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/fr/

Translated using Weblate (French)

Currently translated at 100.0% (716 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/

Translated using Weblate (French)

Currently translated at 100.0% (362 of 362 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/fr/

Translated using Weblate (French)

Currently translated at 100.0% (179 of 179 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/fr/

Translated using Weblate (French)

Currently translated at 98.8% (708 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/

Translated using Weblate (French)

Currently translated at 98.8% (708 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/

Translated using Weblate (French)

Currently translated at 98.4% (705 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/

Translated using Weblate (French)

Currently translated at 98.4% (705 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/

Translated using Weblate (French)

Currently translated at 98.3% (704 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/

Translated using Weblate (Dutch)

Currently translated at 99.9% (2139 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/

Translated using Weblate (Spanish (Latin America))

Currently translated at 98.4% (323 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/es_419/

Translated using Weblate (Japanese)

Currently translated at 98.2% (547 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ja/

Translated using Weblate (Hindi)

Currently translated at 96.7% (90 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/hi/

Translated using Weblate (German)

Currently translated at 100.0% (2141 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/

Translated using Weblate (German)

Currently translated at 100.0% (716 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/

Translated using Weblate (Ukrainian)

Currently translated at 38.7% (36 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Ukrainian)

Currently translated at 38.7% (36 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Russian)

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ru/

Translated using Weblate (Russian)

Currently translated at 100.0% (93 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ru/

Translated using Weblate (German)

Currently translated at 100.0% (2141 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/de/

Translated using Weblate (Ukrainian)

Currently translated at 29.0% (27 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Ukrainian)

Currently translated at 29.0% (27 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Ukrainian)

Currently translated at 27.9% (26 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Ukrainian)

Currently translated at 27.9% (26 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Ukrainian)

Currently translated at 24.7% (23 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Ukrainian)

Currently translated at 24.7% (23 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/

Translated using Weblate (Hindi)

Currently translated at 75.5% (421 of 557 strings)

Translation: Habitica/Backgrounds
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/hi/

Translated using Weblate (Hindi)

Currently translated at 85.7% (120 of 140 strings)

Translation: Habitica/Quests
Translate-URL: https://translate.habitica.com/projects/habitica/quests/hi/

Translated using Weblate (Hindi)

Currently translated at 92.4% (86 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/hi/

Translated using Weblate (Hindi)

Currently translated at 79.4% (1701 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/hi/

Translated using Weblate (Hindi)

Currently translated at 90.3% (84 of 93 strings)

Translation: Habitica/Achievements
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/hi/

Translated using Weblate (Hindi)

Currently translated at 3.9% (13 of 328 strings)

Translation: Habitica/Front
Translate-URL: https://translate.habitica.com/projects/habitica/front/hi/

Translated using Weblate (Spanish (Latin America))

Currently translated at 80.9% (1734 of 2141 strings)

Translation: Habitica/Gear
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es_419/

Translated using Weblate (Italian)

Currently translated at 100.0% (504 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/it/

Translated using Weblate (Italian)

Currently translated at 100.0% (716 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/it/

Translated using Weblate (Italian)

Currently translated at 100.0% (362 of 362 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/it/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (173 of 173 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/zh_Hans/

Translated using Weblate (Russian)

Currently translated at 92.4% (160 of 173 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ru/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (173 of 173 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/

Translated using Weblate (German)

Currently translated at 100.0% (173 of 173 strings)

Translation: Habitica/Subscriber
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/de/

Translated using Weblate (Russian)

Currently translated at 97.8% (493 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/ru/

Translated using Weblate (German)

Currently translated at 100.0% (504 of 504 strings)

Translation: Habitica/Groups
Translate-URL: https://translate.habitica.com/projects/habitica/groups/de/

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.0% (709 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hans/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (716 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/

Translated using Weblate (German)

Currently translated at 99.0% (709 of 716 strings)

Translation: Habitica/Questscontent
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/de/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (362 of 362 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/zh_Hans/

Translated using Weblate (Russian)

Currently translated at 99.7% (361 of 362 strings)

Translation: Habitica/Content
Translate-URL: https://translate.habitica.com/projects/habitica/content/ru/

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (179 of 179 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/zh_Hans/

Translated using Weblate (Russian)

Currently translated at 100.0% (179 of 179 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/ru/

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (179 of 179 strings)

Translation: Habitica/Settings
Translate-URL: https://translate.habitica.com/projects/habitica/settings/pt_BR/
2020-09-17 20:06:09 +02:00
Raithe Of Dureya bf014ad781 Removed all maintenance.json files since no I18N string is being used 2020-09-14 15:57:04 +02:00
Raithe Of Dureya b1fc88d330 Removed unused I18N npc.json strings from all the other languages 2020-09-14 15:08:51 +02:00
Raithe Of Dureya 1e54a474b1 Removed unused I18N strings from the npc.json file (locales\en) 2020-09-14 14:46:45 +02:00
2239 changed files with 53777 additions and 91557 deletions
+1 -2
View File
@@ -1,2 +1 @@
https://github.com/heroku/heroku-buildpack-nodejs.git
https://github.com/stomita/heroku-buildpack-phantomjs.git
https://github.com/heroku/heroku-buildpack-nodejs.git
+9 -9
View File
@@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
node-version: [14.x]
steps:
- uses: actions/checkout@v1
with:
@@ -28,7 +28,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
node-version: [14.x]
steps:
- uses: actions/checkout@v1
with:
@@ -49,7 +49,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
node-version: [14.x]
steps:
- uses: actions/checkout@v1
with:
@@ -71,7 +71,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
node-version: [14.x]
steps:
- uses: actions/checkout@v1
with:
@@ -92,7 +92,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
node-version: [14.x]
steps:
- uses: actions/checkout@v1
with:
@@ -114,7 +114,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
node-version: [14.x]
mongodb-version: [4.2]
steps:
- uses: actions/checkout@v1
@@ -143,7 +143,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
node-version: [14.x]
mongodb-version: [4.2]
steps:
- uses: actions/checkout@v1
@@ -172,7 +172,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
node-version: [14.x]
mongodb-version: [4.2]
steps:
- uses: actions/checkout@v1
@@ -202,7 +202,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x]
node-version: [14.x]
steps:
- uses: actions/checkout@v1
with:
+1 -1
View File
@@ -1 +1 @@
12
14
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:12
FROM node:14
ENV ADMIN_EMAIL admin@habitica.com
ENV EMAILS_COMMUNITY_MANAGER_EMAIL admin@habitica.com
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:12
FROM node:14
# Install global packages
RUN npm install -g gulp-cli mocha
+1
View File
@@ -71,6 +71,7 @@
"SLACK_URL": "https://hooks.slack.com/services/some-url",
"STRIPE_API_KEY": "aaaabbbbccccddddeeeeffff00001111",
"STRIPE_PUB_KEY": "22223333444455556666777788889999",
"STRIPE_WEBHOOKS_ENDPOINT_SECRET": "111111",
"TRANSIFEX_SLACK_CHANNEL": "transifex",
"WEB_CONCURRENCY": 1,
"SKIP_SSL_CHECK_KEY": "key",
+41 -103
View File
@@ -3,9 +3,7 @@ import { exec } from 'child_process';
import gulp from 'gulp';
import os from 'os';
import nconf from 'nconf';
import {
pipe,
} from './taskHelper';
import { pipe } from './taskHelper';
import {
getDevelopmentConnectionUrl,
getDefaultConnectionOptions,
@@ -21,15 +19,16 @@ const TEST_DB_URI = nconf.get('TEST_DB_URI');
const SANITY_TEST_COMMAND = 'npm run test:sanity';
const COMMON_TEST_COMMAND = 'npm run test:common';
const CONTENT_TEST_COMMAND = 'npm run test:content';
const CONTENT_OPTIONS = { maxBuffer: 1024 * 500 };
const LIMIT_MAX_BUFFER_OPTIONS = { maxBuffer: 1024 * 500 };
/* Helper methods for reporting test summary */
/* Helper method for reporting test summary */
const testResults = [];
const testCount = (stdout, regexp) => {
const match = stdout.match(regexp);
return parseInt(match && (match[1] || 0), 10);
};
/* Helper methods to correctly run child test processes */
const testBin = (string, additionalEnvVariables = '') => {
if (os.platform() === 'win32') {
if (additionalEnvVariables !== '') {
@@ -41,6 +40,15 @@ const testBin = (string, additionalEnvVariables = '') => {
return `NODE_ENV=test ${additionalEnvVariables} ${string}`;
};
function runInChildProcess (command, options = {}, envVariables = '') {
return done => pipe(exec(testBin(command, envVariables), options, done));
}
function integrationTestCommand (testDir, coverageDir) {
return `istanbul cover --dir coverage/${coverageDir} --report lcovonly node_modules/mocha/bin/_mocha -- ${testDir} --recursive --require ./test/helpers/start-server`;
}
/* Test task definitions */
gulp.task('test:nodemon', gulp.series(done => {
process.env.PORT = TEST_SERVER_PORT; // eslint-disable-line no-process-env
process.env.NODE_DB_URI = TEST_DB_URI; // eslint-disable-line no-process-env
@@ -82,31 +90,9 @@ gulp.task('test:prepare', gulp.series(
done => done(),
));
gulp.task('test:sanity', cb => {
const runner = exec(
testBin(SANITY_TEST_COMMAND),
err => {
if (err) {
process.exit(1);
}
cb();
},
);
pipe(runner);
});
gulp.task('test:sanity', runInChildProcess(SANITY_TEST_COMMAND));
gulp.task('test:common', gulp.series('test:prepare:build', cb => {
const runner = exec(
testBin(COMMON_TEST_COMMAND),
err => {
if (err) {
process.exit(1);
}
cb();
},
);
pipe(runner);
}));
gulp.task('test:common', gulp.series('test:prepare:build', runInChildProcess(COMMON_TEST_COMMAND)));
gulp.task('test:common:clean', cb => {
pipe(exec(testBin(COMMON_TEST_COMMAND), () => cb()));
@@ -130,22 +116,11 @@ gulp.task('test:common:safe', gulp.series('test:prepare:build', cb => {
pipe(runner);
}));
gulp.task('test:content', gulp.series('test:prepare:build', cb => {
const runner = exec(
testBin(CONTENT_TEST_COMMAND),
CONTENT_OPTIONS,
err => {
if (err) {
process.exit(1);
}
cb();
},
);
pipe(runner);
}));
gulp.task('test:content', gulp.series('test:prepare:build',
runInChildProcess(CONTENT_TEST_COMMAND, LIMIT_MAX_BUFFER_OPTIONS)));
gulp.task('test:content:clean', cb => {
pipe(exec(testBin(CONTENT_TEST_COMMAND), CONTENT_OPTIONS, () => cb()));
pipe(exec(testBin(CONTENT_TEST_COMMAND), LIMIT_MAX_BUFFER_OPTIONS, () => cb()));
});
gulp.task('test:content:watch', gulp.series('test:content:clean', () => gulp.watch(['common/script/content/**', 'test/**'], gulp.series('test:content:clean', done => done()))));
@@ -153,7 +128,7 @@ gulp.task('test:content:watch', gulp.series('test:content:clean', () => gulp.wat
gulp.task('test:content:safe', gulp.series('test:prepare:build', cb => {
const runner = exec(
testBin(CONTENT_TEST_COMMAND),
CONTENT_OPTIONS,
LIMIT_MAX_BUFFER_OPTIONS,
(err, stdout) => { // eslint-disable-line handle-callback-err
testResults.push({
suite: 'Content Specs\t',
@@ -167,76 +142,39 @@ gulp.task('test:content:safe', gulp.series('test:prepare:build', cb => {
pipe(runner);
}));
gulp.task('test:api:unit:run', done => {
const runner = exec(
testBin('istanbul cover --dir coverage/api-unit node_modules/mocha/bin/_mocha -- test/api/unit --recursive --require ./test/helpers/start-server'),
err => {
if (err) {
process.exit(1);
}
done();
},
);
pipe(runner);
});
gulp.task('test:api:unit:run',
runInChildProcess(integrationTestCommand('test/api/unit', 'coverage/api-unit')));
gulp.task('test:api:unit:watch', () => gulp.watch(['website/server/libs/*', 'test/api/unit/**/*', 'website/server/controllers/**/*'], gulp.series('test:api:unit:run', done => done())));
gulp.task('test:api-v3:integration', gulp.series('test:prepare:mongo', done => {
const runner = exec(
testBin('istanbul cover --dir coverage/api-v3-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v3/integration --recursive --require ./test/helpers/start-server'),
{ maxBuffer: 500 * 1024 },
err => {
if (err) {
process.exit(1);
}
done();
},
);
pipe(runner);
}));
gulp.task('test:api-v3:integration', gulp.series('test:prepare:mongo',
runInChildProcess(
integrationTestCommand('test/api/v3/integration', 'coverage/api-v3-integration'),
LIMIT_MAX_BUFFER_OPTIONS,
)));
gulp.task('test:api-v3:integration:watch', () => gulp.watch([
'website/server/controllers/api-v3/**/*', 'common/script/ops/*', 'website/server/libs/*.js',
'test/api/v3/integration/**/*',
], gulp.series('test:api-v3:integration', done => done())));
gulp.task('test:api-v3:integration:separate-server', done => {
const runner = exec(
testBin('mocha test/api/v3/integration --recursive --require ./test/helpers/start-server', 'LOAD_SERVER=0'),
{ maxBuffer: 500 * 1024 },
err => done(err),
);
gulp.task('test:api-v3:integration:separate-server', runInChildProcess(
'mocha test/api/v3/integration --recursive --require ./test/helpers/start-server',
LIMIT_MAX_BUFFER_OPTIONS,
'LOAD_SERVER=0',
));
pipe(runner);
});
gulp.task('test:api-v4:integration', gulp.series('test:prepare:mongo',
runInChildProcess(
integrationTestCommand('test/api/v4', 'api-v4-integration'),
LIMIT_MAX_BUFFER_OPTIONS,
)));
gulp.task('test:api-v4:integration', gulp.series('test:prepare:mongo', done => {
const runner = exec(
testBin('istanbul cover --dir coverage/api-v4-integration --report lcovonly node_modules/mocha/bin/_mocha -- test/api/v4 --recursive --require ./test/helpers/start-server'),
{ maxBuffer: 500 * 1024 },
err => {
if (err) {
process.exit(1);
}
done();
},
);
pipe(runner);
}));
gulp.task('test:api-v4:integration:separate-server', done => {
const runner = exec(
testBin('mocha test/api/v4 --recursive --require ./test/helpers/start-server', 'LOAD_SERVER=0'),
{ maxBuffer: 500 * 1024 },
err => done(err),
);
pipe(runner);
});
gulp.task('test:api-v4:integration:separate-server', runInChildProcess(
'mocha test/api/v4 --recursive --require ./test/helpers/start-server',
LIMIT_MAX_BUFFER_OPTIONS,
'LOAD_SERVER=0',
));
gulp.task('test:api:unit', gulp.series(
'test:prepare:mongo',
@@ -0,0 +1,82 @@
/* eslint-disable no-console */
const MIGRATION_NAME = '20201020_pet_color_achievements';
import { model as User } from '../../../website/server/models/user';
const progressCount = 1000;
let count = 0;
async function updateUser (user) {
count++;
const set = {
migration: MIGRATION_NAME,
};
if (user && user.items && user.items.pets) {
const pets = user.items.pets;
if (pets['Wolf-Golden'] > 0
&& pets['TigerCub-Skeleton'] > 0
&& pets['PandaCub-Skeleton'] > 0
&& pets['LionCub-Skeleton'] > 0
&& pets['Fox-Skeleton'] > 0
&& pets['FlyingPig-Skeleton'] > 0
&& pets['Dragon-Skeleton'] > 0
&& pets['Cactus-Skeleton'] > 0
&& pets['BearCub-Skeleton'] > 0) {
set['achievements.boneCollector'] = true;
}
}
if (user && user.items && user.items.mounts) {
const mounts = user.items.mounts;
if (mounts['Wolf-Skeleton']
&& mounts['TigerCub-Skeleton']
&& mounts['PandaCub-Skeleton']
&& mounts['LionCub-Skeleton']
&& mounts['Fox-Skeleton']
&& mounts['FlyingPig-Skeleton']
&& mounts['Dragon-Skeleton']
&& mounts['Cactus-Skeleton']
&& mounts['BearCub-Skeleton'] ) {
set['achievements.skeletonCrew'] = true;
}
}
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
return await User.update({ _id: user._id }, { $set: set }).exec();
}
module.exports = async function processUsers () {
let query = {
migration: { $ne: MIGRATION_NAME },
'auth.timestamps.loggedin': { $gt: new Date('2020-10-01') },
};
const fields = {
_id: 1,
items: 1,
};
while (true) { // eslint-disable-line no-constant-condition
const users = await User // eslint-disable-line no-await-in-loop
.find(query)
.limit(250)
.sort({_id: 1})
.select(fields)
.lean()
.exec();
if (users.length === 0) {
console.warn('All appropriate users found and modified.');
console.warn(`\n${count} users processed\n`);
break;
} else {
query._id = {
$gt: users[users.length - 1]._id,
};
}
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
}
};
@@ -0,0 +1,84 @@
/*
* Award Habitoween ladder items to participants in this month's Habitoween festivities
*/
/* eslint-disable no-console */
const MIGRATION_NAME = '20201029_habitoween_ladder'; // Update when running in future years
import { model as User } from '../../../website/server/models/user';
const progressCount = 1000;
let count = 0;
async function updateUser (user) {
count++;
const set = {};
const inc = {
'items.food.Candy_Skeleton': 1,
'items.food.Candy_Base': 1,
'items.food.Candy_CottonCandyBlue': 1,
'items.food.Candy_CottonCandyPink': 1,
'items.food.Candy_Shade': 1,
'items.food.Candy_White': 1,
'items.food.Candy_Golden': 1,
'items.food.Candy_Zombie': 1,
'items.food.Candy_Desert': 1,
'items.food.Candy_Red': 1,
};
set.migration = MIGRATION_NAME;
if (user && user.items && user.items.mounts && user.items.mounts['JackOLantern-Glow']) {
set['items.pets.JackOLantern-RoyalPurple'] = 5;
} else if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Glow']) {
set['items.mounts.JackOLantern-Glow'] = true;
} else if (user && user.items && user.items.mounts && user.items.mounts['JackOLantern-Ghost']) {
set['items.pets.JackOLantern-Glow'] = 5;
} else if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Ghost']) {
set['items.mounts.JackOLantern-Ghost'] = true;
} else if (user && user.items && user.items.mounts && user.items.mounts['JackOLantern-Base']) {
set['items.pets.JackOLantern-Ghost'] = 5;
} else if (user && user.items && user.items.pets && user.items.pets['JackOLantern-Base']) {
set['items.mounts.JackOLantern-Base'] = true;
} else {
set['items.pets.JackOLantern-Base'] = 5;
}
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
return await User.update({_id: user._id}, {$inc: inc, $set: set}).exec();
}
module.exports = async function processUsers () {
let query = {
migration: {$ne: MIGRATION_NAME},
'auth.timestamps.loggedin': {$gt: new Date('2020-10-01')},
};
const fields = {
_id: 1,
items: 1,
};
while (true) { // eslint-disable-line no-constant-condition
const users = await User // eslint-disable-line no-await-in-loop
.find(query)
.limit(250)
.sort({_id: 1})
.select(fields)
.lean()
.exec();
if (users.length === 0) {
console.warn('All appropriate users found and modified.');
console.warn(`\n${count} users processed\n`);
break;
} else {
query._id = {
$gt: users[users.length - 1],
};
}
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
}
};
@@ -0,0 +1,58 @@
/*
* Fix JackOLantern-Base for users that signed up recently
*/
/* eslint-disable no-console */
const MIGRATION_NAME = '20201102_fix_habitoween'; // Update when running in future years
import { model as User } from '../../../website/server/models/user';
const progressCount = 1000;
let count = 0;
async function updateUser (user) {
count++;
const set = {};
set.migration = MIGRATION_NAME;
set['items.pets.JackOLantern-Base'] = 5;
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
return await User.update({_id: user._id}, {$inc: inc, $set: set}).exec();
}
module.exports = async function processUsers () {
let query = {
migration: {$ne: MIGRATION_NAME},
'auth.timestamps.created': {$gt: new Date('2020-10-26')},
'items.pets.JackOLantern-Base': true,
};
const fields = {
_id: 1,
items: 1,
};
while (true) { // eslint-disable-line no-constant-condition
const users = await User // eslint-disable-line no-await-in-loop
.find(query)
.limit(250)
.sort({_id: 1})
.select(fields)
.lean()
.exec();
if (users.length === 0) {
console.warn('All appropriate users found and modified.');
console.warn(`\n${count} users processed\n`);
break;
} else {
query._id = {
$gt: users[users.length - 1],
};
}
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
}
};
@@ -0,0 +1,62 @@
/*
* All web users should be enrolled in the Drop Cap AB Test
*/
/* eslint-disable no-console */
const MIGRATION_NAME = '20201103_drop_cap_ab_tweaks';
import { model as User } from '../../../website/server/models/user';
const progressCount = 1000;
let count = 0;
async function updateUser (user) {
count++;
const set = {};
set.migration = MIGRATION_NAME;
const testGroup = Math.random();
// Enroll 100% of users, splitting them 50/50
const value = testGroup <= 0.50 ? 'drop-cap-notif-enabled' : 'drop-cap-notif-disabled';
set['_ABtests.dropCapNotif'] = value;
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
return await User.update({_id: user._id}, {$set: set}).exec();
}
module.exports = async function processUsers () {
let query = {
migration: {$ne: MIGRATION_NAME},
'auth.timestamps.loggedin': {$gt: new Date('2020-10-10')},
'_ABtests.dropCapNotif': 'drop-cap-notif-not-enrolled',
};
const fields = {
_id: 1,
_ABtests: 1,
};
while (true) { // eslint-disable-line no-constant-condition
const users = await User // eslint-disable-line no-await-in-loop
.find(query)
.limit(250)
.sort({_id: 1})
.select(fields)
.lean()
.exec();
if (users.length === 0) {
console.warn('All appropriate users found and modified.');
console.warn(`\n${count} users processed\n`);
break;
} else {
query._id = {
$gt: users[users.length - 1],
};
}
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
}
};
@@ -0,0 +1,82 @@
/* eslint-disable no-console */
const MIGRATION_NAME = '20201124_pet_color_achievements';
import { model as User } from '../../../website/server/models/user';
const progressCount = 1000;
let count = 0;
async function updateUser (user) {
count++;
const set = {
migration: MIGRATION_NAME,
};
if (user && user.items && user.items.pets) {
const pets = user.items.pets;
if (pets['Wolf-Red'] > 0
&& pets['TigerCub-Red'] > 0
&& pets['PandaCub-Red'] > 0
&& pets['LionCub-Red'] > 0
&& pets['Fox-Red'] > 0
&& pets['FlyingPig-Red'] > 0
&& pets['Dragon-Red'] > 0
&& pets['Cactus-Red'] > 0
&& pets['BearCub-Red'] > 0) {
set['achievements.seeingRed'] = true;
}
}
if (user && user.items && user.items.mounts) {
const mounts = user.items.mounts;
if (mounts['Wolf-Red']
&& mounts['TigerCub-Red']
&& mounts['PandaCub-Red']
&& mounts['LionCub-Red']
&& mounts['Fox-Red']
&& mounts['FlyingPig-Red']
&& mounts['Dragon-Red']
&& mounts['Cactus-Red']
&& mounts['BearCub-Red'] ) {
set['achievements.redLetterDay'] = true;
}
}
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
return await User.update({ _id: user._id }, { $set: set }).exec();
}
module.exports = async function processUsers () {
let query = {
migration: { $ne: MIGRATION_NAME },
'auth.timestamps.loggedin': { $gt: new Date('2020-11-01') },
};
const fields = {
_id: 1,
items: 1,
};
while (true) { // eslint-disable-line no-constant-condition
const users = await User // eslint-disable-line no-await-in-loop
.find(query)
.limit(250)
.sort({_id: 1})
.select(fields)
.lean()
.exec();
if (users.length === 0) {
console.warn('All appropriate users found and modified.');
console.warn(`\n${count} users processed\n`);
break;
} else {
query._id = {
$gt: users[users.length - 1]._id,
};
}
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
}
};
@@ -0,0 +1,126 @@
/* eslint-disable no-console */
const MIGRATION_NAME = '20201126_harvest_feast';
import { v4 as uuid } from 'uuid';
import { model as User } from '../../../website/server/models/user';
const progressCount = 1000;
let count = 0;
async function updateUser (user) {
count++;
const set = {};
let inc;
let push;
set.migration = MIGRATION_NAME;
if (typeof user.items.gear.owned.head_special_turkeyHelmGilded !== 'undefined') {
inc = {
'items.food.Pie_Base': 1,
'items.food.Pie_CottonCandyBlue': 1,
'items.food.Pie_CottonCandyPink': 1,
'items.food.Pie_Desert': 1,
'items.food.Pie_Golden': 1,
'items.food.Pie_Red': 1,
'items.food.Pie_Shade': 1,
'items.food.Pie_Skeleton': 1,
'items.food.Pie_Zombie': 1,
'items.food.Pie_White': 1,
}
} else if (typeof user.items.gear.owned.armor_special_turkeyArmorBase !== 'undefined') {
set['items.gear.owned.head_special_turkeyHelmGilded'] = false;
set['items.gear.owned.armor_special_turkeyArmorGilded'] = false;
set['items.gear.owned.back_special_turkeyTailGilded'] = false;
push = [
{
type: 'marketGear',
path: 'gear.flat.head_special_turkeyHelmGilded',
_id: uuid(),
},
{
type: 'marketGear',
path: 'gear.flat.armor_special_turkeyArmorGilded',
_id: uuid(),
},
{
type: 'marketGear',
path: 'gear.flat.back_special_turkeyTailGilded',
_id: uuid(),
},
];
} else if (user.items && user.items.mounts && user.items.mounts['Turkey-Gilded']) {
set['items.gear.owned.head_special_turkeyHelmBase'] = false;
set['items.gear.owned.armor_special_turkeyArmorBase'] = false;
set['items.gear.owned.back_special_turkeyTailBase'] = false;
push = [
{
type: 'marketGear',
path: 'gear.flat.head_special_turkeyHelmBase',
_id: uuid(),
},
{
type: 'marketGear',
path: 'gear.flat.armor_special_turkeyArmorBase',
_id: uuid(),
},
{
type: 'marketGear',
path: 'gear.flat.back_special_turkeyTailBase',
_id: uuid(),
},
];
} else if (user.items && user.items.pets && user.items.pets['Turkey-Gilded']) {
set['items.mounts.Turkey-Gilded'] = true;
} else if (user.items && user.items.mounts && user.items.mounts['Turkey-Base']) {
set['items.pets.Turkey-Gilded'] = 5;
} else if (user.items && user.items.pets && user.items.pets['Turkey-Base']) {
set['items.mounts.Turkey-Base'] = true;
} else {
set['items.pets.Turkey-Base'] = 5;
}
if (count % progressCount === 0) console.warn(`${count} ${user._id}`);
if (inc) {
return await User.update({_id: user._id}, {$inc: inc, $set: set}).exec();
} else if (push) {
return await User.update({_id: user._id}, {$set: set, $push: {pinnedItems: {$each: push}}}).exec();
} else {
return await User.update({_id: user._id}, {$set: set}).exec();
}
}
export default async function processUsers () {
let query = {
migration: {$ne: MIGRATION_NAME},
'auth.timestamps.loggedin': {$gt: new Date('2019-11-01')},
};
const fields = {
_id: 1,
items: 1,
};
while (true) { // eslint-disable-line no-constant-condition
const users = await User // eslint-disable-line no-await-in-loop
.find(query)
.limit(250)
.sort({_id: 1})
.select(fields)
.lean()
.exec();
if (users.length === 0) {
console.warn('All appropriate users found and modified.');
console.warn(`\n${count} users processed\n`);
break;
} else {
query._id = {
$gt: users[users.length - 1],
};
}
await Promise.all(users.map(updateUser)); // eslint-disable-line no-await-in-loop
}
};
+869 -1036
View File
File diff suppressed because it is too large Load Diff
+25 -25
View File
@@ -1,26 +1,26 @@
{
"name": "habitica",
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
"version": "4.157.1",
"version": "4.174.0",
"main": "./website/server/index.js",
"dependencies": {
"@babel/core": "^7.11.6",
"@babel/preset-env": "^7.11.5",
"@babel/register": "^7.11.5",
"@google-cloud/trace-agent": "^5.1.0",
"@slack/client": "^4.12.0",
"@babel/core": "^7.12.9",
"@babel/preset-env": "^7.12.7",
"@babel/register": "^7.12.1",
"@google-cloud/trace-agent": "^5.1.1",
"@slack/webhook": "^5.0.3",
"@parse/node-apn": "^4.0.0",
"accepts": "^1.3.5",
"amazon-payments": "^0.2.8",
"amplitude": "^3.5.0",
"amplitude": "^5.1.4",
"apidoc": "^0.25.0",
"apn": "^2.2.0",
"apple-auth": "^1.0.6",
"bcrypt": "^5.0.0",
"body-parser": "^1.18.3",
"compression": "^1.7.4",
"cookie-session": "^1.4.0",
"coupon-code": "^0.4.5",
"csv-stringify": "^5.5.1",
"csv-stringify": "^5.5.3",
"cwait": "^1.1.1",
"domain-middleware": "~0.1.0",
"eslint": "^6.8.0",
@@ -30,27 +30,27 @@
"express-basic-auth": "^1.1.5",
"express-validator": "^5.2.0",
"glob": "^7.1.6",
"got": "^11.6.2",
"got": "^11.8.0",
"gulp": "^4.0.0",
"gulp-babel": "^8.0.0",
"gulp-imagemin": "^7.1.0",
"gulp-nodemon": "^2.5.0",
"gulp.spritesmith": "^6.9.0",
"habitica-markdown": "^3.0.0",
"helmet": "^3.23.3",
"image-size": "^0.9.1",
"helmet": "^4.2.0",
"image-size": "^0.9.3",
"in-app-purchase": "^1.11.3",
"js2xmlparser": "^4.0.1",
"jsonwebtoken": "^8.5.1",
"jwks-rsa": "^1.9.0",
"jwks-rsa": "^1.11.0",
"lodash": "^4.17.20",
"merge-stream": "^2.0.0",
"method-override": "^3.0.0",
"moment": "^2.28.0",
"moment": "^2.29.1",
"moment-recur": "^1.0.7",
"mongoose": "^5.10.3",
"mongoose": "^5.10.18",
"morgan": "^1.10.0",
"nconf": "^0.10.0",
"nconf": "^0.11.0",
"node-gcm": "^1.0.3",
"on-headers": "^1.0.2",
"passport": "^0.4.1",
@@ -60,18 +60,18 @@
"paypal-rest-sdk": "^1.8.1",
"pp-ipn": "^1.1.0",
"ps-tree": "^1.0.0",
"rate-limiter-flexible": "^2.1.10",
"rate-limiter-flexible": "^2.1.13",
"redis": "^3.0.2",
"regenerator-runtime": "^0.13.7",
"remove-markdown": "^0.3.0",
"rimraf": "^3.0.2",
"short-uuid": "^3.0.0",
"stripe": "^7.15.0",
"short-uuid": "^4.1.0",
"stripe": "^8.121.0",
"superagent": "^6.1.0",
"universal-analytics": "^0.4.23",
"useragent": "^2.1.9",
"uuid": "^8.3.0",
"validator": "^13.1.1",
"uuid": "^8.3.1",
"validator": "^13.1.17",
"vinyl-buffer": "^1.0.1",
"winston": "^3.3.3",
"winston-loggly-bulk": "^3.1.1",
@@ -79,7 +79,7 @@
},
"private": true,
"engines": {
"node": "^12",
"node": "^14",
"npm": "^6"
},
"scripts": {
@@ -109,7 +109,7 @@
"apidoc": "gulp apidoc"
},
"devDependencies": {
"axios": "^0.19.2",
"axios": "^0.21.0",
"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"chai-moment": "^0.1.0",
@@ -120,8 +120,8 @@
"mocha": "^5.1.1",
"monk": "^7.3.2",
"require-again": "^2.0.0",
"run-rs": "^0.6.2",
"sinon": "^9.0.3",
"run-rs": "^0.7.3",
"sinon": "^9.2.1",
"sinon-chai": "^3.5.0",
"sinon-stub-promise": "^4.0.0"
},
@@ -1,4 +1,5 @@
/* eslint-disable camelcase */
import nconf from 'nconf';
import Amplitude from 'amplitude';
import { Visitor } from 'universal-analytics';
import * as analyticsService from '../../../../website/server/libs/analyticsService';
@@ -15,6 +16,22 @@ describe('analyticsService', () => {
sandbox.restore();
});
describe('#getServiceByEnvironment', () => {
it('returns mock methods when not in production', () => {
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(false);
expect(analyticsService.getAnalyticsServiceByEnvironment())
.to.equal(analyticsService.mockAnalyticsService);
});
it('returns real methods when in production', () => {
sandbox.stub(nconf, 'get').withArgs('IS_PROD').returns(true);
expect(analyticsService.getAnalyticsServiceByEnvironment().track)
.to.equal(analyticsService.track);
expect(analyticsService.getAnalyticsServiceByEnvironment().trackPurchase)
.to.equal(analyticsService.trackPurchase);
});
});
describe('#track', () => {
let eventType; let
data;
+19 -15
View File
@@ -171,28 +171,32 @@ describe('highlightMentions', () => {
it('github issue 12118, method crashes when square brackets are used', async () => {
const text = '[test]';
let err;
const result = await highlightMentions(text);
try {
await highlightMentions(text);
} catch (e) {
err = e;
}
expect(err).to.be.undefined;
expect(result[0]).to.equal(text);
});
it('github issue 12138, method crashes when regex chars are used in code block', async () => {
const text = '`[test]`';
let err;
const result = await highlightMentions(text);
try {
await highlightMentions(text);
} catch (e) {
err = e;
}
expect(result[0]).to.equal(text);
});
expect(err).to.be.undefined;
it('github issue 12586, method crashes when empty link is used', async () => {
const text = '[]()';
const result = await highlightMentions(text);
expect(result[0]).to.equal(text);
});
it('github issue 12586, method crashes when link without title is used', async () => {
const text = '[](www.google.com)';
const result = await highlightMentions(text);
expect(result[0]).to.equal(text);
});
});
@@ -2,13 +2,15 @@ import { model as User } from '../../../../../../website/server/models/user';
import amzLib from '../../../../../../website/server/libs/payments/amazon';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
import apiError from '../../../../../../website/server/libs/apiError';
import * as gems from '../../../../../../website/server/libs/payments/gems';
const { i18n } = common;
describe('Amazon Payments - Checkout', () => {
const subKey = 'basic_3mo';
let user; let orderReferenceId; let
headers;
headers; const gemsBlockKey = '21gems'; const gemsBlock = common.content.gems[gemsBlockKey];
let setOrderReferenceDetailsSpy;
let confirmOrderReferenceSpy;
let authorizeSpy;
@@ -16,7 +18,7 @@ describe('Amazon Payments - Checkout', () => {
let paymentBuyGemsStub;
let paymentCreateSubscritionStub;
let amount = 5;
let amount = gemsBlock.price / 100;
function expectOrderReferenceSpy () {
expect(setOrderReferenceDetailsSpy).to.be.calledOnce;
@@ -87,6 +89,7 @@ describe('Amazon Payments - Checkout', () => {
paymentCreateSubscritionStub.resolves({});
sinon.stub(common, 'uuid').returns('uuid-generated');
sandbox.stub(gems, 'validateGiftMessage');
});
afterEach(() => {
@@ -107,13 +110,23 @@ describe('Amazon Payments - Checkout', () => {
paymentMethod,
headers,
};
if (gift) expectedArgs.gift = gift;
if (gift) {
expectedArgs.gift = gift;
expectedArgs.gemsBlock = undefined;
expect(gems.validateGiftMessage).to.be.calledOnce;
expect(gems.validateGiftMessage).to.be.calledWith(gift, user);
} else {
expect(gems.validateGiftMessage).to.not.be.called;
expectedArgs.gemsBlock = gemsBlock;
}
expect(paymentBuyGemsStub).to.be.calledWith(expectedArgs);
}
it('should purchase gems', async () => {
sinon.stub(user, 'canGetGems').resolves(true);
await amzLib.checkout({ user, orderReferenceId, headers });
await amzLib.checkout({
user, orderReferenceId, headers, gemsBlock: gemsBlockKey,
});
expectBuyGemsStub(amzLib.constants.PAYMENT_METHOD);
expectAmazonStubs();
@@ -144,7 +157,9 @@ describe('Amazon Payments - Checkout', () => {
it('should error if user cannot get gems gems', async () => {
sinon.stub(user, 'canGetGems').resolves(false);
await expect(amzLib.checkout({ user, orderReferenceId, headers }))
await expect(amzLib.checkout({
user, orderReferenceId, headers, gemsBlock: gemsBlockKey,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
message: i18n.t('groupPolicyCannotGetGems'),
@@ -153,6 +168,17 @@ describe('Amazon Payments - Checkout', () => {
user.canGetGems.restore();
});
it('should error if gems block is not valid', async () => {
await expect(amzLib.checkout({
user, orderReferenceId, headers, gemsBlock: 'invalid',
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
message: apiError('invalidGemsBlock'),
name: 'BadRequest',
});
});
it('should gift gems', async () => {
const receivingUser = new User();
await receivingUser.save();
@@ -195,6 +221,7 @@ describe('Amazon Payments - Checkout', () => {
paymentMethod: amzLib.constants.PAYMENT_METHOD_GIFT,
headers,
gift,
gemsBlock: undefined,
});
expectAmazonStubs();
});
+24 -14
View File
@@ -5,7 +5,7 @@ import applePayments from '../../../../../website/server/libs/payments/apple';
import iap from '../../../../../website/server/libs/inAppPurchases';
import { model as User } from '../../../../../website/server/models/user';
import common from '../../../../../website/common';
import { mockFindById, restoreFindById } from '../../../../helpers/mongoose.helper';
import * as gems from '../../../../../website/server/libs/payments/gems';
const { i18n } = common;
@@ -16,7 +16,7 @@ describe('Apple Payments', () => {
let sku; let user; let token; let receipt; let
headers;
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub; let paymentBuyGemsStub; let
iapGetPurchaseDataStub;
iapGetPurchaseDataStub; let validateGiftMessageStub;
beforeEach(() => {
token = 'testToken';
@@ -37,6 +37,7 @@ describe('Apple Payments', () => {
transactionId: token,
}]);
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
validateGiftMessageStub = sinon.stub(gems, 'validateGiftMessage');
});
afterEach(() => {
@@ -45,6 +46,7 @@ describe('Apple Payments', () => {
iap.isValidated.restore();
iap.getPurchaseData.restore();
payments.buyGems.restore();
gems.validateGiftMessage.restore();
});
it('should throw an error if receipt is invalid', async () => {
@@ -84,7 +86,7 @@ describe('Apple Payments', () => {
user.canGetGems.restore();
});
it('errors if amount does not exist', async () => {
it('errors if gemsBlock does not exist', async () => {
sinon.stub(user, 'canGetGems').resolves(true);
iapGetPurchaseDataStub.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
@@ -106,23 +108,23 @@ describe('Apple Payments', () => {
const gemsCanPurchase = [
{
productId: 'com.habitrpg.ios.Habitica.4gems',
amount: 1,
gemsBlock: '4gems',
},
{
productId: 'com.habitrpg.ios.Habitica.20gems',
amount: 5.25,
gemsBlock: '21gems',
},
{
productId: 'com.habitrpg.ios.Habitica.21gems',
amount: 5.25,
gemsBlock: '21gems',
},
{
productId: 'com.habitrpg.ios.Habitica.42gems',
amount: 10.5,
gemsBlock: '42gems',
},
{
productId: 'com.habitrpg.ios.Habitica.84gems',
amount: 21,
gemsBlock: '84gems',
},
];
@@ -144,13 +146,15 @@ describe('Apple Payments', () => {
expect(iapIsValidatedStub).to.be.calledOnce;
expect(iapIsValidatedStub).to.be.calledWith({});
expect(iapGetPurchaseDataStub).to.be.calledOnce;
expect(validateGiftMessageStub).to.not.be.called;
expect(paymentBuyGemsStub).to.be.calledOnce;
expect(paymentBuyGemsStub).to.be.calledWith({
user,
paymentMethod: applePayments.constants.PAYMENT_METHOD_APPLE,
amount: gemTest.amount,
gemsBlock: common.content.gems[gemTest.gemsBlock],
headers,
gift: undefined,
});
expect(user.canGetGems).to.be.calledOnce;
user.canGetGems.restore();
@@ -161,8 +165,6 @@ describe('Apple Payments', () => {
const receivingUser = new User();
await receivingUser.save();
mockFindById(receivingUser);
iapGetPurchaseDataStub.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
@@ -182,14 +184,22 @@ describe('Apple Payments', () => {
expect(iapIsValidatedStub).to.be.calledWith({});
expect(iapGetPurchaseDataStub).to.be.calledOnce;
expect(validateGiftMessageStub).to.be.calledOnce;
expect(validateGiftMessageStub).to.be.calledWith(gift, user);
expect(paymentBuyGemsStub).to.be.calledOnce;
expect(paymentBuyGemsStub).to.be.calledWith({
user: receivingUser,
user,
paymentMethod: applePayments.constants.PAYMENT_METHOD_APPLE,
amount: gemsCanPurchase[0].amount,
headers,
gift: {
type: 'gems',
gems: { amount: 4 },
member: sinon.match({ _id: receivingUser._id }),
uuid: receivingUser._id,
},
gemsBlock: common.content.gems['4gems'],
});
restoreFindById();
});
});
+66
View File
@@ -0,0 +1,66 @@
import common from '../../../../../website/common';
import {
getGemsBlock,
validateGiftMessage,
} from '../../../../../website/server/libs/payments/gems';
import { model as User } from '../../../../../website/server/models/user';
const { i18n } = common;
describe('payments/gems', () => {
describe('#getGemsBlock', () => {
it('throws an error if the gem block key is invalid', () => {
expect(() => getGemsBlock('invalid')).to.throw;
});
it('returns the gem block for the given key', () => {
expect(getGemsBlock('21gems')).to.equal(common.content.gems['21gems']);
});
});
describe('#validateGiftMessage', () => {
let user;
let gift;
beforeEach(() => {
user = new User();
gift = {
message: (` // exactly 201 chars
A gift message that is over the 200 chars limit.
A gift message that is over the 200 chars limit.
A gift message that is over the 200 chars limit.
A gift message that is over the 200 chars limit. 1
`).trim().substring(0, 201),
};
expect(gift.message.length).to.equal(201);
});
it('throws if the gift message is too long', () => {
let expectedErr;
try {
validateGiftMessage(gift, user);
} catch (err) {
expectedErr = err;
}
expect(expectedErr).to.exist;
expect(expectedErr).to.eql({
httpCode: 400,
name: 'BadRequest',
message: i18n.t('giftMessageTooLong', { maxGiftMessageLength: 200 }),
});
});
it('does not throw if the gift message is not too long', () => {
gift.message = gift.message.substring(0, 200);
expect(() => validateGiftMessage(gift, user)).to.not.throw;
});
it('does not throw if it is not a gift', () => {
expect(() => validateGiftMessage(null, user)).to.not.throw;
});
});
});
+20 -9
View File
@@ -5,7 +5,7 @@ import googlePayments from '../../../../../website/server/libs/payments/google';
import iap from '../../../../../website/server/libs/inAppPurchases';
import { model as User } from '../../../../../website/server/models/user';
import common from '../../../../../website/common';
import { mockFindById, restoreFindById } from '../../../../helpers/mongoose.helper';
import * as gems from '../../../../../website/server/libs/payments/gems';
const { i18n } = common;
@@ -14,9 +14,9 @@ describe('Google Payments', () => {
describe('verifyGemPurchase', () => {
let sku; let user; let token; let receipt; let signature; let
headers;
headers; const gemsBlock = common.content.gems['21gems'];
let iapSetupStub; let iapValidateStub; let iapIsValidatedStub; let
paymentBuyGemsStub;
paymentBuyGemsStub; let validateGiftMessageStub;
beforeEach(() => {
sku = 'com.habitrpg.android.habitica.iap.21gems';
@@ -32,6 +32,7 @@ describe('Google Payments', () => {
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(true);
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
validateGiftMessageStub = sinon.stub(gems, 'validateGiftMessage');
});
afterEach(() => {
@@ -39,6 +40,7 @@ describe('Google Payments', () => {
iap.validate.restore();
iap.isValidated.restore();
payments.buyGems.restore();
gems.validateGiftMessage.restore();
});
it('should throw an error if receipt is invalid', async () => {
@@ -90,6 +92,8 @@ describe('Google Payments', () => {
user, receipt, signature, headers,
});
expect(validateGiftMessageStub).to.not.be.called;
expect(iapSetupStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledWith(iap.GOOGLE, {
@@ -103,8 +107,9 @@ describe('Google Payments', () => {
expect(paymentBuyGemsStub).to.be.calledWith({
user,
paymentMethod: googlePayments.constants.PAYMENT_METHOD_GOOGLE,
amount: 5.25,
gemsBlock,
headers,
gift: undefined,
});
expect(user.canGetGems).to.be.calledOnce;
user.canGetGems.restore();
@@ -114,13 +119,14 @@ describe('Google Payments', () => {
const receivingUser = new User();
await receivingUser.save();
mockFindById(receivingUser);
const gift = { uuid: receivingUser._id };
await googlePayments.verifyGemPurchase({
user, gift, receipt, signature, headers,
});
expect(validateGiftMessageStub).to.be.calledOnce;
expect(validateGiftMessageStub).to.be.calledWith(gift, user);
expect(iapSetupStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledWith(iap.GOOGLE, {
@@ -132,12 +138,17 @@ describe('Google Payments', () => {
expect(paymentBuyGemsStub).to.be.calledOnce;
expect(paymentBuyGemsStub).to.be.calledWith({
user: receivingUser,
user,
paymentMethod: googlePayments.constants.PAYMENT_METHOD_GOOGLE,
amount: 5.25,
gemsBlock,
headers,
gift: {
type: 'gems',
gems: { amount: 21 },
member: sinon.match({ _id: receivingUser._id }),
uuid: receivingUser._id,
},
});
restoreFindById();
});
});
@@ -22,7 +22,9 @@ describe('Purchasing a group plan for group', () => {
let plan; let group; let user; let
data;
const stripe = stripeModule('test');
const stripe = stripeModule('test', {
apiVersion: '2020-08-27',
});
const groupLeaderName = 'sender';
const groupName = 'test group';
+71 -37
View File
@@ -1,6 +1,7 @@
import moment from 'moment';
import * as sender from '../../../../../website/server/libs/email';
import common from '../../../../../website/common';
import api from '../../../../../website/server/libs/payments/payments';
import * as analytics from '../../../../../website/server/libs/analyticsService';
import * as notifications from '../../../../../website/server/libs/pushNotifications';
@@ -9,6 +10,7 @@ import { translate as t } from '../../../../helpers/api-integration/v3';
import {
generateGroup,
} from '../../../../helpers/api-unit.helper';
import * as worldState from '../../../../../website/server/libs/worldState';
describe('payments/index', () => {
let user; let group; let data; let
@@ -30,8 +32,8 @@ describe('payments/index', () => {
sandbox.stub(sender, 'sendTxn');
sandbox.stub(user, 'sendMessage');
sandbox.stub(analytics, 'trackPurchase');
sandbox.stub(analytics, 'track');
sandbox.stub(analytics.mockAnalyticsService, 'trackPurchase');
sandbox.stub(analytics.mockAnalyticsService, 'track');
sandbox.stub(notifications, 'sendNotification');
data = {
@@ -235,8 +237,8 @@ describe('payments/index', () => {
it('tracks subscription purchase as gift', async () => {
await api.createSubscription(data);
expect(analytics.trackPurchase).to.be.calledOnce;
expect(analytics.trackPurchase).to.be.calledWith({
expect(analytics.mockAnalyticsService.trackPurchase).to.be.calledOnce;
expect(analytics.mockAnalyticsService.trackPurchase).to.be.calledWith({
uuid: user._id,
groupId: undefined,
itemPurchased: 'Subscription',
@@ -246,6 +248,7 @@ describe('payments/index', () => {
quantity: 1,
gift: true,
purchaseValue: 15,
firstPurchase: true,
headers: {
'x-client': 'habitica-web',
'user-agent': '',
@@ -332,8 +335,8 @@ describe('payments/index', () => {
it('tracks subscription purchase', async () => {
await api.createSubscription(data);
expect(analytics.trackPurchase).to.be.calledOnce;
expect(analytics.trackPurchase).to.be.calledWith({
expect(analytics.mockAnalyticsService.trackPurchase).to.be.calledOnce;
expect(analytics.mockAnalyticsService.trackPurchase).to.be.calledWith({
uuid: user._id,
groupId: undefined,
itemPurchased: 'Subscription',
@@ -343,6 +346,7 @@ describe('payments/index', () => {
quantity: 1,
gift: false,
purchaseValue: 15,
firstPurchase: true,
headers: {
'x-client': 'habitica-web',
'user-agent': '',
@@ -419,10 +423,22 @@ describe('payments/index', () => {
});
context('Mystery Items', () => {
it('awards mystery items when within the timeframe for a mystery item', async () => {
const mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
const fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
let clock;
const mayMysteryItem = 'armor_mystery_201605';
beforeEach(() => {
const mayMysteryItemTimeframe = new Date(2016, 4, 31); // May 31st 2016
clock = sinon.useFakeTimers({
now: mayMysteryItemTimeframe,
toFake: ['Date'],
});
});
afterEach(() => {
if (clock) clock.restore();
});
it('awards mystery items when within the timeframe for a mystery item', async () => {
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
const oldNotificationsCount = user.notifications.length;
@@ -435,14 +451,9 @@ describe('payments/index', () => {
expect(user.purchased.plan.mysteryItems).to.include('head_mystery_201605');
expect(user.notifications.length).to.equal(oldNotificationsCount + 1);
expect(user.notifications[0].type).to.equal('NEW_MYSTERY_ITEMS');
fakeClock.restore();
});
it('does not award mystery item when user already owns the item', async () => {
const mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
const fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
const mayMysteryItem = 'armor_mystery_201605';
user.items.gear.owned[mayMysteryItem] = true;
data = { paymentMethod: 'PaymentMethod', user, sub: { key: 'basic_3mo' } };
@@ -451,14 +462,9 @@ describe('payments/index', () => {
expect(user.purchased.plan.mysteryItems).to.have.a.lengthOf(1);
expect(user.purchased.plan.mysteryItems).to.include('head_mystery_201605');
fakeClock.restore();
});
it('does not award mystery item when user already has the item in the mystery box', async () => {
const mayMysteryItemTimeframe = 1464725113000; // May 31st 2016
const fakeClock = sinon.useFakeTimers(mayMysteryItemTimeframe);
const mayMysteryItem = 'armor_mystery_201605';
user.purchased.plan.mysteryItems = [mayMysteryItem];
sandbox.spy(user.purchased.plan.mysteryItems, 'push');
@@ -468,8 +474,6 @@ describe('payments/index', () => {
expect(user.purchased.plan.mysteryItems.push).to.be.calledOnce;
expect(user.purchased.plan.mysteryItems.push).to.be.calledWith('head_mystery_201605');
fakeClock.restore();
});
});
});
@@ -555,6 +559,7 @@ describe('payments/index', () => {
beforeEach(() => {
data = {
user,
gemsBlock: common.content.gems['21gems'],
paymentMethod: 'payment',
headers: {
'x-client': 'habitica-web',
@@ -564,22 +569,6 @@ describe('payments/index', () => {
});
context('Self Purchase', () => {
it('amount property defaults to 5', async () => {
expect(user.balance).to.eql(0);
await api.buyGems(data);
expect(user.balance).to.eql(5);
});
it('can set amount that is purchased', async () => {
data.amount = 13;
await api.buyGems(data);
expect(user.balance).to.eql(13);
});
it('sends a donation email', async () => {
await api.buyGems(data);
@@ -588,6 +577,51 @@ describe('payments/index', () => {
});
});
context('No Active Promotion', () => {
beforeEach(() => {
sinon.stub(worldState, 'getCurrentEvent').returns(null);
});
afterEach(() => {
worldState.getCurrentEvent.restore();
});
it('does not apply a discount', async () => {
const balanceBefore = user.balance;
await api.buyGems(data);
const balanceAfter = user.balance;
const balanceDiff = balanceAfter - balanceBefore;
expect(balanceDiff * 4).to.eql(21);
});
});
context('Active Promotion', () => {
beforeEach(() => {
sinon.stub(worldState, 'getCurrentEvent').returns({
...common.content.events.fall2020,
event: 'fall2020',
});
});
afterEach(() => {
worldState.getCurrentEvent.restore();
});
it('applies a discount', async () => {
const balanceBefore = user.balance;
await api.buyGems(data);
const balanceAfter = user.balance;
const balanceDiff = balanceAfter - balanceBefore;
expect(balanceDiff * 4).to.eql(30);
});
});
context('Gift', () => {
let recipient;
@@ -2,11 +2,13 @@
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
import payments from '../../../../../../website/server/libs/payments/payments';
import { model as User } from '../../../../../../website/server/models/user';
import common from '../../../../../../website/common';
describe('checkout success', () => {
describe('paypal - checkout success', () => {
const subKey = 'basic_3mo';
let user; let gift; let customerId; let
paymentId;
const gemsBlockKey = '21gems'; const gemsBlock = common.content.gems[gemsBlockKey];
let paypalPaymentExecuteStub; let paymentBuyGemsStub; let
paymentsCreateSubscritionStub;
@@ -28,7 +30,7 @@ describe('checkout success', () => {
it('purchases gems', async () => {
await paypalPayments.checkoutSuccess({
user, gift, paymentId, customerId,
user, gift, paymentId, customerId, gemsBlock: gemsBlockKey,
});
expect(paypalPaymentExecuteStub).to.be.calledOnce;
@@ -38,6 +40,7 @@ describe('checkout success', () => {
user,
customerId,
paymentMethod: 'Paypal',
gemsBlock,
});
});
@@ -4,12 +4,15 @@ import nconf from 'nconf';
import paypalPayments from '../../../../../../website/server/libs/payments/paypal';
import { model as User } from '../../../../../../website/server/models/user';
import common from '../../../../../../website/common';
import apiError from '../../../../../../website/server/libs/apiError';
import * as gems from '../../../../../../website/server/libs/payments/gems';
const BASE_URL = nconf.get('BASE_URL');
const { i18n } = common;
describe('checkout', () => {
describe('paypal - checkout', () => {
const subKey = 'basic_3mo';
const gemsBlockKey = '21gems';
let paypalPaymentCreateStub;
let approvalHerf;
@@ -46,6 +49,7 @@ describe('checkout', () => {
.resolves({
links: [{ rel: 'approval_url', href: approvalHerf }],
});
sandbox.stub(gems, 'validateGiftMessage');
});
afterEach(() => {
@@ -53,10 +57,11 @@ describe('checkout', () => {
});
it('creates a link for gem purchases', async () => {
const link = await paypalPayments.checkout({ user: new User() });
const link = await paypalPayments.checkout({ user: new User(), gemsBlock: gemsBlockKey });
expect(gems.validateGiftMessage).to.not.be.called;
expect(paypalPaymentCreateStub).to.be.calledOnce;
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('Habitica Gems', 5.00));
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('Habitica Gems', 4.99));
expect(link).to.eql(approvalHerf);
});
@@ -83,14 +88,27 @@ describe('checkout', () => {
const user = new User();
sinon.stub(user, 'canGetGems').resolves(false);
await expect(paypalPayments.checkout({ user })).to.eventually.be.rejected.and.to.eql({
httpCode: 401,
message: i18n.t('groupPolicyCannotGetGems'),
name: 'NotAuthorized',
});
await expect(paypalPayments.checkout({ user, gemsBlock: gemsBlockKey }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
message: i18n.t('groupPolicyCannotGetGems'),
name: 'NotAuthorized',
});
});
it('should error if the gems block is not valid', async () => {
const user = new User();
await expect(paypalPayments.checkout({ user, gemsBlock: 'invalid' }))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
message: apiError('invalidGemsBlock'),
name: 'BadRequest',
});
});
it('creates a link for gifting gems', async () => {
const user = new User();
const receivingUser = new User();
await receivingUser.save();
const gift = {
@@ -101,14 +119,17 @@ describe('checkout', () => {
},
};
const link = await paypalPayments.checkout({ gift });
const link = await paypalPayments.checkout({ user, gift });
expect(gems.validateGiftMessage).to.be.calledOnce;
expect(gems.validateGiftMessage).to.be.calledWith(gift, user);
expect(paypalPaymentCreateStub).to.be.calledOnce;
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('Habitica Gems (Gift)', '4.00'));
expect(link).to.eql(approvalHerf);
});
it('creates a link for gifting a subscription', async () => {
const user = new User();
const receivingUser = new User();
receivingUser.save();
const gift = {
@@ -119,7 +140,10 @@ describe('checkout', () => {
},
};
const link = await paypalPayments.checkout({ gift });
const link = await paypalPayments.checkout({ user, gift });
expect(gems.validateGiftMessage).to.be.calledOnce;
expect(gems.validateGiftMessage).to.be.calledWith(gift, user);
expect(paypalPaymentCreateStub).to.be.calledOnce;
expect(paypalPaymentCreateStub).to.be.calledWith(getPaypalCreateOptions('mo. Habitica Subscription (Gift)', '15.00'));
@@ -6,7 +6,7 @@ import {
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
describe('ipn', () => {
describe('paypal - ipn', () => {
const subKey = 'basic_3mo';
let user; let group; let txn_type; let userPaymentId; let
groupPaymentId;
@@ -10,7 +10,7 @@ import { createNonLeaderGroupMember } from '../paymentHelpers';
const { i18n } = common;
describe('subscribeCancel', () => {
describe('paypal - subscribeCancel', () => {
const subKey = 'basic_3mo';
let user; let group; let groupId; let customerId; let groupCustomerId; let
nextBillingDate;
@@ -7,7 +7,7 @@ import {
import { model as User } from '../../../../../../website/server/models/user';
import common from '../../../../../../website/common';
describe('subscribeSuccess', () => {
describe('paypal - subscribeSuccess', () => {
const subKey = 'basic_3mo';
let user; let group; let block; let groupId; let token; let headers; let
customerId;
@@ -8,7 +8,7 @@ import common from '../../../../../../website/common';
const { i18n } = common;
describe('subscribe', () => {
describe('paypal - subscribe', () => {
const subKey = 'basic_3mo';
let coupon; let sub; let
approvalHerf;
@@ -4,7 +4,7 @@ import api from '../../../../../../website/server/libs/payments/payments';
const groupPlanId = api.constants.GROUP_PLAN_CUSTOMER_ID;
describe('#calculateSubscriptionTerminationDate', () => {
describe('stripe - #calculateSubscriptionTerminationDate', () => {
let plan;
let nextBill;
@@ -1,149 +0,0 @@
import stripeModule from 'stripe';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
const { i18n } = common;
describe('cancel subscription', () => {
const subKey = 'basic_3mo';
const stripe = stripeModule('test');
let user; let groupId; let
group;
beforeEach(async () => {
user = new User();
user.profile.name = 'sender';
user.purchased.plan.customerId = 'customer-id';
user.purchased.plan.planId = subKey;
user.purchased.plan.lastBillingDate = new Date();
group = generateGroup({
name: 'test group',
type: 'guild',
privacy: 'public',
leader: user._id,
});
group.purchased.plan.customerId = 'customer-id';
group.purchased.plan.planId = subKey;
await group.save();
groupId = group._id;
});
it('throws an error if there is no customer id', async () => {
user.purchased.plan.customerId = undefined;
await expect(stripePayments.cancelSubscription({
user,
groupId: undefined,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('missingSubscription'),
});
});
it('throws an error if the group is not found', async () => {
await expect(stripePayments.cancelSubscription({
user,
groupId: 'fake-group',
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 404,
name: 'NotFound',
message: i18n.t('groupNotFound'),
});
});
it('throws an error if user is not the group leader', async () => {
const nonLeader = new User();
nonLeader.guilds.push(groupId);
await nonLeader.save();
await expect(stripePayments.cancelSubscription({
user: nonLeader,
groupId,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('onlyGroupLeaderCanManageSubscription'),
});
});
describe('success', () => {
let stripeDeleteCustomerStub; let paymentsCancelSubStub;
let stripeRetrieveStub; let subscriptionId; let
currentPeriodEndTimeStamp;
beforeEach(() => {
subscriptionId = 'subId';
stripeDeleteCustomerStub = sinon.stub(stripe.customers, 'del').resolves({});
paymentsCancelSubStub = sinon.stub(payments, 'cancelSubscription').resolves({});
currentPeriodEndTimeStamp = (new Date()).getTime();
stripeRetrieveStub = sinon.stub(stripe.customers, 'retrieve')
.resolves({
subscriptions: {
data: [{
id: subscriptionId,
current_period_end: currentPeriodEndTimeStamp,
}], // eslint-disable-line camelcase
},
});
});
afterEach(() => {
stripe.customers.del.restore();
stripe.customers.retrieve.restore();
payments.cancelSubscription.restore();
});
it('cancels a user subscription', async () => {
await stripePayments.cancelSubscription({
user,
groupId: undefined,
}, stripe);
expect(stripeDeleteCustomerStub).to.be.calledOnce;
expect(stripeDeleteCustomerStub).to.be.calledWith(user.purchased.plan.customerId);
expect(stripeRetrieveStub).to.be.calledOnce;
expect(stripeRetrieveStub).to.be.calledWith(user.purchased.plan.customerId);
expect(paymentsCancelSubStub).to.be.calledOnce;
expect(paymentsCancelSubStub).to.be.calledWith({
user,
groupId: undefined,
nextBill: currentPeriodEndTimeStamp * 1000, // timestamp in seconds
paymentMethod: 'Stripe',
cancellationReason: undefined,
});
});
it('cancels a group subscription', async () => {
await stripePayments.cancelSubscription({
user,
groupId,
}, stripe);
expect(stripeDeleteCustomerStub).to.be.calledOnce;
expect(stripeDeleteCustomerStub).to.be.calledWith(group.purchased.plan.customerId);
expect(stripeRetrieveStub).to.be.calledOnce;
expect(stripeRetrieveStub).to.be.calledWith(user.purchased.plan.customerId);
expect(paymentsCancelSubStub).to.be.calledOnce;
expect(paymentsCancelSubStub).to.be.calledWith({
user,
groupId,
nextBill: currentPeriodEndTimeStamp * 1000, // timestamp in seconds
paymentMethod: 'Stripe',
cancellationReason: undefined,
});
});
});
});
@@ -1,321 +0,0 @@
import stripeModule from 'stripe';
import cc from 'coupon-code';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Coupon } from '../../../../../../website/server/models/coupon';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
const { i18n } = common;
describe('checkout with subscription', () => {
const subKey = 'basic_3mo';
const stripe = stripeModule('test');
let user; let group; let data; let gift; let sub;
let groupId; let email; let headers; let coupon;
let customerIdResponse; let subscriptionId; let
token;
let spy;
let stripeCreateCustomerSpy;
let stripePaymentsCreateSubSpy;
beforeEach(async () => {
user = new User();
user.profile.name = 'sender';
user.purchased.plan.customerId = 'customer-id';
user.purchased.plan.planId = subKey;
user.purchased.plan.lastBillingDate = new Date();
group = generateGroup({
name: 'test group',
type: 'guild',
privacy: 'public',
leader: user._id,
});
group.purchased.plan.customerId = 'customer-id';
group.purchased.plan.planId = subKey;
await group.save();
sub = {
key: 'basic_3mo',
};
data = {
user,
sub,
customerId: 'customer-id',
paymentMethod: 'Payment Method',
};
email = 'example@example.com';
customerIdResponse = 'test-id';
subscriptionId = 'test-sub-id';
token = 'test-token';
spy = sinon.stub(stripe.subscriptions, 'update');
spy.resolves;
stripeCreateCustomerSpy = sinon.stub(stripe.customers, 'create');
const stripCustomerResponse = {
id: customerIdResponse,
subscriptions: {
data: [{ id: subscriptionId }],
},
};
stripeCreateCustomerSpy.resolves(stripCustomerResponse);
stripePaymentsCreateSubSpy = sinon.stub(payments, 'createSubscription');
stripePaymentsCreateSubSpy.resolves({});
data.groupId = group._id;
data.sub.quantity = 3;
});
afterEach(() => {
stripe.subscriptions.update.restore();
stripe.customers.create.restore();
payments.createSubscription.restore();
});
it('should throw an error if we are missing a token', async () => {
await expect(stripePayments.checkout({
user,
gift,
sub,
groupId,
email,
headers,
coupon,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: 'Missing req.body.id',
});
});
it('should throw an error when coupon code is missing', async () => {
sub.discount = 40;
await expect(stripePayments.checkout({
token,
user,
gift,
sub,
groupId,
email,
headers,
coupon,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: i18n.t('couponCodeRequired'),
});
});
it('should throw an error when coupon code is invalid', async () => {
sub.discount = 40;
sub.key = 'google_6mo';
coupon = 'example-coupon';
const couponModel = new Coupon();
couponModel.event = 'google_6mo';
await couponModel.save();
sinon.stub(cc, 'validate').returns('invalid');
await expect(stripePayments.checkout({
token,
user,
gift,
sub,
groupId,
email,
headers,
coupon,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: i18n.t('invalidCoupon'),
});
cc.validate.restore();
});
it('subscribes with stripe with a coupon', async () => {
sub.discount = 40;
sub.key = 'google_6mo';
coupon = 'example-coupon';
const couponModel = new Coupon();
couponModel.event = 'google_6mo';
const updatedCouponModel = await couponModel.save();
sinon.stub(cc, 'validate').returns(updatedCouponModel._id);
await stripePayments.checkout({
token,
user,
gift,
sub,
groupId,
email,
headers,
coupon,
}, stripe);
expect(stripeCreateCustomerSpy).to.be.calledOnce;
expect(stripeCreateCustomerSpy).to.be.calledWith({
email,
metadata: { uuid: user._id },
card: token,
plan: sub.key,
});
expect(stripePaymentsCreateSubSpy).to.be.calledOnce;
expect(stripePaymentsCreateSubSpy).to.be.calledWith({
user,
customerId: customerIdResponse,
paymentMethod: 'Stripe',
sub,
headers,
groupId: undefined,
subscriptionId: undefined,
});
cc.validate.restore();
});
it('subscribes a user', async () => {
sub = data.sub;
await stripePayments.checkout({
token,
user,
gift,
sub,
groupId,
email,
headers,
coupon,
}, stripe);
expect(stripeCreateCustomerSpy).to.be.calledOnce;
expect(stripeCreateCustomerSpy).to.be.calledWith({
email,
metadata: { uuid: user._id },
card: token,
plan: sub.key,
});
expect(stripePaymentsCreateSubSpy).to.be.calledOnce;
expect(stripePaymentsCreateSubSpy).to.be.calledWith({
user,
customerId: customerIdResponse,
paymentMethod: 'Stripe',
sub,
headers,
groupId: undefined,
subscriptionId: undefined,
});
});
it('subscribes a group', async () => {
token = 'test-token';
sub = data.sub;
groupId = group._id;
email = 'test@test.com';
// Add user to group
user.guilds.push(groupId);
await user.save();
headers = {};
await stripePayments.checkout({
token,
user,
gift,
sub,
groupId,
email,
headers,
coupon,
}, stripe);
expect(stripeCreateCustomerSpy).to.be.calledOnce;
expect(stripeCreateCustomerSpy).to.be.calledWith({
email,
metadata: { uuid: user._id },
card: token,
plan: sub.key,
quantity: 3,
});
expect(stripePaymentsCreateSubSpy).to.be.calledOnce;
expect(stripePaymentsCreateSubSpy).to.be.calledWith({
user,
customerId: customerIdResponse,
paymentMethod: 'Stripe',
sub,
headers,
groupId,
subscriptionId,
});
});
it('subscribes a group with the correct number of group members', async () => {
token = 'test-token';
sub = data.sub;
groupId = group._id;
email = 'test@test.com';
headers = {};
// Add user to group
user.guilds.push(groupId);
await user.save();
user = new User();
user.guilds.push(groupId);
await user.save();
group.memberCount = 2;
await group.save();
await stripePayments.checkout({
token,
user,
gift,
sub,
groupId,
email,
headers,
coupon,
}, stripe);
expect(stripeCreateCustomerSpy).to.be.calledOnce;
expect(stripeCreateCustomerSpy).to.be.calledWith({
email,
metadata: { uuid: user._id },
card: token,
plan: sub.key,
quantity: 4,
});
expect(stripePaymentsCreateSubSpy).to.be.calledOnce;
expect(stripePaymentsCreateSubSpy).to.be.calledWith({
user,
customerId: customerIdResponse,
paymentMethod: 'Stripe',
sub,
headers,
groupId,
subscriptionId,
});
});
});
@@ -1,210 +1,484 @@
import stripeModule from 'stripe';
import { model as User } from '../../../../../../website/server/models/user';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../website/server/libs/payments/payments';
import nconf from 'nconf';
import common from '../../../../../../website/common';
import * as subscriptions from '../../../../../../website/server/libs/payments/stripe/subscriptions';
import * as oneTimePayments from '../../../../../../website/server/libs/payments/stripe/oneTimePayments';
import {
createCheckoutSession,
createEditCardCheckoutSession,
} from '../../../../../../website/server/libs/payments/stripe/checkout';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../website/server/models/group';
import * as gems from '../../../../../../website/server/libs/payments/gems';
const { i18n } = common;
describe('checkout', () => {
const subKey = 'basic_3mo';
const stripe = stripeModule('test');
let stripeChargeStub; let paymentBuyGemsStub; let
paymentCreateSubscritionStub;
let user; let gift; let groupId; let email; let headers; let coupon; let customerIdResponse; let
token;
beforeEach(() => {
user = new User();
user.profile.name = 'sender';
user.purchased.plan.customerId = 'customer-id';
user.purchased.plan.planId = subKey;
user.purchased.plan.lastBillingDate = new Date();
token = 'test-token';
customerIdResponse = 'example-customerIdResponse';
const stripCustomerResponse = {
id: customerIdResponse,
};
stripeChargeStub = sinon.stub(stripe.charges, 'create').resolves(stripCustomerResponse);
paymentBuyGemsStub = sinon.stub(payments, 'buyGems').resolves({});
paymentCreateSubscritionStub = sinon.stub(payments, 'createSubscription').resolves({});
describe('Stripe - Checkout', () => {
const stripe = stripeModule('test', {
apiVersion: '2020-08-27',
});
const BASE_URL = nconf.get('BASE_URL');
const redirectUrls = {
success_url: `${BASE_URL}/redirect/stripe-success-checkout`,
cancel_url: `${BASE_URL}/redirect/stripe-error-checkout`,
};
afterEach(() => {
stripe.charges.create.restore();
payments.buyGems.restore();
payments.createSubscription.restore();
});
describe('createCheckoutSession', () => {
let user;
const sessionId = 'session-id';
it('should error if there is no token', async () => {
await expect(stripePayments.checkout({
user,
gift,
groupId,
email,
headers,
coupon,
}, stripe))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
message: 'Missing req.body.id',
name: 'BadRequest',
beforeEach(() => {
user = new User();
sandbox.stub(stripe.checkout.sessions, 'create').returns(sessionId);
sandbox.stub(gems, 'validateGiftMessage');
});
it('gems', async () => {
const amount = 999;
const gemsBlockKey = '21gems';
sandbox.stub(oneTimePayments, 'getOneTimePaymentInfo').returns({
amount,
gemsBlock: common.content.gems[gemsBlockKey],
});
});
it('should error if gem amount is too low', async () => {
const receivingUser = new User();
receivingUser.save();
gift = {
type: 'gems',
gems: {
amount: 0,
uuid: receivingUser._id,
},
};
const res = await createCheckoutSession({ user, gemsBlock: gemsBlockKey }, stripe);
expect(res).to.equal(sessionId);
await expect(stripePayments.checkout({
token,
user,
gift,
groupId,
email,
headers,
coupon,
}, stripe))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
message: 'Amount must be at least 1.',
name: 'BadRequest',
const metadata = {
type: 'gems',
userId: user._id,
gift: undefined,
sub: undefined,
gemsBlock: gemsBlockKey,
};
expect(gems.validateGiftMessage).to.not.be.called;
expect(oneTimePayments.getOneTimePaymentInfo).to.be.calledOnce;
expect(oneTimePayments.getOneTimePaymentInfo).to.be.calledWith(gemsBlockKey, undefined, user);
expect(stripe.checkout.sessions.create).to.be.calledOnce;
expect(stripe.checkout.sessions.create).to.be.calledWith({
payment_method_types: ['card'],
metadata,
line_items: [{
price_data: {
product_data: {
name: common.i18n.t('nGems', { nGems: 21 }),
},
unit_amount: amount,
currency: 'usd',
},
quantity: 1,
}],
mode: 'payment',
...redirectUrls,
});
});
it('should error if user cannot get gems', async () => {
gift = undefined;
sinon.stub(user, 'canGetGems').resolves(false);
await expect(stripePayments.checkout({
token,
user,
gift,
groupId,
email,
headers,
coupon,
}, stripe)).to.eventually.be.rejected.and.to.eql({
httpCode: 401,
message: i18n.t('groupPolicyCannotGetGems'),
name: 'NotAuthorized',
});
});
it('should purchase gems', async () => {
gift = undefined;
sinon.stub(user, 'canGetGems').resolves(true);
await stripePayments.checkout({
token,
user,
gift,
groupId,
email,
headers,
coupon,
}, stripe);
expect(stripeChargeStub).to.be.calledOnce;
expect(stripeChargeStub).to.be.calledWith({
amount: 500,
currency: 'usd',
card: token,
});
expect(paymentBuyGemsStub).to.be.calledOnce;
expect(paymentBuyGemsStub).to.be.calledWith({
user,
customerId: customerIdResponse,
paymentMethod: 'Stripe',
gift,
});
expect(user.canGetGems).to.be.calledOnce;
user.canGetGems.restore();
});
it('gems gift', async () => {
const receivingUser = new User();
await receivingUser.save();
it('should gift gems', async () => {
const receivingUser = new User();
await receivingUser.save();
gift = {
type: 'gems',
uuid: receivingUser._id,
gems: {
amount: 16,
},
};
await stripePayments.checkout({
token,
user,
gift,
groupId,
email,
headers,
coupon,
}, stripe);
expect(stripeChargeStub).to.be.calledOnce;
expect(stripeChargeStub).to.be.calledWith({
amount: '400',
currency: 'usd',
card: token,
});
expect(paymentBuyGemsStub).to.be.calledOnce;
expect(paymentBuyGemsStub).to.be.calledWith({
user,
customerId: customerIdResponse,
paymentMethod: 'Gift',
gift,
});
});
it('should gift a subscription', async () => {
const receivingUser = new User();
receivingUser.save();
gift = {
type: 'subscription',
subscription: {
key: subKey,
const gift = {
type: 'gems',
uuid: receivingUser._id,
},
};
gems: {
amount: 4,
},
};
const amount = 100;
sandbox.stub(oneTimePayments, 'getOneTimePaymentInfo').returns({
amount,
gemsBlock: null,
});
await stripePayments.checkout({
token,
user,
gift,
groupId,
email,
headers,
coupon,
}, stripe);
const res = await createCheckoutSession({ user, gift }, stripe);
expect(res).to.equal(sessionId);
gift.member = receivingUser;
expect(stripeChargeStub).to.be.calledOnce;
expect(stripeChargeStub).to.be.calledWith({
amount: '1500',
currency: 'usd',
card: token,
const metadata = {
type: 'gift-gems',
userId: user._id,
gift: JSON.stringify(gift),
sub: undefined,
gemsBlock: undefined,
};
expect(gems.validateGiftMessage).to.be.calledOnce;
expect(gems.validateGiftMessage).to.be.calledWith(gift, user);
expect(oneTimePayments.getOneTimePaymentInfo).to.be.calledOnce;
expect(oneTimePayments.getOneTimePaymentInfo).to.be.calledWith(undefined, gift, user);
expect(stripe.checkout.sessions.create).to.be.calledOnce;
expect(stripe.checkout.sessions.create).to.be.calledWith({
payment_method_types: ['card'],
metadata,
line_items: [{
price_data: {
product_data: {
name: common.i18n.t('nGemsGift', { nGems: 4 }),
},
unit_amount: amount,
currency: 'usd',
},
quantity: 1,
}],
mode: 'payment',
...redirectUrls,
});
});
expect(paymentCreateSubscritionStub).to.be.calledOnce;
expect(paymentCreateSubscritionStub).to.be.calledWith({
user,
customerId: customerIdResponse,
paymentMethod: 'Gift',
gift,
it('subscription gift', async () => {
const receivingUser = new User();
await receivingUser.save();
const subKey = 'basic_3mo';
const gift = {
type: 'subscription',
uuid: receivingUser._id,
subscription: {
key: subKey,
},
};
const amount = 1500;
sandbox.stub(oneTimePayments, 'getOneTimePaymentInfo').returns({
amount,
gemsBlock: null,
subscription: common.content.subscriptionBlocks[subKey],
});
const res = await createCheckoutSession({ user, gift }, stripe);
expect(res).to.equal(sessionId);
const metadata = {
type: 'gift-sub',
userId: user._id,
gift: JSON.stringify(gift),
sub: undefined,
gemsBlock: undefined,
};
expect(oneTimePayments.getOneTimePaymentInfo).to.be.calledOnce;
expect(oneTimePayments.getOneTimePaymentInfo).to.be.calledWith(undefined, gift, user);
expect(stripe.checkout.sessions.create).to.be.calledOnce;
expect(stripe.checkout.sessions.create).to.be.calledWith({
payment_method_types: ['card'],
metadata,
line_items: [{
price_data: {
product_data: {
name: common.i18n.t('nMonthsSubscriptionGift', { nMonths: 3 }),
},
unit_amount: amount,
currency: 'usd',
},
quantity: 1,
}],
mode: 'payment',
...redirectUrls,
});
});
it('subscription', async () => {
const subKey = 'basic_3mo';
const coupon = null;
sandbox.stub(subscriptions, 'checkSubData').returns(undefined);
const sub = common.content.subscriptionBlocks[subKey];
const res = await createCheckoutSession({ user, sub, coupon }, stripe);
expect(res).to.equal(sessionId);
const metadata = {
type: 'subscription',
userId: user._id,
gift: undefined,
sub: JSON.stringify(sub),
};
expect(subscriptions.checkSubData).to.be.calledOnce;
expect(subscriptions.checkSubData).to.be.calledWith(sub, false, coupon);
expect(stripe.checkout.sessions.create).to.be.calledOnce;
expect(stripe.checkout.sessions.create).to.be.calledWith({
payment_method_types: ['card'],
metadata,
line_items: [{
price: sub.key,
quantity: 1,
// @TODO proper copy
}],
mode: 'subscription',
...redirectUrls,
});
});
it('throws if group does not exists', async () => {
const groupId = 'invalid';
sandbox.stub(Group.prototype, 'getMemberCount').resolves(4);
const subKey = 'group_monthly';
const coupon = null;
const sub = common.content.subscriptionBlocks[subKey];
await expect(createCheckoutSession({
user, sub, coupon, groupId,
}, stripe))
.to.eventually.be.rejected.and.to.eql({
httpCode: 404,
name: 'NotFound',
message: i18n.t('groupNotFound'),
});
});
it('group plan', async () => {
const group = generateGroup({
name: 'test group',
type: 'guild',
privacy: 'public',
leader: user._id,
});
const groupId = group._id;
await group.save();
sandbox.stub(Group.prototype, 'getMemberCount').resolves(4);
// Add user to group
user.guilds.push(groupId);
await user.save();
const subKey = 'group_monthly';
const coupon = null;
sandbox.stub(subscriptions, 'checkSubData').returns(undefined);
const sub = common.content.subscriptionBlocks[subKey];
const res = await createCheckoutSession({
user, sub, coupon, groupId,
}, stripe);
expect(res).to.equal(sessionId);
const metadata = {
type: 'subscription',
userId: user._id,
gift: undefined,
sub: JSON.stringify(sub),
groupId,
};
expect(Group.prototype.getMemberCount).to.be.calledOnce;
expect(subscriptions.checkSubData).to.be.calledOnce;
expect(subscriptions.checkSubData).to.be.calledWith(sub, true, coupon);
expect(stripe.checkout.sessions.create).to.be.calledOnce;
expect(stripe.checkout.sessions.create).to.be.calledWith({
payment_method_types: ['card'],
metadata,
line_items: [{
price: sub.key,
quantity: 6,
// @TODO proper copy
}],
mode: 'subscription',
...redirectUrls,
});
});
// no gift, sub or gem payment
it('throws if type is invalid', async () => {
await expect(createCheckoutSession({ user }, stripe))
.to.eventually.be.rejected;
});
});
describe('createEditCardCheckoutSession', () => {
let user;
const sessionId = 'session-id';
const customerId = 'customerId';
const subscriptionId = 'subscription-id';
let subscriptionsListStub;
beforeEach(() => {
user = new User();
sandbox.stub(stripe.checkout.sessions, 'create').returns(sessionId);
subscriptionsListStub = sandbox.stub(stripe.subscriptions, 'list');
subscriptionsListStub.resolves({ data: [{ id: subscriptionId }] });
});
it('throws if no valid data is supplied', async () => {
await expect(createEditCardCheckoutSession({}, stripe))
.to.eventually.be.rejected;
});
it('throws if customer does not exists', async () => {
await expect(createEditCardCheckoutSession({ user }, stripe))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('missingSubscription'),
});
});
it('throws if subscription does not exists', async () => {
user.purchased.plan.customerId = customerId;
subscriptionsListStub.resolves({ data: [] });
await expect(createEditCardCheckoutSession({ user }, stripe))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('missingSubscription'),
});
});
it('change card for user subscription', async () => {
user.purchased.plan.customerId = customerId;
const metadata = {
userId: user._id,
type: 'edit-card-user',
};
const res = await createEditCardCheckoutSession({ user }, stripe);
expect(res).to.equal(sessionId);
expect(subscriptionsListStub).to.be.calledOnce;
expect(subscriptionsListStub).to.be.calledWith({ customer: customerId });
expect(stripe.checkout.sessions.create).to.be.calledOnce;
expect(stripe.checkout.sessions.create).to.be.calledWith({
mode: 'setup',
payment_method_types: ['card'],
metadata,
customer: customerId,
setup_intent_data: {
metadata: {
customer_id: customerId,
subscription_id: subscriptionId,
},
},
...redirectUrls,
});
});
it('throws if group does not exists', async () => {
const groupId = 'invalid';
await expect(createEditCardCheckoutSession({ user, groupId }, stripe))
.to.eventually.be.rejected.and.to.eql({
httpCode: 404,
name: 'NotFound',
message: i18n.t('groupNotFound'),
});
});
describe('with group', () => {
let group; let groupId;
beforeEach(async () => {
group = generateGroup({
name: 'test group',
type: 'guild',
privacy: 'public',
leader: user._id,
});
groupId = group._id;
await group.save();
});
it('throws if user is not allowed to change group plan', async () => {
const anotherUser = new User();
anotherUser.guilds.push(groupId);
await anotherUser.save();
await expect(createEditCardCheckoutSession({ user: anotherUser, groupId }, stripe))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('onlyGroupLeaderCanManageSubscription'),
});
});
it('throws if customer does not exists (group)', async () => {
await expect(createEditCardCheckoutSession({ user, groupId }, stripe))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('missingSubscription'),
});
});
it('throws if subscription does not exists (group)', async () => {
group.purchased.plan.customerId = customerId;
subscriptionsListStub.resolves({ data: [] });
await expect(createEditCardCheckoutSession({ user, groupId }, stripe))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('missingSubscription'),
});
});
it('change card for group plans - leader', async () => {
group.purchased.plan.customerId = customerId;
await group.save();
const metadata = {
userId: user._id,
type: 'edit-card-group',
groupId,
};
const res = await createEditCardCheckoutSession({ user, groupId }, stripe);
expect(res).to.equal(sessionId);
expect(subscriptionsListStub).to.be.calledOnce;
expect(subscriptionsListStub).to.be.calledWith({ customer: customerId });
expect(stripe.checkout.sessions.create).to.be.calledOnce;
expect(stripe.checkout.sessions.create).to.be.calledWith({
mode: 'setup',
payment_method_types: ['card'],
metadata,
customer: customerId,
setup_intent_data: {
metadata: {
customer_id: customerId,
subscription_id: subscriptionId,
},
},
...redirectUrls,
});
});
it('change card for group plans - plan owner', async () => {
const anotherUser = new User();
anotherUser.guilds.push(groupId);
await anotherUser.save();
group.purchased.plan.customerId = customerId;
group.purchased.plan.owner = anotherUser._id;
await group.save();
const metadata = {
userId: anotherUser._id,
type: 'edit-card-group',
groupId,
};
const res = await createEditCardCheckoutSession({ user: anotherUser, groupId }, stripe);
expect(res).to.equal(sessionId);
expect(subscriptionsListStub).to.be.calledOnce;
expect(subscriptionsListStub).to.be.calledWith({ customer: customerId });
expect(stripe.checkout.sessions.create).to.be.calledOnce;
expect(stripe.checkout.sessions.create).to.be.calledWith({
mode: 'setup',
payment_method_types: ['card'],
metadata,
customer: customerId,
setup_intent_data: {
metadata: {
customer_id: customerId,
subscription_id: subscriptionId,
},
},
...redirectUrls,
});
});
});
});
});
@@ -1,151 +0,0 @@
import stripeModule from 'stripe';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import common from '../../../../../../website/common';
const { i18n } = common;
describe('edit subscription', () => {
const subKey = 'basic_3mo';
const stripe = stripeModule('test');
let user; let groupId; let group; let
token;
beforeEach(async () => {
user = new User();
user.profile.name = 'sender';
user.purchased.plan.customerId = 'customer-id';
user.purchased.plan.planId = subKey;
user.purchased.plan.lastBillingDate = new Date();
group = generateGroup({
name: 'test group',
type: 'guild',
privacy: 'public',
leader: user._id,
});
group.purchased.plan.customerId = 'customer-id';
group.purchased.plan.planId = subKey;
await group.save();
groupId = group._id;
token = 'test-token';
});
it('throws an error if there is no customer id', async () => {
user.purchased.plan.customerId = undefined;
await expect(stripePayments.editSubscription({
user,
groupId: undefined,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('missingSubscription'),
});
});
it('throws an error if a token is not provided', async () => {
await expect(stripePayments.editSubscription({
user,
groupId: undefined,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: 'Missing req.body.id',
});
});
it('throws an error if the group is not found', async () => {
await expect(stripePayments.editSubscription({
token,
user,
groupId: 'fake-group',
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 404,
name: 'NotFound',
message: i18n.t('groupNotFound'),
});
});
it('throws an error if user is not the group leader', async () => {
const nonLeader = new User();
nonLeader.guilds.push(groupId);
await nonLeader.save();
await expect(stripePayments.editSubscription({
token,
user: nonLeader,
groupId,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('onlyGroupLeaderCanManageSubscription'),
});
});
describe('success', () => {
let stripeListSubscriptionStub; let stripeUpdateSubscriptionStub; let
subscriptionId;
beforeEach(() => {
subscriptionId = 'subId';
stripeListSubscriptionStub = sinon.stub(stripe.subscriptions, 'list')
.resolves({
data: [{ id: subscriptionId }],
});
stripeUpdateSubscriptionStub = sinon.stub(stripe.subscriptions, 'update').resolves({});
});
afterEach(() => {
stripe.subscriptions.list.restore();
stripe.subscriptions.update.restore();
});
it('edits a user subscription', async () => {
await stripePayments.editSubscription({
token,
user,
groupId: undefined,
}, stripe);
expect(stripeListSubscriptionStub).to.be.calledOnce;
expect(stripeListSubscriptionStub).to.be.calledWith({
customer: user.purchased.plan.customerId,
});
expect(stripeUpdateSubscriptionStub).to.be.calledOnce;
expect(stripeUpdateSubscriptionStub).to.be.calledWith(
subscriptionId,
{ card: token },
);
});
it('edits a group subscription', async () => {
await stripePayments.editSubscription({
token,
user,
groupId,
}, stripe);
expect(stripeListSubscriptionStub).to.be.calledOnce;
expect(stripeListSubscriptionStub).to.be.calledWith({
customer: group.purchased.plan.customerId,
});
expect(stripeUpdateSubscriptionStub).to.be.calledOnce;
expect(stripeUpdateSubscriptionStub).to.be.calledWith(
subscriptionId,
{ card: token },
);
});
});
});
@@ -0,0 +1,316 @@
import apiError from '../../../../../../website/server/libs/apiError';
import common from '../../../../../../website/common';
import {
getOneTimePaymentInfo,
applyGemPayment,
} from '../../../../../../website/server/libs/payments/stripe/oneTimePayments';
import * as subscriptions from '../../../../../../website/server/libs/payments/stripe/subscriptions';
import { model as User } from '../../../../../../website/server/models/user';
import payments from '../../../../../../website/server/libs/payments/payments';
const { i18n } = common;
describe('Stripe - One Time Payments', () => {
describe('getOneTimePaymentInfo', () => {
let user;
beforeEach(() => {
user = new User();
sandbox.stub(subscriptions, 'checkSubData');
});
describe('gemsBlock', () => {
it('returns the gemsBlock and amount', async () => {
const { gemsBlock, amount, subscription } = await getOneTimePaymentInfo('21gems', null, user);
expect(gemsBlock).to.equal(common.content.gems['21gems']);
expect(amount).to.equal(gemsBlock.price);
expect(amount).to.equal(499);
expect(subscription).to.be.null;
expect(subscriptions.checkSubData).to.not.be.called;
});
it('throws if the gemsBlock does not exist', async () => {
await expect(getOneTimePaymentInfo('not existant', null, user))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: apiError('invalidGemsBlock'),
});
});
it('throws if the user cannot receive gems', async () => {
sandbox.stub(user, 'canGetGems').resolves(false);
await expect(getOneTimePaymentInfo('21gems', null, user))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('groupPolicyCannotGetGems'),
});
});
});
describe('gift', () => {
it('throws if the receiver does not exist', async () => {
const gift = {
type: 'gems',
uuid: 'invalid',
gems: {
amount: 3,
},
};
await expect(getOneTimePaymentInfo(null, gift, user))
.to.eventually.be.rejected.and.to.eql({
httpCode: 404,
name: 'NotFound',
message: i18n.t('userWithIDNotFound', { userId: 'invalid' }),
});
});
it('throws if the user cannot receive gems', async () => {
const receivingUser = new User();
await receivingUser.save();
sandbox.stub(User.prototype, 'canGetGems').resolves(false);
const gift = {
type: 'gems',
uuid: receivingUser._id,
gems: {
amount: 2,
},
};
await expect(getOneTimePaymentInfo(null, gift, user))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('groupPolicyCannotGetGems'),
});
});
it('throws if the amount of gems is <= 0', async () => {
const receivingUser = new User();
await receivingUser.save();
const gift = {
type: 'gems',
uuid: receivingUser._id,
gems: {
amount: 0,
},
};
await expect(getOneTimePaymentInfo(null, gift, user))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: i18n.t('badAmountOfGemsToPurchase'),
});
});
it('throws if the subscription block does not exist', async () => {
const receivingUser = new User();
await receivingUser.save();
const gift = {
type: 'subscription',
uuid: receivingUser._id,
subscription: {
key: 'invalid',
},
};
await expect(getOneTimePaymentInfo(null, gift, user))
.to.eventually.throw;
});
it('returns the amount (gems)', async () => {
const receivingUser = new User();
await receivingUser.save();
const gift = {
type: 'gems',
uuid: receivingUser._id,
gems: {
amount: 4,
},
};
expect(subscriptions.checkSubData).to.not.be.called;
const { gemsBlock, amount, subscription } = await getOneTimePaymentInfo(null, gift, user);
expect(gemsBlock).to.equal(null);
expect(amount).to.equal('100');
expect(subscription).to.be.null;
});
it('returns the amount (subscription)', async () => {
const receivingUser = new User();
await receivingUser.save();
const gift = {
type: 'subscription',
uuid: receivingUser._id,
subscription: {
key: 'basic_3mo',
},
};
const sub = common.content.subscriptionBlocks['basic_3mo']; // eslint-disable-line dot-notation
const { gemsBlock, amount, subscription } = await getOneTimePaymentInfo(null, gift, user);
expect(subscriptions.checkSubData).to.be.calledOnce;
expect(subscriptions.checkSubData).to.be.calledWith(sub, false, null);
expect(gemsBlock).to.equal(null);
expect(amount).to.equal('1500');
expect(Number(amount)).to.equal(sub.price * 100);
expect(subscription).to.equal(sub);
});
});
});
describe('applyGemPayment', () => {
let user;
let customerId;
let subKey;
let userFindByIdStub;
let paymentsCreateSubSpy;
let paymentBuyGemsStub;
beforeEach(async () => {
subKey = 'basic_3mo';
user = new User();
await user.save();
customerId = 'test-id';
paymentsCreateSubSpy = sandbox.stub(payments, 'createSubscription');
paymentsCreateSubSpy.resolves({});
paymentBuyGemsStub = sandbox.stub(payments, 'buyGems');
paymentBuyGemsStub.resolves({});
});
it('throws if the user does not exist', async () => {
const metadata = { userId: 'invalid' };
const session = { metadata, customer: customerId };
await expect(applyGemPayment(session))
.to.eventually.be.rejected.and.to.eql({
httpCode: 404,
name: 'NotFound',
message: i18n.t('userWithIDNotFound', { userId: metadata.userId }),
});
});
it('throws if the receiving user does not exist', async () => {
const metadata = { userId: 'invalid' };
const session = { metadata, customer: customerId };
await expect(applyGemPayment(session))
.to.eventually.be.rejected.and.to.eql({
httpCode: 404,
name: 'NotFound',
message: i18n.t('userWithIDNotFound', { userId: metadata.userId }),
});
});
it('throws if the gems block does not exist', async () => {
const gift = {
type: 'gems',
uuid: 'invalid',
gems: {
amount: 16,
},
};
const metadata = { userId: user._id, gift: JSON.stringify(gift) };
const session = { metadata, customer: customerId };
await expect(applyGemPayment(session))
.to.eventually.be.rejected.and.to.eql({
httpCode: 404,
name: 'NotFound',
message: i18n.t('userWithIDNotFound', { userId: 'invalid' }),
});
});
describe('with existing user', () => {
beforeEach(() => {
const execStub = sandbox.stub().resolves(user);
userFindByIdStub = sandbox.stub(User, 'findById');
userFindByIdStub.withArgs(user._id).returns({ exec: execStub });
});
it('buys gems', async () => {
const metadata = { userId: user._id, gemsBlock: '21gems' };
const session = { metadata, customer: customerId };
await applyGemPayment(session);
expect(paymentBuyGemsStub).to.be.calledOnce;
expect(paymentBuyGemsStub).to.be.calledWith({
user,
customerId,
paymentMethod: 'Stripe',
gift: undefined,
gemsBlock: common.content.gems['21gems'],
});
});
it('gift gems', async () => {
const receivingUser = new User();
const execStub = sandbox.stub().resolves(receivingUser);
userFindByIdStub.withArgs(receivingUser._id).returns({ exec: execStub });
const gift = {
type: 'gems',
uuid: receivingUser._id,
gems: {
amount: 16,
},
};
sandbox.stub(JSON, 'parse').returns(gift);
const metadata = { userId: user._id, gift: JSON.stringify(gift) };
const session = { metadata, customer: customerId };
await applyGemPayment(session);
expect(paymentBuyGemsStub).to.be.calledOnce;
expect(paymentBuyGemsStub).to.be.calledWith({
user,
customerId,
paymentMethod: 'Gift',
gift,
gemsBlock: undefined,
});
});
it('gift sub', async () => {
const receivingUser = new User();
const execStub = sandbox.stub().resolves(receivingUser);
userFindByIdStub.withArgs(receivingUser._id).returns({ exec: execStub });
const gift = {
type: 'subscription',
uuid: receivingUser._id,
subscription: {
key: subKey,
},
};
sandbox.stub(JSON, 'parse').returns(gift);
const metadata = { userId: user._id, gift: JSON.stringify(gift) };
const session = { metadata, customer: customerId };
await applyGemPayment(session);
expect(paymentsCreateSubSpy).to.be.calledOnce;
expect(paymentsCreateSubSpy).to.be.calledWith({
user,
customerId,
paymentMethod: 'Gift',
gift,
gemsBlock: undefined,
});
});
});
});
});
@@ -0,0 +1,442 @@
import cc from 'coupon-code';
import stripeModule from 'stripe';
import { model as Coupon } from '../../../../../../website/server/models/coupon';
import common from '../../../../../../website/common';
import {
checkSubData,
applySubscription,
chargeForAdditionalGroupMember,
handlePaymentMethodChange,
} from '../../../../../../website/server/libs/payments/stripe/subscriptions';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import payments from '../../../../../../website/server/libs/payments/payments';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
const { i18n } = common;
describe('Stripe - Subscriptions', () => {
describe('checkSubData', () => {
it('does not throw if the subscription can be used', async () => {
const sub = common.content.subscriptionBlocks['basic_3mo']; // eslint-disable-line dot-notation
const res = await checkSubData(sub);
expect(res).to.equal(undefined);
});
it('throws if the subscription does not exists', async () => {
await expect(checkSubData())
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: i18n.t('missingSubscriptionCode'),
});
});
it('throws if the subscription can\'t be used', async () => {
const sub = common.content.subscriptionBlocks['group_plan_auto']; // eslint-disable-line dot-notation
await expect(checkSubData(sub, true))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: i18n.t('missingSubscriptionCode'),
});
});
it('throws if the subscription targets a group and an user is making the request', async () => {
const sub = common.content.subscriptionBlocks['group_monthly']; // eslint-disable-line dot-notation
await expect(checkSubData(sub, false))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: i18n.t('missingSubscriptionCode'),
});
});
it('throws if the subscription targets an user and a group is making the request', async () => {
const sub = common.content.subscriptionBlocks['basic_3mo']; // eslint-disable-line dot-notation
await expect(checkSubData(sub, true))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: i18n.t('missingSubscriptionCode'),
});
});
it('throws if the coupon is required but not passed', async () => {
const sub = common.content.subscriptionBlocks['google_6mo']; // eslint-disable-line dot-notation
await expect(checkSubData(sub, false))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: i18n.t('couponCodeRequired'),
});
});
it('throws if the coupon is required but does not exist', async () => {
const coupon = 'not-valid';
const sub = common.content.subscriptionBlocks['google_6mo']; // eslint-disable-line dot-notation
await expect(checkSubData(sub, false, coupon))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: i18n.t('invalidCoupon'),
});
});
it('throws if the coupon is required but is invalid', async () => {
const couponModel = new Coupon();
couponModel.event = 'google_6mo';
await couponModel.save();
sandbox.stub(cc, 'validate').returns('invalid');
const sub = common.content.subscriptionBlocks['google_6mo']; // eslint-disable-line dot-notation
await expect(checkSubData(sub, false, couponModel._id))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: i18n.t('invalidCoupon'),
});
});
it('works if the coupon is required and valid', async () => {
const couponModel = new Coupon();
couponModel.event = 'google_6mo';
await couponModel.save();
sandbox.stub(cc, 'validate').returns(couponModel._id);
const sub = common.content.subscriptionBlocks['google_6mo']; // eslint-disable-line dot-notation
await checkSubData(sub, false, couponModel._id);
});
});
describe('applySubscription', () => {
let user; let group; let sub;
let groupId;
let customerId; let subscriptionId;
let subKey;
let userFindByIdStub;
let stripePaymentsCreateSubSpy;
beforeEach(async () => {
subKey = 'basic_3mo';
sub = common.content.subscriptionBlocks[subKey];
user = new User();
await user.save();
const execStub = sandbox.stub().resolves(user);
userFindByIdStub = sandbox.stub(User, 'findById');
userFindByIdStub.withArgs(user._id).returns({ exec: execStub });
group = generateGroup({
name: 'test group',
type: 'guild',
privacy: 'public',
leader: user._id,
});
groupId = group._id;
await group.save();
// Add user to group
user.guilds.push(groupId);
await user.save();
customerId = 'test-id';
subscriptionId = 'test-sub-id';
stripePaymentsCreateSubSpy = sandbox.stub(payments, 'createSubscription');
stripePaymentsCreateSubSpy.resolves({});
});
it('subscribes a user', async () => {
await applySubscription({
customer: customerId,
subscription: subscriptionId,
metadata: {
sub: JSON.stringify(sub),
userId: user._id,
groupId: null,
},
user,
});
expect(stripePaymentsCreateSubSpy).to.be.calledOnce;
expect(stripePaymentsCreateSubSpy).to.be.calledWith({
user,
customerId,
subscriptionId,
paymentMethod: 'Stripe',
sub: sinon.match({ ...sub }),
groupId: null,
});
});
it('subscribes a group', async () => {
sub = common.content.subscriptionBlocks['group_monthly']; // eslint-disable-line dot-notation
await applySubscription({
customer: customerId,
subscription: subscriptionId,
metadata: {
sub: JSON.stringify(sub),
userId: user._id,
groupId,
},
user,
});
expect(stripePaymentsCreateSubSpy).to.be.calledOnce;
expect(stripePaymentsCreateSubSpy).to.be.calledWith({
user,
customerId,
subscriptionId,
paymentMethod: 'Stripe',
sub: sinon.match({ ...sub }),
groupId,
});
});
it('subscribes a group with multiple users', async () => {
const user2 = new User();
user2.guilds.push(groupId);
await user2.save();
const execStub2 = sandbox.stub().resolves(user);
userFindByIdStub.withArgs(user2._id).returns({ exec: execStub2 });
group.memberCount = 2;
await group.save();
sub = common.content.subscriptionBlocks['group_monthly']; // eslint-disable-line dot-notation
await applySubscription({
customer: customerId,
subscription: subscriptionId,
metadata: {
sub: JSON.stringify(sub),
userId: user._id,
groupId,
},
user,
});
expect(stripePaymentsCreateSubSpy).to.be.calledOnce;
expect(stripePaymentsCreateSubSpy).to.be.calledWith({
user,
customerId,
subscriptionId,
paymentMethod: 'Stripe',
sub: sinon.match({ ...sub }),
groupId,
});
});
});
describe('handlePaymentMethodChange', () => {
const stripe = stripeModule('test', {
apiVersion: '2020-08-27',
});
it('updates the plan quantity based on the number of group members', async () => {
const stripeIntentRetrieveStub = sandbox.stub(stripe.setupIntents, 'retrieve').resolves({
payment_method: 1,
metadata: {
subscription_id: 2,
},
});
const stripeSubUpdateStub = sandbox.stub(stripe.subscriptions, 'update');
await handlePaymentMethodChange({}, stripe);
expect(stripeIntentRetrieveStub).to.be.calledOnce;
expect(stripeSubUpdateStub).to.be.calledOnce;
expect(stripeSubUpdateStub).to.be.calledWith(2, {
default_payment_method: 1,
});
});
});
describe('chargeForAdditionalGroupMember', () => {
const stripe = stripeModule('test', {
apiVersion: '2020-08-27',
});
let stripeUpdateSubStub;
const plan = common.content.subscriptionBlocks['group_monthly']; // eslint-disable-line dot-notation
let user; let group;
beforeEach(async () => {
user = new User();
group = generateGroup({
name: 'test group',
type: 'guild',
privacy: 'public',
leader: user._id,
});
group.purchased.plan.customerId = 'customer-id';
group.purchased.plan.planId = plan.key;
group.purchased.plan.subscriptionId = 'sub-id';
await group.save();
stripeUpdateSubStub = sandbox.stub(stripe.subscriptions, 'update').resolves({});
});
it('updates the plan quantity based on the number of group members', async () => {
group.memberCount = 4;
const newQuantity = group.memberCount + plan.quantity - 1;
await chargeForAdditionalGroupMember(group, stripe);
expect(stripeUpdateSubStub).to.be.calledWithMatch(
group.purchased.plan.subscriptionId,
sinon.match({
plan: group.purchased.plan.planId,
quantity: newQuantity,
}),
);
expect(group.purchased.plan.quantity).to.equal(newQuantity);
});
});
describe('cancelSubscription', () => {
const subKey = 'basic_3mo';
const stripe = stripeModule('test', {
apiVersion: '2020-08-27',
});
let user; let groupId; let
group;
beforeEach(async () => {
user = new User();
user.profile.name = 'sender';
user.purchased.plan.customerId = 'customer-id';
user.purchased.plan.planId = subKey;
user.purchased.plan.lastBillingDate = new Date();
group = generateGroup({
name: 'test group',
type: 'guild',
privacy: 'public',
leader: user._id,
});
group.purchased.plan.customerId = 'customer-id';
group.purchased.plan.planId = subKey;
await group.save();
groupId = group._id;
});
it('throws an error if there is no customer id', async () => {
user.purchased.plan.customerId = undefined;
await expect(stripePayments.cancelSubscription({
user,
groupId: undefined,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('missingSubscription'),
});
});
it('throws an error if the group is not found', async () => {
await expect(stripePayments.cancelSubscription({
user,
groupId: 'fake-group',
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 404,
name: 'NotFound',
message: i18n.t('groupNotFound'),
});
});
it('throws an error if user is not the group leader', async () => {
const nonLeader = new User();
nonLeader.guilds.push(groupId);
await nonLeader.save();
await expect(stripePayments.cancelSubscription({
user: nonLeader,
groupId,
}))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: i18n.t('onlyGroupLeaderCanManageSubscription'),
});
});
describe('success', () => {
let stripeDeleteCustomerStub; let paymentsCancelSubStub;
let stripeRetrieveStub; let subscriptionId; let
currentPeriodEndTimeStamp;
beforeEach(() => {
subscriptionId = 'subId';
stripeDeleteCustomerStub = sinon.stub(stripe.customers, 'del').resolves({});
paymentsCancelSubStub = sinon.stub(payments, 'cancelSubscription').resolves({});
currentPeriodEndTimeStamp = (new Date()).getTime();
stripeRetrieveStub = sinon.stub(stripe.customers, 'retrieve')
.resolves({
subscriptions: {
data: [{
id: subscriptionId,
current_period_end: currentPeriodEndTimeStamp,
}], // eslint-disable-line camelcase
},
});
});
afterEach(() => {
stripe.customers.del.restore();
stripe.customers.retrieve.restore();
payments.cancelSubscription.restore();
});
it('cancels a user subscription', async () => {
await stripePayments.cancelSubscription({
user,
groupId: undefined,
}, stripe);
expect(stripeDeleteCustomerStub).to.be.calledOnce;
expect(stripeDeleteCustomerStub).to.be.calledWith(user.purchased.plan.customerId);
expect(stripeRetrieveStub).to.be.calledOnce;
expect(stripeRetrieveStub).to.be.calledWith(user.purchased.plan.customerId);
expect(paymentsCancelSubStub).to.be.calledOnce;
expect(paymentsCancelSubStub).to.be.calledWith({
user,
groupId: undefined,
nextBill: currentPeriodEndTimeStamp * 1000, // timestamp in seconds
paymentMethod: 'Stripe',
cancellationReason: undefined,
});
});
it('cancels a group subscription', async () => {
await stripePayments.cancelSubscription({
user,
groupId,
}, stripe);
expect(stripeDeleteCustomerStub).to.be.calledOnce;
expect(stripeDeleteCustomerStub).to.be.calledWith(group.purchased.plan.customerId);
expect(stripeRetrieveStub).to.be.calledOnce;
expect(stripeRetrieveStub).to.be.calledWith(user.purchased.plan.customerId);
expect(paymentsCancelSubStub).to.be.calledOnce;
expect(paymentsCancelSubStub).to.be.calledWith({
user,
groupId,
nextBill: currentPeriodEndTimeStamp * 1000, // timestamp in seconds
paymentMethod: 'Stripe',
cancellationReason: undefined,
});
});
});
});
});
@@ -1,70 +0,0 @@
import stripeModule from 'stripe';
import {
generateGroup,
} from '../../../../../helpers/api-unit.helper';
import { model as User } from '../../../../../../website/server/models/user';
import { model as Group } from '../../../../../../website/server/models/group';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import payments from '../../../../../../website/server/libs/payments/payments';
describe('Stripe - Upgrade Group Plan', () => {
const stripe = stripeModule('test');
let spy; let data; let user; let
group;
beforeEach(async () => {
user = new User();
user.profile.name = 'sender';
data = {
user,
sub: {
key: 'basic_3mo', // @TODO: Validate that this is group
},
customerId: 'customer-id',
paymentMethod: 'Payment Method',
headers: {
'x-client': 'habitica-web',
'user-agent': '',
},
};
group = generateGroup({
name: 'test group',
type: 'guild',
privacy: 'private',
leader: user._id,
});
await group.save();
user.guilds.push(group._id);
await user.save();
spy = sinon.stub(stripe.subscriptions, 'update');
spy.resolves([]);
data.groupId = group._id;
data.sub.quantity = 3;
stripePayments.setStripeApi(stripe);
});
afterEach(() => {
stripe.subscriptions.update.restore();
});
it('updates a group plan quantity', async () => {
data.paymentMethod = 'Stripe';
await payments.createSubscription(data);
const updatedGroup = await Group.findById(group._id).exec();
expect(updatedGroup.purchased.plan.quantity).to.eql(3);
updatedGroup.memberCount += 1;
await updatedGroup.save();
await stripePayments.chargeForAdditionalGroupMember(updatedGroup);
expect(spy.calledOnce).to.be.true;
expect(updatedGroup.purchased.plan.quantity).to.eql(4);
});
});
@@ -1,5 +1,5 @@
import stripeModule from 'stripe';
import nconf from 'nconf';
import { v4 as uuid } from 'uuid';
import moment from 'moment';
import {
@@ -10,76 +10,104 @@ import stripePayments from '../../../../../../website/server/libs/payments/strip
import payments from '../../../../../../website/server/libs/payments/payments';
import common from '../../../../../../website/common';
import logger from '../../../../../../website/server/libs/logger';
import * as oneTimePayments from '../../../../../../website/server/libs/payments/stripe/oneTimePayments';
import * as subscriptions from '../../../../../../website/server/libs/payments/stripe/subscriptions';
const { i18n } = common;
describe('Stripe - Webhooks', () => {
const stripe = stripeModule('test');
const stripe = stripeModule('test', {
apiVersion: '2020-08-27',
});
const endpointSecret = nconf.get('STRIPE_WEBHOOKS_ENDPOINT_SECRET');
const headers = {};
const body = {};
describe('all events', () => {
const eventType = 'account.updated';
const event = { id: 123 };
const eventRetrieved = { type: eventType };
let event;
let constructEventStub;
beforeEach(() => {
sinon.stub(stripe.events, 'retrieve').resolves(eventRetrieved);
sinon.stub(logger, 'error');
event = { type: 'payment_intent.created' };
constructEventStub = sandbox.stub(stripe.webhooks, 'constructEvent');
constructEventStub.returns(event);
sandbox.stub(logger, 'error');
});
afterEach(() => {
stripe.events.retrieve.restore();
logger.error.restore();
it('throws if the event can\'t be validated', async () => {
const err = new Error('fail');
constructEventStub.throws(err);
await expect(stripePayments.handleWebhooks({ body: event, headers }, stripe))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: `Webhook Error: ${err.message}`,
});
expect(logger.error).to.have.been.calledOnce;
const calledWith = logger.error.getCall(0).args;
expect(calledWith[0].message).to.equal('Error verifying Stripe webhook');
expect(calledWith[1]).to.eql({ err });
});
it('logs an error if an unsupported webhook event is passed', async () => {
const error = new Error(`Missing handler for Stripe webhook ${eventType}`);
await stripePayments.handleWebhooks({ requestBody: event }, stripe);
expect(logger.error).to.have.been.calledOnce;
event.type = 'account.updated';
await expect(stripePayments.handleWebhooks({ body, headers }, stripe))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: `Missing handler for Stripe webhook ${event.type}`,
});
expect(logger.error).to.have.been.calledOnce;
const calledWith = logger.error.getCall(0).args;
expect(calledWith[0].message).to.equal(error.message);
expect(calledWith[1].event).to.equal(eventRetrieved);
expect(calledWith[0].message).to.equal('Error handling Stripe webhook');
expect(calledWith[1].event).to.eql(event);
expect(calledWith[1].err.message).to.eql(`Missing handler for Stripe webhook ${event.type}`);
});
it('retrieves and validates the event from Stripe', async () => {
await stripePayments.handleWebhooks({ requestBody: event }, stripe);
expect(stripe.events.retrieve).to.have.been.calledOnce;
expect(stripe.events.retrieve).to.have.been.calledWith(event.id);
await stripePayments.handleWebhooks({ body, headers }, stripe);
expect(stripe.webhooks.constructEvent).to.have.been.calledOnce;
expect(stripe.webhooks.constructEvent)
.to.have.been.calledWith(body, undefined, endpointSecret);
});
});
describe('customer.subscription.deleted', () => {
const eventType = 'customer.subscription.deleted';
let event;
let constructEventStub;
beforeEach(() => {
sinon.stub(stripe.customers, 'del').resolves({});
sinon.stub(payments, 'cancelSubscription').resolves({});
event = { type: eventType };
constructEventStub = sandbox.stub(stripe.webhooks, 'constructEvent');
constructEventStub.returns(event);
});
afterEach(() => {
stripe.customers.del.restore();
payments.cancelSubscription.restore();
beforeEach(() => {
sandbox.stub(stripe.customers, 'del').resolves({});
sandbox.stub(payments, 'cancelSubscription').resolves({});
});
it('does not do anything if event.request is null (subscription cancelled manually)', async () => {
sinon.stub(stripe.events, 'retrieve').resolves({
constructEventStub.returns({
id: 123,
type: eventType,
request: 123,
});
await stripePayments.handleWebhooks({ requestBody: {} }, stripe);
await stripePayments.handleWebhooks({ body, headers }, stripe);
expect(stripe.events.retrieve).to.have.been.calledOnce;
expect(stripe.webhooks.constructEvent).to.have.been.calledOnce;
expect(stripe.customers.del).to.not.have.been.called;
expect(payments.cancelSubscription).to.not.have.been.called;
stripe.events.retrieve.restore();
});
describe('user subscription', () => {
it('throws an error if the user is not found', async () => {
const customerId = 456;
sinon.stub(stripe.events, 'retrieve').resolves({
constructEventStub.returns({
id: 123,
type: eventType,
data: {
@@ -93,7 +121,7 @@ describe('Stripe - Webhooks', () => {
request: null,
});
await expect(stripePayments.handleWebhooks({ requestBody: {} }, stripe))
await expect(stripePayments.handleWebhooks({ body, headers }, stripe))
.to.eventually.be.rejectedWith({
message: i18n.t('userNotFound'),
httpCode: 404,
@@ -102,8 +130,6 @@ describe('Stripe - Webhooks', () => {
expect(stripe.customers.del).to.not.have.been.called;
expect(payments.cancelSubscription).to.not.have.been.called;
stripe.events.retrieve.restore();
});
it('deletes the customer on Stripe and calls payments.cancelSubscription', async () => {
@@ -114,7 +140,7 @@ describe('Stripe - Webhooks', () => {
subscriber.purchased.plan.paymentMethod = 'Stripe';
await subscriber.save();
sinon.stub(stripe.events, 'retrieve').resolves({
constructEventStub.returns({
id: 123,
type: eventType,
data: {
@@ -128,7 +154,7 @@ describe('Stripe - Webhooks', () => {
request: null,
});
await stripePayments.handleWebhooks({ requestBody: {} }, stripe);
await stripePayments.handleWebhooks({ body, headers }, stripe);
expect(stripe.customers.del).to.have.been.calledOnce;
expect(stripe.customers.del).to.have.been.calledWith(customerId);
@@ -139,15 +165,13 @@ describe('Stripe - Webhooks', () => {
expect(cancelSubscriptionOpts.paymentMethod).to.equal('Stripe');
expect(Math.round(moment(cancelSubscriptionOpts.nextBill).diff(new Date(), 'days', true))).to.equal(3);
expect(cancelSubscriptionOpts.groupId).to.be.undefined;
stripe.events.retrieve.restore();
});
});
describe('group plan subscription', () => {
it('throws an error if the group is not found', async () => {
const customerId = 456;
sinon.stub(stripe.events, 'retrieve').resolves({
constructEventStub.returns({
id: 123,
type: eventType,
data: {
@@ -161,7 +185,7 @@ describe('Stripe - Webhooks', () => {
request: null,
});
await expect(stripePayments.handleWebhooks({ requestBody: {} }, stripe))
await expect(stripePayments.handleWebhooks({ body, headers }, stripe))
.to.eventually.be.rejectedWith({
message: i18n.t('groupNotFound'),
httpCode: 404,
@@ -170,8 +194,6 @@ describe('Stripe - Webhooks', () => {
expect(stripe.customers.del).to.not.have.been.called;
expect(payments.cancelSubscription).to.not.have.been.called;
stripe.events.retrieve.restore();
});
it('throws an error if the group leader is not found', async () => {
@@ -187,7 +209,7 @@ describe('Stripe - Webhooks', () => {
subscriber.purchased.plan.paymentMethod = 'Stripe';
await subscriber.save();
sinon.stub(stripe.events, 'retrieve').resolves({
constructEventStub.returns({
id: 123,
type: eventType,
data: {
@@ -201,7 +223,7 @@ describe('Stripe - Webhooks', () => {
request: null,
});
await expect(stripePayments.handleWebhooks({ requestBody: {} }, stripe))
await expect(stripePayments.handleWebhooks({ body, headers }, stripe))
.to.eventually.be.rejectedWith({
message: i18n.t('userNotFound'),
httpCode: 404,
@@ -210,8 +232,6 @@ describe('Stripe - Webhooks', () => {
expect(stripe.customers.del).to.not.have.been.called;
expect(payments.cancelSubscription).to.not.have.been.called;
stripe.events.retrieve.restore();
});
it('deletes the customer on Stripe and calls payments.cancelSubscription', async () => {
@@ -230,7 +250,7 @@ describe('Stripe - Webhooks', () => {
subscriber.purchased.plan.paymentMethod = 'Stripe';
await subscriber.save();
sinon.stub(stripe.events, 'retrieve').resolves({
constructEventStub.returns({
id: 123,
type: eventType,
data: {
@@ -244,7 +264,7 @@ describe('Stripe - Webhooks', () => {
request: null,
});
await stripePayments.handleWebhooks({ requestBody: {} }, stripe);
await stripePayments.handleWebhooks({ body, headers }, stripe);
expect(stripe.customers.del).to.have.been.calledOnce;
expect(stripe.customers.del).to.have.been.calledWith(customerId);
@@ -255,9 +275,65 @@ describe('Stripe - Webhooks', () => {
expect(cancelSubscriptionOpts.paymentMethod).to.equal('Stripe');
expect(Math.round(moment(cancelSubscriptionOpts.nextBill).diff(new Date(), 'days', true))).to.equal(3);
expect(cancelSubscriptionOpts.groupId).to.equal(subscriber._id);
stripe.events.retrieve.restore();
});
});
});
describe('checkout.session.completed', () => {
const eventType = 'checkout.session.completed';
let event;
let constructEventStub;
const session = {};
beforeEach(() => {
session.metadata = {};
event = { type: eventType, data: { object: session } };
constructEventStub = sandbox.stub(stripe.webhooks, 'constructEvent');
constructEventStub.returns(event);
sandbox.stub(oneTimePayments, 'applyGemPayment').resolves({});
sandbox.stub(subscriptions, 'applySubscription').resolves({});
sandbox.stub(subscriptions, 'handlePaymentMethodChange').resolves({});
});
it('handles changing an user sub', async () => {
session.metadata.type = 'edit-card-user';
await stripePayments.handleWebhooks({ body, headers }, stripe);
expect(stripe.webhooks.constructEvent).to.have.been.calledOnce;
expect(subscriptions.handlePaymentMethodChange).to.have.been.calledOnce;
expect(subscriptions.handlePaymentMethodChange).to.have.been.calledWith(session);
});
it('handles changing a group sub', async () => {
session.metadata.type = 'edit-card-group';
await stripePayments.handleWebhooks({ body, headers }, stripe);
expect(stripe.webhooks.constructEvent).to.have.been.calledOnce;
expect(subscriptions.handlePaymentMethodChange).to.have.been.calledOnce;
expect(subscriptions.handlePaymentMethodChange).to.have.been.calledWith(session);
});
it('applies a subscription', async () => {
session.metadata.type = 'subscription';
await stripePayments.handleWebhooks({ body, headers }, stripe);
expect(stripe.webhooks.constructEvent).to.have.been.calledOnce;
expect(subscriptions.applySubscription).to.have.been.calledOnce;
expect(subscriptions.applySubscription).to.have.been.calledWith(session);
});
it('handles a one time payment', async () => {
session.metadata.type = 'something else';
await stripePayments.handleWebhooks({ body, headers }, stripe);
expect(stripe.webhooks.constructEvent).to.have.been.calledOnce;
expect(oneTimePayments.applyGemPayment).to.have.been.calledOnce;
expect(oneTimePayments.applyGemPayment).to.have.been.calledWith(session);
});
});
});
+1 -1
View File
@@ -1,4 +1,4 @@
import apn from 'apn/mock';
import apn from '@parse/node-apn/mock';
import _ from 'lodash';
import nconf from 'nconf';
import gcmLib from 'node-gcm'; // works with FCM notifications too
+3 -2
View File
@@ -1,5 +1,5 @@
/* eslint-disable camelcase */
import { IncomingWebhook } from '@slack/client';
import { IncomingWebhook } from '@slack/webhook';
import requireAgain from 'require-again';
import nconf from 'nconf';
import moment from 'moment';
@@ -12,7 +12,7 @@ describe('slack', () => {
let data;
beforeEach(() => {
sandbox.stub(IncomingWebhook.prototype, 'send');
sandbox.stub(IncomingWebhook.prototype, 'send').returns(Promise.resolve());
data = {
authorEmail: 'author@example.com',
flagger: {
@@ -112,6 +112,7 @@ describe('slack', () => {
it('noops if no flagging url is provided', () => {
sandbox.stub(nconf, 'get').withArgs('SLACK_FLAGGING_URL').returns('');
nconf.get.withArgs('IS_TEST').returns(true);
sandbox.stub(logger, 'error');
const reRequiredSlack = requireAgain('../../../../website/server/libs/slack');
+5
View File
@@ -8,5 +8,10 @@ describe('stringUtils', () => {
const matches = getMatchesByWordArray(message, bannedWords);
expect(matches.length).to.equal(bannedWords.length);
});
it('doesn\'t flag names with accented characters', () => {
const name = 'TESTPLACEHOLDERSWEARWORDHEREé';
const matches = getMatchesByWordArray(name, bannedWords);
expect(matches.length).to.equal(0);
});
});
});
+44
View File
@@ -0,0 +1,44 @@
import * as xmlMarshaller from '../../../../website/server/libs/xmlMarshaller';
describe('xml marshaller marshalls user data', () => {
const minimumUser = {
pinnedItems: [],
unpinnedItems: [],
inbox: {},
};
function userDataWith (fields) {
return { ...minimumUser, ...fields };
}
it('maps the newMessages field to have id as a value in a list.', () => {
const userData = userDataWith({
newMessages: {
'283171a5-422c-4991-bc78-95b1b5b51629': {
name: 'The Language Hackers',
value: true,
},
'283171a6-422c-4991-bc78-95b1b5b51629': {
name: 'The Bug Hackers',
value: false,
},
},
});
const xml = xmlMarshaller.marshallUserData(userData);
expect(xml).to.equal(`<user>
<inbox/>
<newMessages>
<id>283171a5-422c-4991-bc78-95b1b5b51629</id>
<name>The Language Hackers</name>
<value>true</value>
</newMessages>
<newMessages>
<id>283171a6-422c-4991-bc78-95b1b5b51629</id>
<name>The Bug Hackers</name>
<value>false</value>
</newMessages>
</user>`);
});
});
@@ -293,4 +293,90 @@ describe('cron middleware', () => {
});
});
});
context('Drop Cap A/B Test', async () => {
it('enrolls web users', async () => {
user.lastCron = moment(new Date()).subtract({ days: 2 });
await user.save();
req.headers['x-client'] = 'habitica-web';
await new Promise((resolve, reject) => {
cronMiddleware(req, res, async err => {
if (err) return reject(err);
user = await User.findById(user._id).exec();
expect(user._ABtests.dropCapNotif).to.be.a.string;
return resolve();
});
});
});
it('enables the new notification for 50% of users', async () => {
sandbox.stub(Math, 'random').returns(0.5);
user.lastCron = moment(new Date()).subtract({ days: 2 });
await user.save();
req.headers['x-client'] = 'habitica-web';
await new Promise((resolve, reject) => {
cronMiddleware(req, res, async err => {
if (err) return reject(err);
user = await User.findById(user._id).exec();
expect(user._ABtests.dropCapNotif).to.be.equal('drop-cap-notif-enabled');
return resolve();
});
});
});
it('disables the new notification for 50% of users', async () => {
sandbox.stub(Math, 'random').returns(0.51);
user.lastCron = moment(new Date()).subtract({ days: 2 });
await user.save();
req.headers['x-client'] = 'habitica-web';
await new Promise((resolve, reject) => {
cronMiddleware(req, res, async err => {
if (err) return reject(err);
user = await User.findById(user._id).exec();
expect(user._ABtests.dropCapNotif).to.be.equal('drop-cap-notif-disabled');
return resolve();
});
});
});
it('does not affect subscribers', async () => {
sandbox.stub(Math, 'random').returns(0.2);
user.lastCron = moment(new Date()).subtract({ days: 2 });
await user.save();
req.headers['x-client'] = 'habitica-web';
sandbox.stub(User.prototype, 'isSubscribed').returns(true);
await new Promise((resolve, reject) => {
cronMiddleware(req, res, async err => {
if (err) return reject(err);
user = await User.findById(user._id).exec();
expect(user._ABtests.dropCapNotif).to.not.exist;
return resolve();
});
});
});
it('does not affect mobile users', async () => {
user.lastCron = moment(new Date()).subtract({ days: 2 });
await user.save();
req.headers['x-client'] = 'habitica-ios';
await new Promise((resolve, reject) => {
cronMiddleware(req, res, async err => {
if (err) return reject(err);
user = await User.findById(user._id).exec();
expect(user._ABtests.dropCapNotif).to.not.exist;
return resolve();
});
});
});
});
});
@@ -5,7 +5,7 @@ import {
generateNext,
} from '../../../helpers/api-unit.helper';
import i18n from '../../../../website/common/script/i18n';
import { ensureAdmin, ensureSudo } from '../../../../website/server/middlewares/ensureAccessRight';
import { ensureAdmin, ensureSudo, ensureNewsPoster } from '../../../../website/server/middlewares/ensureAccessRight';
import { NotAuthorized } from '../../../../website/server/libs/errors';
import apiError from '../../../../website/server/libs/apiError';
@@ -40,6 +40,27 @@ describe('ensure access middlewares', () => {
});
});
context('ensure newsPoster', () => {
it('returns not authorized when user is not a newsPoster', () => {
res.locals = { user: { contributor: { newsPoster: false } } };
ensureNewsPoster(req, res, next);
const calledWith = next.getCall(0).args;
expect(calledWith[0].message).to.equal(apiError('noNewsPosterAccess'));
expect(calledWith[0] instanceof NotAuthorized).to.equal(true);
});
it('passes when user is a newsPoster', () => {
res.locals = { user: { contributor: { newsPoster: true } } };
ensureNewsPoster(req, res, next);
expect(next).to.be.calledOnce;
expect(next.args[0]).to.be.empty;
});
});
context('ensure sudo', () => {
it('returns not authorized when user is not a sudo user', () => {
res.locals = { user: { contributor: { sudo: false } } };
+138
View File
@@ -0,0 +1,138 @@
import { v4 } from 'uuid';
import { model as NewsPost, refreshNewsPost } from '../../../../website/server/models/newsPost';
import { sleep } from '../../../helpers/api-unit.helper';
describe('NewsPost Model', () => {
const publishDate = Number(new Date());
// NOTE publishDate is manually increased by +500 for each test
// to make sure it's always in the future from the previous one
// bevause NewsPost.lastNewsPost() is not reset between tests.
// And without a more recent publishDate it wouldn't update
it('#lastNewsPost', () => {
const lastPost = { _id: v4(), publishDate, published: true };
NewsPost.updateLastNewsPost(lastPost);
expect(NewsPost.lastNewsPost()).to.equal(lastPost);
});
it('#getLastPostFromDatabase', async () => {
const expectedId = v4();
await NewsPost.create([
// more recent but not published
{
_id: v4(),
publishDate: new Date(publishDate + 50),
author: v4(),
published: false,
title: 'Title',
credits: 'credits',
text: 'text',
},
// expected
{
_id: expectedId,
publishDate,
author: v4(),
published: true,
title: 'Title',
credits: 'credits',
text: 'text',
},
// published but less recent
{
_id: v4(),
publishDate: new Date(Number(publishDate) - 50),
author: v4(),
published: true,
title: 'Title',
credits: 'credits',
text: 'text',
},
]);
const fetched = await NewsPost.getLastPostFromDatabase();
expect(fetched._id).to.equal(expectedId);
});
context('#updateLastNewsPost', () => {
it('updates the post if new one is more recent and published', () => {
const previousPost = {
_id: v4(),
publishDate: new Date(publishDate + 100),
published: true,
};
NewsPost.updateLastNewsPost(previousPost);
const newPost = {
_id: v4(),
publishDate: new Date(publishDate + 150),
published: true,
};
NewsPost.updateLastNewsPost(newPost);
expect(NewsPost.lastNewsPost()._id).to.equal(newPost._id);
});
it('does not update the post if new one is from the past', () => {
const previousPost = new NewsPost({
_id: v4(), publishDate: new Date(publishDate + 200), published: true,
});
NewsPost.updateLastNewsPost(previousPost);
const newPost = new NewsPost({
_id: v4(), publishDate: new Date(publishDate + 175), published: true,
});
NewsPost.updateLastNewsPost(newPost);
expect(NewsPost.lastNewsPost()._id).to.equal(previousPost._id);
});
it('does not update the post if new one is not published', () => {
const previousPost = new NewsPost({
_id: v4(), publishDate: new Date(publishDate + 250), published: true,
});
NewsPost.updateLastNewsPost(previousPost);
const newPost = new NewsPost({
_id: v4(), publishDate: new Date(publishDate + 300), published: false,
});
NewsPost.updateLastNewsPost(newPost);
expect(NewsPost.lastNewsPost()._id).to.equal(previousPost._id);
});
});
context('refreshes NewsPost', () => {
let intervalId;
beforeEach(async () => {
// Delete all existing posts from the database
await NewsPost.remove();
});
afterEach(() => {
if (intervalId) clearInterval(intervalId);
});
it('refreshes the last post at a specific interval', async () => {
await sleep(0.1); // wait 100ms to make sure all previous posts are in the past
const previousPost = {
_id: v4(), publishDate: new Date(), published: true,
};
NewsPost.updateLastNewsPost(previousPost);
intervalId = refreshNewsPost(50); // refreshes every 50ms
await sleep(0.1); // wait 100ms to make sure the new post has a more recent publishDate
const newPost = await NewsPost.create({
_id: v4(),
publishDate: new Date(),
author: v4(),
published: true,
title: 'Title',
credits: 'credits',
text: 'text',
});
expect(NewsPost.lastNewsPost()._id).to.equal(previousPost._id);
await sleep(0.15); // wait 150ms
expect(NewsPost.lastNewsPost()._id).to.equal(newPost._id);
});
});
});
+153 -64
View File
@@ -1,87 +1,90 @@
import moment from 'moment';
import { model as User } from '../../../../website/server/models/user';
import { model as NewsPost } from '../../../../website/server/models/newsPost';
import { model as Group } from '../../../../website/server/models/group';
import common from '../../../../website/common';
describe('User Model', () => {
it('keeps user._tmp when calling .toJSON', () => {
const user = new User({
auth: {
local: {
username: 'username',
lowerCaseUsername: 'username',
email: 'email@email.email',
salt: 'salt',
hashed_password: 'hashed_password', // eslint-disable-line camelcase
describe('.toJSON()', () => {
it('keeps user._tmp when calling .toJSON', () => {
const user = new User({
auth: {
local: {
username: 'username',
lowerCaseUsername: 'username',
email: 'email@email.email',
salt: 'salt',
hashed_password: 'hashed_password', // eslint-disable-line camelcase
},
},
},
});
user._tmp = { ok: true };
user._nonTmp = { ok: true };
expect(user._tmp).to.eql({ ok: true });
expect(user._nonTmp).to.eql({ ok: true });
const toObject = user.toObject();
const toJSON = user.toJSON();
expect(toObject).to.not.have.keys('_tmp');
expect(toObject).to.not.have.keys('_nonTmp');
expect(toJSON).to.have.any.key('_tmp');
expect(toJSON._tmp).to.eql({ ok: true });
expect(toJSON).to.not.have.keys('_nonTmp');
});
user._tmp = { ok: true };
user._nonTmp = { ok: true };
it('can add computed stats to a JSONified user object', () => {
const user = new User();
const userToJSON = user.toJSON();
expect(user._tmp).to.eql({ ok: true });
expect(user._nonTmp).to.eql({ ok: true });
expect(userToJSON.stats.maxMP).to.not.exist;
expect(userToJSON.stats.maxHealth).to.not.exist;
expect(userToJSON.stats.toNextLevel).to.not.exist;
const toObject = user.toObject();
const toJSON = user.toJSON();
User.addComputedStatsToJSONObj(userToJSON.stats, userToJSON);
expect(toObject).to.not.have.keys('_tmp');
expect(toObject).to.not.have.keys('_nonTmp');
expect(userToJSON.stats.maxMP).to.exist;
expect(userToJSON.stats.maxHealth).to.equal(common.maxHealth);
expect(userToJSON.stats.toNextLevel).to.equal(common.tnl(user.stats.lvl));
});
expect(toJSON).to.have.any.key('_tmp');
expect(toJSON._tmp).to.eql({ ok: true });
expect(toJSON).to.not.have.keys('_nonTmp');
});
it('can transform user object without mongoose helpers', async () => {
const user = new User();
await user.save();
const userToJSON = await User.findById(user._id).lean().exec();
it('can add computed stats to a JSONified user object', () => {
const user = new User();
const userToJSON = user.toJSON();
expect(userToJSON.stats.maxMP).to.not.exist;
expect(userToJSON.stats.maxHealth).to.not.exist;
expect(userToJSON.stats.toNextLevel).to.not.exist;
expect(userToJSON.id).to.not.exist;
expect(userToJSON.stats.maxMP).to.not.exist;
expect(userToJSON.stats.maxHealth).to.not.exist;
expect(userToJSON.stats.toNextLevel).to.not.exist;
User.transformJSONUser(userToJSON);
User.addComputedStatsToJSONObj(userToJSON.stats, userToJSON);
expect(userToJSON.id).to.equal(userToJSON._id);
expect(userToJSON.stats.maxMP).to.not.exist;
expect(userToJSON.stats.maxHealth).to.not.exist;
expect(userToJSON.stats.toNextLevel).to.not.exist;
});
expect(userToJSON.stats.maxMP).to.exist;
expect(userToJSON.stats.maxHealth).to.equal(common.maxHealth);
expect(userToJSON.stats.toNextLevel).to.equal(common.tnl(user.stats.lvl));
});
it('can transform user object without mongoose helpers (including computed stats)', async () => {
const user = new User();
await user.save();
const userToJSON = await User.findById(user._id).lean().exec();
it('can transform user object without mongoose helpers', async () => {
const user = new User();
await user.save();
const userToJSON = await User.findById(user._id).lean().exec();
expect(userToJSON.stats.maxMP).to.not.exist;
expect(userToJSON.stats.maxHealth).to.not.exist;
expect(userToJSON.stats.toNextLevel).to.not.exist;
expect(userToJSON.stats.maxMP).to.not.exist;
expect(userToJSON.stats.maxHealth).to.not.exist;
expect(userToJSON.stats.toNextLevel).to.not.exist;
expect(userToJSON.id).to.not.exist;
User.transformJSONUser(userToJSON, true);
User.transformJSONUser(userToJSON);
expect(userToJSON.id).to.equal(userToJSON._id);
expect(userToJSON.stats.maxMP).to.not.exist;
expect(userToJSON.stats.maxHealth).to.not.exist;
expect(userToJSON.stats.toNextLevel).to.not.exist;
});
it('can transform user object without mongoose helpers (including computed stats)', async () => {
const user = new User();
await user.save();
const userToJSON = await User.findById(user._id).lean().exec();
expect(userToJSON.stats.maxMP).to.not.exist;
expect(userToJSON.stats.maxHealth).to.not.exist;
expect(userToJSON.stats.toNextLevel).to.not.exist;
User.transformJSONUser(userToJSON, true);
expect(userToJSON.id).to.equal(userToJSON._id);
expect(userToJSON.stats.maxMP).to.exist;
expect(userToJSON.stats.maxHealth).to.equal(common.maxHealth);
expect(userToJSON.stats.toNextLevel).to.equal(common.tnl(user.stats.lvl));
expect(userToJSON.id).to.equal(userToJSON._id);
expect(userToJSON.stats.maxMP).to.exist;
expect(userToJSON.stats.maxHealth).to.equal(common.maxHealth);
expect(userToJSON.stats.toNextLevel).to.equal(common.tnl(user.stats.lvl));
});
});
context('achievements', () => {
@@ -589,6 +592,50 @@ describe('User Model', () => {
});
context('pre-save hook', () => {
it('enrolls users that signup through web in the Drop Cap AB test', async () => {
let user = new User();
user.registeredThrough = 'habitica-web';
user = await user.save();
expect(user._ABtests.dropCapNotif).to.exist;
});
it('does not enroll users that signup through modal in the Drop Cap AB test', async () => {
let user = new User();
user.registeredThrough = 'habitica-ios';
user = await user.save();
expect(user._ABtests.dropCapNotif).to.not.exist;
});
it('marks the last news post as read for new users', async () => {
const lastNewsPost = { _id: '1' };
sandbox.stub(NewsPost, 'lastNewsPost').returns(lastNewsPost);
let user = new User();
expect(user.isNew).to.equal(true);
user = await user.save();
expect(user.checkNewStuff()).to.equal(false);
expect(user.toJSON().flags.newStuff).to.equal(false);
expect(user.flags.lastNewStuffRead).to.equal(lastNewsPost._id);
});
it('does not mark the last news post as read for existing users', async () => {
const lastNewsPost = { _id: '1' };
const lastNewsPostStub = sandbox.stub(NewsPost, 'lastNewsPost');
lastNewsPostStub.returns(lastNewsPost);
let user = new User();
user = await user.save();
expect(user.isNew).to.equal(false);
user.profile.name = 'new name';
lastNewsPostStub.returns({ _id: '2' });
user = await user.save();
expect(user.flags.lastNewStuffRead).to.equal(lastNewsPost._id); // not _id: 2
});
it('does not try to award achievements when achievements or items not selected in query', async () => {
let user = new User();
user = await user.save(); // necessary for user.isSelected to work correctly
@@ -827,4 +874,46 @@ describe('User Model', () => {
expect(daysMissed).to.eql(0);
});
});
it('isNewsPoster', async () => {
const user = new User();
await user.save();
expect(user.isNewsPoster()).to.equal(false);
user.contributor.newsPoster = true;
expect(user.isNewsPoster()).to.equal(true);
});
describe('checkNewStuff', () => {
let user;
beforeEach(() => {
user = new User();
});
afterEach(() => {
sandbox.restore();
});
it('no last news post', () => {
sandbox.stub(NewsPost, 'lastNewsPost').returns(null);
expect(user.checkNewStuff()).to.equal(false);
expect(user.toJSON().flags.newStuff).to.equal(false);
});
it('last news post read', () => {
sandbox.stub(NewsPost, 'lastNewsPost').returns({ _id: '123' });
user.flags.lastNewStuffRead = '123';
expect(user.checkNewStuff()).to.equal(false);
expect(user.toJSON().flags.newStuff).to.equal(false);
});
it('last news post not read', () => {
sandbox.stub(NewsPost, 'lastNewsPost').returns({ _id: '123' });
user.flags.lastNewStuffRead = '124';
expect(user.checkNewStuff()).to.equal(true);
expect(user.toJSON().flags.newStuff).to.equal(true);
});
});
});
@@ -0,0 +1,19 @@
import {
generateUser,
requester,
} from '../../../../helpers/api-integration/v3';
import { mockAnalyticsService as analytics } from '../../../../../website/server/libs/analyticsService';
describe('POST /analytics/track/:eventName', () => {
it('calls res.analytics', async () => {
const user = await generateUser();
sandbox.spy(analytics, 'track');
const requestWithHeaders = requester(user, { 'x-client': 'habitica-web' });
await requestWithHeaders.post('/analytics/track/eventName', { data: 'example' }, { 'x-client': 'habitica-web' });
expect(analytics.track).to.be.calledOnce;
expect(analytics.track).to.be.calledWith('eventName', sandbox.match({ data: 'example' }));
sandbox.restore();
});
});
@@ -117,26 +117,7 @@ describe('GET /challenges/:challengeId/members', () => {
expect(res[0].profile).to.have.all.keys(['name']);
});
it('returns only first 30 members if req.query.includeAllMembers is not true and req.query.limit is undefined', async () => {
const group = await generateGroup(user, { type: 'party', name: generateUUID() });
const challenge = await generateChallenge(user, group);
await user.post(`/challenges/${challenge._id}/join`);
const usersToGenerate = [];
for (let i = 0; i < 31; i += 1) {
usersToGenerate.push(generateUser({ challenges: [challenge._id] }));
}
await Promise.all(usersToGenerate);
const res = await user.get(`/challenges/${challenge._id}/members?includeAllMembers=not-true`);
expect(res.length).to.equal(30);
res.forEach(member => {
expect(member).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile']);
expect(member.profile).to.have.all.keys(['name']);
});
});
it('returns only first 30 members if req.query.includeAllMembers is not defined and req.query.limit is undefined', async () => {
it('returns only first 30 members if req.query.limit is undefined', async () => {
const group = await generateGroup(user, { type: 'party', name: generateUUID() });
const challenge = await generateChallenge(user, group);
await user.post(`/challenges/${challenge._id}/join`);
@@ -217,25 +198,6 @@ describe('GET /challenges/:challengeId/members', () => {
});
}).timeout(30000);
it('returns all members if req.query.includeAllMembers is true', async () => {
const group = await generateGroup(user, { type: 'party', name: generateUUID() });
const challenge = await generateChallenge(user, group);
await user.post(`/challenges/${challenge._id}/join`);
const usersToGenerate = [];
for (let i = 0; i < 31; i += 1) {
usersToGenerate.push(generateUser({ challenges: [challenge._id] }));
}
await Promise.all(usersToGenerate);
const res = await user.get(`/challenges/${challenge._id}/members?includeAllMembers=true`);
expect(res.length).to.equal(32);
res.forEach(member => {
expect(member).to.have.all.keys(['_id', 'auth', 'flags', 'id', 'profile']);
expect(member.profile).to.have.all.keys(['name']);
});
});
it('supports using req.query.lastId to get more members', async function test () {
this.timeout(30000); // @TODO: times out after 8 seconds
const group = await generateGroup(user, { type: 'party', name: generateUUID() });
@@ -259,6 +221,34 @@ describe('GET /challenges/:challengeId/members', () => {
expect(resIds).to.eql(expectedIds.sort());
});
it('supports using req.query.includeTasks in order to add challenge-related tasks of all members', async () => {
const group = await generateGroup(user, { type: 'party', name: generateUUID() });
const challenge = await generateChallenge(user, group);
await user.post(`/challenges/${challenge._id}/join`);
const usersToGenerate = [];
for (let i = 0; i < 8; i += 1) {
usersToGenerate.push(generateUser({ challenges: [challenge._id] }));
}
await Promise.all(usersToGenerate);
await user.post(`/tasks/challenge/${challenge._id}`, [{ type: 'habit', text: 'Some task' }]);
await user.post(`/tasks/challenge/${challenge._id}`, [{ type: 'daily', text: 'Some different task' }]);
const res = await user.get(`/challenges/${challenge._id}/members?includeTasks=true`);
expect(res.length).to.equal(9);
res.forEach(member => {
expect(member).to.have.property('tasks');
expect(member.tasks).to.be.an('array');
expect(member.tasks).to.have.lengthOf(2);
member.tasks.forEach(task => {
expect(task).to.include.all.keys(['type', 'value', 'priority', 'text', '_id', 'userId']);
expect(task).to.not.have.any.keys(['tags', 'checklist']);
expect(task.challenge.id).to.be.equal(challenge._id);
expect(task.userId).to.be.equal(member._id);
});
});
});
it('supports using req.query.search to get search members', async () => {
const group = await generateGroup(user, { type: 'party', name: generateUUID() });
const challenge = await generateChallenge(user, group);
@@ -116,7 +116,6 @@ describe('GET /challenges/:challengeId/members/:memberId', () => {
}]);
const memberProgress = await user.get(`/challenges/${challenge._id}/members/${user._id}`);
expect(memberProgress.tasks[0]).not.to.have.key('tags');
expect(memberProgress.tasks[0].checklist).to.eql([]);
expect(memberProgress.tasks[0]).to.not.have.any.keys(['tags', 'checklist']);
});
});
@@ -56,7 +56,7 @@ describe('GET challenges/user', () => {
});
context('all challenges', () => {
it('should return challenges user has joined', async () => {
const challenges = await nonMember.get('/challenges/user');
const challenges = await nonMember.get('/challenges/user?page=0');
const foundChallenge = _.find(challenges, { _id: challenge._id });
expect(foundChallenge).to.exist;
@@ -65,14 +65,14 @@ describe('GET challenges/user', () => {
});
it('should not return challenges a non-member has not joined', async () => {
const challenges = await nonMember.get('/challenges/user');
const challenges = await nonMember.get('/challenges/user?page=0');
const foundChallenge2 = _.find(challenges, { _id: challenge2._id });
expect(foundChallenge2).to.not.exist;
});
it('should return challenges user has created', async () => {
const challenges = await user.get('/challenges/user');
const challenges = await user.get('/challenges/user?page=0');
const foundChallenge1 = _.find(challenges, { _id: challenge._id });
expect(foundChallenge1).to.exist;
@@ -85,7 +85,7 @@ describe('GET challenges/user', () => {
});
it('should return challenges in user\'s group', async () => {
const challenges = await member.get('/challenges/user');
const challenges = await member.get('/challenges/user?page=0');
const foundChallenge1 = _.find(challenges, { _id: challenge._id });
expect(foundChallenge1).to.exist;
@@ -98,7 +98,7 @@ describe('GET challenges/user', () => {
});
it('should return newest challenges first', async () => {
let challenges = await user.get('/challenges/user');
let challenges = await user.get('/challenges/user?page=0');
let foundChallengeIndex = _.findIndex(challenges, { _id: challenge2._id });
expect(foundChallengeIndex).to.eql(0);
@@ -106,7 +106,7 @@ describe('GET challenges/user', () => {
const newChallenge = await generateChallenge(user, publicGuild);
await user.post(`/challenges/${newChallenge._id}/join`);
challenges = await user.get('/challenges/user');
challenges = await user.get('/challenges/user?page=0');
foundChallengeIndex = _.findIndex(challenges, { _id: newChallenge._id });
expect(foundChallengeIndex).to.eql(0);
@@ -125,7 +125,7 @@ describe('GET challenges/user', () => {
const privateChallenge = await generateChallenge(groupLeader, group);
await groupLeader.post(`/challenges/${privateChallenge._id}/join`);
const challenges = await nonMember.get('/challenges/user');
const challenges = await nonMember.get('/challenges/user?page=0');
const foundChallenge = _.find(challenges, { _id: privateChallenge._id });
expect(foundChallenge).to.not.exist;
@@ -149,7 +149,7 @@ describe('GET challenges/user', () => {
});
await groupLeader.post(`/challenges/${privateChallenge._id}/join`);
const challenges = await nonMember.get('/challenges/user?categories=academics&owned=not_owned');
const challenges = await nonMember.get('/challenges/user?page=0&categories=academics&owned=not_owned');
const foundChallenge = _.find(challenges, { _id: privateChallenge._id });
expect(foundChallenge).to.not.exist;
@@ -158,7 +158,7 @@ describe('GET challenges/user', () => {
context('my challenges', () => {
it('should return challenges user has joined', async () => {
const challenges = await nonMember.get(`/challenges/user?member=${true}`);
const challenges = await nonMember.get(`/challenges/user?page=0&member=${true}`);
const foundChallenge = _.find(challenges, { _id: challenge._id });
expect(foundChallenge).to.exist;
@@ -167,7 +167,7 @@ describe('GET challenges/user', () => {
});
it('should return challenges user has created', async () => {
const challenges = await user.get(`/challenges/user?member=${true}`);
const challenges = await user.get(`/challenges/user?page=0&member=${true}`);
const foundChallenge1 = _.find(challenges, { _id: challenge._id });
expect(foundChallenge1).to.exist;
@@ -180,7 +180,7 @@ describe('GET challenges/user', () => {
});
it('should return challenges user has created if filter by owned', async () => {
const challenges = await user.get(`/challenges/user?member=${true}&owned=owned`);
const challenges = await user.get(`/challenges/user?member=${true}&owned=owned&page=0`);
const foundChallenge1 = _.find(challenges, { _id: challenge._id });
expect(foundChallenge1).to.exist;
@@ -193,7 +193,7 @@ describe('GET challenges/user', () => {
});
it('should not return challenges user has created if filter by not owned', async () => {
const challenges = await user.get(`/challenges/user?owned=not_owned&member=${true}`);
const challenges = await user.get(`/challenges/user?page=0&owned=not_owned&member=${true}`);
const foundChallenge1 = _.find(challenges, { _id: challenge._id });
expect(foundChallenge1).to.not.exist;
@@ -202,7 +202,7 @@ describe('GET challenges/user', () => {
});
it('should not return challenges in user groups', async () => {
const challenges = await member.get(`/challenges/user?member=${true}`);
const challenges = await member.get(`/challenges/user?page=0&member=${true}`);
const foundChallenge1 = _.find(challenges, { _id: challenge._id });
expect(foundChallenge1).to.not.exist;
@@ -253,7 +253,7 @@ describe('GET challenges/user', () => {
});
it('should return official challenges first', async () => {
const challenges = await user.get('/challenges/user');
const challenges = await user.get('/challenges/user?page=0');
const foundChallengeIndex = _.findIndex(challenges, { _id: officialChallenge._id });
expect(foundChallengeIndex).to.eql(0);
@@ -274,7 +274,7 @@ describe('GET challenges/user', () => {
const newChallenge = await generateChallenge(user, publicGuild);
await user.post(`/challenges/${newChallenge._id}/join`);
challenges = await user.get('/challenges/user');
challenges = await user.get('/challenges/user?page=0');
const foundChallengeIndex = _.findIndex(challenges, { _id: newChallenge._id });
expect(foundChallengeIndex).to.eql(1);
@@ -314,18 +314,12 @@ describe('GET challenges/user', () => {
it('returns public guilds filtered by category', async () => {
const categoryChallenge = await generateChallenge(user, guild, { categories });
await user.post(`/challenges/${categoryChallenge._id}/join`);
const challenges = await user.get(`/challenges/user?categories=${categories[0].slug}`);
const challenges = await user.get(`/challenges/user?page=0&categories=${categories[0].slug}`);
expect(challenges[0]._id).to.eql(categoryChallenge._id);
expect(challenges.length).to.eql(1);
});
it('does not page challenges if page parameter is absent', async () => {
const challenges = await user.get('/challenges/user');
expect(challenges.length).to.be.above(11);
});
it('paginates challenges', async () => {
const challenges = await user.get('/challenges/user?page=0');
const challengesPaged = await user.get('/challenges/user?page=1&owned=owned');
@@ -335,7 +329,7 @@ describe('GET challenges/user', () => {
});
it('filters by owned', async () => {
const challenges = await member.get('/challenges/user?owned=owned');
const challenges = await member.get('/challenges/user?page=0&owned=owned');
expect(challenges.length).to.eql(0);
});
@@ -103,7 +103,15 @@ describe('POST /challenges/:challengeId/winner/:winnerId', () => {
await expect(winningUser.sync()).to.eventually.have.nested.property('achievements.challenges').to.include(challenge.name);
// 2 because winningUser just joined the challenge, which now awards an achievement
expect(winningUser.notifications.length).to.equal(2);
expect(winningUser.notifications[1].type).to.equal('WON_CHALLENGE');
const notif = winningUser.notifications[1];
expect(notif.type).to.equal('WON_CHALLENGE');
expect(notif.data).to.eql({
id: challenge._id,
name: challenge.name,
prize: challenge.prize,
leader: challenge.leader,
});
});
it('gives winner gems as reward', async () => {
@@ -1,7 +1,7 @@
import { find } from 'lodash';
import moment from 'moment';
import nconf from 'nconf';
import { IncomingWebhook } from '@slack/client';
import { IncomingWebhook } from '@slack/webhook';
import {
generateUser,
translate as t,
@@ -20,7 +20,7 @@ describe('POST /chat/:chatId/flag', () => {
admin = await generateUser({ balance: 1, 'contributor.admin': true });
anotherUser = await generateUser({ 'auth.timestamps.created': moment().subtract(USER_AGE_FOR_FLAGGING + 1, 'days').toDate() });
newUser = await generateUser({ 'auth.timestamps.created': moment().subtract(1, 'days').toDate() });
sandbox.stub(IncomingWebhook.prototype, 'send');
sandbox.stub(IncomingWebhook.prototype, 'send').returns(Promise.resolve());
group = await user.post('/groups', {
name: 'Test Guild',
@@ -1,4 +1,4 @@
import { IncomingWebhook } from '@slack/client';
import { IncomingWebhook } from '@slack/webhook';
import nconf from 'nconf';
import { v4 as generateUUID } from 'uuid';
import {
@@ -133,7 +133,7 @@ describe('POST /chat', () => {
describe('shadow-mute user', () => {
beforeEach(() => {
sandbox.spy(email, 'sendTxn');
sandbox.stub(IncomingWebhook.prototype, 'send');
sandbox.stub(IncomingWebhook.prototype, 'send').returns(Promise.resolve());
});
afterEach(() => {
@@ -355,7 +355,7 @@ describe('POST /chat', () => {
context('banned slur', () => {
beforeEach(() => {
sandbox.spy(email, 'sendTxn');
sandbox.stub(IncomingWebhook.prototype, 'send');
sandbox.stub(IncomingWebhook.prototype, 'send').returns(Promise.resolve());
});
afterEach(() => {
@@ -251,6 +251,29 @@ describe('POST /groups/:groupId/removeMember/:memberId', () => {
expect(party.quest.members[partyMember._id]).to.not.exist;
});
it('prevents user from being removed if they are the quest owner', async () => {
const petQuest = 'whale';
await partyMember.update({
[`items.quests.${petQuest}`]: 1,
});
await partyMember.post(`/groups/${party._id}/quests/invite/${petQuest}`);
await partyLeader.post(`/groups/${party._id}/quests/accept`);
await party.sync();
expect(party.quest.members[partyLeader._id]).to.be.true;
expect(party.quest.members[partyMember._id]).to.be.true;
await party.sync();
expect(leader.post(`/groups/${party._id}/removeMember/${partyMember._id}`))
.to.eventually.be.rejected.and.eql({
code: 401,
text: t('cannotRemoveQuestOwner'),
});
});
it('sends email to user with rescinded invite', async () => {
await partyLeader.post(`/groups/${party._id}/removeMember/${partyInvitedUser._id}`);
@@ -4,7 +4,6 @@ import {
describe('GET /news', () => {
let api;
beforeEach(async () => {
api = requester();
});
@@ -1,24 +1,27 @@
import {
generateUser,
} from '../../../../helpers/api-integration/v3';
import { model as NewsPost } from '../../../../../website/server/models/newsPost';
describe('POST /news/tell-me-later', () => {
let user;
beforeEach(async () => {
user = await generateUser({
'flags.newStuff': true,
NewsPost.updateLastNewsPost({
_id: '1234', publishDate: new Date(), title: 'Title', published: true,
});
user = await generateUser();
});
it('marks new stuff as read and adds notification', async () => {
expect(user.flags.newStuff).to.equal(true);
const initialNotifications = user.notifications.length;
await user.post('/news/tell-me-later');
await user.sync();
expect(user.flags.newStuff).to.equal(false);
expect(user.flags.lastNewStuffRead).to.equal('1234');
// fetching the user because newStuff is a computed property
expect((await user.get('/user')).flags.newStuff).to.equal(false);
expect(user.notifications.length).to.equal(initialNotifications + 1);
const notification = user.notifications[user.notifications.length - 1];
@@ -0,0 +1,45 @@
import {
generateUser,
} from '../../../../../helpers/api-integration/v3';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
import common from '../../../../../../website/common';
describe('payments - stripe - #createCheckoutSession', () => {
const endpoint = '/stripe/checkout-session';
let user; const groupId = 'groupId';
const gift = {}; const subKey = 'basic_3mo';
const gemsBlock = '21gems'; const coupon = 'coupon';
let stripeCreateCheckoutSessionStub; const sessionId = 'sessionId';
beforeEach(async () => {
user = await generateUser();
stripeCreateCheckoutSessionStub = sinon
.stub(stripePayments, 'createCheckoutSession')
.resolves({ id: sessionId });
});
afterEach(() => {
stripePayments.createCheckoutSession.restore();
});
it('works', async () => {
const res = await user.post(endpoint, {
groupId,
gift,
sub: subKey,
gemsBlock,
coupon,
});
expect(res.sessionId).to.equal(sessionId);
expect(stripeCreateCheckoutSessionStub).to.be.calledOnce;
expect(stripeCreateCheckoutSessionStub.args[0][0].user._id).to.eql(user._id);
expect(stripeCreateCheckoutSessionStub.args[0][0].groupId).to.eql(groupId);
expect(stripeCreateCheckoutSessionStub.args[0][0].gift).to.eql(gift);
expect(stripeCreateCheckoutSessionStub.args[0][0].sub)
.to.eql(common.content.subscriptionBlocks[subKey]);
expect(stripeCreateCheckoutSessionStub.args[0][0].gemsBlock).to.eql(gemsBlock);
expect(stripeCreateCheckoutSessionStub.args[0][0].coupon).to.eql(coupon);
});
});
@@ -1,76 +0,0 @@
import {
generateUser,
generateGroup,
} from '../../../../../helpers/api-integration/v3';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
describe('payments - stripe - #checkout', () => {
const endpoint = '/stripe/checkout';
let user; let
group;
beforeEach(async () => {
user = await generateUser();
});
it('verifies credentials', async () => {
await expect(user.post(endpoint, { id: 123 })).to.eventually.be.rejected.and.include({
code: 401,
error: 'Error',
// message: 'Invalid API Key provided: aaaabbbb********************1111',
});
});
describe('success', () => {
let stripeCheckoutSubscriptionStub;
beforeEach(async () => {
stripeCheckoutSubscriptionStub = sinon.stub(stripePayments, 'checkout').resolves({});
});
afterEach(() => {
stripePayments.checkout.restore();
});
it('creates a user subscription', async () => {
user = await generateUser({
'profile.name': 'sender',
'purchased.plan.customerId': 'customer-id',
'purchased.plan.planId': 'basic_3mo',
'purchased.plan.lastBillingDate': new Date(),
balance: 2,
});
await user.post(endpoint);
expect(stripeCheckoutSubscriptionStub).to.be.calledOnce;
expect(stripeCheckoutSubscriptionStub.args[0][0].user._id).to.eql(user._id);
expect(stripeCheckoutSubscriptionStub.args[0][0].groupId).to.eql(undefined);
});
it('creates a group subscription', async () => {
user = await generateUser({
'profile.name': 'sender',
'purchased.plan.customerId': 'customer-id',
'purchased.plan.planId': 'basic_3mo',
'purchased.plan.lastBillingDate': new Date(),
balance: 2,
});
group = await generateGroup(user, {
name: 'test group',
type: 'guild',
privacy: 'public',
'purchased.plan.customerId': 'customer-id',
'purchased.plan.planId': 'basic_3mo',
'purchased.plan.lastBillingDate': new Date(),
});
await user.post(`${endpoint}?groupId=${group._id}`);
expect(stripeCheckoutSubscriptionStub).to.be.calledOnce;
expect(stripeCheckoutSubscriptionStub.args[0][0].user._id).to.eql(user._id);
expect(stripeCheckoutSubscriptionStub.args[0][0].groupId).to.eql(group._id);
});
});
});
@@ -1,79 +1,31 @@
import {
generateUser,
generateGroup,
translate as t,
} from '../../../../../helpers/api-integration/v3';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
describe('payments - stripe - #subscribeEdit', () => {
const endpoint = '/stripe/subscribe/edit';
let user; let
group;
let user; const groupId = 'groupId';
let stripeEditSubscriptionStub;
const sessionId = 'sessionId';
beforeEach(async () => {
user = await generateUser();
stripeEditSubscriptionStub = sinon
.stub(stripePayments, 'createEditCardCheckoutSession')
.resolves({ id: sessionId });
});
it('verifies credentials', async () => {
await expect(user.post(endpoint)).to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
message: t('missingSubscription'),
});
afterEach(() => {
stripePayments.createEditCardCheckoutSession.restore();
});
describe('success', () => {
let stripeEditSubscriptionStub;
it('works', async () => {
const res = await user.post(endpoint, { groupId });
expect(res.sessionId).to.equal(sessionId);
beforeEach(async () => {
stripeEditSubscriptionStub = sinon.stub(stripePayments, 'editSubscription').resolves({});
});
afterEach(() => {
stripePayments.editSubscription.restore();
});
it('cancels a user subscription', async () => {
user = await generateUser({
'profile.name': 'sender',
'purchased.plan.customerId': 'customer-id',
'purchased.plan.planId': 'basic_3mo',
'purchased.plan.lastBillingDate': new Date(),
balance: 2,
});
await user.post(endpoint);
expect(stripeEditSubscriptionStub).to.be.calledOnce;
expect(stripeEditSubscriptionStub.args[0][0].user._id).to.eql(user._id);
expect(stripeEditSubscriptionStub.args[0][0].groupId).to.eql(undefined);
});
it('cancels a group subscription', async () => {
user = await generateUser({
'profile.name': 'sender',
'purchased.plan.customerId': 'customer-id',
'purchased.plan.planId': 'basic_3mo',
'purchased.plan.lastBillingDate': new Date(),
balance: 2,
});
group = await generateGroup(user, {
name: 'test group',
type: 'guild',
privacy: 'public',
'purchased.plan.customerId': 'customer-id',
'purchased.plan.planId': 'basic_3mo',
'purchased.plan.lastBillingDate': new Date(),
});
await user.post(endpoint, {
groupId: group._id,
});
expect(stripeEditSubscriptionStub).to.be.calledOnce;
expect(stripeEditSubscriptionStub.args[0][0].user._id).to.eql(user._id);
expect(stripeEditSubscriptionStub.args[0][0].groupId).to.eql(group._id);
});
expect(stripeEditSubscriptionStub).to.be.calledOnce;
expect(stripeEditSubscriptionStub.args[0][0].user._id).to.eql(user._id);
expect(stripeEditSubscriptionStub.args[0][0].groupId).to.eql(groupId);
});
});
@@ -0,0 +1,30 @@
import {
generateUser,
} from '../../../../../helpers/api-integration/v3';
import stripePayments from '../../../../../../website/server/libs/payments/stripe';
describe('payments - stripe - #handleWebhooks', () => {
const endpoint = '/stripe/webhooks';
let user; const body = '{"key": "val"}';
let stripeHandleWebhooksStub;
beforeEach(async () => {
user = await generateUser();
stripeHandleWebhooksStub = sinon
.stub(stripePayments, 'handleWebhooks')
.resolves({});
});
afterEach(() => {
stripePayments.handleWebhooks.restore();
});
it('works', async () => {
const res = await user.post(endpoint, body);
expect(res).to.eql({});
expect(stripeHandleWebhooksStub).to.be.calledOnce;
expect(stripeHandleWebhooksStub.args[0][0].body).to.exist;
expect(stripeHandleWebhooksStub.args[0][0].headers).to.exist;
});
});
@@ -83,22 +83,6 @@ describe('POST /groups/:groupId/quests/invite/:questKey', () => {
});
});
it('does not issue invites if the user is of insufficient Level', async () => {
const LEVELED_QUEST = 'atom1';
const LEVELED_QUEST_REQ = questScrolls[LEVELED_QUEST].lvl;
const leaderUpdate = {};
leaderUpdate[`items.quests.${LEVELED_QUEST}`] = 1;
leaderUpdate['stats.lvl'] = LEVELED_QUEST_REQ - 1;
await leader.update(leaderUpdate);
await expect(leader.post(`/groups/${questingGroup._id}/quests/invite/${LEVELED_QUEST}`)).to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
message: t('questLevelTooHigh', { level: LEVELED_QUEST_REQ }),
});
});
it('does not issue invites if a quest is already underway', async () => {
const QUEST_IN_PROGRESS = 'atom1';
const leaderUpdate = {};
@@ -212,6 +196,18 @@ describe('POST /groups/:groupId/quests/invite/:questKey', () => {
expect(returnedGroup.chat[0]._meta).to.be.undefined;
});
it('successfully issues a quest invitation when quest level is higher than user level', async () => {
const LEVELED_QUEST = 'atom1';
const LEVELED_QUEST_REQ = questScrolls[LEVELED_QUEST].lvl;
const leaderUpdate = {};
leaderUpdate[`items.quests.${LEVELED_QUEST}`] = 1;
leaderUpdate['stats.lvl'] = LEVELED_QUEST_REQ - 1;
await leader.update(leaderUpdate);
await leader.post(`/groups/${questingGroup._id}/quests/invite/${LEVELED_QUEST}`);
});
context('sending quest activity webhooks', () => {
before(async () => {
await server.start();
@@ -91,7 +91,9 @@ describe('POST /tasks/:taskId/move/to/:position', () => {
const taskToMove = tasks[1];
expect(taskToMove.text).to.equal('habit 2');
const newOrder = await user.post(`/tasks/${tasks[1]._id}/move/to/-1`);
await user.post(`/tasks/${tasks[1]._id}/move/to/-1`);
await user.sync();
const newOrder = user.tasksOrder.habits;
expect(newOrder[4]).to.equal(taskToMove._id);
expect(newOrder.length).to.equal(5);
});
@@ -3,6 +3,7 @@ import {
generateUser,
translate as t,
} from '../../../../helpers/api-integration/v3';
import { model as NewsPost } from '../../../../../website/server/models/newsPost';
describe('PUT /user', () => {
let user;
@@ -101,6 +102,24 @@ describe('PUT /user', () => {
message: t('displaynameIssueNewline'),
});
});
it('can set flags.newStuff to false', async () => {
NewsPost.updateLastNewsPost({
_id: '1234', publishDate: new Date(), title: 'Title', published: true,
});
await user.update({
'flags.lastNewStuffRead': '123',
});
await user.put('/user', {
'flags.newStuff': false,
});
await user.sync();
expect(user.flags.lastNewStuffRead).to.eql('1234');
});
});
context('Top Level Protected Operations', () => {
@@ -4,6 +4,8 @@ import {
requester,
resetHabiticaDB,
} from '../../../../helpers/api-integration/v3';
import * as worldState from '../../../../../website/server/libs/worldState';
import common from '../../../../../website/common';
describe('GET /world-state', () => {
before(async () => {
@@ -39,4 +41,41 @@ describe('GET /world-state', () => {
expect(res).to.have.nested.property('npcImageSuffix');
expect(res.npcImageSuffix).to.be.a('string');
});
context('no current event', () => {
beforeEach(async () => {
sinon.stub(worldState, 'getCurrentEvent').returns(null);
});
afterEach(() => {
worldState.getCurrentEvent.restore();
});
it('returns null for the current event when there is none active', async () => {
const res = await requester().get('/world-state');
expect(res.currentEvent).to.be.null;
});
});
context('no current event', () => {
const evt = {
...common.content.events.fall2020,
event: 'fall2020',
};
beforeEach(async () => {
sinon.stub(worldState, 'getCurrentEvent').returns(evt);
});
afterEach(() => {
worldState.getCurrentEvent.restore();
});
it('returns the current event when there is an active one', async () => {
const res = await requester().get('/world-state');
expect(res.currentEvent).to.eql(evt);
});
});
});
+49
View File
@@ -0,0 +1,49 @@
import { v4 } from 'uuid';
import {
generateUser,
translate as t,
} from '../../../helpers/api-integration/v4';
describe('DELETE /news/:newsID', () => {
let user;
const newsPost = {
title: 'New Post',
publishDate: new Date(),
published: true,
credits: 'credits',
text: 'news body',
};
beforeEach(async () => {
user = await generateUser({
'contributor.newsPoster': true,
});
});
it('disallows access to non-newsPosters', async () => {
const nonAdminUser = await generateUser({ 'contributor.newsPoster': false });
await expect(nonAdminUser.del(`/news/${v4()}`)).to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
message: 'You don\'t have news poster access.',
});
});
it('returns an error if the post does not exist', async () => {
await expect(user.del(`/news/${v4()}`)).to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
message: t('newsPostNotFound'),
});
});
it('deletes news posts', async () => {
const existingPost = await user.post('/news', newsPost);
await user.del(`/news/${existingPost._id}`);
const returnedPosts = await user.get('/news');
const deletedPost = returnedPosts.find(returnedPost => returnedPost._id === existingPost._id);
expect(returnedPosts).is.an('array');
expect(deletedPost).to.not.exist;
});
});
+50
View File
@@ -0,0 +1,50 @@
import {
requester, generateUser,
} from '../../../helpers/api-integration/v4';
describe('GET /news', () => {
let api;
const newsPost = {
title: 'New Post',
publishDate: new Date(),
published: true,
credits: 'credits',
text: 'news body',
};
before(async () => {
api = requester();
const user = await generateUser({
'contributor.newsPoster': true,
});
await Promise.all([
user.post('/news', newsPost),
user.post('/news', newsPost),
user.post('/news', newsPost),
user.post('/news', newsPost),
user.post('/news', newsPost),
user.post('/news', newsPost),
user.post('/news', newsPost),
user.post('/news', newsPost),
user.post('/news', newsPost),
user.post('/news', newsPost),
user.post('/news', newsPost),
user.post('/news', newsPost),
]);
});
it('returns the latest news in json format, does not require authentication, 10 per page', async () => {
const res = await api.get('/news');
expect(res.length).to.be.equal(10);
expect(res[0].title).to.be.not.empty;
expect(res[0].text).to.be.not.empty;
});
it('supports pagination', async () => {
const res = await api.get('/news?page=1');
expect(res.length).to.be.equal(2);
expect(res[0].title).to.be.not.empty;
expect(res[0].text).to.be.not.empty;
});
});
+36
View File
@@ -0,0 +1,36 @@
import { v4 } from 'uuid';
import {
generateUser,
translate as t,
} from '../../../helpers/api-integration/v4';
describe('GET /news/:newsID', () => {
let user;
const newsPost = {
title: 'New Post',
publishDate: new Date(),
published: true,
credits: 'credits',
text: 'news body',
};
beforeEach(async () => {
user = await generateUser({
'contributor.newsPoster': true,
});
});
it('returns an error if the post does not exist', async () => {
await expect(user.get(`/news/${v4()}`)).to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
message: t('newsPostNotFound'),
});
});
it('fetches an existing post', async () => {
const existingPost = await user.post('/news', newsPost);
const fetchedPost = await user.get(`/news/${existingPost._id}`);
expect(fetchedPost._id).to.equal(existingPost._id);
});
});
+134
View File
@@ -0,0 +1,134 @@
import moment from 'moment';
import {
generateUser,
sleep,
} from '../../../helpers/api-integration/v4';
import { model as NewsPost } from '../../../../website/server/models/newsPost';
describe('POST /news', () => {
let user;
const newsPost = {
title: 'New Post',
publishDate: new Date(),
published: true,
credits: 'credits',
text: 'news body',
};
beforeEach(async () => {
user = await generateUser({
'contributor.newsPoster': true,
});
});
it('disallows access to non-admins', async () => {
const nonAdminUser = await generateUser({ 'contributor.newsPoster': false });
await expect(nonAdminUser.post('/news')).to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
message: 'You don\'t have news poster access.',
});
});
it('creates news posts', async () => {
const response = await user.post('/news', newsPost);
expect(response.title).to.equal(newsPost.title);
expect(response.credits).to.equal(newsPost.credits);
expect(response.text).to.equal(newsPost.text);
expect(response._id).to.exist;
const res = await user.get('/news');
expect(res[0]._id).to.equal(response._id);
expect(res[0].title).to.equal(newsPost.title);
expect(res[0].text).to.equal(newsPost.text);
});
context('calls updateLastNewsPost', () => {
beforeEach(async () => {
await NewsPost.remove({ });
});
afterEach(async () => {
newsPost.publishDate = new Date();
newsPost.published = true;
});
it('new post is published and the most recent one', async () => {
newsPost.publishDate = new Date();
const newPost = await user.post('/news', newsPost);
await sleep(0.05);
expect(NewsPost.lastNewsPost()._id).to.equal(newPost._id);
});
it('new post is not published', async () => {
newsPost.published = false;
const newPost = await user.post('/news', newsPost);
await sleep(0.05);
expect(NewsPost.lastNewsPost()._id).to.not.equal(newPost._id);
});
it('new post is published but in the future', async () => {
newsPost.publishDate = moment().add({ days: 1 }).toDate();
const newPost = await user.post('/news', newsPost);
await sleep(0.05);
expect(NewsPost.lastNewsPost()._id).to.not.equal(newPost._id);
});
it('new post is published but not the most recent one', async () => {
const oldPost = await user.post('/news', newsPost);
newsPost.publishDate = moment().subtract({ days: 1 }).toDate();
await user.post('/news', newsPost);
await sleep(0.05);
expect(NewsPost.lastNewsPost()._id).to.equal(oldPost._id);
});
});
it('sets default fields', async () => {
const response = await user.post('/news', {
title: 'A post',
credits: 'Credits',
text: 'Text',
});
expect(response.published).to.equal(false);
expect(response.publishDate).to.exist;
expect(response.author).to.equal(user._id);
expect(response.createdAt).to.exist;
expect(response.updatedAt).to.exist;
});
context('required fields', () => {
it('title', async () => {
await expect(user.post('/news', {
text: 'Text',
credits: 'Credits',
})).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: 'NewsPost validation failed',
});
});
it('credits', async () => {
await expect(user.post('/news', {
text: 'Text',
title: 'Title',
})).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: 'NewsPost validation failed',
});
});
it('text', async () => {
await expect(user.post('/news', {
credits: 'credits',
title: 'Title',
})).to.eventually.be.rejected.and.eql({
code: 400,
error: 'BadRequest',
message: 'NewsPost validation failed',
});
});
});
});
+22
View File
@@ -0,0 +1,22 @@
import {
generateUser,
} from '../../../helpers/api-integration/v4';
import { model as NewsPost } from '../../../../website/server/models/newsPost';
describe('POST /news/read', () => {
let user;
beforeEach(async () => {
user = await generateUser();
});
it('marks new stuff as read', async () => {
NewsPost.updateLastNewsPost({ _id: '1234', publishDate: new Date(), published: true });
await user.post('/news/read');
await user.sync();
expect(user.flags.lastNewStuffRead).to.equal('1234');
// fetching the user because newStuff is a computed property
expect((await user.get('/user')).flags.newStuff).to.equal(false);
});
});
+103
View File
@@ -0,0 +1,103 @@
import { v4 } from 'uuid';
import {
generateUser,
translate as t,
sleep,
} from '../../../helpers/api-integration/v4';
import { model as NewsPost } from '../../../../website/server/models/newsPost';
describe('PUT /news/:newsID', () => {
let user;
const newsPost = {
title: 'New Post',
publishDate: new Date(),
published: true,
credits: 'credits',
text: 'news body',
};
beforeEach(async () => {
user = await generateUser({
'contributor.newsPoster': true,
});
});
it('disallows access to non-admins', async () => {
const nonAdminUser = await generateUser({ 'contributor.newsPoster': false });
await expect(nonAdminUser.put('/news/1234')).to.eventually.be.rejected.and.eql({
code: 401,
error: 'NotAuthorized',
message: 'You don\'t have news poster access.',
});
});
it('returns an error if the post does not exist', async () => {
await expect(user.put(`/news/${v4()}`)).to.eventually.be.rejected.and.eql({
code: 404,
error: 'NotFound',
message: t('newsPostNotFound'),
});
});
it('updates existing news posts', async () => {
const existingPost = await user.post('/news', newsPost);
const updatedPost = await user.put(`/news/${existingPost._id}`, {
title: 'Changed Title',
});
expect(updatedPost.title).to.equal('Changed Title');
expect(updatedPost.credits).to.equal(existingPost.credits);
expect(updatedPost.text).to.equal(existingPost.text);
expect(updatedPost.published).to.equal(existingPost.published);
expect(updatedPost._id).to.equal(existingPost._id);
});
context('calls updateLastNewsPost', () => {
beforeEach(async () => {
await NewsPost.remove({ });
});
it('updates post data', async () => {
const existingPost = await user.post('/news', { ...newsPost, publishDate: new Date() });
const updatedPost = await user.put(`/news/${existingPost._id}`, {
title: 'Changed Title',
});
await sleep(0.05);
expect(NewsPost.lastNewsPost().title).to.equal(updatedPost.title);
});
it('updated post is not published', async () => {
const oldPost = await user.post('/news', { ...newsPost, publishDate: new Date() });
const newUnpublished = await user.post('/news', { ...newsPost, published: false });
await user.put(`/news/${newUnpublished._id}`, {
title: 'Changed Title',
});
await sleep(0.05);
expect(NewsPost.lastNewsPost()._id).to.equal(oldPost._id);
});
it('updated post is published', async () => {
await user.post('/news', { ...newsPost, publishDate: new Date() });
const newUnpublished = await user.post('/news', { ...newsPost, published: false, publishDate: new Date() });
await user.put(`/news/${newUnpublished._id}`, {
publishDate: new Date(),
published: true,
});
await sleep(0.05);
expect(NewsPost.lastNewsPost()._id).to.equal(newUnpublished._id);
});
it('updated post publishDate is in future', async () => {
const oldPost = await user.post('/news', { ...newsPost, publishDate: new Date() });
const newUnpublished = await user.post('/news', newsPost);
await user.put(`/news/${newUnpublished._id}`, {
publishDate: Date.now() + 50000,
});
await sleep(0.05);
expect(NewsPost.lastNewsPost()._id).to.equal(oldPost._id);
});
});
});
@@ -0,0 +1,52 @@
import {
generateUser,
} from '../../../helpers/api-integration/v4';
import { UNEQUIP_EQUIPPED } from '../../../../website/common/script/ops/unequip';
describe('POST /user/unequip', () => {
let user;
beforeEach(async () => {
user = await generateUser({
preferences: {
background: 'violet',
},
items: {
currentMount: 'BearCub-Base',
currentPet: 'BearCub-Base',
gear: {
owned: {
weapon_warrior_0: true,
weapon_warrior_1: true,
weapon_warrior_2: true,
weapon_wizard_1: true,
weapon_wizard_2: true,
shield_base_0: true,
shield_warrior_1: true,
},
equipped: {
weapon: 'weapon_warrior_2',
shield: 'shield_warrior_1',
},
costume: {
weapon: 'weapon_warrior_2',
shield: 'shield_warrior_1',
},
},
},
stats: { gp: 200 },
});
});
// More tests in common code unit tests
context('Gear', () => {
it('should unequip all battle gear items', async () => {
await user.post(`/user/unequip/${UNEQUIP_EQUIPPED}`);
await user.sync();
expect(user.items.gear.equipped.weapon).to.eq('weapon_base_0');
expect(user.items.gear.equipped.shield).to.eq('shield_base_0');
});
});
});
+144
View File
@@ -1,4 +1,5 @@
import randomDrop from '../../../website/common/script/fns/randomDrop';
import i18n from '../../../website/common/script/i18n';
import {
generateUser,
generateTodo,
@@ -144,5 +145,148 @@ describe('common.fns.randomDrop', () => {
expect(acceptableDrops).to.contain(user._tmp.drop.key); // always Desert
});
});
context('drop cap notification', () => {
let analytics;
const req = {};
let isSubscribedStub;
beforeEach(() => {
user.addNotification = () => {};
sandbox.stub(user, 'addNotification');
user.isSubscribed = () => {};
isSubscribedStub = sandbox.stub(user, 'isSubscribed');
isSubscribedStub.returns(false);
analytics = { track () {} };
sandbox.stub(analytics, 'track');
});
it('sends a notification if A/B test is enabled when drop cap is reached', () => {
user._ABtests.dropCapNotif = 'drop-cap-notif-enabled';
predictableRandom.returns(0.1);
// Max Drop Count is 5
expect(user.items.lastDrop.count).to.equal(0);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
expect(user.items.lastDrop.count).to.equal(5);
expect(user.addNotification).to.be.calledOnce;
expect(user.addNotification).to.be.calledWith('DROP_CAP_REACHED', {
message: i18n.t('dropCapReached'),
items: 5,
});
});
it('does not send a notification if user is enrolled in disabled A/B test group', () => {
user._ABtests.dropCapNotif = 'drop-cap-notif-disabled';
predictableRandom.returns(0.1);
// Max Drop Count is 5
expect(user.items.lastDrop.count).to.equal(0);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
expect(user.items.lastDrop.count).to.equal(5);
expect(user.addNotification).to.not.be.called;
});
it('does not send a notification if user is enrolled in disabled A/B test group', () => {
user._ABtests.dropCapNotif = 'drop-cap-notif-not-enrolled';
predictableRandom.returns(0.1);
// Max Drop Count is 5
expect(user.items.lastDrop.count).to.equal(0);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
expect(user.items.lastDrop.count).to.equal(5);
expect(user.addNotification).to.not.be.called;
});
it('does not send a notification if drop cap is not reached', () => {
user._ABtests.dropCapNotif = 'drop-cap-notif-enabled';
predictableRandom.returns(0.1);
// Max Drop Count is 5
expect(user.items.lastDrop.count).to.equal(0);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
expect(user.items.lastDrop.count).to.equal(4);
expect(user.addNotification).to.not.be.called;
});
it('does not send a notification if user is subscribed', () => {
user._ABtests.dropCapNotif = 'drop-cap-notif-enabled';
predictableRandom.returns(0.1);
isSubscribedStub.returns(true);
// Max Drop Count is 5
expect(user.items.lastDrop.count).to.equal(0);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
expect(user.items.lastDrop.count).to.equal(5);
expect(user.addNotification).to.not.be.called;
});
it('tracks drop cap reached event for enrolled users (notification enabled)', () => {
user._ABtests.dropCapNotif = 'drop-cap-notif-enabled';
predictableRandom.returns(0.1);
isSubscribedStub.returns(true);
// Max Drop Count is 5
expect(user.items.lastDrop.count).to.equal(0);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
expect(user.items.lastDrop.count).to.equal(5);
expect(analytics.track).to.be.calledWith('drop cap reached');
});
it('tracks drop cap reached event for enrolled users (notification disabled)', () => {
user._ABtests.dropCapNotif = 'drop-cap-notif-disabled';
predictableRandom.returns(0.1);
isSubscribedStub.returns(true);
// Max Drop Count is 5
expect(user.items.lastDrop.count).to.equal(0);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
expect(user.items.lastDrop.count).to.equal(5);
expect(analytics.track).to.be.calledWith('drop cap reached');
});
it('does not track drop cap reached event for users not enrolled in A/B test', () => {
user._ABtests.dropCapNotif = 'drop-cap-notif-not-enrolled';
predictableRandom.returns(0.1);
isSubscribedStub.returns(true);
// Max Drop Count is 5
expect(user.items.lastDrop.count).to.equal(0);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
randomDrop(user, { task, predictableRandom }, req, analytics);
expect(user.items.lastDrop.count).to.equal(5);
expect(analytics.track).to.not.be.calledWith('drop cap reached');
});
});
});
});
+100
View File
@@ -0,0 +1,100 @@
/* eslint-disable camelcase */
import {
generateUser,
} from '../../helpers/common.helper';
import {
UNEQUIP_ALL,
UNEQUIP_BACKGROUND,
UNEQUIP_COSTUME,
UNEQUIP_EQUIPPED,
UNEQUIP_PET_MOUNT,
unEquipByType,
} from '../../../website/common/script/ops/unequip';
describe('shared.ops.unequip', () => {
let user;
beforeEach(() => {
user = generateUser({
preferences: {
background: 'violet',
},
items: {
currentMount: 'BearCub-Base',
currentPet: 'BearCub-Base',
gear: {
owned: {
weapon_warrior_0: true,
weapon_warrior_1: true,
weapon_warrior_2: true,
weapon_wizard_1: true,
weapon_wizard_2: true,
shield_base_0: true,
shield_warrior_1: true,
},
equipped: {
weapon: 'weapon_warrior_2',
shield: 'shield_warrior_1',
},
costume: {
weapon: 'weapon_warrior_2',
shield: 'shield_warrior_1',
},
},
},
stats: { gp: 200 },
});
});
context('Gear', () => {
it('should unequip all battle gear items', () => {
unEquipByType(user, { params: { type: UNEQUIP_EQUIPPED } });
expect(user.items.gear.equipped.weapon).to.eq('weapon_base_0');
expect(user.items.gear.equipped.shield).to.eq('shield_base_0');
});
});
context('Costume', () => {
it('should unequip all costume items', () => {
unEquipByType(user, { params: { type: UNEQUIP_COSTUME } });
expect(user.items.gear.costume.weapon).to.eq('weapon_base_0');
expect(user.items.gear.costume.shield).to.eq('shield_base_0');
});
});
context('Pet and Mount', () => {
it('should unequip Pet and Mount', () => {
unEquipByType(user, { params: { type: UNEQUIP_PET_MOUNT } });
expect(user.items.currentMount).to.eq('');
expect(user.items.currentPet).to.eq('');
});
});
context('Background', () => {
it('should unequip Background', () => {
unEquipByType(user, { params: { type: UNEQUIP_BACKGROUND } });
expect(user.preferences.background).to.eq('');
});
});
context('All Items', () => {
it('should unequip all Items', () => {
unEquipByType(user, { params: { type: UNEQUIP_ALL } });
expect(user.items.gear.equipped.weapon).to.eq('weapon_base_0');
expect(user.items.gear.equipped.shield).to.eq('shield_base_0');
expect(user.items.gear.costume.weapon).to.eq('weapon_base_0');
expect(user.items.gear.costume.shield).to.eq('shield_base_0');
expect(user.items.currentMount).to.eq('');
expect(user.items.currentPet).to.eq('');
expect(user.preferences.background).to.eq('');
});
});
});
@@ -41,6 +41,7 @@ function _requestMaker (user, method, additionalSets = {}) {
|| route.indexOf('/amazon') === 0
|| route.indexOf('/stripe') === 0
|| route.indexOf('/qr-code') === 0
|| route.indexOf('/analytics') === 0
) {
url += `${route}`;
} else {
@@ -50,4 +50,5 @@ function loadStories () {
req.keys().forEach(filename => req(filename));
}
configure(loadStories, module);
+1319 -1111
View File
File diff suppressed because it is too large Load Diff
+19 -19
View File
@@ -18,48 +18,48 @@
"@storybook/addon-links": "^5.3.19",
"@storybook/addon-notes": "^5.3.21",
"@storybook/vue": "^5.3.19",
"@vue/cli-plugin-babel": "^4.5.6",
"@vue/cli-plugin-eslint": "^4.5.6",
"@vue/cli-plugin-router": "^4.5.6",
"@vue/cli-plugin-unit-mocha": "^4.5.6",
"@vue/cli-service": "^4.5.6",
"@vue/cli-plugin-babel": "^4.5.9",
"@vue/cli-plugin-eslint": "^4.5.9",
"@vue/cli-plugin-router": "^4.5.9",
"@vue/cli-plugin-unit-mocha": "^4.5.9",
"@vue/cli-service": "^4.5.9",
"@vue/test-utils": "1.0.0-beta.29",
"amplitude-js": "^7.1.1",
"axios": "^0.19.2",
"amplitude-js": "^7.3.3",
"axios": "^0.21.0",
"axios-progress-bar": "^1.2.0",
"babel-eslint": "^10.1.0",
"bootstrap": "^4.5.2",
"bootstrap-vue": "^2.17.0",
"bootstrap": "^4.5.3",
"bootstrap-vue": "^2.19.0",
"chai": "^4.1.2",
"core-js": "^3.6.5",
"core-js": "^3.8.0",
"eslint": "^6.8.0",
"eslint-config-habitrpg": "^6.2.0",
"eslint-plugin-mocha": "^5.3.0",
"eslint-plugin-vue": "^6.2.2",
"habitica-markdown": "^3.0.0",
"hellojs": "^1.18.4",
"hellojs": "^1.18.6",
"inspectpack": "^4.5.2",
"intro.js": "^2.9.3",
"jquery": "^3.5.1",
"lodash": "^4.17.20",
"moment": "^2.28.0",
"nconf": "^0.10.0",
"sass": "^1.26.10",
"moment": "^2.29.1",
"nconf": "^0.11.0",
"sass": "^1.29.0",
"sass-loader": "^8.0.2",
"smartbanner.js": "^1.16.0",
"svg-inline-loader": "^0.8.2",
"svg-url-loader": "^6.0.0",
"svgo": "^1.3.2",
"svgo-loader": "^2.2.1",
"uuid": "^8.3.0",
"validator": "^13.1.1",
"uuid": "^8.3.1",
"validator": "^13.1.17",
"vue": "^2.6.12",
"vue-cli-plugin-storybook": "^0.6.1",
"vue-mugen-scroll": "^0.2.6",
"vue-router": "^3.4.3",
"vue-router": "^3.4.9",
"vue-template-compiler": "^2.6.12",
"vuedraggable": "^2.24.1",
"vuedraggable": "^2.24.3",
"vuejs-datepicker": "git://github.com/habitrpg/vuejs-datepicker.git#153d339e4dbebb73733658aeda1d5b7fcc55b0a0",
"webpack": "^4.44.1"
"webpack": "^4.44.2"
}
}
+7 -98
View File
@@ -26,7 +26,6 @@
id="app"
:class="{
'casting-spell': castingSpell,
'resting': showRestingBanner
}"
>
<!-- <banned-account-modal /> -->
@@ -38,31 +37,8 @@
<router-view v-if="!isUserLoggedIn || isStaticPage" />
<template v-else>
<template v-if="isUserLoaded">
<div
v-show="showRestingBanner"
ref="restingBanner"
class="resting-banner"
>
<span class="content">
<span class="label d-inline d-sm-none">{{ $t('innCheckOutBannerShort') }}</span>
<span class="label d-none d-sm-inline">{{ $t('innCheckOutBanner') }}</span>
<span class="separator">|</span>
<span
class="resume"
@click="resumeDamage()"
>{{ $t('resumeDamage') }}</span>
</span>
<div
class="closepadding"
@click="hideBanner()"
>
<span
class="svg-icon inline icon-10"
aria-hidden="true"
v-html="icons.close"
></span>
</div>
</div>
<damage-paused-banner />
<!-- <gems-promo-banner /> -->
<notifications-display />
<app-menu />
<div
@@ -99,20 +75,11 @@
<style lang='scss' scoped>
@import '~@/assets/scss/colors.scss';
@import '~@/assets/scss/variables.scss';
#app {
display: flex;
flex-direction: column;
overflow-x: hidden;
&.resting {
--banner-resting-height: #{$restingToolbarHeight};
}
&.giftingBanner {
--banner-gifting-height: 2.5rem;
}
}
#loading-screen-inapp {
@@ -143,15 +110,6 @@
cursor: crosshair;
}
.closepadding {
margin: 11px 24px;
display: inline-block;
position: relative;
right: 0;
top: 0;
cursor: pointer;
}
.container-fluid {
flex: 1 0 auto;
}
@@ -172,51 +130,11 @@
margin-top: .5em;
margin-bottom: .5em;
}
.resting-banner {
width: 100%;
height: $restingToolbarHeight;
background-color: $blue-10;
top: 0;
z-index: 1300;
display: flex;
.content {
line-height: 1.71;
text-align: center;
color: $white;
padding: 8px 38px 8px 8px;
margin: auto;
}
@media only screen and (max-width: 768px) {
.content {
font-size: 12px;
line-height: 1.4;
}
}
.separator {
color: $blue-100;
margin: 0px 15px;
}
.resume {
font-weight: bold;
cursor: pointer;
white-space:nowrap;
}
}
</style>
<style lang='scss'>
@import '~@/assets/scss/colors.scss';
.closepadding span svg path {
stroke: #FFF;
opacity: 0.48;
}
.modal-backdrop {
opacity: .9 !important;
background-color: $purple-100 !important;
@@ -234,6 +152,8 @@ import { loadProgressBar } from 'axios-progress-bar';
import AppMenu from './components/header/menu';
import AppHeader from './components/header/index';
import DamagePausedBanner from './components/header/banners/damagePaused';
// import GemsPromoBanner from './components/header/banners/gemsPromo';
import AppFooter from './components/appFooter';
import notificationsDisplay from './components/notifications';
import snackbars from './components/snackbars/notifications';
@@ -255,8 +175,6 @@ import {
removeLocalSetting,
} from '@/libs/userlocalManager';
import svgClose from '@/assets/svg/close.svg';
const COMMUNITY_MANAGER_EMAIL = process.env.EMAILS_COMMUNITY_MANAGER_EMAIL; // eslint-disable-line
export default {
@@ -265,6 +183,8 @@ export default {
AppMenu,
AppHeader,
AppFooter,
DamagePausedBanner,
// GemsPromoBanner,
notificationsDisplay,
snackbars,
BuyModal,
@@ -277,9 +197,6 @@ export default {
mixins: [notifications, spellsMixin],
data () {
return {
icons: Object.freeze({
close: svgClose,
}),
selectedItemToBuy: null,
selectedSpellToBuy: null,
@@ -299,9 +216,6 @@ export default {
castingSpell () {
return this.$store.state.spellOptions.castingSpell;
},
showRestingBanner () {
return !this.bannerHidden && this.user && this.user.preferences.sleep;
},
noMargin () {
return ['privateMessages'].includes(this.$route.name);
},
@@ -589,12 +503,6 @@ export default {
hideLoadingScreen () {
this.loading = false;
},
hideBanner () {
this.bannerHidden = true;
},
resumeDamage () {
this.$store.dispatch('user:sleep');
},
},
};
</script>
@@ -632,5 +540,6 @@ export default {
<style src="@/assets/css/sprites/spritesmith-main-26.css"></style>
<style src="@/assets/css/sprites/spritesmith-main-27.css"></style>
<style src="@/assets/css/sprites/spritesmith-main-28.css"></style>
<style src="@/assets/css/sprites/spritesmith-main-29.css"></style>
<style src="@/assets/css/sprites.css"></style>
<style src="smartbanner.js/dist/smartbanner.min.css"></style>
@@ -1,62 +1,68 @@
.promo_armoire_backgrounds_202007 {
.promo_armoire_backgrounds_202010 {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: 0px -431px;
background-position: 0px -639px;
width: 423px;
height: 147px;
}
.promo_armoire_backgrounds_202008 {
.promo_fall_customizations {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -424px -431px;
width: 423px;
height: 147px;
background-position: -532px 0px;
width: 336px;
height: 207px;
}
.promo_armoire_backgrounds_202009 {
.promo_fall_festival_2019 {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: 0px -579px;
width: 423px;
height: 147px;
background-position: 0px -449px;
width: 360px;
height: 189px;
}
.promo_golden_achievements {
.promo_fall_festival_2020 {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: 0px -727px;
width: 246px;
height: 112px;
}
.promo_mystery_202008 {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -532px -196px;
width: 294px;
height: 156px;
background-position: -361px -449px;
width: 360px;
height: 174px;
}
.promo_mystery_202009 {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -424px -579px;
background-position: -869px -296px;
width: 282px;
height: 147px;
}
.promo_mystery_202010 {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -869px -444px;
width: 282px;
height: 147px;
}
.promo_sandy_sidekicks_bundle {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -869px -148px;
width: 420px;
height: 147px;
}
.promo_skeleton_achievements {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: 0px -244px;
width: 366px;
height: 204px;
}
.promo_spooky_sparkles {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -424px -639px;
width: 423px;
height: 147px;
}
.promo_take_this {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -532px -353px;
background-position: -1152px -296px;
width: 96px;
height: 69px;
}
.promo_time_travelers {
.promo_vampire_potions {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: 0px -244px;
width: 375px;
height: 186px;
}
.scene_CernyPie {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -376px -244px;
width: 141px;
height: 167px;
}
.scene_achievement {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -878px 0px;
width: 210px;
height: 210px;
background-position: -869px 0px;
width: 423px;
height: 147px;
}
.scene_positivity {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
@@ -64,27 +70,15 @@
width: 531px;
height: 243px;
}
.scene_public_space {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -532px 0px;
width: 345px;
height: 195px;
}
.scene_reading {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -878px -392px;
width: 171px;
height: 144px;
}
.scene_rewards {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -878px -211px;
width: 207px;
height: 180px;
}
.scene_squall {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -878px -537px;
background-position: -532px -208px;
width: 141px;
height: 169px;
}
.scene_strength {
background-image: url('~@/assets/images/sprites/spritesmith-largeSprites-0.png');
background-position: -869px -592px;
width: 192px;
height: 129px;
}
@@ -1,228 +1,234 @@
.achievement-alien {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1671px -1480px;
background-position: -1659px -1480px;
width: 24px;
height: 26px;
}
.achievement-alien2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -524px -1549px;
background-position: -480px -1549px;
width: 48px;
height: 52px;
}
.achievement-allThatGlitters2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -954px -1480px;
background-position: -812px -1480px;
width: 64px;
height: 56px;
}
.achievement-allYourBase2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1019px -1480px;
background-position: -877px -1480px;
width: 64px;
height: 56px;
}
.achievement-alpha2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -573px -1549px;
background-position: -529px -1549px;
width: 48px;
height: 52px;
}
.achievement-aridAuthority2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1084px -1480px;
background-position: -942px -1480px;
width: 64px;
height: 56px;
}
.achievement-armor2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -622px -1549px;
background-position: -578px -1549px;
width: 48px;
height: 52px;
}
.achievement-backToBasics2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1279px -1480px;
background-position: -1267px -1480px;
width: 48px;
height: 56px;
}
.achievement-bareNecessities2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -426px -1480px;
background-position: -284px -1480px;
width: 68px;
height: 68px;
}
.achievement-bewilder2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -671px -1549px;
background-position: -627px -1549px;
width: 48px;
height: 52px;
}
.achievement-birthday2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -720px -1549px;
background-position: -676px -1549px;
width: 48px;
height: 52px;
}
.achievement-boneCollector2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1316px -1480px;
width: 48px;
height: 56px;
}
.achievement-boot2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -769px -1549px;
background-position: -725px -1549px;
width: 48px;
height: 52px;
}
.achievement-bow2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -818px -1549px;
background-position: -774px -1549px;
width: 48px;
height: 52px;
}
.achievement-bugBonanza2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -771px -1480px;
background-position: -629px -1480px;
width: 60px;
height: 64px;
}
.achievement-burnout2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -867px -1549px;
background-position: -823px -1549px;
width: 48px;
height: 52px;
}
.achievement-cactus2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -916px -1549px;
background-position: -872px -1549px;
width: 48px;
height: 52px;
}
.achievement-cake2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -965px -1549px;
background-position: -921px -1549px;
width: 48px;
height: 52px;
}
.achievement-cave2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1014px -1549px;
background-position: -970px -1549px;
width: 48px;
height: 52px;
}
.achievement-challenge2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1063px -1549px;
background-position: -1019px -1549px;
width: 48px;
height: 52px;
}
.achievement-comment2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1112px -1549px;
background-position: -1068px -1549px;
width: 48px;
height: 52px;
}
.achievement-completedTask2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1328px -1480px;
background-position: -1365px -1480px;
width: 48px;
height: 56px;
}
.achievement-congrats2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1161px -1549px;
background-position: -1117px -1549px;
width: 48px;
height: 52px;
}
.achievement-costumeContest2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1210px -1549px;
background-position: -1166px -1549px;
width: 48px;
height: 52px;
}
.achievement-createdTask2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1377px -1480px;
background-position: -1414px -1480px;
width: 48px;
height: 56px;
}
.achievement-dilatory2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1259px -1549px;
background-position: -1215px -1549px;
width: 48px;
height: 52px;
}
.achievement-dustDevil2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1426px -1480px;
background-position: -1463px -1480px;
width: 48px;
height: 56px;
}
.achievement-dysheartener2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1308px -1549px;
background-position: -1264px -1549px;
width: 48px;
height: 52px;
}
.achievement-fedPet2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1475px -1480px;
background-position: -1512px -1480px;
width: 48px;
height: 56px;
}
.achievement-freshwaterFriends2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -495px -1480px;
background-position: -353px -1480px;
width: 68px;
height: 68px;
}
.achievement-friends2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1357px -1549px;
background-position: -1313px -1549px;
width: 48px;
height: 52px;
}
.achievement-getwell2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1406px -1549px;
background-position: -1362px -1549px;
width: 48px;
height: 52px;
}
.achievement-goodAsGold2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1524px -1480px;
background-position: -1561px -1480px;
width: 48px;
height: 56px;
}
.achievement-goodluck2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1455px -1549px;
background-position: -1411px -1549px;
width: 48px;
height: 52px;
}
.achievement-greeting2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1504px -1549px;
background-position: -1460px -1549px;
width: 48px;
height: 52px;
}
.achievement-guild2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1553px -1549px;
background-position: -1509px -1549px;
width: 48px;
height: 52px;
}
.achievement-habitBirthday2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1602px -1549px;
background-position: -1558px -1549px;
width: 48px;
height: 52px;
}
.achievement-habiticaDay2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1651px -1549px;
background-position: -1607px -1549px;
width: 48px;
height: 52px;
}
.achievement-hatchedPet2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1573px -1480px;
background-position: -1610px -1480px;
width: 48px;
height: 56px;
}
@@ -234,7 +240,7 @@
}
.achievement-justAddWater2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -832px -1480px;
background-position: -690px -1480px;
width: 60px;
height: 64px;
}
@@ -246,13 +252,13 @@
}
.achievement-karaoke {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1671px -1507px;
background-position: -1659px -1507px;
width: 24px;
height: 26px;
}
.achievement-kickstarter20192x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -564px -1480px;
background-position: -422px -1480px;
width: 68px;
height: 68px;
}
@@ -264,13 +270,13 @@
}
.achievement-mindOverMatter2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -893px -1480px;
background-position: -751px -1480px;
width: 60px;
height: 64px;
}
.achievement-monsterMagus2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1622px -1480px;
background-position: -284px -1549px;
width: 48px;
height: 56px;
}
@@ -306,7 +312,7 @@
}
.achievement-pearlyPro2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1149px -1480px;
background-position: -1007px -1480px;
width: 64px;
height: 56px;
}
@@ -318,13 +324,13 @@
}
.achievement-primedForPainting2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -426px -1549px;
background-position: -333px -1549px;
width: 48px;
height: 56px;
}
.achievement-purchasedEquipment2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -475px -1549px;
background-position: -382px -1549px;
width: 48px;
height: 56px;
}
@@ -334,9 +340,15 @@
width: 48px;
height: 52px;
}
.achievement-redLetterDay2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1072px -1480px;
width: 64px;
height: 56px;
}
.achievement-rosyOutlook2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -633px -1480px;
background-position: -491px -1480px;
width: 68px;
height: 68px;
}
@@ -352,6 +364,12 @@
width: 48px;
height: 52px;
}
.achievement-seeingRed2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -431px -1549px;
width: 48px;
height: 56px;
}
.achievement-shield2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -588px -1628px;
@@ -364,6 +382,12 @@
width: 48px;
height: 52px;
}
.achievement-skeletonCrew2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1137px -1480px;
width: 64px;
height: 56px;
}
.achievement-snowball2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -686px -1628px;
@@ -408,7 +432,7 @@
}
.achievement-tickledPink2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -702px -1480px;
background-position: -560px -1480px;
width: 68px;
height: 68px;
}
@@ -450,7 +474,7 @@
}
.achievement-undeadUndertaker2x {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1214px -1480px;
background-position: -1202px -1480px;
width: 64px;
height: 56px;
}
@@ -748,489 +772,483 @@
width: 141px;
height: 147px;
}
.background_crosscountry_ski_trail {
.background_crescent_moon {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -994px -296px;
width: 141px;
height: 147px;
}
.background_crystal_cave {
.background_crosscountry_ski_trail {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -994px -444px;
width: 141px;
height: 147px;
}
.background_dark_deep {
.background_crystal_cave {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -994px -592px;
width: 141px;
height: 147px;
}
.background_deep_mine {
.background_dark_deep {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -994px -740px;
width: 141px;
height: 147px;
}
.background_deep_sea {
.background_deep_mine {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: 0px -888px;
width: 141px;
height: 147px;
}
.background_desert_dunes {
.background_deep_sea {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -142px -888px;
width: 141px;
height: 147px;
}
.background_desert_with_snow {
.background_desert_dunes {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -284px -888px;
width: 141px;
height: 147px;
}
.background_dilatory_castle {
.background_desert_with_snow {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -426px -888px;
width: 141px;
height: 147px;
}
.background_dilatory_city {
.background_dilatory_castle {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -568px -888px;
width: 141px;
height: 147px;
}
.background_dilatory_ruins {
.background_dilatory_city {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -710px -888px;
width: 141px;
height: 147px;
}
.background_distant_castle {
.background_dilatory_ruins {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -852px -888px;
width: 141px;
height: 147px;
}
.background_dojo {
.background_distant_castle {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -994px -888px;
width: 141px;
height: 147px;
}
.background_drifting_raft {
.background_dojo {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1136px 0px;
width: 141px;
height: 147px;
}
.background_driving_a_coach {
.background_drifting_raft {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1136px -148px;
width: 141px;
height: 147px;
}
.background_driving_a_sleigh {
.background_driving_a_coach {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1136px -296px;
width: 141px;
height: 147px;
}
.background_duck_pond {
.background_driving_a_sleigh {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1136px -444px;
width: 141px;
height: 147px;
}
.background_dungeon {
.background_duck_pond {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1136px -592px;
width: 141px;
height: 147px;
}
.background_dusty_canyons {
.background_dungeon {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1136px -740px;
width: 141px;
height: 147px;
}
.background_elegant_balcony {
.background_dusty_canyons {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1136px -888px;
width: 141px;
height: 147px;
}
.background_elegant_ballroom {
.background_elegant_balcony {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: 0px -1036px;
width: 141px;
height: 147px;
}
.background_fairy_ring {
.background_elegant_ballroom {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -142px -1036px;
width: 141px;
height: 147px;
}
.background_fantastical_shoe_store {
.background_fairy_ring {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -284px -1036px;
width: 141px;
height: 147px;
}
.background_farmers_market {
.background_fantastical_shoe_store {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -426px -1036px;
width: 141px;
height: 147px;
}
.background_farmhouse {
.background_farmers_market {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -568px -1036px;
width: 141px;
height: 147px;
}
.background_fiber_arts_room {
.background_farmhouse {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -710px -1036px;
width: 141px;
height: 147px;
}
.background_field_with_colored_eggs {
.background_fiber_arts_room {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -852px -1036px;
width: 141px;
height: 147px;
}
.background_floating_islands {
.background_field_with_colored_eggs {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -994px -1036px;
width: 141px;
height: 147px;
}
.background_floral_meadow {
.background_floating_islands {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1136px -1036px;
width: 141px;
height: 147px;
}
.background_flower_market {
.background_floral_meadow {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1278px 0px;
width: 141px;
height: 147px;
}
.customize-option.background_flower_market {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1303px -15px;
width: 60px;
height: 60px;
}
.background_flying_in_a_thunderstorm {
.background_flower_market {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1278px -148px;
width: 141px;
height: 147px;
}
.background_flying_over_a_field_of_wildflowers {
.customize-option.background_flower_market {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1303px -163px;
width: 60px;
height: 60px;
}
.background_flying_in_a_thunderstorm {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1278px -296px;
width: 141px;
height: 147px;
}
.customize-option.background_flying_over_a_field_of_wildflowers {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1303px -311px;
width: 60px;
height: 60px;
}
.background_flying_over_an_ancient_forest {
.background_flying_over_a_field_of_wildflowers {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1278px -444px;
width: 141px;
height: 147px;
}
.background_flying_over_an_autumn_forest {
.customize-option.background_flying_over_a_field_of_wildflowers {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1303px -459px;
width: 60px;
height: 60px;
}
.background_flying_over_an_ancient_forest {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1278px -592px;
width: 141px;
height: 147px;
}
.background_flying_over_icy_steppes {
.background_flying_over_an_autumn_forest {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1278px -740px;
width: 141px;
height: 147px;
}
.background_flying_over_rocky_canyon {
.background_flying_over_icy_steppes {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1278px -888px;
width: 141px;
height: 147px;
}
.background_flying_over_snowy_mountains {
.background_flying_over_rocky_canyon {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1278px -1036px;
width: 141px;
height: 147px;
}
.background_flying_over_tropical_islands {
.background_flying_over_snowy_mountains {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: 0px -1184px;
width: 141px;
height: 147px;
}
.background_foggy_moor {
.background_flying_over_tropical_islands {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -142px -1184px;
width: 141px;
height: 147px;
}
.background_forest {
.background_foggy_moor {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -284px -1184px;
width: 141px;
height: 147px;
}
.background_frigid_peak {
.background_forest {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -426px -1184px;
width: 141px;
height: 147px;
}
.background_frosty_forest {
.background_frigid_peak {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -568px -1184px;
width: 141px;
height: 147px;
}
.background_frozen_lake {
.background_frosty_forest {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -710px -1184px;
width: 141px;
height: 147px;
}
.background_garden_shed {
.background_frozen_lake {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -852px -1184px;
width: 141px;
height: 147px;
}
.background_gazebo {
.background_garden_shed {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -994px -1184px;
width: 141px;
height: 147px;
}
.background_giant_autumn_leaf {
.background_gazebo {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1136px -1184px;
width: 141px;
height: 147px;
}
.background_giant_birdhouse {
.background_giant_autumn_leaf {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1278px -1184px;
width: 141px;
height: 147px;
}
.background_giant_book {
.background_giant_birdhouse {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1420px 0px;
width: 141px;
height: 147px;
}
.background_giant_dandelions {
.background_giant_book {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1420px -148px;
width: 141px;
height: 147px;
}
.background_giant_florals {
.background_giant_dandelions {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1420px -296px;
width: 141px;
height: 147px;
}
.background_giant_seashell {
.background_giant_florals {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1420px -444px;
width: 141px;
height: 147px;
}
.background_giant_wave {
.background_giant_seashell {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1420px -592px;
width: 141px;
height: 147px;
}
.background_glowing_mushroom_cave {
.background_giant_wave {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1420px -740px;
width: 141px;
height: 147px;
}
.background_gorgeous_greenhouse {
.background_gingerbread_house {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1420px -888px;
width: 141px;
height: 147px;
}
.background_grand_staircase {
.background_glowing_mushroom_cave {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1420px -1036px;
width: 141px;
height: 147px;
}
.background_graveyard {
.background_gorgeous_greenhouse {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1420px -1184px;
width: 141px;
height: 147px;
}
.background_green {
.background_grand_staircase {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: 0px -1332px;
width: 141px;
height: 147px;
}
.background_guardian_statues {
.background_graveyard {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -142px -1332px;
width: 141px;
height: 147px;
}
.background_gumdrop_land {
.background_green {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -284px -1332px;
width: 141px;
height: 147px;
}
.background_habit_city_rooftops {
.background_guardian_statues {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -426px -1332px;
width: 141px;
height: 147px;
}
.background_habit_city_streets {
.background_gumdrop_land {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -568px -1332px;
width: 141px;
height: 147px;
}
.background_halflings_house {
.background_habit_city_rooftops {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -710px -1332px;
width: 141px;
height: 147px;
}
.background_hall_of_heroes {
.background_habit_city_streets {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -852px -1332px;
width: 141px;
height: 147px;
}
.background_harvest_feast {
.background_halflings_house {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -994px -1332px;
width: 141px;
height: 147px;
}
.background_harvest_fields {
.background_hall_of_heroes {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1136px -1332px;
width: 141px;
height: 147px;
}
.background_harvest_moon {
.background_harvest_feast {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1278px -1332px;
width: 141px;
height: 147px;
}
.background_haunted_house {
.background_harvest_fields {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1420px -1332px;
width: 141px;
height: 147px;
}
.background_heather_field {
.background_harvest_moon {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1562px 0px;
width: 141px;
height: 147px;
}
.background_herding_sheep_in_autumn {
.background_haunted_forest {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1562px -148px;
width: 141px;
height: 147px;
}
.background_holiday_market {
.background_haunted_house {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1562px -296px;
width: 141px;
height: 147px;
}
.background_holiday_wreath {
.background_heather_field {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1562px -444px;
width: 141px;
height: 147px;
}
.background_hot_air_balloon {
.background_herding_sheep_in_autumn {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1562px -592px;
width: 141px;
height: 147px;
}
.background_ice_cave {
.background_holiday_hearth {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1562px -740px;
width: 141px;
height: 147px;
}
.background_iceberg {
.background_holiday_market {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1562px -888px;
width: 141px;
height: 147px;
}
.background_idyllic_cabin {
.background_holiday_wreath {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1562px -1036px;
width: 141px;
height: 147px;
}
.background_in_a_classroom {
.background_hot_air_balloon {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1562px -1184px;
width: 141px;
height: 147px;
}
.background_in_an_ancient_tomb {
.background_ice_cave {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -1562px -1332px;
width: 141px;
height: 147px;
}
.background_island_waterfalls {
.background_iceberg {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: 0px -1480px;
width: 141px;
height: 147px;
}
.background_jungle_canopy {
.background_idyllic_cabin {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -142px -1480px;
width: 141px;
height: 147px;
}
.background_kelp_forest {
background-image: url('~@/assets/images/sprites/spritesmith-main-0.png');
background-position: -284px -1480px;
width: 141px;
height: 147px;
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More