Compare commits

..

212 Commits

Author SHA1 Message Date
SabreCat 57027a1a62 4.267.2 2023-04-25 15:50:55 -05:00
SabreCat 92b4a8029d fix(links): handle meta key 2023-04-25 15:14:59 -05:00
SabreCat 7b4dd36827 4.267.1 2023-04-20 15:30:46 -05:00
SabreCat be65042463 Merge branch 'external-link-modal' into release 2023-04-20 15:30:37 -05:00
SabreCat cccb6a9c02 Merge branch 'develop' into release 2023-04-20 15:30:29 -05:00
Weblate 916c7c49e7 Translated using Weblate (Danish)
Currently translated at 79.2% (321 of 405 strings)

Translated using Weblate (Slovak)

Currently translated at 54.5% (119 of 218 strings)

Translated using Weblate (Slovak)

Currently translated at 67.0% (63 of 94 strings)

Translated using Weblate (Hebrew)

Currently translated at 70.9% (93 of 131 strings)

Translated using Weblate (Slovak)

Currently translated at 80.2% (325 of 405 strings)

Translated using Weblate (Slovak)

Currently translated at 87.5% (7 of 8 strings)

Translated using Weblate (Hebrew)

Currently translated at 45.5% (1281 of 2813 strings)

Translated using Weblate (Slovak)

Currently translated at 87.9% (160 of 182 strings)

Translated using Weblate (Hebrew)

Currently translated at 74.1% (135 of 182 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (376 of 376 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (98 of 98 strings)

Translated using Weblate (Slovak)

Currently translated at 53.2% (410 of 770 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Malay)

Currently translated at 47.2% (128 of 271 strings)

Translated using Weblate (French)

Currently translated at 100.0% (2813 of 2813 strings)

Translated using Weblate (Hebrew)

Currently translated at 45.2% (1272 of 2813 strings)

Translated using Weblate (Hebrew)

Currently translated at 76.1% (163 of 214 strings)

Translated using Weblate (Hebrew)

Currently translated at 91.9% (137 of 149 strings)

Translated using Weblate (Hebrew)

Currently translated at 87.9% (131 of 149 strings)

Translated using Weblate (Hebrew)

Currently translated at 100.0% (56 of 56 strings)

Translated using Weblate (Italian)

Currently translated at 98.1% (2760 of 2813 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (54 of 54 strings)

Translated using Weblate (Hebrew)

Currently translated at 61.0% (133 of 218 strings)

Translated using Weblate (Hebrew)

Currently translated at 64.2% (72 of 112 strings)

Translated using Weblate (Hebrew)

Currently translated at 67.9% (89 of 131 strings)

Translated using Weblate (Hebrew)

Currently translated at 26.1% (71 of 271 strings)

Translated using Weblate (Hebrew)

Currently translated at 45.6% (185 of 405 strings)

Translated using Weblate (Hebrew)

Currently translated at 45.1% (1271 of 2813 strings)

Translated using Weblate (Hebrew)

Currently translated at 82.9% (39 of 47 strings)

Translated using Weblate (Hebrew)

Currently translated at 84.4% (157 of 186 strings)

Translated using Weblate (Ukrainian)

Currently translated at 28.4% (799 of 2813 strings)

Translated using Weblate (Indonesian)

Currently translated at 62.7% (170 of 271 strings)

Translated using Weblate (Hebrew)

Currently translated at 75.1% (112 of 149 strings)

Translated using Weblate (Hebrew)

Currently translated at 73.1% (109 of 149 strings)

Translated using Weblate (Hebrew)

Currently translated at 73.1% (109 of 149 strings)

Translated using Weblate (Hebrew)

Currently translated at 73.1% (109 of 149 strings)

Translated using Weblate (Hebrew)

Currently translated at 69.1% (103 of 149 strings)

Translated using Weblate (Hebrew)

Currently translated at 69.1% (103 of 149 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2809 of 2809 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2809 of 2809 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Irish)

Currently translated at 12.5% (14 of 112 strings)

Translated using Weblate (Irish)

Currently translated at 60.4% (1700 of 2813 strings)

Translated using Weblate (Indonesian)

Currently translated at 66.0% (144 of 218 strings)

Translated using Weblate (Irish)

Currently translated at 10.7% (12 of 112 strings)

Translated using Weblate (Irish)

Currently translated at 74.4% (111 of 149 strings)

Translated using Weblate (Irish)

Currently translated at 60.3% (1698 of 2813 strings)

Translated using Weblate (Irish)

Currently translated at 5.3% (6 of 112 strings)

Translated using Weblate (Irish)

Currently translated at 100.0% (1 of 1 strings)

Translated using Weblate (Irish)

Currently translated at 74.4% (111 of 149 strings)

Translated using Weblate (Irish)

Currently translated at 50.0% (4 of 8 strings)

Translated using Weblate (Irish)

Currently translated at 89.2% (191 of 214 strings)

Translated using Weblate (Irish)

Currently translated at 29.6% (16 of 54 strings)

Translated using Weblate (Irish)

Currently translated at 93.3% (14 of 15 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Indonesian)

Currently translated at 95.6% (174 of 182 strings)

Translated using Weblate (Malay)

Currently translated at 48.0% (87 of 181 strings)

Translated using Weblate (Arabic)

Currently translated at 45.0% (27 of 60 strings)

Translated using Weblate (Arabic)

Currently translated at 56.8% (124 of 218 strings)

Translated using Weblate (Arabic)

Currently translated at 81.1% (620 of 764 strings)

Translated using Weblate (Arabic)

Currently translated at 61.4% (75 of 122 strings)

Translated using Weblate (French)

Currently translated at 100.0% (218 of 218 strings)

Translated using Weblate (French)

Currently translated at 100.0% (376 of 376 strings)

Translated using Weblate (French)

Currently translated at 100.0% (222 of 222 strings)

Translated using Weblate (Malay)

Currently translated at 45.0% (122 of 271 strings)

Translated using Weblate (Turkish)

Currently translated at 95.7% (90 of 94 strings)

Translated using Weblate (Turkish)

Currently translated at 95.5% (107 of 112 strings)

Translated using Weblate (Ukrainian)

Currently translated at 27.6% (777 of 2813 strings)

Translated using Weblate (Indonesian)

Currently translated at 68.5% (37 of 54 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (121 of 121 strings)

Translated using Weblate (Turkish)

Currently translated at 100.0% (376 of 376 strings)

Translated using Weblate (Turkish)

Currently translated at 87.9% (131 of 149 strings)

Translated using Weblate (Malay)

Currently translated at 44.6% (121 of 271 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (376 of 376 strings)

Translated using Weblate (Malay)

Currently translated at 46.6% (28 of 60 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (376 of 376 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (222 of 222 strings)

Translated using Weblate (Ukrainian)

Currently translated at 74.0% (566 of 764 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (376 of 376 strings)

Translated using Weblate (Indonesian)

Currently translated at 94.6% (356 of 376 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (222 of 222 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (376 of 376 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (222 of 222 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (121 of 121 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (376 of 376 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (222 of 222 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (121 of 121 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Spanish)

Currently translated at 91.9% (2587 of 2813 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (135 of 135 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (376 of 376 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (60 of 60 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (98 of 98 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (221 of 221 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (376 of 376 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (221 of 221 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (22 of 22 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (376 of 376 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (135 of 135 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (221 of 221 strings)

Translated using Weblate (Belarusian)

Currently translated at 4.0% (6 of 149 strings)

Translated using Weblate (Hungarian)

Currently translated at 55.0% (120 of 218 strings)

Translated using Weblate (Hungarian)

Currently translated at 78.6% (103 of 131 strings)

Translated using Weblate (Hungarian)

Currently translated at 39.8% (108 of 271 strings)

Translated using Weblate (Hungarian)

Currently translated at 74.3% (301 of 405 strings)

Translated using Weblate (Ukrainian)

Currently translated at 27.4% (772 of 2813 strings)

Translated using Weblate (Indonesian)

Currently translated at 61.0% (1718 of 2813 strings)

Translated using Weblate (Hungarian)

Currently translated at 60.3% (1697 of 2813 strings)

Translated using Weblate (Hungarian)

Currently translated at 88.4% (161 of 182 strings)

Translated using Weblate (Hungarian)

Currently translated at 66.6% (40 of 60 strings)

Translated using Weblate (Hungarian)

Currently translated at 73.8% (564 of 764 strings)

Translated using Weblate (Hungarian)

Currently translated at 62.2% (76 of 122 strings)

Translated using Weblate (Hungarian)

Currently translated at 60.4% (90 of 149 strings)

Translated using Weblate (Hungarian)

Currently translated at 57.0% (85 of 149 strings)

Translated using Weblate (Ukrainian)

Currently translated at 27.4% (771 of 2813 strings)

Translated using Weblate (Russian)

Currently translated at 85.2% (104 of 122 strings)

Translated using Weblate (Malay)

Currently translated at 46.4% (52 of 112 strings)

Translated using Weblate (Malay)

Currently translated at 53.5% (412 of 770 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (218 of 218 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (218 of 218 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Arabic)

Currently translated at 86.1% (663 of 770 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Indonesian)

Currently translated at 81.6% (107 of 131 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (121 of 121 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Malay)

Currently translated at 43.5% (118 of 271 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.5% (217 of 218 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (121 of 121 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (218 of 218 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (Galician)

Currently translated at 63.9% (78 of 122 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (131 of 131 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (60 of 60 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Galician)

Currently translated at 63.9% (78 of 122 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (217 of 217 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (218 of 218 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2813 of 2813 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Galician)

Currently translated at 73.0% (296 of 405 strings)

Translated using Weblate (Spanish)

Currently translated at 91.9% (2587 of 2813 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Galician)

Currently translated at 64.6% (262 of 405 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (218 of 218 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Galician)

Currently translated at 42.4% (115 of 271 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (217 of 217 strings)

Translated using Weblate (Galician)

Currently translated at 40.9% (166 of 405 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (Croatian)

Currently translated at 100.0% (56 of 56 strings)

Translated using Weblate (Croatian)

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (Croatian)

Currently translated at 100.0% (135 of 135 strings)

Translated using Weblate (Croatian)

Currently translated at 99.2% (269 of 271 strings)

Translated using Weblate (Croatian)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2809 of 2809 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (121 of 121 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (131 of 131 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Galician)

Currently translated at 71.5% (133 of 186 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (131 of 131 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (13 of 13 strings)

Translated using Weblate (Galician)

Currently translated at 94.3% (202 of 214 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (13 of 13 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Croatian)

Currently translated at 100.0% (770 of 770 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (13 of 13 strings)

Translated using Weblate (Ukrainian)

Currently translated at 73.8% (564 of 764 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (94 of 94 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (98 of 98 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Croatian)

Currently translated at 100.0% (98 of 98 strings)

Translated using Weblate (Croatian)

Currently translated at 99.2% (764 of 770 strings)

Translated using Weblate (Croatian)

Currently translated at 99.2% (134 of 135 strings)

Translated using Weblate (Croatian)

Currently translated at 92.3% (12 of 13 strings)

Translated using Weblate (Croatian)

Currently translated at 80.7% (617 of 764 strings)

Translated using Weblate (Ukrainian)

Currently translated at 73.6% (563 of 764 strings)

Translated using Weblate (Croatian)

Currently translated at 84.0% (647 of 770 strings)

Translated using Weblate (Croatian)

Currently translated at 83.8% (646 of 770 strings)

Translated using Weblate (Croatian)

Currently translated at 83.7% (645 of 770 strings)

Translated using Weblate (Croatian)

Currently translated at 83.7% (645 of 770 strings)

Translated using Weblate (Croatian)

Currently translated at 83.6% (644 of 770 strings)

Translated using Weblate (Croatian)

Currently translated at 83.5% (643 of 770 strings)

Translated using Weblate (Galician)

Currently translated at 96.7% (59 of 61 strings)

Translated using Weblate (Croatian)

Currently translated at 83.3% (642 of 770 strings)

Translated using Weblate (Croatian)

Currently translated at 83.2% (641 of 770 strings)

Translated using Weblate (Croatian)

Currently translated at 83.1% (640 of 770 strings)

Translated using Weblate (Croatian)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (56 of 56 strings)

Translated using Weblate (Galician)

Currently translated at 71.5% (133 of 186 strings)

Translated using Weblate (Croatian)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Galician)

Currently translated at 94.9% (356 of 375 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (60 of 60 strings)

Translated using Weblate (Galician)

Currently translated at 94.3% (202 of 214 strings)

Translated using Weblate (Croatian)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (22 of 22 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (15 of 15 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (13 of 13 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (54 of 54 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (2 of 2 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (1 of 1 strings)

Translated using Weblate (French)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Croatian)

Currently translated at 91.7% (167 of 182 strings)

Translated using Weblate (Croatian)

Currently translated at 87.5% (7 of 8 strings)

Translated using Weblate (Croatian)

Currently translated at 98.6% (147 of 149 strings)

Translated using Weblate (Croatian)

Currently translated at 96.3% (261 of 271 strings)

Translated using Weblate (Croatian)

Currently translated at 87.5% (7 of 8 strings)

Translated using Weblate (Croatian)

Currently translated at 100.0% (54 of 54 strings)

Translated using Weblate (Indonesian)

Currently translated at 74.0% (566 of 764 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (121 of 121 strings)

Translated using Weblate (Croatian)

Currently translated at 36.2% (66 of 182 strings)

Translated using Weblate (Croatian)

Currently translated at 75.0% (6 of 8 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (60 of 60 strings)

Translated using Weblate (Ukrainian)

Currently translated at 73.4% (561 of 764 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (121 of 121 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (121 of 121 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (1 of 1 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (1 of 1 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Turkish)

Currently translated at 60.7% (468 of 770 strings)

Translated using Weblate (Malay)

Currently translated at 44.7% (81 of 181 strings)

Translated using Weblate (Indonesian)

Currently translated at 98.3% (119 of 121 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (56 of 56 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (54 of 54 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (13 of 13 strings)

Translated using Weblate (Galician)

Currently translated at 42.3% (326 of 770 strings)

Translated using Weblate (Galician)

Currently translated at 65.7% (502 of 764 strings)

Translated using Weblate (Galician)

Currently translated at 40.9% (166 of 405 strings)

Translated using Weblate (Galician)

Currently translated at 94.9% (356 of 375 strings)

Translated using Weblate (Galician)

Currently translated at 43.6% (336 of 770 strings)

Translated using Weblate (Galician)

Currently translated at 66.6% (509 of 764 strings)

Translated using Weblate (Galician)

Currently translated at 42.4% (172 of 405 strings)

Translated using Weblate (Galician)

Currently translated at 96.8% (363 of 375 strings)

Translated using Weblate (Ukrainian)

Currently translated at 72.9% (557 of 764 strings)

Translated using Weblate (Galician)

Currently translated at 49.4% (381 of 770 strings)

Translated using Weblate (Galician)

Currently translated at 70.6% (540 of 764 strings)

Translated using Weblate (Galician)

Currently translated at 36.1% (98 of 271 strings)

Translated using Weblate (Galician)

Currently translated at 51.3% (208 of 405 strings)

Translated using Weblate (Indonesian)

Currently translated at 64.5% (140 of 217 strings)

Translated using Weblate (Ukrainian)

Currently translated at 26.9% (756 of 2809 strings)

Translated using Weblate (Ukrainian)

Currently translated at 71.5% (547 of 764 strings)

Translated using Weblate (Galician)

Currently translated at 64.2% (36 of 56 strings)

Translated using Weblate (Galician)

Currently translated at 63.3% (83 of 131 strings)

Translated using Weblate (Galician)

Currently translated at 93.3% (56 of 60 strings)

Translated using Weblate (Galician)

Currently translated at 71.5% (133 of 186 strings)

Translated using Weblate (Galician)

Currently translated at 52.7% (406 of 770 strings)

Translated using Weblate (Galician)

Currently translated at 36.8% (80 of 217 strings)

Translated using Weblate (Galician)

Currently translated at 76.9% (10 of 13 strings)

Translated using Weblate (Galician)

Currently translated at 73.2% (560 of 764 strings)

Translated using Weblate (Galician)

Currently translated at 79.7% (75 of 94 strings)

Translated using Weblate (Galician)

Currently translated at 87.5% (7 of 8 strings)

Translated using Weblate (Galician)

Currently translated at 10.0% (15 of 149 strings)

Translated using Weblate (Galician)

Currently translated at 77.0% (47 of 61 strings)

Translated using Weblate (Galician)

Currently translated at 36.5% (99 of 271 strings)

Translated using Weblate (Galician)

Currently translated at 56.2% (228 of 405 strings)

Translated using Weblate (Galician)

Currently translated at 94.3% (202 of 214 strings)

Translated using Weblate (Galician)

Currently translated at 60.7% (1706 of 2809 strings)

Translated using Weblate (Galician)

Currently translated at 98.1% (53 of 54 strings)

Translated using Weblate (Galician)

Currently translated at 93.6% (44 of 47 strings)

Translated using Weblate (Galician)

Currently translated at 43.4% (53 of 122 strings)

Translated using Weblate (Ukrainian)

Currently translated at 26.9% (756 of 2809 strings)

Translated using Weblate (Indonesian)

Currently translated at 94.9% (356 of 375 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (60 of 60 strings)

Translated using Weblate (Ukrainian)

Currently translated at 71.5% (547 of 764 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (94 of 94 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Galician)

Currently translated at 48.3% (29 of 60 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (131 of 131 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (135 of 135 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (56 of 56 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (54 of 54 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Galician)

Currently translated at 100.0% (13 of 13 strings)

Translated using Weblate (Malay)

Currently translated at 42.4% (115 of 271 strings)

Translated using Weblate (Ukrainian)

Currently translated at 26.4% (742 of 2809 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (135 of 135 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Ukrainian)

Currently translated at 71.2% (544 of 764 strings)

Translated using Weblate (Spanish)

Currently translated at 92.0% (2587 of 2809 strings)

Translated using Weblate (Ukrainian)

Currently translated at 70.9% (542 of 764 strings)

Translated using Weblate (Indonesian)

Currently translated at 80.1% (105 of 131 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2809 of 2809 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2809 of 2809 strings)

Translated using Weblate (Ukrainian)

Currently translated at 26.0% (732 of 2809 strings)

Translated using Weblate (Dutch)

Currently translated at 98.3% (120 of 122 strings)

Translated using Weblate (Indonesian)

Currently translated at 95.8% (116 of 121 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.6% (270 of 271 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.8% (2804 of 2809 strings)

Translated using Weblate (Malay)

Currently translated at 42.8% (48 of 112 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (94 of 94 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.2% (269 of 271 strings)

Translated using Weblate (Indonesian)

Currently translated at 77.5% (314 of 405 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.6% (2799 of 2809 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (15 of 15 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (French)

Currently translated at 100.0% (2809 of 2809 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (770 of 770 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Polish)

Currently translated at 87.0% (189 of 217 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 98.5% (267 of 271 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.0% (2782 of 2809 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 99.0% (2782 of 2809 strings)

Translated using Weblate (Polish)

Currently translated at 96.6% (144 of 149 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2809 of 2809 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2809 of 2809 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Malay)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Indonesian)

Currently translated at 98.1% (210 of 214 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (186 of 186 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (French)

Currently translated at 99.1% (2786 of 2809 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (French)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (French)

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (French)

Currently translated at 99.0% (2783 of 2809 strings)

Translated using Weblate (French)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.9% (2808 of 2809 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Spanish)

Currently translated at 92.9% (252 of 271 strings)

Translated using Weblate (Ukrainian)

Currently translated at 25.0% (704 of 2809 strings)

Translated using Weblate (Dutch)

Currently translated at 88.0% (2474 of 2809 strings)

Translated using Weblate (Ukrainian)

Currently translated at 70.5% (539 of 764 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Spanish)

Currently translated at 99.7% (768 of 770 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Spanish)

Currently translated at 99.5% (220 of 221 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Ukrainian)

Currently translated at 67.6% (517 of 764 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Ukrainian)

Currently translated at 99.7% (404 of 405 strings)

Translated using Weblate (Spanish)

Currently translated at 92.0% (2587 of 2809 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (271 of 271 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (2805 of 2809 strings)

Translated using Weblate (Dutch)

Currently translated at 87.3% (2453 of 2809 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (216 of 216 strings)

Translated using Weblate (Indonesian)

Currently translated at 86.8% (53 of 61 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.1% (2785 of 2809 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Serbian)

Currently translated at 28.1% (42 of 149 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (135 of 135 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (216 of 216 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (404 of 404 strings)

Translated using Weblate (Indonesian)

Currently translated at 61.7% (1718 of 2781 strings)

Translated using Weblate (Indonesian)

Currently translated at 66.6% (36 of 54 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (221 of 221 strings)

Translated using Weblate (Indonesian)

Currently translated at 62.9% (34 of 54 strings)

Translated using Weblate (Indonesian)

Currently translated at 62.9% (34 of 54 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (404 of 404 strings)

Translated using Weblate (Serbian)

Currently translated at 26.1% (39 of 149 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.3% (148 of 149 strings)

Translated using Weblate (Serbian)

Currently translated at 24.8% (37 of 149 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (404 of 404 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (149 of 149 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (149 of 149 strings)

Co-authored-by: Adrián Chaves Fernández <adrian@chaves.io>
Co-authored-by: Ana Beatriz <anabeatriz.augusto06@yahoo.com>
Co-authored-by: Andressa Murari Sudré <andressa@sudre.com.br>
Co-authored-by: Arthur Ouzlaner <panther1984@gmail.com>
Co-authored-by: Benoit Hetru <me+hbtc@gahanka.net>
Co-authored-by: Delta S <deseji93@gmail.com>
Co-authored-by: Diana <dianazabiyaka@gmail.com>
Co-authored-by: Duygu Erates <duygu.erates@gmail.com>
Co-authored-by: Edward McGibney <edwardmcgibney95@gmail.com>
Co-authored-by: Ellen A M <ellen_a_m@hotmail.com>
Co-authored-by: Ewa Trybuszewski <trybuszewskiewa@gmail.com>
Co-authored-by: Falzart Werefox <muh_fauzi_ramadhan@yahoo.co.id>
Co-authored-by: HURZHII ORYNA <radovaarina@gmail.com>
Co-authored-by: Hanafi <naflizo@gmail.com>
Co-authored-by: Ike Osenberg <ike.osenberg@gmail.com>
Co-authored-by: Jerry Chen <minecjraft@qq.com>
Co-authored-by: Kit Postovnev <sahnonik231@gmail.com>
Co-authored-by: Kovács Máté <kovacsur10@gmail.com>
Co-authored-by: Lauren C <laurenc7834@gmail.com>
Co-authored-by: LiziKnight <liziknight0316@outlook.com>
Co-authored-by: Luna <lunadammandersen@gmail.com>
Co-authored-by: M <maperray@gmail.com>
Co-authored-by: Matúš Goljer <matus.goljer@gmail.com>
Co-authored-by: Michael <mishaopanasuk3@gmail.com>
Co-authored-by: Nazar Paruna <nazarparuna@gmail.com>
Co-authored-by: Ofek yeshurun <ofek.yeshurun@gmail.com>
Co-authored-by: Raithe <RaitheOfDureya@gmail.com>
Co-authored-by: Rara <annisarahmah.xmipa2@gmail.com>
Co-authored-by: Razi H <razi.haj@gmail.com>
Co-authored-by: Sabe Jones <sabe@habitica.com>
Co-authored-by: Sandra Marcial <sandramarcial80@gmail.com>
Co-authored-by: Sciuridae <sweetvshoney@163.com>
Co-authored-by: Stefan Trbojević <garkogidre@gufum.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Yuliia Pastukh <yuliya.bratash666@gmail.com>
Co-authored-by: baozidai <baozidai@outlook.com>
Co-authored-by: burcu atalay <burcuatalay1996@gmail.com>
Co-authored-by: elsaid ata <elsaidata75@gmail.com>
Co-authored-by: fluffstuff <opositesandreality@gmail.com>
Co-authored-by: helio serra carmo junior <theancientguardian@protonmail.com>
Co-authored-by: Коваленко Олексій Володимирович <alex59.kovalenko@gmail.com>
Co-authored-by: Павло Оборін <paka28065@gmail.com>
Co-authored-by: そら <comi4work@gmail.com>
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/be/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ga/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/he/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/hu/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/id/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/it/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ms/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pl/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/sr/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/tr/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ms/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/sk/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/tr/
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/sk/
Translate-URL: https://translate.habitica.com/projects/habitica/character/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/character/he/
Translate-URL: https://translate.habitica.com/projects/habitica/character/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/character/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/character/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/es/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/hu/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/id/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/content/es/
Translate-URL: https://translate.habitica.com/projects/habitica/content/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/content/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/content/he/
Translate-URL: https://translate.habitica.com/projects/habitica/content/id/
Translate-URL: https://translate.habitica.com/projects/habitica/content/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/content/tr/
Translate-URL: https://translate.habitica.com/projects/habitica/content/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/content/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/he/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/death/ga/
Translate-URL: https://translate.habitica.com/projects/habitica/death/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/death/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/ga/
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/id/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/hu/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/ms/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/front/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/front/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/front/he/
Translate-URL: https://translate.habitica.com/projects/habitica/front/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/front/hu/
Translate-URL: https://translate.habitica.com/projects/habitica/front/id/
Translate-URL: https://translate.habitica.com/projects/habitica/front/ms/
Translate-URL: https://translate.habitica.com/projects/habitica/front/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/front/sk/
Translate-URL: https://translate.habitica.com/projects/habitica/front/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/front/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ga/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/he/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/hu/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/id/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/ga/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/he/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/id/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/da/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/he/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/hu/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/id/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/sk/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/ga/
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/sk/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/es/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/he/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/hu/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/id/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ms/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/loginincentives/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/merch/ga/
Translate-URL: https://translate.habitica.com/projects/habitica/merch/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/messages/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/messages/id/
Translate-URL: https://translate.habitica.com/projects/habitica/messages/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/noscript/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/npc/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/npc/he/
Translate-URL: https://translate.habitica.com/projects/habitica/npc/hu/
Translate-URL: https://translate.habitica.com/projects/habitica/npc/id/
Translate-URL: https://translate.habitica.com/projects/habitica/overview/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/overview/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ga/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/he/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ms/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/tr/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/quests/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/quests/sk/
Translate-URL: https://translate.habitica.com/projects/habitica/quests/tr/
Translate-URL: https://translate.habitica.com/projects/habitica/quests/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/hu/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/id/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/es/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/id/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/spells/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/spells/he/
Translate-URL: https://translate.habitica.com/projects/habitica/spells/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/he/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/hu/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/id/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pl/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/sk/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/gl/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/hr/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/id/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/zh_Hans/
Translation: Habitica/Achievements
Translation: Habitica/Backgrounds
Translation: Habitica/Challenge
Translation: Habitica/Character
Translation: Habitica/Communityguidelines
Translation: Habitica/Content
Translation: Habitica/Contrib
Translation: Habitica/Death
Translation: Habitica/Defaulttasks
Translation: Habitica/Faq
Translation: Habitica/Front
Translation: Habitica/Gear
Translation: Habitica/Generic
Translation: Habitica/Groups
Translation: Habitica/Inventory
Translation: Habitica/Limited
Translation: Habitica/Loginincentives
Translation: Habitica/Merch
Translation: Habitica/Messages
Translation: Habitica/Noscript
Translation: Habitica/Npc
Translation: Habitica/Overview
Translation: Habitica/Pets
Translation: Habitica/Quests
Translation: Habitica/Questscontent
Translation: Habitica/Rebirth
Translation: Habitica/Settings
Translation: Habitica/Spells
Translation: Habitica/Subscriber
Translation: Habitica/Tasks
2023-04-20 18:55:54 +02:00
SabreCat 164121d9e4 fix(links): handling in RYA 2023-04-17 14:48:55 -05:00
SabreCat a2d209a34b Merge branch 'release' into external-link-modal 2023-04-17 14:41:59 -05:00
SabreCat c8adf20804 4.267.0 2023-04-10 17:09:37 -05:00
Sabe Jones de132c59ea fix(typo): . 2023-04-10 16:54:15 -05:00
SabreCat e5f6c4ba0f fix(links): handle uhuhu 2023-04-10 16:04:46 -05:00
CuriousMagpie 360c17c56e feat(content): add April backgrounds and enchanted armoire item 2023-04-06 15:37:32 -04:00
SabreCat c8b98678d0 Merge branch 'release' into develop 2023-04-05 14:04:45 -05:00
SabreCat ea7e5d2a8d 4.266.0 2023-04-05 14:04:34 -05:00
SabreCat afee09e7cb fix(tz): adjust release timing for DST 2023-04-05 14:02:38 -05:00
CuriousMagpie 01fea6b968 feat(fix): add correct string for potion end date 2023-04-05 12:13:40 -04:00
SabreCat 2df6b6461b fix(links): better http/s handling 2023-04-04 18:25:14 -05:00
CuriousMagpie 8c96ac241a updated stylesheet 2023-04-04 17:42:45 -04:00
CuriousMagpie c0362c614e feat(content): add April fool day potions 2023-04-04 17:14:25 -04:00
SabreCat 229ed46425 fix(tz): dst 2023-04-01 07:08:38 -05:00
SabreCat 7363f08a86 fix(links): handle ext links in profiles 2023-03-29 16:24:06 -05:00
SabreCat 2322f7e342 Merge branch 'release' into external-link-modal 2023-03-29 16:00:53 -05:00
SabreCat 7ede3acd01 feat(event): add AF2023 event const 2023-03-29 15:35:26 -05:00
SabreCat 57f17a08e8 Merge branch 'release' into develop 2023-03-29 15:08:02 -05:00
SabreCat 63453ce01b 4.265.0 2023-03-29 15:07:47 -05:00
SabreCat 888f6f2486 Merge branch 'sabrecat/fools-2023' into release 2023-03-29 15:07:40 -05:00
Natalie L e8501f5cf8 feat(content): Add April 2023 subscriber items (#14562)
* feat(content): add April Subscriber items

* feat(content): add slim armor version to April subscriber items
2023-03-29 14:53:51 -05:00
Natalie L fc49015ff0 chore(content): update press kit faq and third party app list in settings (#14554)
* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2781 of 2781 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (135 of 135 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (217 of 217 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (56 of 56 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (13 of 13 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (131 of 131 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Portuguese)

Currently translated at 81.7% (331 of 405 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (Portuguese)

Currently translated at 62.5% (5 of 8 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Portuguese)

Currently translated at 63.8% (1777 of 2781 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Portuguese)

Currently translated at 71.6% (43 of 60 strings)

Translated using Weblate (Portuguese)

Currently translated at 79.7% (609 of 764 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (770 of 770 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (German)

Currently translated at 100.0% (404 of 404 strings)

Translated using Weblate (German)

Currently translated at 79.5% (97 of 122 strings)

Translated using Weblate (German)

Currently translated at 97.7% (753 of 770 strings)

Translated using Weblate (German)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Portuguese)

Currently translated at 77.0% (94 of 122 strings)

Translated using Weblate (Indonesian)

Currently translated at 76.7% (310 of 404 strings)

Translated using Weblate (Portuguese)

Currently translated at 76.2% (93 of 122 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 85.6% (2381 of 2781 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (60 of 60 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (217 of 217 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (404 of 404 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 95.8% (732 of 764 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (770 of 770 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Portuguese)

Currently translated at 74.5% (91 of 122 strings)

Translated using Weblate (Portuguese)

Currently translated at 72.1% (88 of 122 strings)

Co-authored-by: Ana Beatriz <anabeatriz.augusto06@yahoo.com>
Co-authored-by: Andressa Murari Sudré <andressa@sudre.com.br>
Co-authored-by: Cachinhos <cachnhos@gmail.com>
Co-authored-by: Falzart Werefox <muh_fauzi_ramadhan@yahoo.co.id>
Co-authored-by: Jay <fallacyofwildlifeconservation@gmail.com>
Co-authored-by: Jerry Chen <minecjraft@qq.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Yu-Wei Tien <a38498987911@gmail.com>
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/de/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/de/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/de/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/content/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/content/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/front/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/front/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/de/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/id/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/messages/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/npc/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/overview/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/spells/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/pt/
Translation: Habitica/Achievements
Translation: Habitica/Backgrounds
Translation: Habitica/Communityguidelines
Translation: Habitica/Content
Translation: Habitica/Contrib
Translation: Habitica/Faq
Translation: Habitica/Front
Translation: Habitica/Gear
Translation: Habitica/Generic
Translation: Habitica/Groups
Translation: Habitica/Limited
Translation: Habitica/Messages
Translation: Habitica/Npc
Translation: Habitica/Overview
Translation: Habitica/Pets
Translation: Habitica/Questscontent
Translation: Habitica/Rebirth
Translation: Habitica/Spells
Translation: Habitica/Subscriber
Translation: Habitica/Tasks

* update press kit and third party app list in settings

---------

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Ana Beatriz <anabeatriz.augusto06@yahoo.com>
Co-authored-by: Andressa Murari Sudré <andressa@sudre.com.br>
Co-authored-by: Cachinhos <cachnhos@gmail.com>
Co-authored-by: Falzart Werefox <muh_fauzi_ramadhan@yahoo.co.id>
Co-authored-by: Jay <fallacyofwildlifeconservation@gmail.com>
Co-authored-by: Jerry Chen <minecjraft@qq.com>
Co-authored-by: Yu-Wei Tien <a38498987911@gmail.com>
Co-authored-by: SabreCat <sabe@habitica.com>
2023-03-28 16:52:15 -05:00
SabreCat eb4e930e63 fix(ext-links): warn in Party and PMs, env config 2023-03-28 16:39:48 -05:00
SabreCat 53c536b525 4.264.4 2023-03-24 19:46:32 -05:00
SabreCat e2defc675e fix(css): don't make invisible links 2023-03-24 19:46:11 -05:00
SabreCat f0fa2508a9 Merge branch 'release' into develop 2023-03-23 14:35:07 -05:00
SabreCat 232a62ffc7 4.264.3 2023-03-23 14:34:57 -05:00
Phillip Thelen d2d4af227b Fix an issue with gifting subs (#14550)
* Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2781 of 2781 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (135 of 135 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (217 of 217 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (56 of 56 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (13 of 13 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (131 of 131 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Portuguese)

Currently translated at 81.7% (331 of 405 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (Portuguese)

Currently translated at 62.5% (5 of 8 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Portuguese)

Currently translated at 63.8% (1777 of 2781 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Portuguese)

Currently translated at 71.6% (43 of 60 strings)

Translated using Weblate (Portuguese)

Currently translated at 79.7% (609 of 764 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (770 of 770 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (German)

Currently translated at 100.0% (404 of 404 strings)

Translated using Weblate (German)

Currently translated at 79.5% (97 of 122 strings)

Translated using Weblate (German)

Currently translated at 97.7% (753 of 770 strings)

Translated using Weblate (German)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Portuguese)

Currently translated at 77.0% (94 of 122 strings)

Translated using Weblate (Indonesian)

Currently translated at 76.7% (310 of 404 strings)

Translated using Weblate (Portuguese)

Currently translated at 76.2% (93 of 122 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 85.6% (2381 of 2781 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (60 of 60 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (217 of 217 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (404 of 404 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 95.8% (732 of 764 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (770 of 770 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Portuguese)

Currently translated at 74.5% (91 of 122 strings)

Translated using Weblate (Portuguese)

Currently translated at 72.1% (88 of 122 strings)

Co-authored-by: Ana Beatriz <anabeatriz.augusto06@yahoo.com>
Co-authored-by: Andressa Murari Sudré <andressa@sudre.com.br>
Co-authored-by: Cachinhos <cachnhos@gmail.com>
Co-authored-by: Falzart Werefox <muh_fauzi_ramadhan@yahoo.co.id>
Co-authored-by: Jay <fallacyofwildlifeconservation@gmail.com>
Co-authored-by: Jerry Chen <minecjraft@qq.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Yu-Wei Tien <a38498987911@gmail.com>
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/de/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/de/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/de/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/content/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/content/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/front/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/front/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/de/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/id/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/messages/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/npc/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/overview/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/spells/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/pt/
Translation: Habitica/Achievements
Translation: Habitica/Backgrounds
Translation: Habitica/Communityguidelines
Translation: Habitica/Content
Translation: Habitica/Contrib
Translation: Habitica/Faq
Translation: Habitica/Front
Translation: Habitica/Gear
Translation: Habitica/Generic
Translation: Habitica/Groups
Translation: Habitica/Limited
Translation: Habitica/Messages
Translation: Habitica/Npc
Translation: Habitica/Overview
Translation: Habitica/Pets
Translation: Habitica/Questscontent
Translation: Habitica/Rebirth
Translation: Habitica/Spells
Translation: Habitica/Subscriber
Translation: Habitica/Tasks

* gift subscription fix

* remove only

---------

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Ana Beatriz <anabeatriz.augusto06@yahoo.com>
Co-authored-by: Andressa Murari Sudré <andressa@sudre.com.br>
Co-authored-by: Cachinhos <cachnhos@gmail.com>
Co-authored-by: Falzart Werefox <muh_fauzi_ramadhan@yahoo.co.id>
Co-authored-by: Jay <fallacyofwildlifeconservation@gmail.com>
Co-authored-by: Jerry Chen <minecjraft@qq.com>
Co-authored-by: Yu-Wei Tien <a38498987911@gmail.com>
Co-authored-by: SabreCat <sabe@habitica.com>
2023-03-23 14:34:40 -05:00
SabreCat ca1200b689 feat(links): new external link implementation 2023-03-22 18:06:53 -05:00
SabreCat 008579363c Merge remote-tracking branch 'CuriousMagpie/external-link-modal' into external-link-modal 2023-03-22 16:02:34 -05:00
CuriousMagpie 786b1ec670 add underline to cancel link 2023-03-21 17:07:40 -04:00
SabreCat 573de80a91 Merge remote-tracking branch 'CuriousMagpie/external-link-modal' into external-link-modal 2023-03-21 15:17:21 -05:00
SabreCat 115340e62d Merge branch 'release' into develop 2023-03-21 13:54:35 -05:00
SabreCat 5de2573521 4.264.2 2023-03-21 13:54:23 -05:00
SabreCat b472af532c Merge branch 'apple_sub_fix' into release 2023-03-21 13:54:16 -05:00
CuriousMagpie b264e539f4 add crtl/cmd instructions to skip modal 2023-03-21 14:49:43 -04:00
CuriousMagpie c726208d6e add cancel option 2023-03-21 13:00:15 -04:00
SabreCat b1d2fff13f Merge branch 'release' into develop 2023-03-17 17:25:10 -05:00
SabreCat 027e61a93e 4.264.1 2023-03-17 17:24:56 -05:00
SabreCat c35afb7cfe fix(string): add missing party invite text 2023-03-17 17:24:49 -05:00
SabreCat 8cd706fd95 feat(links): route to selected link 2023-03-17 16:37:16 -05:00
SabreCat 3a4620976e Merge branch 'release' into external-link-modal 2023-03-17 15:59:28 -05:00
SabreCat a16098ccda 4.264.0 2023-03-17 15:09:12 -05:00
SabreCat 118c8421fe fix(tz): account for DST 2023-03-17 15:09:02 -05:00
Natalie L a363e68080 feat(cont): 2023 Spring Fling content (#14525)
* feat(cont): 2023 Spring Fling

* feat(content): 2023 Spring Fling (attempt to add Jungle Buddies Quest Bundle)

* fix(event): various typos and date ranges

* fix(event): correct countdown on Shiny Seed

* fix(quests): correct TypeError in featured list

* feat(content): update Spring gear to canon desc

---------

Co-authored-by: SabreCat <sabe@habitica.com>
2023-03-17 15:05:04 -05:00
SabreCat 1940062200 4.263.1 2023-03-16 16:23:00 -05:00
SabreCat aea075d0bf chore(content): make Jungle Buddies available 2023-03-16 16:22:47 -05:00
Weblate 7388707a43 Merge branch 'origin/develop' into Weblate. 2023-03-16 18:57:12 +01:00
SabreCat 3e63d74b2c 4.263.0 2023-03-16 12:52:15 -05:00
SabreCat 199ce3e6f7 fix(text): update description of group task approval by @CuriousMagpie 2023-03-16 12:51:51 -05:00
Weblate 597f74c84b Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2781 of 2781 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (135 of 135 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (217 of 217 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (56 of 56 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (13 of 13 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (131 of 131 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (405 of 405 strings)

Translated using Weblate (Portuguese)

Currently translated at 81.7% (331 of 405 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (Portuguese)

Currently translated at 62.5% (5 of 8 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Portuguese)

Currently translated at 63.8% (1777 of 2781 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Portuguese)

Currently translated at 71.6% (43 of 60 strings)

Translated using Weblate (Portuguese)

Currently translated at 79.7% (609 of 764 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (47 of 47 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (770 of 770 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (German)

Currently translated at 100.0% (404 of 404 strings)

Translated using Weblate (German)

Currently translated at 79.5% (97 of 122 strings)

Translated using Weblate (German)

Currently translated at 97.7% (753 of 770 strings)

Translated using Weblate (German)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Portuguese)

Currently translated at 77.0% (94 of 122 strings)

Translated using Weblate (Indonesian)

Currently translated at 76.7% (310 of 404 strings)

Translated using Weblate (Portuguese)

Currently translated at 76.2% (93 of 122 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 85.6% (2381 of 2781 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (60 of 60 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (217 of 217 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (404 of 404 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 95.8% (732 of 764 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (770 of 770 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Portuguese)

Currently translated at 74.5% (91 of 122 strings)

Translated using Weblate (Portuguese)

Currently translated at 72.1% (88 of 122 strings)

Co-authored-by: Ana Beatriz <anabeatriz.augusto06@yahoo.com>
Co-authored-by: Andressa Murari Sudré <andressa@sudre.com.br>
Co-authored-by: Cachinhos <cachnhos@gmail.com>
Co-authored-by: Falzart Werefox <muh_fauzi_ramadhan@yahoo.co.id>
Co-authored-by: Jay <fallacyofwildlifeconservation@gmail.com>
Co-authored-by: Jerry Chen <minecjraft@qq.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Yu-Wei Tien <a38498987911@gmail.com>
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/de/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/de/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/de/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/content/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/content/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/contrib/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/front/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/front/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/de/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/id/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/messages/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/npc/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/overview/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/rebirth/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/spells/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/pt/
Translation: Habitica/Achievements
Translation: Habitica/Backgrounds
Translation: Habitica/Communityguidelines
Translation: Habitica/Content
Translation: Habitica/Contrib
Translation: Habitica/Faq
Translation: Habitica/Front
Translation: Habitica/Gear
Translation: Habitica/Generic
Translation: Habitica/Groups
Translation: Habitica/Limited
Translation: Habitica/Messages
Translation: Habitica/Npc
Translation: Habitica/Overview
Translation: Habitica/Pets
Translation: Habitica/Questscontent
Translation: Habitica/Rebirth
Translation: Habitica/Spells
Translation: Habitica/Subscriber
Translation: Habitica/Tasks
2023-03-16 17:39:07 +01:00
SabreCat c83a8c9766 fix(stable): correctly suppress hatching modal 2023-03-15 16:15:55 -05:00
CuriousMagpie c481354f78 feat(content): add new achievement, Plant Parent 2023-03-15 15:51:04 -05:00
CuriousMagpie ec9973f9d2 feature(upgrade): added btn-block styling to "Unpause Damage" button 2023-03-15 15:24:02 -05:00
CuriousMagpie 971b124b05 apply correct opacity to close icon 2023-03-15 11:21:25 -04:00
SabreCat de3f1b3f5e chore(sprites): compile 2023-03-14 16:47:14 -05:00
SabreCat 7098d2a72e Merge branch 'release' into sabrecat/fools-2023 2023-03-14 16:46:11 -05:00
SabreCat bbea789700 fix(test): don't cross two month boundaries when anticipating +1 perk 2023-03-14 16:27:09 -05:00
SabreCat 5359a2bf3d fix(lint): === 2023-03-14 16:14:48 -05:00
Phillip Thelen 93e922e774 fix logic 2023-03-14 15:55:41 +01:00
SabreCat 377b152ffd 4.262.2 2023-03-14 09:25:42 -05:00
SabreCat 8ff8213954 Merge branch 'sabrecat/invite-notif' into release 2023-03-14 09:25:29 -05:00
SabreCat 00bdf81902 4.262.1 2023-03-14 09:15:37 -05:00
SabreCat 4ae50e4d44 Merge branch 'develop' into release 2023-03-14 09:15:18 -05:00
SabreCat 383cd84016 feat(event): Pi Day 2023-03-14 09:12:39 -05:00
Phillip Thelen f6f1202baf better init for perkMonthCount 2023-03-14 14:37:47 +01:00
Weblate 0c65ff6fec Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (98 of 98 strings)

Translated using Weblate (Cebuano)

Currently translated at 0.0% (0 of 146 strings)

Translated using Weblate (Indonesian)

Currently translated at 61.7% (1718 of 2781 strings)

Translated using Weblate (Portuguese)

Currently translated at 59.9% (130 of 217 strings)

Translated using Weblate (Portuguese)

Currently translated at 81.9% (331 of 404 strings)

Translated using Weblate (Portuguese)

Currently translated at 92.5% (198 of 214 strings)

Translated using Weblate (Portuguese)

Currently translated at 71.3% (87 of 122 strings)

Translated using Weblate (Portuguese)

Currently translated at 96.2% (130 of 135 strings)

Translated using Weblate (Portuguese)

Currently translated at 96.2% (130 of 135 strings)

Translated using Weblate (Portuguese)

Currently translated at 98.5% (133 of 135 strings)

Translated using Weblate (Portuguese)

Currently translated at 63.7% (1774 of 2781 strings)

Translated using Weblate (Portuguese)

Currently translated at 99.3% (145 of 146 strings)

Translated using Weblate (Portuguese)

Currently translated at 99.3% (145 of 146 strings)

Translated using Weblate (Portuguese)

Currently translated at 63.7% (1773 of 2781 strings)

Translated using Weblate (Portuguese)

Currently translated at 63.5% (1766 of 2781 strings)

Translated using Weblate (Italian)

Currently translated at 98.7% (760 of 770 strings)

Translated using Weblate (Estonian)

Currently translated at 13.6% (20 of 146 strings)

Translated using Weblate (Ukrainian)

Currently translated at 67.5% (516 of 764 strings)

Translated using Weblate (Estonian)

Currently translated at 4.1% (6 of 146 strings)

Translated using Weblate (Vietnamese)

Currently translated at 79.6% (613 of 770 strings)

Translated using Weblate (Vietnamese)

Currently translated at 78.9% (608 of 770 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Vietnamese)

Currently translated at 77.2% (595 of 770 strings)

Translated using Weblate (Indonesian)

Currently translated at 98.5% (133 of 135 strings)

Translated using Weblate (Indonesian)

Currently translated at 94.1% (353 of 375 strings)

Translated using Weblate (Malay)

Currently translated at 38.6% (70 of 181 strings)

Translated using Weblate (Vietnamese)

Currently translated at 76.3% (588 of 770 strings)

Translated using Weblate (Vietnamese)

Currently translated at 97.0% (131 of 135 strings)

Translated using Weblate (Vietnamese)

Currently translated at 95.2% (139 of 146 strings)

Translated using Weblate (Vietnamese)

Currently translated at 62.5% (167 of 267 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (217 of 217 strings)

Translated using Weblate (Indonesian)

Currently translated at 93.4% (200 of 214 strings)

Translated using Weblate (Ukrainian)

Currently translated at 67.4% (515 of 764 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (770 of 770 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (217 of 217 strings)

Translated using Weblate (French)

Currently translated at 100.0% (217 of 217 strings)

Translated using Weblate (Vietnamese)

Currently translated at 76.0% (111 of 146 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (216 of 216 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2781 of 2781 strings)

Translated using Weblate (Indonesian)

Currently translated at 93.4% (170 of 182 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (764 of 764 strings)

Translated using Weblate (Spanish)

Currently translated at 93.0% (2587 of 2781 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Serbian)

Currently translated at 94.8% (128 of 135 strings)

Translated using Weblate (Serbian)

Currently translated at 100.0% (1 of 1 strings)

Translated using Weblate (Italian)

Currently translated at 98.7% (760 of 770 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (770 of 770 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (770 of 770 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2781 of 2781 strings)

Translated using Weblate (French)

Currently translated at 100.0% (2781 of 2781 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.4% (766 of 770 strings)

Translated using Weblate (Indonesian)

Currently translated at 99.3% (765 of 770 strings)

Translated using Weblate (French)

Currently translated at 100.0% (770 of 770 strings)

Translated using Weblate (Indonesian)

Currently translated at 74.7% (302 of 404 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (French)

Currently translated at 100.0% (2777 of 2777 strings)

Translated using Weblate (Indonesian)

Currently translated at 90.6% (194 of 214 strings)

Translated using Weblate (French)

Currently translated at 100.0% (764 of 764 strings)

Translated using Weblate (French)

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Indonesian)

Currently translated at 92.8% (169 of 182 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Indonesian)

Currently translated at 61.7% (1714 of 2777 strings)

Translated using Weblate (Indonesian)

Currently translated at 61.7% (1714 of 2777 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (94 of 94 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (131 of 131 strings)

Translated using Weblate (Indonesian)

Currently translated at 61.6% (1711 of 2777 strings)

Translated using Weblate (Ukrainian)

Currently translated at 66.6% (509 of 764 strings)

Translated using Weblate (Indonesian)

Currently translated at 61.5% (1709 of 2777 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Malay)

Currently translated at 50.0% (27 of 54 strings)

Translated using Weblate (Indonesian)

Currently translated at 53.3% (32 of 60 strings)

Translated using Weblate (Dutch)

Currently translated at 86.3% (2397 of 2777 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2777 of 2777 strings)

Translated using Weblate (Dutch)

Currently translated at 86.3% (2397 of 2777 strings)

Translated using Weblate (Spanish)

Currently translated at 93.2% (2587 of 2773 strings)

Translated using Weblate (Indonesian)

Currently translated at 93.3% (350 of 375 strings)

Translated using Weblate (Indonesian)

Currently translated at 62.9% (34 of 54 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (15 of 15 strings)

Translated using Weblate (Slovak)

Currently translated at 100.0% (15 of 15 strings)

Translated using Weblate (Czech)

Currently translated at 78.0% (114 of 146 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 98.9% (756 of 764 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Indonesian)

Currently translated at 88.4% (161 of 182 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Indonesian)

Currently translated at 92.5% (347 of 375 strings)

Translated using Weblate (Japanese)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Spanish)

Currently translated at 93.2% (2587 of 2773 strings)

Translated using Weblate (French)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (French)

Currently translated at 99.0% (757 of 764 strings)

Translated using Weblate (French)

Currently translated at 95.0% (116 of 122 strings)

Translated using Weblate (French)

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (French)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Malay)

Currently translated at 36.6% (41 of 112 strings)

Translated using Weblate (Malay)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Indonesian)

Currently translated at 86.6% (117 of 135 strings)

Translated using Weblate (Ukrainian)

Currently translated at 24.9% (693 of 2773 strings)

Translated using Weblate (Indonesian)

Currently translated at 94.2% (114 of 121 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Tagalog)

Currently translated at 96.7% (180 of 186 strings)

Translated using Weblate (Tagalog)

Currently translated at 53.2% (115 of 216 strings)

Translated using Weblate (Tagalog)

Currently translated at 42.6% (114 of 267 strings)

Translated using Weblate (Filipino)

Currently translated at 32.8% (910 of 2773 strings)

Translated using Weblate (Ukrainian)

Currently translated at 65.8% (503 of 764 strings)

Translated using Weblate (Indonesian)

Currently translated at 93.3% (113 of 121 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Filipino)

Currently translated at 32.6% (906 of 2773 strings)

Translated using Weblate (Filipino)

Currently translated at 80.0% (108 of 135 strings)

Translated using Weblate (Filipino)

Currently translated at 32.6% (906 of 2773 strings)

Translated using Weblate (Filipino)

Currently translated at 81.3% (621 of 763 strings)

Translated using Weblate (Filipino)

Currently translated at 71.7% (548 of 764 strings)

Translated using Weblate (Filipino)

Currently translated at 32.5% (903 of 2773 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (764 of 764 strings)

Translated using Weblate (Indonesian)

Currently translated at 84.4% (114 of 135 strings)

Translated using Weblate (Indonesian)

Currently translated at 61.4% (1705 of 2773 strings)

Translated using Weblate (Serbian)

Currently translated at 75.6% (571 of 755 strings)

Translated using Weblate (Serbian)

Currently translated at 96.2% (179 of 186 strings)

Translated using Weblate (Spanish)

Currently translated at 93.2% (2587 of 2773 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Italian)

Currently translated at 94.2% (115 of 122 strings)

Translated using Weblate (Italian)

Currently translated at 91.3% (244 of 267 strings)

Translated using Weblate (Portuguese)

Currently translated at 63.6% (1764 of 2773 strings)

Translated using Weblate (Italian)

Currently translated at 88.5% (108 of 122 strings)

Translated using Weblate (Indonesian)

Currently translated at 92.5% (112 of 121 strings)

Translated using Weblate (Indonesian)

Currently translated at 59.2% (32 of 54 strings)

Translated using Weblate (Spanish)

Currently translated at 93.2% (2587 of 2773 strings)

Translated using Weblate (Arabic)

Currently translated at 85.0% (649 of 763 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 85.8% (2380 of 2773 strings)

Translated using Weblate (Dutch)

Currently translated at 86.0% (2386 of 2773 strings)

Translated using Weblate (Indonesian)

Currently translated at 61.4% (1704 of 2773 strings)

Translated using Weblate (Spanish)

Currently translated at 93.2% (2587 of 2773 strings)

Translated using Weblate (Indonesian)

Currently translated at 92.5% (347 of 375 strings)

Translated using Weblate (Chinese (Traditional))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Malay)

Currently translated at 33.1% (60 of 181 strings)

Translated using Weblate (Indonesian)

Currently translated at 90.6% (340 of 375 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Ukrainian)

Currently translated at 99.2% (265 of 267 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Indonesian)

Currently translated at 90.1% (338 of 375 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Russian)

Currently translated at 82.7% (101 of 122 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Spanish)

Currently translated at 93.2% (2587 of 2773 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Spanish)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Spanish)

Currently translated at 86.0% (105 of 122 strings)

Translated using Weblate (Spanish)

Currently translated at 97.2% (142 of 146 strings)

Translated using Weblate (Spanish)

Currently translated at 80.3% (98 of 122 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (375 of 375 strings)

Translated using Weblate (Indonesian)

Currently translated at 90.9% (110 of 121 strings)

Translated using Weblate (Indonesian)

Currently translated at 88.5% (332 of 375 strings)

Translated using Weblate (Arabic)

Currently translated at 83.2% (635 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 82.6% (631 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 82.0% (626 of 763 strings)

Translated using Weblate (Spanish (Latin America))

Currently translated at 100.0% (374 of 374 strings)

Translated using Weblate (Portuguese)

Currently translated at 63.5% (1761 of 2773 strings)

Translated using Weblate (Arabic)

Currently translated at 81.7% (624 of 763 strings)

Translated using Weblate (Indonesian)

Currently translated at 89.2% (108 of 121 strings)

Translated using Weblate (Arabic)

Currently translated at 81.5% (622 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 80.9% (618 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 78.3% (598 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 77.8% (594 of 763 strings)

Translated using Weblate (Italian)

Currently translated at 82.7% (101 of 122 strings)

Translated using Weblate (Malay)

Currently translated at 20.9% (38 of 181 strings)

Translated using Weblate (Malay)

Currently translated at 19.3% (35 of 181 strings)

Translated using Weblate (Malay)

Currently translated at 18.2% (33 of 181 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2773 of 2773 strings)

Translated using Weblate (Arabic)

Currently translated at 76.8% (586 of 763 strings)

Translated using Weblate (Indonesian)

Currently translated at 87.6% (106 of 121 strings)

Translated using Weblate (Arabic)

Currently translated at 76.2% (582 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 76.1% (581 of 763 strings)

Translated using Weblate (Italian)

Currently translated at 82.7% (101 of 122 strings)

Translated using Weblate (Russian)

Currently translated at 99.8% (762 of 763 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2773 of 2773 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (182 of 182 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 74.3% (567 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 74.1% (566 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 72.2% (551 of 763 strings)

Translated using Weblate (Portuguese)

Currently translated at 63.3% (1757 of 2773 strings)

Translated using Weblate (Portuguese)

Currently translated at 63.3% (1757 of 2773 strings)

Translated using Weblate (Portuguese)

Currently translated at 85.1% (650 of 763 strings)

Translated using Weblate (Malay)

Currently translated at 17.6% (32 of 181 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Bulgarian)

Currently translated at 73.9% (108 of 146 strings)

Translated using Weblate (Russian)

Currently translated at 80.3% (98 of 122 strings)

Translated using Weblate (Arabic)

Currently translated at 71.8% (548 of 763 strings)

Translated using Weblate (Indonesian)

Currently translated at 97.9% (747 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 71.5% (546 of 763 strings)

Translated using Weblate (Indonesian)

Currently translated at 97.1% (741 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 71.1% (543 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 71.0% (542 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 70.6% (539 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Arabic)

Currently translated at 69.8% (533 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 69.2% (528 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 68.9% (526 of 763 strings)

Translated using Weblate (Italian)

Currently translated at 82.7% (101 of 122 strings)

Translated using Weblate (French)

Currently translated at 95.0% (116 of 122 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (221 of 221 strings)

Translated using Weblate (Malay)

Currently translated at 11.6% (21 of 181 strings)

Translated using Weblate (Indonesian)

Currently translated at 95.9% (732 of 763 strings)

Translated using Weblate (Ukrainian)

Currently translated at 94.7% (253 of 267 strings)

Translated using Weblate (French)

Currently translated at 88.5% (108 of 122 strings)

Translated using Weblate (French)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Italian)

Currently translated at 79.5% (97 of 122 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (181 of 181 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Indonesian)

Currently translated at 95.0% (725 of 763 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (216 of 216 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Filipino)

Currently translated at 83.0% (93 of 112 strings)

Translated using Weblate (Filipino)

Currently translated at 73.0% (195 of 267 strings)

Translated using Weblate (Filipino)

Currently translated at 32.7% (909 of 2773 strings)

Translated using Weblate (Filipino)

Currently translated at 91.9% (343 of 373 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (216 of 216 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2773 of 2773 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (122 of 122 strings)

Translated using Weblate (Filipino)

Currently translated at 32.8% (910 of 2773 strings)

Translated using Weblate (Filipino)

Currently translated at 32.8% (911 of 2773 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Filipino)

Currently translated at 32.0% (889 of 2773 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 95.0% (116 of 122 strings)

Translated using Weblate (Indonesian)

Currently translated at 93.3% (712 of 763 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (2769 of 2773 strings)

Translated using Weblate (Italian)

Currently translated at 99.2% (757 of 763 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Filipino)

Currently translated at 95.6% (178 of 186 strings)

Translated using Weblate (Filipino)

Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (French)

Currently translated at 100.0% (216 of 216 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (15 of 15 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (French)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 86.8% (106 of 122 strings)

Translated using Weblate (Malay)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Indonesian)

Currently translated at 84.2% (107 of 127 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 66.9% (511 of 763 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (214 of 214 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Malay)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (216 of 216 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (755 of 755 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Indonesian)

Currently translated at 92.0% (702 of 763 strings)

Translated using Weblate (Indonesian)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (135 of 135 strings)

Translated using Weblate (Dutch)

Currently translated at 95.3% (205 of 215 strings)

Translated using Weblate (Dutch)

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Dutch)

Currently translated at 96.1% (126 of 131 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (8 of 8 strings)

Translated using Weblate (Spanish)

Currently translated at 93.0% (2581 of 2773 strings)

Translated using Weblate (Dutch)

Currently translated at 97.2% (176 of 181 strings)

Translated using Weblate (Dutch)

Currently translated at 95.0% (57 of 60 strings)

Translated using Weblate (Dutch)

Currently translated at 98.6% (144 of 146 strings)

Translated using Weblate (Dutch)

Currently translated at 91.4% (202 of 221 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (404 of 404 strings)

Translated using Weblate (Indonesian)

Currently translated at 91.4% (698 of 763 strings)

Translated using Weblate (German)

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (German)

Currently translated at 89.8% (240 of 267 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (2769 of 2773 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2773 of 2773 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.6% (760 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 63.4% (484 of 763 strings)

Translated using Weblate (Russian)

Currently translated at 99.2% (2745 of 2767 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (763 of 763 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.4% (759 of 763 strings)

Translated using Weblate (Indonesian)

Currently translated at 91.0% (695 of 763 strings)

Translated using Weblate (Arabic)

Currently translated at 61.7% (467 of 756 strings)

Translated using Weblate (French)

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (French)

Currently translated at 100.0% (2763 of 2763 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Indonesian)

Currently translated at 90.0% (681 of 756 strings)

Translated using Weblate (Malay)

Currently translated at 10.4% (19 of 181 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (2763 of 2763 strings)

Translated using Weblate (Spanish)

Currently translated at 93.4% (2581 of 2763 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Indonesian)

Currently translated at 89.5% (677 of 756 strings)

Translated using Weblate (Spanish)

Currently translated at 93.4% (2581 of 2763 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (135 of 135 strings)

Translated using Weblate (Russian)

Currently translated at 95.5% (255 of 267 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Indonesian)

Currently translated at 89.1% (674 of 756 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (2763 of 2763 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 95.8% (256 of 267 strings)

Translated using Weblate (Malay)

Currently translated at 6.0% (11 of 181 strings)

Translated using Weblate (Filipino)

Currently translated at 98.3% (183 of 186 strings)

Translated using Weblate (Malay)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Ukrainian)

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Indonesian)

Currently translated at 88.0% (666 of 756 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.9% (2762 of 2763 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Filipino)

Currently translated at 98.3% (183 of 186 strings)

Translated using Weblate (Tagalog)

Currently translated at 96.7% (180 of 186 strings)

Translated using Weblate (Filipino)

Currently translated at 98.9% (184 of 186 strings)

Translated using Weblate (Filipino)

Currently translated at 80.8% (76 of 94 strings)

Translated using Weblate (Malay)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Filipino)

Currently translated at 100.0% (61 of 61 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (135 of 135 strings)

Translated using Weblate (Russian)

Currently translated at 99.5% (214 of 215 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (215 of 215 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Russian)

Currently translated at 94.3% (252 of 267 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 89.5% (239 of 267 strings)

Translated using Weblate (Russian)

Currently translated at 99.3% (2745 of 2763 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Indonesian)

Currently translated at 87.1% (659 of 756 strings)

Translated using Weblate (Portuguese)

Currently translated at 80.9% (179 of 221 strings)

Translated using Weblate (Arabic)

Currently translated at 60.0% (454 of 756 strings)

Translated using Weblate (Arabic)

Currently translated at 67.0% (63 of 94 strings)

Translated using Weblate (Malay)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (French)

Currently translated at 100.0% (215 of 215 strings)

Translated using Weblate (Russian)

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (French)

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Russian)

Currently translated at 99.1% (2740 of 2763 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.8% (2758 of 2763 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.7% (754 of 756 strings)

Translated using Weblate (French)

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Portuguese)

Currently translated at 100.0% (146 of 146 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (215 of 215 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (112 of 112 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (267 of 267 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (2763 of 2763 strings)

Translated using Weblate (Chinese (Simplified))

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (756 of 756 strings)

Translated using Weblate (Indonesian)

Currently translated at 86.7% (656 of 756 strings)

Co-authored-by: An Nguyen <nguyen.thienan.business@gmail.com>
Co-authored-by: Ana Beatriz <anabeatriz.augusto06@yahoo.com>
Co-authored-by: Andressa Murari Sudré <andressa@sudre.com.br>
Co-authored-by: Anfasa Rabbany <lelcraft96@gmail.com>
Co-authored-by: Benoit Hetru <me+hbtc@gahanka.net>
Co-authored-by: Binny <45uipcik@duck.com>
Co-authored-by: Camille <barberacamille47@gmail.com>
Co-authored-by: Chloé Fonson <chl.fsn@gmail.com>
Co-authored-by: Daniel Villarroel Aguilera <y4v7l45j@duck.com>
Co-authored-by: Falzart Werefox <muh_fauzi_ramadhan@yahoo.co.id>
Co-authored-by: Hanafi <naflizo@gmail.com>
Co-authored-by: Harvey James <harveymoldon@gmail.com>
Co-authored-by: Ike Osenberg <ike.osenberg@gmail.com>
Co-authored-by: Jerry Chen <minecjraft@qq.com>
Co-authored-by: Jonathan Garcia <jonathangarcia0@duck.com>
Co-authored-by: Karylle Mae Treuse G. Labitad <treuse2006@gmail.com>
Co-authored-by: Kris <dawnut.x@gmail.com>
Co-authored-by: Kuan Yu Chou <jenny2311@gmail.com>
Co-authored-by: LiziKnight <liziknight0316@outlook.com>
Co-authored-by: M <maperray@gmail.com>
Co-authored-by: Maria Otonuo <mariaotonio@gmail.com>
Co-authored-by: Martim Pinto Paiva <pintopaivam@gmail.com>
Co-authored-by: Natalie Luhrs <eilatan@gmail.com>
Co-authored-by: Nazar Paruna <nazarparuna@gmail.com>
Co-authored-by: Nero <pablofh004@gmail.com>
Co-authored-by: Nina Glasbergen <ninaglas2002@gmail.com>
Co-authored-by: Phillip Thelen <phillip@habitica.com>
Co-authored-by: Pyotr Stolnikov <pitmysterio@gmail.com>
Co-authored-by: Raithe <RaitheOfDureya@gmail.com>
Co-authored-by: Rara <annisarahmah.xmipa2@gmail.com>
Co-authored-by: Ruben <r.tartwijk@gmail.com>
Co-authored-by: Sandra Marcial <sandramarcial80@gmail.com>
Co-authored-by: Sciuridae <sweetvshoney@163.com>
Co-authored-by: Sergey Shevelev <vlkgamer45@gmail.com>
Co-authored-by: Soul <joninsoul@gmail.com>
Co-authored-by: Tristan Roosipuu <roosipuutristan@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: endriw cisersa batistela correa <endriwbatistela@gmail.com>
Co-authored-by: fluffstuff <opositesandreality@gmail.com>
Co-authored-by: maikodoglas <maickeldouglas.mm@outlook.com>
Co-authored-by: polyglottericus <vincemorel.vilan.889@gmail.com>
Co-authored-by: そら <comi4work@gmail.com>
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/bg/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ceb/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/cs/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/es/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/et/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/id/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/it/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/ms/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/vi/
Translate-URL: https://translate.habitica.com/projects/habitica/achievements/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/es/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/id/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/it/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/vi/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/backgrounds/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/challenge/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/character/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/character/sr/
Translate-URL: https://translate.habitica.com/projects/habitica/character/tl/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/es/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/id/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/it/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/communityguidelines/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/content/es_419/
Translate-URL: https://translate.habitica.com/projects/habitica/content/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/content/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/content/id/
Translate-URL: https://translate.habitica.com/projects/habitica/content/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/content/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/content/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/death/sk/
Translate-URL: https://translate.habitica.com/projects/habitica/death/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/id/
Translate-URL: https://translate.habitica.com/projects/habitica/defaulttasks/ms/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/id/
Translate-URL: https://translate.habitica.com/projects/habitica/faq/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/front/es/
Translate-URL: https://translate.habitica.com/projects/habitica/front/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/front/id/
Translate-URL: https://translate.habitica.com/projects/habitica/front/ja/
Translate-URL: https://translate.habitica.com/projects/habitica/front/ms/
Translate-URL: https://translate.habitica.com/projects/habitica/front/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/front/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/front/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/front/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/es/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/id/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/it/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/gear/zh_Hant/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/id/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/generic/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/id/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/groups/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/inventory/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/de/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/it/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/tl/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/vi/
Translate-URL: https://translate.habitica.com/projects/habitica/limited/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/merch/sr/
Translate-URL: https://translate.habitica.com/projects/habitica/messages/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/messages/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/npc/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/npc/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/overview/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/de/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ms/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/pets/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/quests/ar/
Translate-URL: https://translate.habitica.com/projects/habitica/quests/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/quests/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/sr/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/questscontent/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/settings/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/fr/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/pt_BR/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/tl/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/uk/
Translate-URL: https://translate.habitica.com/projects/habitica/subscriber/zh_Hans/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/fil/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/id/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/nl/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/pt/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/ru/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/sr/
Translate-URL: https://translate.habitica.com/projects/habitica/tasks/vi/
Translation: Habitica/Achievements
Translation: Habitica/Backgrounds
Translation: Habitica/Challenge
Translation: Habitica/Character
Translation: Habitica/Communityguidelines
Translation: Habitica/Content
Translation: Habitica/Death
Translation: Habitica/Defaulttasks
Translation: Habitica/Faq
Translation: Habitica/Front
Translation: Habitica/Gear
Translation: Habitica/Generic
Translation: Habitica/Groups
Translation: Habitica/Inventory
Translation: Habitica/Limited
Translation: Habitica/Merch
Translation: Habitica/Messages
Translation: Habitica/Npc
Translation: Habitica/Overview
Translation: Habitica/Pets
Translation: Habitica/Quests
Translation: Habitica/Questscontent
Translation: Habitica/Settings
Translation: Habitica/Subscriber
Translation: Habitica/Tasks
2023-03-14 10:16:35 +01:00
SabreCat 83f5c92ff1 fix(lint): loop no likey ++ 2023-03-13 18:36:14 -05:00
Phillip Thelen 8dcacdc92e Only update user objects that don’t have notification yet (#14514)
* build(deps): bump stopword from 2.0.5 to 2.0.7 in /website/client (#14504)

Bumps [stopword](https://github.com/fergiemcdowall/stopword) from 2.0.5 to 2.0.7.
- [Release notes](https://github.com/fergiemcdowall/stopword/releases)
- [Commits](https://github.com/fergiemcdowall/stopword/commits/v.2.0.7)

---
updated-dependencies:
- dependency-name: stopword
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump stripe from 11.6.0 to 11.10.0 (#14503)

Bumps [stripe](https://github.com/stripe/stripe-node) from 11.6.0 to 11.10.0.
- [Release notes](https://github.com/stripe/stripe-node/releases)
- [Changelog](https://github.com/stripe/stripe-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-node/compare/v11.6.0...v11.10.0)

---
updated-dependencies:
- dependency-name: stripe
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump apidoc from 0.53.1 to 0.54.0 (#14501)

Bumps [apidoc](https://github.com/apidoc/apidoc) from 0.53.1 to 0.54.0.
- [Release notes](https://github.com/apidoc/apidoc/releases)
- [Changelog](https://github.com/apidoc/apidoc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/apidoc/apidoc/compare/0.53.1...0.54.0)

---
updated-dependencies:
- dependency-name: apidoc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump @sideway/formula in /website/client (#14495)

Bumps [@sideway/formula](https://github.com/sideway/formula) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/sideway/formula/releases)
- [Commits](https://github.com/sideway/formula/compare/v3.0.0...v3.0.1)

---
updated-dependencies:
- dependency-name: "@sideway/formula"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump validator from 13.7.0 to 13.9.0 in /website/client (#14492)

Bumps [validator](https://github.com/validatorjs/validator.js) from 13.7.0 to 13.9.0.
- [Release notes](https://github.com/validatorjs/validator.js/releases)
- [Changelog](https://github.com/validatorjs/validator.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/validatorjs/validator.js/compare/13.7.0...13.9.0)

---
updated-dependencies:
- dependency-name: validator
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump validator from 13.7.0 to 13.9.0 (#14488)

Bumps [validator](https://github.com/validatorjs/validator.js) from 13.7.0 to 13.9.0.
- [Release notes](https://github.com/validatorjs/validator.js/releases)
- [Changelog](https://github.com/validatorjs/validator.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/validatorjs/validator.js/compare/13.7.0...13.9.0)

---
updated-dependencies:
- dependency-name: validator
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump hellojs from 1.19.5 to 1.20.0 in /website/client (#14479)

Bumps [hellojs](https://github.com/MrSwitch/hello.js) from 1.19.5 to 1.20.0.
- [Release notes](https://github.com/MrSwitch/hello.js/releases)
- [Changelog](https://github.com/MrSwitch/hello.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/MrSwitch/hello.js/compare/v1.19.5...v1.20.0)

---
updated-dependencies:
- dependency-name: hellojs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump ua-parser-js from 0.7.31 to 0.7.33 in /website/client (#14463)

Bumps [ua-parser-js](https://github.com/faisalman/ua-parser-js) from 0.7.31 to 0.7.33.
- [Release notes](https://github.com/faisalman/ua-parser-js/releases)
- [Changelog](https://github.com/faisalman/ua-parser-js/blob/master/changelog.md)
- [Commits](https://github.com/faisalman/ua-parser-js/compare/0.7.31...0.7.33)

---
updated-dependencies:
- dependency-name: ua-parser-js
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump cookiejar from 2.1.3 to 2.1.4 (#14462)

Bumps [cookiejar](https://github.com/bmeck/node-cookiejar) from 2.1.3 to 2.1.4.
- [Release notes](https://github.com/bmeck/node-cookiejar/releases)
- [Commits](https://github.com/bmeck/node-cookiejar/commits)

---
updated-dependencies:
- dependency-name: cookiejar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump glob from 8.0.3 to 8.1.0 (#14448)

Bumps [glob](https://github.com/isaacs/node-glob) from 8.0.3 to 8.1.0.
- [Release notes](https://github.com/isaacs/node-glob/releases)
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v8.0.3...v8.1.0)

---
updated-dependencies:
- dependency-name: glob
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* build(deps): bump dompurify from 2.4.1 to 2.4.3 in /website/client (#14443)

Bumps [dompurify](https://github.com/cure53/DOMPurify) from 2.4.1 to 2.4.3.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/2.4.1...2.4.3)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fixed typo (#14417)

In   "weaponSpecialWinter2023RogueNotes", changed "Incrases" to "Increases"

* Only update user objects that don’t have notification yet

* fix test

* fix spy

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: gwenexner <49045733+gwenexner@users.noreply.github.com>
Co-authored-by: SabreCat <sabe@habitica.com>
2023-03-13 16:24:00 -05:00
SabreCat 7874ae5092 fix(hyperlinks): WHITE inactive drawer tabs 2023-03-13 15:28:26 -05:00
SabreCat 481719e513 Revert "fix(hyperlinks): gray inactive drawer tabs"
This reverts commit 9657112bca.
2023-03-13 15:19:41 -05:00
SabreCat 9657112bca fix(hyperlinks): gray inactive drawer tabs 2023-03-13 14:35:43 -05:00
SabreCat f7026b2478 Merge branch 'release' into sabrecat/invite-notif 2023-03-13 14:13:06 -05:00
negue e39b3bdd35 open the modal by click override 2023-03-11 00:40:05 +01:00
SabreCat a210ab57b0 WIP(external-link): hacky attempt number one 2023-03-10 13:33:51 -06:00
CuriousMagpie 3f3e0e2ae8 modal essentially complete but for scripts 2023-03-08 15:17:15 -05:00
CuriousMagpie 65f12ac9ea adding console log messages 2023-03-08 12:55:58 -05:00
CuriousMagpie d0941810a7 trying to make a modal 2023-03-08 12:52:22 -05:00
CuriousMagpie b77deb28b4 initial commit 2023-03-08 12:01:50 -05:00
SabreCat 458aee9a3a Merge branch 'release' into develop 2023-03-07 11:48:14 -06:00
SabreCat 0b6b967753 4.262.0 2023-03-07 10:33:10 -06:00
Natalie L 57f86bac70 feat(content): March backgrounds and Enchanted Armoire items (#14524)
* feat(content): March backgrounds and Enchanted Armoire

* fix(backgrounds): trivial syntax consistency

* fix(gear): missing verbiage

* fix(gear): correct usage of <%= attrs %>

* fix(backgrounds): broken string tokens

* fix(backgrounds): more broken tokens

---------

Co-authored-by: SabreCat <sabe@habitica.com>
Co-authored-by: Sabe Jones <sabrecat@gmail.com>
2023-03-06 16:57:56 -06:00
Natalie L f2fe83a469 feature(upgrade): copy Pause Damage button to Settings page (#14532)
* feature(upgrade): copying Pause Damage button to Settings page

* Removing duplicate string 'cause I can't search effectively. 😅
2023-03-06 16:16:23 -06:00
SabreCat 3354ca048c fix(analytics): record missing group ID info
also update subproject while I'm here
2023-03-06 15:36:17 -06:00
SabreCat 99c46602c4 fix(fooling): correct special pet mapping 2023-03-06 09:47:53 -06:00
SabreCat ee585c0ff3 feat(event): April Fools 2023 2023-03-03 14:32:56 -06:00
Phillip Thelen 0754c0ff05 correctly set limit 2023-03-02 18:04:02 +01:00
Phillip Thelen 5d1346e65c fix lint 2023-03-01 15:06:08 +01:00
Phillip Thelen a2ce0ab099 Set request size limit higher, because of iOS receipt sizes 2023-03-01 14:48:50 +01:00
SabreCat 16ae182f34 Merge branch 'release' into develop 2023-02-28 15:37:35 -06:00
Phillip Thelen 6887fd70c0 try something 2023-02-28 16:17:52 +01:00
SabreCat f327795761 4.261.1 2023-02-27 16:17:17 -06:00
SabreCat 8cf5a380da fix(strings): more silly 2023-02-27 16:17:09 -06:00
Phillip Thelen def24142ca remove wrong test 2023-02-27 13:30:44 +01:00
Phillip Thelen c29049146d prevent sub accidentally also being applied to other account 2023-02-27 12:06:27 +01:00
SabreCat cc419385f6 4.261.0 2023-02-24 16:32:41 -06:00
SabreCat 45107fe48f Merge branch 'sabrecat/transactions-404' into release 2023-02-24 16:32:35 -06:00
SabreCat 80f517f1ad feat(content): subscriber items March 2023
Also fixes Vue templating in one paragraph of the Community Guidelines.
2023-02-24 16:31:50 -06:00
Phillip Thelen 57fb7ca6f2 fix 2023-02-24 11:25:53 +01:00
Phillip Thelen 62b171ffa5 fix linting 2023-02-24 10:47:50 +01:00
Phillip Thelen be18476292 correctly set perkMonthCount 2023-02-23 13:20:47 +01:00
SabreCat b6e9d0c9c0 Merge branch 'sabrecat/transactions-404' into develop 2023-02-22 15:20:16 -06:00
SabreCat 442d9ca9cd fix(permissions): route away from purchase history for non-support 2023-02-22 15:15:03 -06:00
Phillip Thelen 3f56b7fa3f fix offset calculation 2023-02-17 15:42:31 +01:00
SabreCat 14f9debfdb fix(css): remove yet more blue-10 overrides 2023-02-16 14:34:24 -06:00
SabreCat 4a1011f1af fix(hyperlinks): remove some blue overrides 2023-02-16 12:57:35 -06:00
Phillip Thelen d69de2948b fix import 2023-02-16 09:58:09 +01:00
Phillip Thelen c5f5da1d32 Merge remote-tracking branch 'origin/develop' into apple_sub_fix 2023-02-16 09:38:14 +01:00
Phillip Thelen e338fb8ce7 Merge branch 'apple_sub_fix' of https://github.com/HabitRPG/habitica into apple_sub_fix 2023-02-16 09:37:36 +01:00
Phillip Thelen 2d5dcae406 fix tests 2023-02-16 09:37:00 +01:00
SabreCat 9ec1917e6d feat(invites): provide link to inviting user in party notif
Also changes basic links sitewide to purple-300
2023-02-15 16:54:46 -06:00
SabreCat 409ce5dbfb Merge branch 'release' into develop 2023-02-15 15:29:34 -06:00
SabreCat ab706abed5 fix(test): remove outdated event expectation 2023-02-15 15:29:23 -06:00
Phillip Thelen 3203b09b7a reset perkMonthCount when subscription ends 2023-02-15 10:05:18 +01:00
gwenexner 2ea023299c fixed typo (#14417)
In   "weaponSpecialWinter2023RogueNotes", changed "Incrases" to "Increases"
2023-02-13 16:33:10 -06:00
dependabot[bot] ce1ce47d18 build(deps): bump dompurify from 2.4.1 to 2.4.3 in /website/client (#14443)
Bumps [dompurify](https://github.com/cure53/DOMPurify) from 2.4.1 to 2.4.3.
- [Release notes](https://github.com/cure53/DOMPurify/releases)
- [Commits](https://github.com/cure53/DOMPurify/compare/2.4.1...2.4.3)

---
updated-dependencies:
- dependency-name: dompurify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 16:27:33 -06:00
dependabot[bot] 0d1e8ec3f9 build(deps): bump glob from 8.0.3 to 8.1.0 (#14448)
Bumps [glob](https://github.com/isaacs/node-glob) from 8.0.3 to 8.1.0.
- [Release notes](https://github.com/isaacs/node-glob/releases)
- [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md)
- [Commits](https://github.com/isaacs/node-glob/compare/v8.0.3...v8.1.0)

---
updated-dependencies:
- dependency-name: glob
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 16:27:03 -06:00
dependabot[bot] 4a849e6d15 build(deps): bump cookiejar from 2.1.3 to 2.1.4 (#14462)
Bumps [cookiejar](https://github.com/bmeck/node-cookiejar) from 2.1.3 to 2.1.4.
- [Release notes](https://github.com/bmeck/node-cookiejar/releases)
- [Commits](https://github.com/bmeck/node-cookiejar/commits)

---
updated-dependencies:
- dependency-name: cookiejar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 16:26:33 -06:00
dependabot[bot] 7f65079cfe build(deps): bump ua-parser-js from 0.7.31 to 0.7.33 in /website/client (#14463)
Bumps [ua-parser-js](https://github.com/faisalman/ua-parser-js) from 0.7.31 to 0.7.33.
- [Release notes](https://github.com/faisalman/ua-parser-js/releases)
- [Changelog](https://github.com/faisalman/ua-parser-js/blob/master/changelog.md)
- [Commits](https://github.com/faisalman/ua-parser-js/compare/0.7.31...0.7.33)

---
updated-dependencies:
- dependency-name: ua-parser-js
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 16:26:11 -06:00
dependabot[bot] 04f54d5e03 build(deps): bump hellojs from 1.19.5 to 1.20.0 in /website/client (#14479)
Bumps [hellojs](https://github.com/MrSwitch/hello.js) from 1.19.5 to 1.20.0.
- [Release notes](https://github.com/MrSwitch/hello.js/releases)
- [Changelog](https://github.com/MrSwitch/hello.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/MrSwitch/hello.js/compare/v1.19.5...v1.20.0)

---
updated-dependencies:
- dependency-name: hellojs
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 16:03:23 -06:00
dependabot[bot] 925e2e5ec6 build(deps): bump validator from 13.7.0 to 13.9.0 (#14488)
Bumps [validator](https://github.com/validatorjs/validator.js) from 13.7.0 to 13.9.0.
- [Release notes](https://github.com/validatorjs/validator.js/releases)
- [Changelog](https://github.com/validatorjs/validator.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/validatorjs/validator.js/compare/13.7.0...13.9.0)

---
updated-dependencies:
- dependency-name: validator
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 15:41:09 -06:00
dependabot[bot] a549668522 build(deps): bump validator from 13.7.0 to 13.9.0 in /website/client (#14492)
Bumps [validator](https://github.com/validatorjs/validator.js) from 13.7.0 to 13.9.0.
- [Release notes](https://github.com/validatorjs/validator.js/releases)
- [Changelog](https://github.com/validatorjs/validator.js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/validatorjs/validator.js/compare/13.7.0...13.9.0)

---
updated-dependencies:
- dependency-name: validator
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 15:40:52 -06:00
dependabot[bot] 02e0e45da6 build(deps): bump @sideway/formula in /website/client (#14495)
Bumps [@sideway/formula](https://github.com/sideway/formula) from 3.0.0 to 3.0.1.
- [Release notes](https://github.com/sideway/formula/releases)
- [Commits](https://github.com/sideway/formula/compare/v3.0.0...v3.0.1)

---
updated-dependencies:
- dependency-name: "@sideway/formula"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 15:40:31 -06:00
dependabot[bot] 1e72dbe155 build(deps): bump apidoc from 0.53.1 to 0.54.0 (#14501)
Bumps [apidoc](https://github.com/apidoc/apidoc) from 0.53.1 to 0.54.0.
- [Release notes](https://github.com/apidoc/apidoc/releases)
- [Changelog](https://github.com/apidoc/apidoc/blob/master/CHANGELOG.md)
- [Commits](https://github.com/apidoc/apidoc/compare/0.53.1...0.54.0)

---
updated-dependencies:
- dependency-name: apidoc
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 15:39:05 -06:00
dependabot[bot] e71f0558fe build(deps): bump stripe from 11.6.0 to 11.10.0 (#14503)
Bumps [stripe](https://github.com/stripe/stripe-node) from 11.6.0 to 11.10.0.
- [Release notes](https://github.com/stripe/stripe-node/releases)
- [Changelog](https://github.com/stripe/stripe-node/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-node/compare/v11.6.0...v11.10.0)

---
updated-dependencies:
- dependency-name: stripe
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 15:38:38 -06:00
dependabot[bot] b3d83431e6 build(deps): bump stopword from 2.0.5 to 2.0.7 in /website/client (#14504)
Bumps [stopword](https://github.com/fergiemcdowall/stopword) from 2.0.5 to 2.0.7.
- [Release notes](https://github.com/fergiemcdowall/stopword/releases)
- [Commits](https://github.com/fergiemcdowall/stopword/commits/v.2.0.7)

---
updated-dependencies:
- dependency-name: stopword
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-02-13 15:38:02 -06:00
SabreCat 2ac21104a4 4.260.1 2023-02-13 11:51:45 -06:00
SabreCat 6b95f648c4 Merge remote-tracking branch 'CuriousMagpie/footer-link-updates' into release 2023-02-13 11:28:14 -06:00
SabreCat f9db4b9b5b fix(event): correct logic for various Valentine's items 2023-02-13 11:25:02 -06:00
Phillip Thelen 6ee2e3a379 Merge remote-tracking branch 'origin/develop' into apple_sub_fix 2023-02-13 17:38:14 +01:00
SabreCat 74da6d8798 4.260.0 2023-02-12 23:17:16 -06:00
Natalie L a73e4d399e chore(content): add Pink Marble Magic Hatching Potion (#14497)
* chore(content): add quest text

* chore(content): add rest of potion quest content

* fix(image): pad quest scroll image

* feat(quest): add Rage action

---------

Co-authored-by: SabreCat <sabe@habitica.com>
2023-02-12 23:17:56 -06:00
Natalie L 8f4d668b0f chore(content): add pet quest bundle and magic hatching potions for February (#14499) 2023-02-12 23:17:09 -06:00
CuriousMagpie 945c19cc80 chore(links): add weblate link to footer and update data display tool 2023-02-10 15:11:36 -05:00
gwenexner 7b4cfee290 Fixed release info for Set 105 (#14494)
Removed a stray space at the front of "Set 105", changed year to 2023.
2023-02-10 10:30:27 -06:00
Phillip Thelen 77229f3e5e show year for next hourglass 2023-02-10 17:13:20 +01:00
Phillip Thelen 41cdab1672 adjust tests 2023-02-10 17:13:10 +01:00
Phillip Thelen 58f4dd0c43 fix typo 2023-02-10 17:13:04 +01:00
Phillip Thelen 0ce64a0197 fix next hourglass calculation 2023-02-09 16:20:46 +01:00
Natalie L 0b8f2bc58e update(content): revise community guidelines (#14481)
* update(content); revise community guidelines

* fix(CG): remove outdated spoiler advice, remove unneeded string token

* chore(CG): update date line to intended publication

---------

Co-authored-by: SabreCat <sabe@habitica.com>
2023-02-08 15:04:30 -06:00
SabreCat 015631685b 4.259.1 2023-02-08 15:04:19 -06:00
SabreCat 6c536c0b89 Merge branch 'release' into develop 2023-02-07 09:12:03 -06:00
SabreCat 1de2adf301 4.259.0 2023-02-07 09:11:52 -06:00
Natalie L 0335eb1f7e chore(content): add February backgrounds and Enchanted Armoire Items (#14482)
* chore(content): add February backgrounds and Enchanted Armoire Items

* fix(test): birthday week adjustment

* fix(strings): .

* fix(strings): correct background tokens

---------

Co-authored-by: SabreCat <sabe@habitica.com>
Co-authored-by: Sabe Jones <sabrecat@gmail.com>
2023-02-07 09:12:19 -06:00
SabreCat e0a5938711 fix(test): update expectations for new flagging logic 2023-02-06 21:34:51 -06:00
Phillip Thelen ad6555c92b fix import 2023-02-06 17:16:43 +01:00
Phillip Thelen c04e8ea514 comma 2023-02-06 13:01:06 +01:00
Phillip Thelen aec2409227 lint fixes 2023-02-06 12:59:54 +01:00
Phillip Thelen 87aebcc19e Merge branch 'apple_sub_fix' of https://github.com/HabitRPG/habitica into apple_sub_fix
# Conflicts:
#	test/api/unit/libs/payments/apple.test.js
#	website/server/libs/payments/subscriptions.js
2023-02-06 11:19:00 +01:00
Phillip Thelen a3bc20f855 Fix case where a number was sometimes a string 2023-02-06 11:17:35 +01:00
Phillip Thelen 86e33b2364 remove log 2023-02-06 11:17:35 +01:00
Phillip Thelen 12479edb77 fix tests and some cases 2023-02-06 11:17:35 +01:00
Phillip Thelen c0c6657536 handle upgrades and creations better 2023-02-06 11:17:35 +01:00
SabreCat e81a052f66 fix(lint): line lengths and so on 2023-02-06 11:17:35 +01:00
Phillip Thelen 82a1d6ff0e Improve handling 2023-02-06 11:17:35 +01:00
Phillip Thelen 0f7001b609 fix lint 2023-02-06 11:17:35 +01:00
Phillip Thelen 87558a325e Handle subscription cancelation better 2023-02-06 11:17:35 +01:00
Phillip Thelen de48925341 remove only 2023-02-06 11:17:35 +01:00
Phillip Thelen 614850e56c fix tests 2023-02-06 11:17:35 +01:00
Phillip Thelen 64a3515c10 Add logic for different types of sub upgrades 2023-02-06 11:17:35 +01:00
Phillip Thelen 8dfa21a4b8 Add field to track when current subscription type started 2023-02-06 11:17:35 +01:00
Phillip Thelen f9a9d4919b Improve recheck handling for test subs 2023-02-06 11:17:35 +01:00
Phillip Thelen ddf1b4060d Better handling for cancellation when user had multiple subs 2023-02-06 11:17:35 +01:00
Phillip Thelen 967717a010 Fix logic for apple subscriptions 2023-02-06 11:17:35 +01:00
SabreCat 9b791b4ba0 fix(test): save user to avoid lock errors 2023-02-06 11:17:35 +01:00
SabreCat 5aca5b4be7 fix(test): linting 2023-02-06 11:17:35 +01:00
Phillip Thelen 0dd25b6431 fix issue where subs would be applied multiple times 2023-02-06 11:17:35 +01:00
Phillip Thelen cf75d941fa fix test 2023-02-06 11:17:35 +01:00
Phillip Thelen 777f7887b4 fix lint errors 2023-02-06 11:17:35 +01:00
Phillip Thelen f07d0f6441 Implement correct handling for when subs are up/downgraded 2023-02-06 11:17:24 +01:00
Phillip Thelen 98ec1757f9 fix tests 2023-02-06 11:16:24 +01:00
SabreCat 742da1f2c6 fix(typo): customER 2023-02-06 11:16:24 +01:00
SabreCat b3d5a8d083 fix(lint): line length 2023-02-06 11:16:24 +01:00
Phillip Thelen b5f2e66025 fix check 2023-02-06 11:16:24 +01:00
Phillip Thelen 9a40674d8d Allow sub upgrades/downgrades on iOS 2023-02-06 11:16:24 +01:00
SabreCat c7deb1eb19 4.258.2 2023-02-03 09:23:27 -06:00
SabreCat a213fb723a fix(purchases): correct hardcoded date range for Gryph 2023-02-03 09:23:21 -06:00
SabreCat 0f9b6ab591 fix(lint): revert bad lint rule again 2023-01-31 11:00:08 -06:00
Phillip Thelen cde5fbef85 Fix case where a number was sometimes a string 2022-12-09 12:16:33 +01:00
Phillip Thelen 8b2af1ef56 remove log 2022-12-05 15:38:30 +01:00
Phillip Thelen 21652c2670 fix tests and some cases 2022-12-02 17:12:17 +01:00
Phillip Thelen d1ee679810 handle upgrades and creations better 2022-12-02 11:51:33 +01:00
SabreCat 67988da33c fix(lint): line lengths and so on 2022-11-30 15:27:53 -06:00
Phillip Thelen fae26a517d Improve handling 2022-11-30 15:06:50 +01:00
Phillip Thelen e3c86349b4 fix lint 2022-11-11 13:58:45 +01:00
Phillip Thelen 6604f38144 Handle subscription cancelation better 2022-11-11 13:54:17 +01:00
Phillip Thelen 037882b50a remove only 2022-11-10 13:55:58 +01:00
Phillip Thelen 15deb778fd fix tests 2022-11-10 13:48:58 +01:00
Phillip Thelen 7d2529f5e1 Add logic for different types of sub upgrades 2022-11-09 19:49:53 +01:00
Phillip Thelen 8d732c59c4 Add field to track when current subscription type started 2022-11-08 12:38:24 +01:00
Phillip Thelen 3a34aa4cc5 Improve recheck handling for test subs 2022-11-08 12:19:17 +01:00
Phillip Thelen e7fc7feddd Better handling for cancellation when user had multiple subs 2022-11-04 13:30:50 +01:00
Phillip Thelen 7fd899b642 Fix logic for apple subscriptions 2022-11-03 17:48:36 +01:00
SabreCat 36d2ad6b9b fix(test): save user to avoid lock errors 2022-11-02 15:15:28 -05:00
SabreCat 164dbdcf10 Merge branch 'develop' into apple_sub_fix 2022-11-02 15:00:24 -05:00
SabreCat b65fa941b9 fix(test): linting 2022-11-02 14:44:49 -05:00
Phillip Thelen ab953440e3 fix issue where subs would be applied multiple times 2022-11-02 16:36:09 +01:00
Phillip Thelen 1143f690d1 fix test 2022-10-28 15:28:46 +02:00
Phillip Thelen 08469c556b fix lint errors 2022-10-28 12:41:43 +02:00
Phillip Thelen 13a25ad89e Implement correct handling for when subs are up/downgraded 2022-10-28 11:23:48 +02:00
Phillip Thelen 8e2e170930 fix tests 2022-10-26 16:30:35 +02:00
SabreCat e6a7d15644 fix(typo): customER 2022-10-25 16:59:59 -05:00
SabreCat 6a4b08203f fix(lint): line length 2022-10-25 16:52:16 -05:00
SabreCat c9016c8d42 Merge branch 'develop' into phillip/sub_change 2022-10-25 16:47:51 -05:00
Phillip Thelen 31685c3e94 fix check 2022-10-21 16:59:18 +02:00
Phillip Thelen c25b09c7ed Allow sub upgrades/downgrades on iOS 2022-10-21 16:57:12 +02:00
393 changed files with 10997 additions and 4836 deletions
+2 -1
View File
@@ -86,5 +86,6 @@
"RATE_LIMITER_ENABLED": "false",
"REDIS_HOST": "aaabbbcccdddeeefff",
"REDIS_PORT": "1234",
"REDIS_PASSWORD": "12345678"
"REDIS_PASSWORD": "12345678",
"TRUSTED_DOMAINS": "https://localhost,https://habitica.com"
}
+2 -2
View File
@@ -3,7 +3,7 @@ import { v4 as uuid } from 'uuid';
import { model as User } from '../../website/server/models/user';
const MIGRATION_NAME = '20220314_pi_day';
const MIGRATION_NAME = '20230314_pi_day';
const progressCount = 1000;
let count = 0;
@@ -54,7 +54,7 @@ async function updateUser (user) {
export default async function processUsers () {
const query = {
migration: { $ne: MIGRATION_NAME },
'auth.timestamps.loggedin': { $gt: new Date('2022-02-15') },
'auth.timestamps.loggedin': { $gt: new Date('2023-02-15') },
};
const fields = {
+234 -229
View File
@@ -1,6 +1,6 @@
{
"name": "habitica",
"version": "4.258.1",
"version": "4.267.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
@@ -1667,15 +1667,135 @@
"integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw=="
},
"@esbuild/android-arm": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.15.12.tgz",
"integrity": "sha512-IC7TqIqiyE0MmvAhWkl/8AEzpOtbhRNDo7aph47We1NbE5w2bt/Q+giAhe0YYeVpYnIhGMcuZY92qDK6dQauvA==",
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.16.17.tgz",
"integrity": "sha512-N9x1CMXVhtWEAMS7pNNONyA14f71VPQN9Cnavj1XQh6T7bskqiLLrSca4O0Vr8Wdcga943eThxnVp3JLnBMYtw==",
"optional": true
},
"@esbuild/android-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.16.17.tgz",
"integrity": "sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==",
"optional": true
},
"@esbuild/android-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.16.17.tgz",
"integrity": "sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==",
"optional": true
},
"@esbuild/darwin-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz",
"integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==",
"optional": true
},
"@esbuild/darwin-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.16.17.tgz",
"integrity": "sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==",
"optional": true
},
"@esbuild/freebsd-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.16.17.tgz",
"integrity": "sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==",
"optional": true
},
"@esbuild/freebsd-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.16.17.tgz",
"integrity": "sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==",
"optional": true
},
"@esbuild/linux-arm": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.16.17.tgz",
"integrity": "sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==",
"optional": true
},
"@esbuild/linux-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.16.17.tgz",
"integrity": "sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==",
"optional": true
},
"@esbuild/linux-ia32": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.16.17.tgz",
"integrity": "sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==",
"optional": true
},
"@esbuild/linux-loong64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.15.12.tgz",
"integrity": "sha512-tZEowDjvU7O7I04GYvWQOS4yyP9E/7YlsB0jjw1Ycukgr2ycEzKyIk5tms5WnLBymaewc6VmRKnn5IJWgK4eFw==",
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.16.17.tgz",
"integrity": "sha512-dTzNnQwembNDhd654cA4QhbS9uDdXC3TKqMJjgOWsC0yNCbpzfWoXdZvp0mY7HU6nzk5E0zpRGGx3qoQg8T2DQ==",
"optional": true
},
"@esbuild/linux-mips64el": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.16.17.tgz",
"integrity": "sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==",
"optional": true
},
"@esbuild/linux-ppc64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.16.17.tgz",
"integrity": "sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==",
"optional": true
},
"@esbuild/linux-riscv64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.16.17.tgz",
"integrity": "sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==",
"optional": true
},
"@esbuild/linux-s390x": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.16.17.tgz",
"integrity": "sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==",
"optional": true
},
"@esbuild/linux-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.16.17.tgz",
"integrity": "sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==",
"optional": true
},
"@esbuild/netbsd-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.16.17.tgz",
"integrity": "sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==",
"optional": true
},
"@esbuild/openbsd-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.16.17.tgz",
"integrity": "sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==",
"optional": true
},
"@esbuild/sunos-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.16.17.tgz",
"integrity": "sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==",
"optional": true
},
"@esbuild/win32-arm64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.16.17.tgz",
"integrity": "sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==",
"optional": true
},
"@esbuild/win32-ia32": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.16.17.tgz",
"integrity": "sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==",
"optional": true
},
"@esbuild/win32-x64": {
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.16.17.tgz",
"integrity": "sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==",
"optional": true
},
"@google-cloud/common": {
@@ -2147,9 +2267,9 @@
}
},
"@types/eslint": {
"version": "8.4.7",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.7.tgz",
"integrity": "sha512-ehM7cCt2RSFs42mb+lcmhFT9ouIlV92PuaeRGn8N8c98oMjG4Z5pJHA9b1QiCcuqnbPSHcyfiD3mlhqMaHsQIw==",
"version": "8.21.0",
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.0.tgz",
"integrity": "sha512-35EhHNOXgxnUgh4XCJsGhE7zdlDhYDN/aMG6UbkByCFFNgQ7b3U+uVoqBpicFydR8JEfgdjCF7SJ7MiJfzuiTA==",
"requires": {
"@types/estree": "*",
"@types/json-schema": "*"
@@ -2636,9 +2756,9 @@
}
},
"apidoc": {
"version": "0.53.1",
"resolved": "https://registry.npmjs.org/apidoc/-/apidoc-0.53.1.tgz",
"integrity": "sha512-ijiLtIVEzTMdF29B/QzkvR4weMatgcElMsYKP1asszrImWYwzlZ9x0ZMLTXZrCe7GVMtkGSwQdugdLTZMZ+lww==",
"version": "0.54.0",
"resolved": "https://registry.npmjs.org/apidoc/-/apidoc-0.54.0.tgz",
"integrity": "sha512-VCOdwkAaFK7bDLbiAiFKqX8SVlAnk7sQCXDARwshBQpVRqRGDNY993kAMPkWmSD1RCVBDMFIOgOfOR9mcISNZQ==",
"requires": {
"bootstrap": "3.4.1",
"commander": "^8.3.0",
@@ -2663,9 +2783,9 @@
},
"dependencies": {
"anymatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
"integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"requires": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -4075,20 +4195,25 @@
"dev": true
},
"browserslist": {
"version": "4.21.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.2.tgz",
"integrity": "sha512-MonuOgAtUB46uP5CezYbRaYKBNt2LxP0yX+Pmj4LkcDFGkn9Cbpi83d9sCjwQDErXsIJSzY5oKGDbgOlF/LPAA==",
"version": "4.21.5",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz",
"integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==",
"requires": {
"caniuse-lite": "^1.0.30001366",
"electron-to-chromium": "^1.4.188",
"node-releases": "^2.0.6",
"update-browserslist-db": "^1.0.4"
"caniuse-lite": "^1.0.30001449",
"electron-to-chromium": "^1.4.284",
"node-releases": "^2.0.8",
"update-browserslist-db": "^1.0.10"
},
"dependencies": {
"electron-to-chromium": {
"version": "1.4.192",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.192.tgz",
"integrity": "sha512-8nCXyIQY9An88NXAp+PuPy5h3/w5ZY7Iu2lag65Q0XREprcat5F8gKhoHsBUnQcFuCRnmevpR8yEBYRU3d2HDw=="
"version": "1.4.295",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.295.tgz",
"integrity": "sha512-lEO94zqf1bDA3aepxwnWoHUjA8sZ+2owgcSZjYQy0+uOSEclJX0VieZC+r+wLpSxUHRd6gG32znTWmr+5iGzFw=="
},
"node-releases": {
"version": "2.0.10",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz",
"integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w=="
}
}
},
@@ -4246,9 +4371,9 @@
}
},
"caniuse-lite": {
"version": "1.0.30001367",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001367.tgz",
"integrity": "sha512-XDgbeOHfifWV3GEES2B8rtsrADx4Jf+juKX2SICJcaUhjYBO3bR96kvEIHa15VU6ohtOhBZuPGGYGbXMRn0NCw=="
"version": "1.0.30001451",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz",
"integrity": "sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w=="
},
"caseless": {
"version": "0.12.0",
@@ -4879,9 +5004,9 @@
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
},
"cookiejar": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz",
"integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ=="
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
"integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw=="
},
"cookies": {
"version": "0.8.0",
@@ -5759,9 +5884,9 @@
}
},
"enhanced-resolve": {
"version": "5.10.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz",
"integrity": "sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==",
"version": "5.12.0",
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz",
"integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==",
"requires": {
"graceful-fs": "^4.2.4",
"tapable": "^2.2.0"
@@ -5871,167 +5996,47 @@
}
},
"esbuild": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.12.tgz",
"integrity": "sha512-PcT+/wyDqJQsRVhaE9uX/Oq4XLrFh0ce/bs2TJh4CSaw9xuvI+xFrH2nAYOADbhQjUgAhNWC5LKoUsakm4dxng==",
"version": "0.16.17",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz",
"integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==",
"requires": {
"@esbuild/android-arm": "0.15.12",
"@esbuild/linux-loong64": "0.15.12",
"esbuild-android-64": "0.15.12",
"esbuild-android-arm64": "0.15.12",
"esbuild-darwin-64": "0.15.12",
"esbuild-darwin-arm64": "0.15.12",
"esbuild-freebsd-64": "0.15.12",
"esbuild-freebsd-arm64": "0.15.12",
"esbuild-linux-32": "0.15.12",
"esbuild-linux-64": "0.15.12",
"esbuild-linux-arm": "0.15.12",
"esbuild-linux-arm64": "0.15.12",
"esbuild-linux-mips64le": "0.15.12",
"esbuild-linux-ppc64le": "0.15.12",
"esbuild-linux-riscv64": "0.15.12",
"esbuild-linux-s390x": "0.15.12",
"esbuild-netbsd-64": "0.15.12",
"esbuild-openbsd-64": "0.15.12",
"esbuild-sunos-64": "0.15.12",
"esbuild-windows-32": "0.15.12",
"esbuild-windows-64": "0.15.12",
"esbuild-windows-arm64": "0.15.12"
"@esbuild/android-arm": "0.16.17",
"@esbuild/android-arm64": "0.16.17",
"@esbuild/android-x64": "0.16.17",
"@esbuild/darwin-arm64": "0.16.17",
"@esbuild/darwin-x64": "0.16.17",
"@esbuild/freebsd-arm64": "0.16.17",
"@esbuild/freebsd-x64": "0.16.17",
"@esbuild/linux-arm": "0.16.17",
"@esbuild/linux-arm64": "0.16.17",
"@esbuild/linux-ia32": "0.16.17",
"@esbuild/linux-loong64": "0.16.17",
"@esbuild/linux-mips64el": "0.16.17",
"@esbuild/linux-ppc64": "0.16.17",
"@esbuild/linux-riscv64": "0.16.17",
"@esbuild/linux-s390x": "0.16.17",
"@esbuild/linux-x64": "0.16.17",
"@esbuild/netbsd-x64": "0.16.17",
"@esbuild/openbsd-x64": "0.16.17",
"@esbuild/sunos-x64": "0.16.17",
"@esbuild/win32-arm64": "0.16.17",
"@esbuild/win32-ia32": "0.16.17",
"@esbuild/win32-x64": "0.16.17"
}
},
"esbuild-android-64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-android-64/-/esbuild-android-64-0.15.12.tgz",
"integrity": "sha512-MJKXwvPY9g0rGps0+U65HlTsM1wUs9lbjt5CU19RESqycGFDRijMDQsh68MtbzkqWSRdEtiKS1mtPzKneaAI0Q==",
"optional": true
},
"esbuild-android-arm64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-android-arm64/-/esbuild-android-arm64-0.15.12.tgz",
"integrity": "sha512-Hc9SEcZbIMhhLcvhr1DH+lrrec9SFTiRzfJ7EGSBZiiw994gfkVV6vG0sLWqQQ6DD7V4+OggB+Hn0IRUdDUqvA==",
"optional": true
},
"esbuild-darwin-64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-darwin-64/-/esbuild-darwin-64-0.15.12.tgz",
"integrity": "sha512-qkmqrTVYPFiePt5qFjP8w/S+GIUMbt6k8qmiPraECUWfPptaPJUGkCKrWEfYFRWB7bY23FV95rhvPyh/KARP8Q==",
"optional": true
},
"esbuild-darwin-arm64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-darwin-arm64/-/esbuild-darwin-arm64-0.15.12.tgz",
"integrity": "sha512-z4zPX02tQ41kcXMyN3c/GfZpIjKoI/BzHrdKUwhC/Ki5BAhWv59A9M8H+iqaRbwpzYrYidTybBwiZAIWCLJAkw==",
"optional": true
},
"esbuild-freebsd-64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-freebsd-64/-/esbuild-freebsd-64-0.15.12.tgz",
"integrity": "sha512-XFL7gKMCKXLDiAiBjhLG0XECliXaRLTZh6hsyzqUqPUf/PY4C6EJDTKIeqqPKXaVJ8+fzNek88285krSz1QECw==",
"optional": true
},
"esbuild-freebsd-arm64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-freebsd-arm64/-/esbuild-freebsd-arm64-0.15.12.tgz",
"integrity": "sha512-jwEIu5UCUk6TjiG1X+KQnCGISI+ILnXzIzt9yDVrhjug2fkYzlLbl0K43q96Q3KB66v6N1UFF0r5Ks4Xo7i72g==",
"optional": true
},
"esbuild-linux-32": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-linux-32/-/esbuild-linux-32-0.15.12.tgz",
"integrity": "sha512-uSQuSEyF1kVzGzuIr4XM+v7TPKxHjBnLcwv2yPyCz8riV8VUCnO/C4BF3w5dHiVpCd5Z1cebBtZJNlC4anWpwA==",
"optional": true
},
"esbuild-linux-64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.12.tgz",
"integrity": "sha512-QcgCKb7zfJxqT9o5z9ZUeGH1k8N6iX1Y7VNsEi5F9+HzN1OIx7ESxtQXDN9jbeUSPiRH1n9cw6gFT3H4qbdvcA==",
"optional": true
},
"esbuild-linux-arm": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-linux-arm/-/esbuild-linux-arm-0.15.12.tgz",
"integrity": "sha512-Wf7T0aNylGcLu7hBnzMvsTfEXdEdJY/hY3u36Vla21aY66xR0MS5I1Hw8nVquXjTN0A6fk/vnr32tkC/C2lb0A==",
"optional": true
},
"esbuild-linux-arm64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-linux-arm64/-/esbuild-linux-arm64-0.15.12.tgz",
"integrity": "sha512-HtNq5xm8fUpZKwWKS2/YGwSfTF+339L4aIA8yphNKYJckd5hVdhfdl6GM2P3HwLSCORS++++7++//ApEwXEuAQ==",
"optional": true
},
"esbuild-linux-mips64le": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-linux-mips64le/-/esbuild-linux-mips64le-0.15.12.tgz",
"integrity": "sha512-Qol3+AvivngUZkTVFgLpb0H6DT+N5/zM3V1YgTkryPYFeUvuT5JFNDR3ZiS6LxhyF8EE+fiNtzwlPqMDqVcc6A==",
"optional": true
},
"esbuild-linux-ppc64le": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-linux-ppc64le/-/esbuild-linux-ppc64le-0.15.12.tgz",
"integrity": "sha512-4D8qUCo+CFKaR0cGXtGyVsOI7w7k93Qxb3KFXWr75An0DHamYzq8lt7TNZKoOq/Gh8c40/aKaxvcZnTgQ0TJNg==",
"optional": true
},
"esbuild-linux-riscv64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-linux-riscv64/-/esbuild-linux-riscv64-0.15.12.tgz",
"integrity": "sha512-G9w6NcuuCI6TUUxe6ka0enjZHDnSVK8bO+1qDhMOCtl7Tr78CcZilJj8SGLN00zO5iIlwNRZKHjdMpfFgNn1VA==",
"optional": true
},
"esbuild-linux-s390x": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-linux-s390x/-/esbuild-linux-s390x-0.15.12.tgz",
"integrity": "sha512-Lt6BDnuXbXeqSlVuuUM5z18GkJAZf3ERskGZbAWjrQoi9xbEIsj/hEzVnSAFLtkfLuy2DE4RwTcX02tZFunXww==",
"optional": true
},
"esbuild-loader": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/esbuild-loader/-/esbuild-loader-2.20.0.tgz",
"integrity": "sha512-dr+j8O4w5RvqZ7I4PPB4EIyVTd679EBQnMm+JBB7av+vu05Zpje2IpK5N3ld1VWa+WxrInIbNFAg093+E1aRsA==",
"version": "2.21.0",
"resolved": "https://registry.npmjs.org/esbuild-loader/-/esbuild-loader-2.21.0.tgz",
"integrity": "sha512-k7ijTkCT43YBSZ6+fBCW1Gin7s46RrJ0VQaM8qA7lq7W+OLsGgtLyFV8470FzYi/4TeDexniTBTPTwZUnXXR5g==",
"requires": {
"esbuild": "^0.15.6",
"esbuild": "^0.16.17",
"joycon": "^3.0.1",
"json5": "^2.2.0",
"loader-utils": "^2.0.0",
"tapable": "^2.2.0",
"webpack-sources": "^2.2.0"
"webpack-sources": "^1.4.3"
}
},
"esbuild-netbsd-64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-netbsd-64/-/esbuild-netbsd-64-0.15.12.tgz",
"integrity": "sha512-jlUxCiHO1dsqoURZDQts+HK100o0hXfi4t54MNRMCAqKGAV33JCVvMplLAa2FwviSojT/5ZG5HUfG3gstwAG8w==",
"optional": true
},
"esbuild-openbsd-64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-openbsd-64/-/esbuild-openbsd-64-0.15.12.tgz",
"integrity": "sha512-1o1uAfRTMIWNOmpf8v7iudND0L6zRBYSH45sofCZywrcf7NcZA+c7aFsS1YryU+yN7aRppTqdUK1PgbZVaB1Dw==",
"optional": true
},
"esbuild-sunos-64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-sunos-64/-/esbuild-sunos-64-0.15.12.tgz",
"integrity": "sha512-nkl251DpoWoBO9Eq9aFdoIt2yYmp4I3kvQjba3jFKlMXuqQ9A4q+JaqdkCouG3DHgAGnzshzaGu6xofGcXyPXg==",
"optional": true
},
"esbuild-windows-32": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-windows-32/-/esbuild-windows-32-0.15.12.tgz",
"integrity": "sha512-WlGeBZHgPC00O08luIp5B2SP4cNCp/PcS+3Pcg31kdcJPopHxLkdCXtadLU9J82LCfw4TVls21A6lilQ9mzHrw==",
"optional": true
},
"esbuild-windows-64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-windows-64/-/esbuild-windows-64-0.15.12.tgz",
"integrity": "sha512-VActO3WnWZSN//xjSfbiGOSyC+wkZtI8I4KlgrTo5oHJM6z3MZZBCuFaZHd8hzf/W9KPhF0lY8OqlmWC9HO5AA==",
"optional": true
},
"esbuild-windows-arm64": {
"version": "0.15.12",
"resolved": "https://registry.npmjs.org/esbuild-windows-arm64/-/esbuild-windows-arm64-0.15.12.tgz",
"integrity": "sha512-Of3MIacva1OK/m4zCNIvBfz8VVROBmQT+gRX6pFTLPngFYcj6TFH/12VveAqq1k9VB2l28EoVMNMUCcmsfwyuA==",
"optional": true
},
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
@@ -7729,9 +7734,9 @@
"dev": true
},
"glob": {
"version": "8.0.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz",
"integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==",
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -7749,9 +7754,9 @@
}
},
"minimatch": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz",
"integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==",
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"requires": {
"brace-expansion": "^2.0.1"
}
@@ -9704,9 +9709,9 @@
"integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg=="
},
"jquery": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.1.tgz",
"integrity": "sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw=="
"version": "3.6.3",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.3.tgz",
"integrity": "sha512-bZ5Sy3YzKo9Fyc8wH2iIQK4JImJ6R0GWI9kL1/k7Z91ZBNgkRXE6U0JfHIizZbort8ZunhSI3jw9I6253ahKfg=="
},
"js-tokens": {
"version": "4.0.0",
@@ -9784,9 +9789,9 @@
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
},
"json5": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.2.tgz",
"integrity": "sha512-46Tk9JiOL2z7ytNQWFLpj99RZkVgeHf87yGQKsIkaPz1qSH9UczKH1rO7K3wgRselo0tYMUNfecYpm/p1vC7tQ=="
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
},
"jsonfile": {
"version": "6.1.0",
@@ -13451,9 +13456,9 @@
}
},
"serialize-javascript": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
"integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
"integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
"requires": {
"randombytes": "^2.1.0"
}
@@ -13612,9 +13617,9 @@
}
},
"simple-update-notifier": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz",
"integrity": "sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==",
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz",
"integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==",
"requires": {
"semver": "~7.0.0"
},
@@ -14286,9 +14291,9 @@
}
},
"stripe": {
"version": "11.6.0",
"resolved": "https://registry.npmjs.org/stripe/-/stripe-11.6.0.tgz",
"integrity": "sha512-ht8S1l8CJJE3jtv2NM1mEQzZBkITYvb9uDpSeXYeNz9iJkFFgDU169htwOW00OdIESvFaIsGgWQatAE5dfOERQ==",
"version": "11.10.0",
"resolved": "https://registry.npmjs.org/stripe/-/stripe-11.10.0.tgz",
"integrity": "sha512-uzQuj/Vangpp8fgkaEr6oRNfPToo5xamOhc7wxFGF/RUm7VKm/IGzoZ0cCtnGHCs5/O1AjMQsTZApgUARRVHOw==",
"requires": {
"@types/node": ">=8.1.0",
"qs": "^6.11.0"
@@ -14600,9 +14605,9 @@
"integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw=="
},
"terser": {
"version": "5.15.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz",
"integrity": "sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw==",
"version": "5.16.3",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz",
"integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==",
"requires": {
"@jridgewell/source-map": "^0.3.2",
"acorn": "^8.5.0",
@@ -14611,9 +14616,9 @@
},
"dependencies": {
"acorn": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
"integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w=="
"version": "8.8.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw=="
},
"commander": {
"version": "2.20.3",
@@ -15310,9 +15315,9 @@
"integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg=="
},
"update-browserslist-db": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.4.tgz",
"integrity": "sha512-jnmO2BEGUjsMOe/Fg9u0oczOe/ppIDZPebzccl1yDWGLFP16Pa1/RM5wEoKYPG2zstNcDuAStejyxsOuKINdGA==",
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
"integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
"requires": {
"escalade": "^3.1.1",
"picocolors": "^1.0.0"
@@ -15514,9 +15519,9 @@
}
},
"validator": {
"version": "13.7.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
"integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw=="
"version": "13.9.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz",
"integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA=="
},
"value-or-function": {
"version": "3.0.0",
@@ -15782,9 +15787,9 @@
"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
},
"webpack": {
"version": "5.74.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.74.0.tgz",
"integrity": "sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA==",
"version": "5.75.0",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz",
"integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==",
"requires": {
"@types/eslint-scope": "^3.7.3",
"@types/estree": "^0.0.51",
@@ -15813,9 +15818,9 @@
},
"dependencies": {
"acorn": {
"version": "8.8.0",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz",
"integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w=="
"version": "8.8.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz",
"integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw=="
},
"eslint-scope": {
"version": "5.1.1",
@@ -15902,12 +15907,12 @@
}
},
"webpack-sources": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz",
"integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==",
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
"integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
"requires": {
"source-list-map": "^2.0.1",
"source-map": "^0.6.1"
"source-list-map": "^2.0.0",
"source-map": "~0.6.1"
},
"dependencies": {
"source-map": {
+5 -5
View File
@@ -1,7 +1,7 @@
{
"name": "habitica",
"description": "A habit tracker app which treats your goals like a Role Playing Game.",
"version": "4.258.1",
"version": "4.267.2",
"main": "./website/server/index.js",
"dependencies": {
"@babel/core": "^7.20.12",
@@ -13,7 +13,7 @@
"accepts": "^1.3.8",
"amazon-payments": "^0.2.9",
"amplitude": "^6.0.0",
"apidoc": "^0.53.1",
"apidoc": "^0.54.0",
"apple-auth": "^1.0.7",
"bcrypt": "^5.1.0",
"body-parser": "^1.20.1",
@@ -30,7 +30,7 @@
"express": "^4.18.2",
"express-basic-auth": "^1.2.1",
"express-validator": "^5.2.0",
"glob": "^8.0.3",
"glob": "^8.1.0",
"got": "^11.8.3",
"gulp": "^4.0.0",
"gulp-babel": "^8.0.0",
@@ -67,12 +67,12 @@
"remove-markdown": "^0.5.0",
"rimraf": "^3.0.2",
"short-uuid": "^4.2.2",
"stripe": "^11.6.0",
"stripe": "^11.10.0",
"superagent": "^8.0.6",
"universal-analytics": "^0.5.3",
"useragent": "^2.1.9",
"uuid": "^9.0.0",
"validator": "^13.7.0",
"validator": "^13.9.0",
"vinyl-buffer": "^1.0.1",
"winston": "^3.8.2",
"winston-loggly-bulk": "^3.2.1",
+100 -21
View File
@@ -231,13 +231,16 @@ describe('cron', async () => {
},
});
// user1 has a 1-month recurring subscription starting today
user1.purchased.plan.customerId = 'subscribedId';
user1.purchased.plan.dateUpdated = moment().toDate();
user1.purchased.plan.planId = 'basic';
user1.purchased.plan.consecutive.count = 0;
user1.purchased.plan.consecutive.offset = 0;
user1.purchased.plan.consecutive.trinkets = 0;
user1.purchased.plan.consecutive.gemCapExtra = 0;
beforeEach(async () => {
user1.purchased.plan.customerId = 'subscribedId';
user1.purchased.plan.dateUpdated = moment().toDate();
user1.purchased.plan.planId = 'basic';
user1.purchased.plan.consecutive.count = 0;
user1.purchased.plan.perkMonthCount = 0;
user1.purchased.plan.consecutive.offset = 0;
user1.purchased.plan.consecutive.trinkets = 0;
user1.purchased.plan.consecutive.gemCapExtra = 0;
});
it('does not increment consecutive benefits after the first month', async () => {
clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(1, 'months')
@@ -271,6 +274,24 @@ describe('cron', async () => {
expect(user1.purchased.plan.consecutive.gemCapExtra).to.equal(0);
});
it('increments consecutive benefits after the second month if they also received a 1 month gift subscription', async () => {
user1.purchased.plan.perkMonthCount = 1;
clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(2, 'months')
.add(2, 'days')
.toDate());
// Add 1 month to simulate what happens a month after the subscription was created.
// Add 2 days so that we're sure we're not affected by any start-of-month effects
// e.g., from time zone oddness.
await cron({
user: user1, tasksByType, daysMissed, analytics,
});
expect(user1.purchased.plan.perkMonthCount).to.equal(0);
expect(user1.purchased.plan.consecutive.count).to.equal(2);
expect(user1.purchased.plan.consecutive.offset).to.equal(0);
expect(user1.purchased.plan.consecutive.trinkets).to.equal(1);
expect(user1.purchased.plan.consecutive.gemCapExtra).to.equal(5);
});
it('increments consecutive benefits after the third month', async () => {
clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(3, 'months')
.add(2, 'days')
@@ -315,6 +336,30 @@ describe('cron', async () => {
expect(user1.purchased.plan.consecutive.trinkets).to.equal(3);
expect(user1.purchased.plan.consecutive.gemCapExtra).to.equal(15);
});
it('initializes plan.perkMonthCount if necessary', async () => {
user.purchased.plan.perkMonthCount = undefined;
clock = sinon.useFakeTimers(moment(user.purchased.plan.dateUpdated)
.utcOffset(0)
.startOf('month')
.add(1, 'months')
.add(2, 'days')
.toDate());
await cron({
user, tasksByType, daysMissed, analytics,
});
expect(user.purchased.plan.perkMonthCount).to.equal(1);
user.purchased.plan.perkMonthCount = undefined;
user.purchased.plan.consecutive.count = 8;
clock.restore();
clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(2, 'months')
.add(2, 'days')
.toDate());
await cron({
user, tasksByType, daysMissed, analytics,
});
expect(user.purchased.plan.perkMonthCount).to.equal(2);
});
});
describe('for a 3-month recurring subscription', async () => {
@@ -330,13 +375,16 @@ describe('cron', async () => {
},
});
// user3 has a 3-month recurring subscription starting today
user3.purchased.plan.customerId = 'subscribedId';
user3.purchased.plan.dateUpdated = moment().toDate();
user3.purchased.plan.planId = 'basic_3mo';
user3.purchased.plan.consecutive.count = 0;
user3.purchased.plan.consecutive.offset = 3;
user3.purchased.plan.consecutive.trinkets = 1;
user3.purchased.plan.consecutive.gemCapExtra = 5;
beforeEach(async () => {
user3.purchased.plan.customerId = 'subscribedId';
user3.purchased.plan.dateUpdated = moment().toDate();
user3.purchased.plan.planId = 'basic_3mo';
user3.purchased.plan.perkMonthCount = 0;
user3.purchased.plan.consecutive.count = 0;
user3.purchased.plan.consecutive.offset = 3;
user3.purchased.plan.consecutive.trinkets = 1;
user3.purchased.plan.consecutive.gemCapExtra = 5;
});
it('does not increment consecutive benefits in the first month of the first paid period that they already have benefits for', async () => {
clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(1, 'months')
@@ -390,6 +438,21 @@ describe('cron', async () => {
expect(user3.purchased.plan.consecutive.gemCapExtra).to.equal(10);
});
it('keeps existing plan.perkMonthCount intact when incrementing consecutive benefits', async () => {
user3.purchased.plan.perkMonthCount = 2;
user3.purchased.plan.consecutive.trinkets = 1;
user3.purchased.plan.consecutive.gemCapExtra = 5;
clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(4, 'months')
.add(2, 'days')
.toDate());
await cron({
user: user3, tasksByType, daysMissed, analytics,
});
expect(user3.purchased.plan.perkMonthCount).to.equal(2);
expect(user3.purchased.plan.consecutive.trinkets).to.equal(2);
expect(user3.purchased.plan.consecutive.gemCapExtra).to.equal(10);
});
it('does not increment consecutive benefits in the second month of the second period that they already have benefits for', async () => {
clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(5, 'months')
.add(2, 'days')
@@ -456,13 +519,16 @@ describe('cron', async () => {
},
});
// user6 has a 6-month recurring subscription starting today
user6.purchased.plan.customerId = 'subscribedId';
user6.purchased.plan.dateUpdated = moment().toDate();
user6.purchased.plan.planId = 'google_6mo';
user6.purchased.plan.consecutive.count = 0;
user6.purchased.plan.consecutive.offset = 6;
user6.purchased.plan.consecutive.trinkets = 2;
user6.purchased.plan.consecutive.gemCapExtra = 10;
beforeEach(async () => {
user6.purchased.plan.customerId = 'subscribedId';
user6.purchased.plan.dateUpdated = moment().toDate();
user6.purchased.plan.planId = 'google_6mo';
user6.purchased.plan.perkMonthCount = 0;
user6.purchased.plan.consecutive.count = 0;
user6.purchased.plan.consecutive.offset = 6;
user6.purchased.plan.consecutive.trinkets = 2;
user6.purchased.plan.consecutive.gemCapExtra = 10;
});
it('does not increment consecutive benefits in the first month of the first paid period that they already have benefits for', async () => {
clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(1, 'months')
@@ -503,6 +569,19 @@ describe('cron', async () => {
expect(user6.purchased.plan.consecutive.gemCapExtra).to.equal(20);
});
it('keeps existing plan.perkMonthCount intact when incrementing consecutive benefits', async () => {
user6.purchased.plan.perkMonthCount = 2;
clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(7, 'months')
.add(2, 'days')
.toDate());
await cron({
user: user6, tasksByType, daysMissed, analytics,
});
expect(user6.purchased.plan.perkMonthCount).to.equal(2);
expect(user6.purchased.plan.consecutive.trinkets).to.equal(4);
expect(user6.purchased.plan.consecutive.gemCapExtra).to.equal(20);
});
it('increments consecutive benefits the month after the third paid period has started', async () => {
clock = sinon.useFakeTimers(moment().utcOffset(0).startOf('month').add(13, 'months')
.add(2, 'days')
+296 -29
View File
@@ -29,8 +29,9 @@ describe('Apple Payments', () => {
.resolves();
iapValidateStub = sinon.stub(iap, 'validate')
.resolves({});
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(true);
iapIsValidatedStub = sinon.stub(iap, 'isValidated').returns(true);
sinon.stub(iap, 'isExpired').returns(false);
sinon.stub(iap, 'isCanceled').returns(false);
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
productId: 'com.habitrpg.ios.Habitica.21gems',
@@ -44,6 +45,8 @@ describe('Apple Payments', () => {
iap.setup.restore();
iap.validate.restore();
iap.isValidated.restore();
iap.isExpired.restore();
iap.isCanceled.restore();
iap.getPurchaseData.restore();
payments.buySkuItem.restore();
gems.validateGiftMessage.restore();
@@ -218,6 +221,7 @@ describe('Apple Payments', () => {
headers = {};
receipt = `{"token": "${token}"}`;
nextPaymentProcessing = moment.utc().add({ days: 2 });
user = new User();
iapSetupStub = sinon.stub(iap, 'setup')
.resolves();
@@ -228,14 +232,17 @@ describe('Apple Payments', () => {
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().subtract({ day: 1 }).toDate(),
purchaseDate: moment.utc().valueOf(),
productId: sku,
transactionId: token,
}, {
expirationDate: moment.utc().add({ day: 1 }).toDate(),
purchaseDate: moment.utc().valueOf(),
productId: 'wrongsku',
transactionId: token,
}, {
expirationDate: moment.utc().add({ day: 1 }).toDate(),
purchaseDate: moment.utc().valueOf(),
productId: sku,
transactionId: token,
}]);
@@ -250,21 +257,12 @@ describe('Apple Payments', () => {
if (payments.createSubscription.restore) payments.createSubscription.restore();
});
it('should throw an error if sku is empty', async () => {
await expect(applePayments.subscribe('', user, receipt, headers, nextPaymentProcessing))
.to.eventually.be.rejected.and.to.eql({
httpCode: 400,
name: 'BadRequest',
message: i18n.t('missingSubscriptionCode'),
});
});
it('should throw an error if receipt is invalid', async () => {
iap.isValidated.restore();
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(false);
await expect(applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing))
await expect(applePayments.subscribe(user, receipt, headers, nextPaymentProcessing))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
@@ -295,13 +293,15 @@ describe('Apple Payments', () => {
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().add({ day: 1 }).toDate(),
expirationDate: moment.utc().add({ day: 2 }).toDate(),
purchaseDate: new Date(),
productId: option.sku,
transactionId: token,
originalTransactionId: token,
}]);
sub = common.content.subscriptionBlocks[option.subKey];
await applePayments.subscribe(option.sku, user, receipt, headers, nextPaymentProcessing);
await applePayments.subscribe(user, receipt, headers, nextPaymentProcessing);
expect(iapSetupStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledOnce;
@@ -321,21 +321,253 @@ describe('Apple Payments', () => {
nextPaymentProcessing,
});
});
if (option !== subOptions[3]) {
const newOption = subOptions[3];
it(`upgrades a subscription from ${option.sku} to ${newOption.sku}`, async () => {
const oldSub = common.content.subscriptionBlocks[option.subKey];
oldSub.logic = 'refundAndRepay';
user.profile.name = 'sender';
user.purchased.plan.paymentMethod = applePayments.constants.PAYMENT_METHOD_APPLE;
user.purchased.plan.customerId = token;
user.purchased.plan.planId = option.subKey;
user.purchased.plan.additionalData = receipt;
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().add({ day: 2 }).toDate(),
purchaseDate: moment.utc().valueOf(),
productId: newOption.sku,
transactionId: `${token}new`,
originalTransactionId: token,
}]);
sub = common.content.subscriptionBlocks[newOption.subKey];
await applePayments.subscribe(user,
receipt,
headers,
nextPaymentProcessing);
expect(iapSetupStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledWith(iap.APPLE, receipt);
expect(iapIsValidatedStub).to.be.calledOnce;
expect(iapIsValidatedStub).to.be.calledWith({});
expect(iapGetPurchaseDataStub).to.be.calledOnce;
expect(paymentsCreateSubscritionStub).to.be.calledOnce;
expect(paymentsCreateSubscritionStub).to.be.calledWith({
user,
customerId: token,
paymentMethod: applePayments.constants.PAYMENT_METHOD_APPLE,
sub,
headers,
additionalData: receipt,
nextPaymentProcessing,
updatedFrom: oldSub,
});
});
}
if (option !== subOptions[0]) {
const newOption = subOptions[0];
it(`downgrades a subscription from ${option.sku} to ${newOption.sku}`, async () => {
const oldSub = common.content.subscriptionBlocks[option.subKey];
user.profile.name = 'sender';
user.purchased.plan.paymentMethod = applePayments.constants.PAYMENT_METHOD_APPLE;
user.purchased.plan.customerId = token;
user.purchased.plan.planId = option.subKey;
user.purchased.plan.additionalData = receipt;
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().add({ day: 2 }).toDate(),
purchaseDate: moment.utc().valueOf(),
productId: newOption.sku,
transactionId: `${token}new`,
originalTransactionId: token,
}]);
sub = common.content.subscriptionBlocks[newOption.subKey];
await applePayments.subscribe(user,
receipt,
headers,
nextPaymentProcessing);
expect(iapSetupStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledWith(iap.APPLE, receipt);
expect(iapIsValidatedStub).to.be.calledOnce;
expect(iapIsValidatedStub).to.be.calledWith({});
expect(iapGetPurchaseDataStub).to.be.calledOnce;
expect(paymentsCreateSubscritionStub).to.be.calledOnce;
expect(paymentsCreateSubscritionStub).to.be.calledWith({
user,
customerId: token,
paymentMethod: applePayments.constants.PAYMENT_METHOD_APPLE,
sub,
headers,
additionalData: receipt,
nextPaymentProcessing,
updatedFrom: oldSub,
});
});
}
});
it('errors when a user is already subscribed', async () => {
payments.createSubscription.restore();
user = new User();
await user.save();
it('uses the most recent subscription data', async () => {
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().add({ day: 4 }).toDate(),
purchaseDate: moment.utc().subtract({ day: 5 }).toDate(),
productId: 'com.habitrpg.ios.habitica.subscription.3month',
transactionId: `${token}oldest`,
originalTransactionId: `${token}evenOlder`,
}, {
expirationDate: moment.utc().add({ day: 2 }).toDate(),
purchaseDate: moment.utc().subtract({ day: 1 }).toDate(),
productId: 'com.habitrpg.ios.habitica.subscription.12month',
transactionId: `${token}newest`,
originalTransactionId: `${token}newest`,
}, {
expirationDate: moment.utc().add({ day: 1 }).toDate(),
purchaseDate: moment.utc().subtract({ day: 2 }).toDate(),
productId: 'com.habitrpg.ios.habitica.subscription.6month',
transactionId: token,
originalTransactionId: token,
}]);
sub = common.content.subscriptionBlocks.basic_12mo;
await applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing);
await applePayments.subscribe(user, receipt, headers, nextPaymentProcessing);
await expect(applePayments.subscribe(sku, user, receipt, headers, nextPaymentProcessing))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: applePayments.constants.RESPONSE_ALREADY_USED,
});
expect(paymentsCreateSubscritionStub).to.be.calledOnce;
expect(paymentsCreateSubscritionStub).to.be.calledWith({
user,
customerId: `${token}newest`,
paymentMethod: applePayments.constants.PAYMENT_METHOD_APPLE,
sub,
headers,
additionalData: receipt,
nextPaymentProcessing,
});
});
describe('does not apply multiple times', async () => {
it('errors when a user is using the same subscription', async () => {
payments.createSubscription.restore();
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().add({ day: 1 }).toDate(),
purchaseDate: moment.utc().toDate(),
productId: sku,
transactionId: token,
originalTransactionId: token,
}]);
await applePayments.subscribe(user, receipt, headers, nextPaymentProcessing);
await expect(applePayments.subscribe(user, receipt, headers, nextPaymentProcessing))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: applePayments.constants.RESPONSE_ALREADY_USED,
});
});
it('errors when a user is using a rebill of the same subscription', async () => {
user = new User();
await user.save();
payments.createSubscription.restore();
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().add({ day: 1 }).toDate(),
purchaseDate: moment.utc().toDate(),
productId: sku,
transactionId: `${token}renew`,
originalTransactionId: token,
}]);
await applePayments.subscribe(user, receipt, headers, nextPaymentProcessing);
await expect(applePayments.subscribe(user, receipt, headers, nextPaymentProcessing))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: applePayments.constants.RESPONSE_ALREADY_USED,
});
});
it('errors when a different user is using the subscription', async () => {
user = new User();
await user.save();
payments.createSubscription.restore();
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().add({ day: 1 }).toDate(),
purchaseDate: moment.utc().toDate(),
productId: sku,
transactionId: token,
originalTransactionId: token,
}]);
await applePayments.subscribe(user, receipt, headers, nextPaymentProcessing);
const secondUser = new User();
await secondUser.save();
await expect(applePayments.subscribe(
secondUser, receipt, headers, nextPaymentProcessing,
))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: applePayments.constants.RESPONSE_ALREADY_USED,
});
});
it('errors when a multiple users exist using the subscription', async () => {
user = new User();
await user.save();
payments.createSubscription.restore();
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().add({ day: 1 }).toDate(),
purchaseDate: moment.utc().toDate(),
productId: sku,
transactionId: token,
originalTransactionId: token,
}]);
await applePayments.subscribe(user, receipt, headers, nextPaymentProcessing);
const secondUser = new User();
secondUser.purchased.plan = user.purchased.plan;
secondUser.purchased.plan.dateTerminate = new Date();
secondUser.save();
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{
expirationDate: moment.utc().add({ day: 1 }).toDate(),
purchaseDate: moment.utc().toDate(),
productId: sku,
transactionId: `${token}new`,
originalTransactionId: token,
}]);
const thirdUser = new User();
await thirdUser.save();
await expect(applePayments.subscribe(
thirdUser, receipt, headers, nextPaymentProcessing,
))
.to.eventually.be.rejected.and.to.eql({
httpCode: 401,
name: 'NotAuthorized',
message: applePayments.constants.RESPONSE_ALREADY_USED,
});
});
});
});
@@ -360,9 +592,9 @@ describe('Apple Payments', () => {
});
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{ expirationDate: expirationDate.toDate() }]);
iapIsValidatedStub = sinon.stub(iap, 'isValidated')
.returns(true);
iapIsValidatedStub = sinon.stub(iap, 'isValidated').returns(true);
sinon.stub(iap, 'isCanceled').returns(false);
sinon.stub(iap, 'isExpired').returns(true);
user = new User();
user.profile.name = 'sender';
user.purchased.plan.paymentMethod = applePayments.constants.PAYMENT_METHOD_APPLE;
@@ -377,6 +609,8 @@ describe('Apple Payments', () => {
iap.setup.restore();
iap.validate.restore();
iap.isValidated.restore();
iap.isExpired.restore();
iap.isCanceled.restore();
iap.getPurchaseData.restore();
payments.cancelSubscription.restore();
});
@@ -396,6 +630,8 @@ describe('Apple Payments', () => {
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{ expirationDate: expirationDate.add({ day: 1 }).toDate() }]);
iap.isExpired.restore();
sinon.stub(iap, 'isExpired').returns(false);
await expect(applePayments.cancelSubscribe(user, headers))
.to.eventually.be.rejected.and.to.eql({
@@ -418,7 +654,38 @@ describe('Apple Payments', () => {
});
});
it('should cancel a user subscription', async () => {
it('should cancel a cancelled subscription with termination date in the future', async () => {
const futureDate = expirationDate.add({ day: 1 });
iap.getPurchaseData.restore();
iapGetPurchaseDataStub = sinon.stub(iap, 'getPurchaseData')
.returns([{ expirationDate: futureDate }]);
iap.isExpired.restore();
sinon.stub(iap, 'isExpired').returns(false);
iap.isCanceled.restore();
sinon.stub(iap, 'isCanceled').returns(true);
await applePayments.cancelSubscribe(user, headers);
expect(iapSetupStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledOnce;
expect(iapValidateStub).to.be.calledWith(iap.APPLE, receipt);
expect(iapIsValidatedStub).to.be.calledOnce;
expect(iapIsValidatedStub).to.be.calledWith({
expirationDate: futureDate,
});
expect(iapGetPurchaseDataStub).to.be.calledOnce;
expect(paymentCancelSubscriptionSpy).to.be.calledOnce;
expect(paymentCancelSubscriptionSpy).to.be.calledWith({
user,
paymentMethod: applePayments.constants.PAYMENT_METHOD_APPLE,
nextBill: futureDate.toDate(),
headers,
});
});
it('should cancel an expired subscription', async () => {
await applePayments.cancelSubscribe(user, headers);
expect(iapSetupStub).to.be.calledOnce;
+799 -2
View File
@@ -203,6 +203,28 @@ describe('payments/index', () => {
expect(recipient.purchased.plan.dateCreated).to.exist;
});
it('sets plan.dateCurrentTypeCreated if it did not previously exist', async () => {
expect(recipient.purchased.plan.dateCurrentTypeCreated).to.not.exist;
await api.createSubscription(data);
expect(recipient.purchased.plan.dateCurrentTypeCreated).to.exist;
});
it('keeps plan.dateCreated when changing subscription type', async () => {
await api.createSubscription(data);
const initialDate = recipient.purchased.plan.dateCreated;
await api.createSubscription(data);
expect(recipient.purchased.plan.dateCreated).to.eql(initialDate);
});
it('sets plan.dateCurrentTypeCreated when changing subscription type', async () => {
await api.createSubscription(data);
const initialDate = recipient.purchased.plan.dateCurrentTypeCreated;
await api.createSubscription(data);
expect(recipient.purchased.plan.dateCurrentTypeCreated).to.not.eql(initialDate);
});
it('does not change plan.customerId if it already exists', async () => {
recipient.purchased.plan = plan;
data.customerId = 'purchaserCustomerId';
@@ -213,6 +235,116 @@ describe('payments/index', () => {
expect(recipient.purchased.plan.customerId).to.eql('customer-id');
});
it('sets plan.perkMonthCount to 1 if user is not subscribed', async () => {
recipient.purchased.plan = plan;
recipient.purchased.plan.perkMonthCount = 1;
recipient.purchased.plan.customerId = undefined;
data.sub.key = 'basic_earned';
data.gift.subscription.key = 'basic_earned';
data.gift.subscription.months = 1;
expect(recipient.purchased.plan.perkMonthCount).to.eql(1);
await api.createSubscription(data);
expect(recipient.purchased.plan.perkMonthCount).to.eql(1);
});
it('sets plan.perkMonthCount to 1 if field is not initialized', async () => {
recipient.purchased.plan = plan;
recipient.purchased.plan.perkMonthCount = -1;
recipient.purchased.plan.customerId = undefined;
data.sub.key = 'basic_earned';
data.gift.subscription.key = 'basic_earned';
data.gift.subscription.months = 1;
expect(recipient.purchased.plan.perkMonthCount).to.eql(-1);
await api.createSubscription(data);
expect(recipient.purchased.plan.perkMonthCount).to.eql(1);
});
it('sets plan.perkMonthCount to 1 if user had previous count but lapsed subscription', async () => {
recipient.purchased.plan = plan;
recipient.purchased.plan.perkMonthCount = 2;
recipient.purchased.plan.customerId = undefined;
data.sub.key = 'basic_earned';
data.gift.subscription.key = 'basic_earned';
data.gift.subscription.months = 1;
expect(recipient.purchased.plan.perkMonthCount).to.eql(2);
await api.createSubscription(data);
expect(recipient.purchased.plan.perkMonthCount).to.eql(1);
});
it('adds to plan.perkMonthCount if user is already subscribed', async () => {
recipient.purchased.plan = plan;
recipient.purchased.plan.perkMonthCount = 1;
data.sub.key = 'basic_earned';
data.gift.subscription.key = 'basic_earned';
data.gift.subscription.months = 1;
expect(recipient.purchased.plan.perkMonthCount).to.eql(1);
await api.createSubscription(data);
expect(recipient.purchased.plan.perkMonthCount).to.eql(2);
});
it('awards perks if plan.perkMonthCount reaches 3 with existing subscription', async () => {
recipient.purchased.plan = plan;
recipient.purchased.plan.perkMonthCount = 2;
data.sub.key = 'basic_earned';
data.gift.subscription.key = 'basic_earned';
data.gift.subscription.months = 1;
expect(recipient.purchased.plan.perkMonthCount).to.eql(2);
expect(recipient.purchased.plan.consecutive.trinkets).to.eql(0);
expect(recipient.purchased.plan.consecutive.gemCapExtra).to.eql(0);
await api.createSubscription(data);
expect(recipient.purchased.plan.perkMonthCount).to.eql(0);
expect(recipient.purchased.plan.consecutive.trinkets).to.eql(1);
expect(recipient.purchased.plan.consecutive.gemCapExtra).to.eql(5);
});
it('awards perks if plan.perkMonthCount reaches 3 without existing subscription', async () => {
recipient.purchased.plan.perkMonthCount = 0;
expect(recipient.purchased.plan.perkMonthCount).to.eql(0);
expect(recipient.purchased.plan.consecutive.trinkets).to.eql(0);
expect(recipient.purchased.plan.consecutive.gemCapExtra).to.eql(0);
await api.createSubscription(data);
expect(recipient.purchased.plan.perkMonthCount).to.eql(0);
expect(recipient.purchased.plan.consecutive.trinkets).to.eql(1);
expect(recipient.purchased.plan.consecutive.gemCapExtra).to.eql(5);
});
it('awards perks if plan.perkMonthCount reaches 3 without initialized field', async () => {
expect(recipient.purchased.plan.perkMonthCount).to.eql(-1);
expect(recipient.purchased.plan.consecutive.trinkets).to.eql(0);
expect(recipient.purchased.plan.consecutive.gemCapExtra).to.eql(0);
await api.createSubscription(data);
expect(recipient.purchased.plan.perkMonthCount).to.eql(0);
expect(recipient.purchased.plan.consecutive.trinkets).to.eql(1);
expect(recipient.purchased.plan.consecutive.gemCapExtra).to.eql(5);
});
it('awards perks if plan.perkMonthCount goes over 3', async () => {
recipient.purchased.plan = plan;
recipient.purchased.plan.perkMonthCount = 2;
data.sub.key = 'basic_earned';
expect(recipient.purchased.plan.perkMonthCount).to.eql(2);
expect(recipient.purchased.plan.consecutive.trinkets).to.eql(0);
expect(recipient.purchased.plan.consecutive.gemCapExtra).to.eql(0);
await api.createSubscription(data);
expect(recipient.purchased.plan.perkMonthCount).to.eql(2);
expect(recipient.purchased.plan.consecutive.trinkets).to.eql(1);
expect(recipient.purchased.plan.consecutive.gemCapExtra).to.eql(5);
});
it('sets plan.customerId to "Gift" if it does not already exist', async () => {
expect(recipient.purchased.plan.customerId).to.not.exist;
@@ -379,6 +511,7 @@ describe('payments/index', () => {
expect(user.purchased.plan.customerId).to.eql('customer-id');
expect(user.purchased.plan.dateUpdated).to.exist;
expect(user.purchased.plan.gemsBought).to.eql(0);
expect(user.purchased.plan.perkMonthCount).to.eql(0);
expect(user.purchased.plan.paymentMethod).to.eql('Payment Method');
expect(user.purchased.plan.extraMonths).to.eql(0);
expect(user.purchased.plan.dateTerminated).to.eql(null);
@@ -386,6 +519,63 @@ describe('payments/index', () => {
expect(user.purchased.plan.dateCreated).to.exist;
});
it('sets plan.dateCreated if it did not previously exist', async () => {
expect(user.purchased.plan.dateCreated).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.dateCreated).to.exist;
});
it('sets plan.dateCurrentTypeCreated if it did not previously exist', async () => {
expect(user.purchased.plan.dateCurrentTypeCreated).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.dateCurrentTypeCreated).to.exist;
});
it('keeps plan.dateCreated when changing subscription type', async () => {
await api.createSubscription(data);
const initialDate = user.purchased.plan.dateCreated;
await api.createSubscription(data);
expect(user.purchased.plan.dateCreated).to.eql(initialDate);
});
it('sets plan.dateCurrentTypeCreated when changing subscription type', async () => {
await api.createSubscription(data);
const initialDate = user.purchased.plan.dateCurrentTypeCreated;
await api.createSubscription(data);
expect(user.purchased.plan.dateCurrentTypeCreated).to.not.eql(initialDate);
});
it('keeps plan.perkMonthCount when changing subscription type', async () => {
await api.createSubscription(data);
user.purchased.plan.perkMonthCount = 2;
await api.createSubscription(data);
expect(user.purchased.plan.perkMonthCount).to.eql(2);
});
it('sets plan.perkMonthCount to zero when creating new monthly subscription', async () => {
user.purchased.plan.perkMonthCount = 2;
await api.createSubscription(data);
expect(user.purchased.plan.perkMonthCount).to.eql(0);
});
it('sets plan.perkMonthCount to zero when creating new 3 month subscription', async () => {
user.purchased.plan.perkMonthCount = 2;
await api.createSubscription(data);
expect(user.purchased.plan.perkMonthCount).to.eql(0);
});
it('updates plan.consecutive.offset when changing subscription type', async () => {
await api.createSubscription(data);
expect(user.purchased.plan.consecutive.offset).to.eql(3);
data.sub.key = 'basic_6mo';
await api.createSubscription(data);
expect(user.purchased.plan.consecutive.offset).to.eql(6);
});
it('awards the Royal Purple Jackalope pet', async () => {
await api.createSubscription(data);
@@ -465,6 +655,89 @@ describe('payments/index', () => {
},
});
});
context('Upgrades subscription', () => {
it('from basic_earned to basic_6mo', async () => {
data.sub.key = 'basic_earned';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.customerId).to.eql('customer-id');
const created = user.purchased.plan.dateCreated;
const updated = user.purchased.plan.dateUpdated;
data.sub.key = 'basic_6mo';
data.updatedFrom = { key: 'basic_earned' };
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.dateCreated).to.eql(created);
expect(user.purchased.plan.dateUpdated).to.not.eql(updated);
expect(user.purchased.plan.customerId).to.eql('customer-id');
});
it('from basic_3mo to basic_12mo', async () => {
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_3mo');
expect(user.purchased.plan.customerId).to.eql('customer-id');
const created = user.purchased.plan.dateCreated;
const updated = user.purchased.plan.dateUpdated;
data.sub.key = 'basic_12mo';
data.updatedFrom = { key: 'basic_3mo' };
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.dateCreated).to.eql(created);
expect(user.purchased.plan.dateUpdated).to.not.eql(updated);
expect(user.purchased.plan.customerId).to.eql('customer-id');
});
});
context('Downgrades subscription', () => {
it('from basic_6mo to basic_earned', async () => {
data.sub.key = 'basic_6mo';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.customerId).to.eql('customer-id');
const created = user.purchased.plan.dateCreated;
const updated = user.purchased.plan.dateUpdated;
data.sub.key = 'basic_earned';
data.updatedFrom = { key: 'basic_6mo' };
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.dateCreated).to.eql(created);
expect(user.purchased.plan.dateUpdated).to.not.eql(updated);
expect(user.purchased.plan.customerId).to.eql('customer-id');
});
it('from basic_12mo to basic_3mo', async () => {
expect(user.purchased.plan.planId).to.not.exist;
data.sub.key = 'basic_12mo';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.customerId).to.eql('customer-id');
const created = user.purchased.plan.dateCreated;
const updated = user.purchased.plan.dateUpdated;
data.sub.key = 'basic_3mo';
data.updatedFrom = { key: 'basic_12mo' };
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_3mo');
expect(user.purchased.plan.dateCreated).to.eql(created);
expect(user.purchased.plan.dateUpdated).to.not.eql(updated);
expect(user.purchased.plan.customerId).to.eql('customer-id');
});
});
});
context('Block subscription perks', () => {
@@ -488,7 +761,6 @@ describe('payments/index', () => {
it('adds 10 to plan.consecutive.gemCapExtra for 6 month block', async () => {
data.sub.key = 'basic_6mo';
await api.createSubscription(data);
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(10);
@@ -496,7 +768,6 @@ describe('payments/index', () => {
it('adds 20 to plan.consecutive.gemCapExtra for 12 month block', async () => {
data.sub.key = 'basic_12mo';
await api.createSubscription(data);
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(20);
@@ -532,6 +803,532 @@ describe('payments/index', () => {
expect(user.purchased.plan.consecutive.trinkets).to.eql(4);
});
context('Upgrades subscription', () => {
context('Using payDifference logic', () => {
beforeEach(async () => {
data.updatedFrom = { logic: 'payDifference' };
});
it('Adds 10 to plan.consecutive.gemCapExtra from basic_earned to basic_6mo', async () => {
data.sub.key = 'basic_earned';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(0);
data.sub.key = 'basic_6mo';
data.updatedFrom.key = 'basic_earned';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(10);
});
it('Adds 15 to plan.consecutive.gemCapExtra when upgrading from basic_3mo to basic_12mo', async () => {
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_3mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(5);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_3mo';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(20);
});
it('Adds 2 to plan.consecutive.trinkets from basic_earned to basic_6mo', async () => {
data.sub.key = 'basic_earned';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.consecutive.trinkets).to.eql(0);
data.sub.key = 'basic_6mo';
data.updatedFrom.key = 'basic_earned';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
});
it('Adds 2 to plan.consecutive.trinkets when upgrading from basic_6mo to basic_12mo', async () => {
data.sub.key = 'basic_6mo';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_6mo';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(4);
});
it('Adds 3 to plan.consecutive.trinkets when upgrading from basic_3mo to basic_12mo', async () => {
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_3mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(1);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_3mo';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(4);
});
});
context('Using payFull logic', () => {
beforeEach(async () => {
data.updatedFrom = { logic: 'payFull' };
});
it('Adds 10 to plan.consecutive.gemCapExtra from basic_earned to basic_6mo', async () => {
data.sub.key = 'basic_earned';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(0);
data.sub.key = 'basic_6mo';
data.updatedFrom.key = 'basic_earned';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(10);
});
it('Adds 20 to plan.consecutive.gemCapExtra when upgrading from basic_3mo to basic_12mo', async () => {
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_3mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(5);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_3mo';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(25);
});
it('Adds 2 to plan.consecutive.trinkets from basic_earned to basic_6mo', async () => {
data.sub.key = 'basic_earned';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.consecutive.trinkets).to.eql(0);
data.sub.key = 'basic_6mo';
data.updatedFrom.key = 'basic_earned';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
});
it('Adds 4 to plan.consecutive.trinkets when upgrading from basic_6mo to basic_12mo', async () => {
data.sub.key = 'basic_6mo';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_6mo';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(6);
});
it('Adds 4 to plan.consecutive.trinkets when upgrading from basic_3mo to basic_12mo', async () => {
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_3mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(1);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_3mo';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(5);
});
});
context('Using refundAndRepay logic', () => {
let clock;
beforeEach(async () => {
clock = sinon.useFakeTimers(new Date('2022-01-01'));
data.updatedFrom = { logic: 'refundAndRepay' };
});
context('Upgrades within first half of subscription', () => {
it('Adds 10 to plan.consecutive.gemCapExtra from basic_earned to basic_6mo', async () => {
data.sub.key = 'basic_earned';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(0);
data.sub.key = 'basic_6mo';
data.updatedFrom.key = 'basic_earned';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-01-10'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(10);
});
it('Adds 15 to plan.consecutive.gemCapExtra when upgrading from basic_3mo to basic_12mo', async () => {
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_3mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(5);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_3mo';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-02-05'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(20);
});
it('Adds 2 to plan.consecutive.trinkets from basic_earned to basic_6mo', async () => {
data.sub.key = 'basic_earned';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.consecutive.trinkets).to.eql(0);
data.sub.key = 'basic_6mo';
data.updatedFrom.key = 'basic_earned';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-01-08'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
});
it('Adds 3 to plan.consecutive.trinkets when upgrading from basic_3mo to basic_12mo', async () => {
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_3mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(1);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_3mo';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-01-31'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(4);
});
it('Adds 2 to plan.consecutive.trinkets when upgrading from basic_6mo to basic_12mo', async () => {
data.sub.key = 'basic_6mo';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_6mo';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-01-28'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(4);
});
it('Adds 2 to plan.consecutive.trinkets from basic_earned to basic_6mo after initial cycle', async () => {
data.sub.key = 'basic_earned';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.consecutive.trinkets).to.eql(0);
data.sub.key = 'basic_6mo';
data.updatedFrom.key = 'basic_earned';
clock.restore();
clock = sinon.useFakeTimers(new Date('2024-01-08'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
});
it('Adds 2 to plan.consecutive.trinkets when upgrading from basic_6mo to basic_12mo after initial cycle', async () => {
data.sub.key = 'basic_6mo';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_6mo';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-08-28'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(4);
});
it('Adds 3 to plan.consecutive.trinkets when upgrading from basic_3mo to basic_12mo after initial cycle', async () => {
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_3mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(1);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_3mo';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-07-31'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(4);
});
});
context('Upgrades within second half of subscription', () => {
it('Adds 10 to plan.consecutive.gemCapExtra from basic_earned to basic_6mo', async () => {
data.sub.key = 'basic_earned';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(0);
data.sub.key = 'basic_6mo';
data.updatedFrom.key = 'basic_earned';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-01-20'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(10);
});
it('Adds 20 to plan.consecutive.gemCapExtra when upgrading from basic_3mo to basic_12mo', async () => {
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_3mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(5);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_3mo';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-02-24'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(25);
});
it('Adds 2 to plan.consecutive.trinkets from basic_earned to basic_6mo', async () => {
data.sub.key = 'basic_earned';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.consecutive.trinkets).to.eql(0);
data.sub.key = 'basic_6mo';
data.updatedFrom.key = 'basic_earned';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-01-28'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
});
it('Adds 4 to plan.consecutive.trinkets when upgrading from basic_6mo to basic_12mo', async () => {
data.sub.key = 'basic_6mo';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_6mo';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-05-28'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(6);
});
it('Adds 4 to plan.consecutive.trinkets when upgrading from basic_3mo to basic_12mo', async () => {
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_3mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(1);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_3mo';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-03-03'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(5);
});
it('Adds 2 to plan.consecutive.trinkets from basic_earned to basic_6mo after initial cycle', async () => {
data.sub.key = 'basic_earned';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.consecutive.trinkets).to.eql(0);
data.sub.key = 'basic_6mo';
data.updatedFrom.key = 'basic_earned';
clock.restore();
clock = sinon.useFakeTimers(new Date('2022-05-28'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
});
it('Adds 4 to plan.consecutive.trinkets when upgrading from basic_6mo to basic_12mo after initial cycle', async () => {
data.sub.key = 'basic_6mo';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_6mo';
clock.restore();
clock = sinon.useFakeTimers(new Date('2023-05-28'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(6);
});
it('Adds 4 to plan.consecutive.trinkets when upgrading from basic_3mo to basic_12mo after initial cycle', async () => {
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_3mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(1);
data.sub.key = 'basic_12mo';
data.updatedFrom.key = 'basic_3mo';
clock.restore();
clock = sinon.useFakeTimers(new Date('2023-09-03'));
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(5);
});
});
afterEach(async () => {
if (clock !== null) clock.restore();
});
});
});
context('Downgrades subscription', () => {
it('does not remove from plan.consecutive.gemCapExtra from basic_6mo to basic_earned', async () => {
data.sub.key = 'basic_6mo';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(10);
data.sub.key = 'basic_earned';
data.updatedFrom = { key: 'basic_6mo' };
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(10);
});
it('does not remove from plan.consecutive.gemCapExtra from basic_12mo to basic_3mo', async () => {
expect(user.purchased.plan.planId).to.not.exist;
data.sub.key = 'basic_12mo';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(20);
data.sub.key = 'basic_3mo';
data.updatedFrom = { key: 'basic_12mo' };
await api.createSubscription(data);
expect(user.purchased.plan.consecutive.gemCapExtra).to.eql(20);
});
it('does not remove from plan.consecutive.trinkets from basic_6mo to basic_earned', async () => {
data.sub.key = 'basic_6mo';
expect(user.purchased.plan.planId).to.not.exist;
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_6mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
data.sub.key = 'basic_earned';
data.updatedFrom = { key: 'basic_6mo' };
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_earned');
expect(user.purchased.plan.consecutive.trinkets).to.eql(2);
});
it('does not remove from plan.consecutive.trinkets from basic_12mo to basic_3mo', async () => {
expect(user.purchased.plan.planId).to.not.exist;
data.sub.key = 'basic_12mo';
await api.createSubscription(data);
expect(user.purchased.plan.planId).to.eql('basic_12mo');
expect(user.purchased.plan.consecutive.trinkets).to.eql(4);
data.sub.key = 'basic_3mo';
data.updatedFrom = { key: 'basic_12mo' };
await api.createSubscription(data);
expect(user.purchased.plan.consecutive.trinkets).to.eql(4);
});
});
});
context('Mystery Items', () => {
+1 -1
View File
@@ -23,7 +23,7 @@ describe('payments/skuItems', () => {
describe('#gryphatrice', () => {
const sku = 'Pet-Gryphatrice-Jubilant';
it('returns true during birthday week', () => {
clock = sinon.useFakeTimers(new Date('2023-01-29'));
clock = sinon.useFakeTimers(new Date('2023-01-31'));
expect(canBuySkuItem(sku, user)).to.be.true;
});
it('returns false outside of birthday week', () => {
+7 -6
View File
@@ -1359,6 +1359,7 @@ describe('Group Model', () => {
describe('#sendChat', () => {
beforeEach(() => {
sandbox.spy(User, 'update');
sandbox.spy(User, 'updateMany');
});
it('formats message', () => {
@@ -1413,8 +1414,8 @@ describe('Group Model', () => {
it('updates users about new messages in party', () => {
party.sendChat({ message: 'message' });
expect(User.update).to.be.calledOnce;
expect(User.update).to.be.calledWithMatch({
expect(User.updateMany).to.be.calledOnce;
expect(User.updateMany).to.be.calledWithMatch({
'party._id': party._id,
_id: { $ne: '' },
});
@@ -1427,8 +1428,8 @@ describe('Group Model', () => {
group.sendChat({ message: 'message' });
expect(User.update).to.be.calledOnce;
expect(User.update).to.be.calledWithMatch({
expect(User.updateMany).to.be.calledOnce;
expect(User.updateMany).to.be.calledWithMatch({
guilds: group._id,
_id: { $ne: '' },
});
@@ -1437,8 +1438,8 @@ describe('Group Model', () => {
it('does not send update to user that sent the message', () => {
party.sendChat({ message: 'message', user: { _id: 'user-id', profile: { name: 'user' } } });
expect(User.update).to.be.calledOnce;
expect(User.update).to.be.calledWithMatch({
expect(User.updateMany).to.be.calledOnce;
expect(User.updateMany).to.be.calledWithMatch({
'party._id': party._id,
_id: { $ne: 'user-id' },
});
@@ -66,7 +66,7 @@ describe('POST /groups/:id/chat/:id/clearflags', () => {
type: 'party',
privacy: 'private',
},
members: 1,
members: 2,
});
await members[0].update({ 'auth.timestamps.created': new Date('2022-01-01') });
@@ -76,12 +76,17 @@ describe('POST /groups/:id/chat/:id/clearflags', () => {
await admin.post(`/groups/${group._id}/chat/${privateMessage.id}/flag`);
// first test that the flag was actually successful
// author always sees own message; flag count is hidden from non-admins
let messages = await members[0].get(`/groups/${group._id}/chat`);
expect(messages[0].flagCount).to.eql(5);
expect(messages[0].flagCount).to.eql(0);
messages = await members[1].get(`/groups/${group._id}/chat`);
expect(messages.length).to.eql(0);
// admin cannot directly request private group chat, but after unflag,
// message should be revealed again and still have flagCount of 0
await admin.post(`/groups/${group._id}/chat/${privateMessage.id}/clearflags`);
messages = await members[0].get(`/groups/${group._id}/chat`);
messages = await members[1].get(`/groups/${group._id}/chat`);
expect(messages.length).to.eql(1);
expect(messages[0].flagCount).to.eql(0);
});
@@ -45,11 +45,10 @@ describe('payments : apple #subscribe', () => {
});
expect(subscribeStub).to.be.calledOnce;
expect(subscribeStub.args[0][0]).to.eql(sku);
expect(subscribeStub.args[0][1]._id).to.eql(user._id);
expect(subscribeStub.args[0][2]).to.eql('receipt');
expect(subscribeStub.args[0][3]['x-api-key']).to.eql(user.apiToken);
expect(subscribeStub.args[0][3]['x-api-user']).to.eql(user._id);
expect(subscribeStub.args[0][0]._id).to.eql(user._id);
expect(subscribeStub.args[0][1]).to.eql('receipt');
expect(subscribeStub.args[0][2]['x-api-key']).to.eql(user.apiToken);
expect(subscribeStub.args[0][2]['x-api-user']).to.eql(user._id);
});
});
});
@@ -35,13 +35,6 @@ describe('GET /world-state', () => {
});
});
it('returns a string representing the current season for NPC sprites', async () => {
const res = await requester().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);
+12
View File
@@ -215,6 +215,7 @@ describe('cron utility functions', () => {
it('monthly plan, next date in 3 months', () => {
const user = baseUserData(60, 0, 'group_plan_auto');
user.purchased.plan.perkMonthCount = 0;
const planContext = getPlanContext(user, now);
@@ -224,6 +225,7 @@ describe('cron utility functions', () => {
it('monthly plan, next date in 1 month', () => {
const user = baseUserData(62, 0, 'group_plan_auto');
user.purchased.plan.perkMonthCount = 2;
const planContext = getPlanContext(user, now);
@@ -248,5 +250,15 @@ describe('cron utility functions', () => {
expect(planContext.nextHourglassDate)
.to.be.sameMoment('2022-07-10T02:00:00.144Z');
});
it('multi-month plan with perk count', () => {
const user = baseUserData(60, 1, 'basic_3mo');
user.purchased.plan.perkMonthCount = 2;
const planContext = getPlanContext(user, now);
expect(planContext.nextHourglassDate)
.to.be.sameMoment('2022-07-10T02:00:00.144Z');
});
});
});
@@ -12,8 +12,9 @@ const webhookData = {};
app.use(bodyParser.urlencoded({
extended: true,
limit: '10mb',
}));
app.use(bodyParser.json());
app.use(bodyParser.json({ limit: '10mb' }));
app.post('/webhooks/:id', (req, res) => {
const { id } = req.params;
+73 -88
View File
@@ -4979,9 +4979,9 @@
}
},
"@sideway/formula": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz",
"integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg=="
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz",
"integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg=="
},
"@sideway/pinpoint": {
"version": "2.0.0",
@@ -13318,11 +13318,34 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"emojis-list": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
"optional": true
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"optional": true
},
"is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
},
"loader-utils": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"optional": true,
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@@ -13354,6 +13377,38 @@
"ansi-regex": "^5.0.1"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"optional": true,
"requires": {
"has-flag": "^4.0.0"
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.3",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
"optional": true,
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
},
"dependencies": {
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"optional": true,
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
}
}
},
"wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
@@ -17903,9 +17958,9 @@
}
},
"dompurify": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.1.tgz",
"integrity": "sha512-ewwFzHzrrneRjxzmK6oVz/rZn9VWspGFRDb4/rRtIsM1n36t9AKma/ye8syCpcw+XJ25kOK/hOG7t1j2I2yBqA=="
"version": "2.4.3",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.3.tgz",
"integrity": "sha512-q6QaLcakcRjebxjg8/+NP+h0rPfatOgOzc46Fst9VAA3jF2ApfKBNKMzdP4DYTqtUMXSCd5pRS/8Po/OmoCHZQ=="
},
"domutils": {
"version": "1.7.0",
@@ -20652,9 +20707,9 @@
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
},
"hellojs": {
"version": "1.19.5",
"resolved": "https://registry.npmjs.org/hellojs/-/hellojs-1.19.5.tgz",
"integrity": "sha512-hFlublej5rHFWjGe6MMMmj78otSIXBbrfvtWPZSSRmXKFoLMFlL41PJ1JPS8xwiSIZca2ve8uHoPZUDwU+/8gg=="
"version": "1.20.0",
"resolved": "https://registry.npmjs.org/hellojs/-/hellojs-1.20.0.tgz",
"integrity": "sha512-zfZGRt0J0OpJHnw2GJz4uh+rzMNAMWpIymiaRbSmCqCvqDMLSx2/qR5JucqnHPsZHUEjyKj5aLJ8K54kyHHjLQ=="
},
"hex-color-regex": {
"version": "1.1.0",
@@ -28120,9 +28175,9 @@
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
},
"stopword": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/stopword/-/stopword-2.0.5.tgz",
"integrity": "sha512-MgmxgmVs0Uo9G4mMqRc/QBXdPePZUnVNYqnNiv8QdCXTqHmGRw36mrjToCeNxhu/7Ifa7RxAtd/KR/GLZdnN9g=="
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/stopword/-/stopword-2.0.7.tgz",
"integrity": "sha512-s+uLKAxrproCLrq0Wcd3JAIjlJLx6l80b2Rzt0u8+ra5SzGkHnNG8PS3DfGmYk2TrKePDVLL4SdKYwKpgSLc+w=="
},
"store2": {
"version": "2.10.0",
@@ -29770,9 +29825,9 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
},
"ua-parser-js": {
"version": "0.7.31",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.31.tgz",
"integrity": "sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ=="
"version": "0.7.33",
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.33.tgz",
"integrity": "sha512-s8ax/CeZdK9R/56Sui0WM6y9OFREJarMRHqLB2EwkovemBxNQ+Bqu8GAsUnVcXKgphb++ghr/B2BZx4mahujPw=="
},
"uc.micro": {
"version": "1.0.6",
@@ -30240,9 +30295,9 @@
}
},
"validator": {
"version": "13.7.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.7.0.tgz",
"integrity": "sha512-nYXQLCBkpJ8X6ltALua9dRrZDHVYxjJ1wgskNt1lH9fzGjs3tgojGSCBjmEPwkWS1y29+DrizMTW19Pr9uB2nw=="
"version": "13.9.0",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz",
"integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA=="
},
"vary": {
"version": "1.1.2",
@@ -30574,76 +30629,6 @@
}
}
},
"vue-loader-v16": {
"version": "npm:vue-loader@16.8.3",
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
"integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
"requires": {
"chalk": "^4.1.0",
"hash-sum": "^2.0.0",
"loader-utils": "^2.0.0"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "^2.0.1"
}
},
"chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"requires": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
}
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"emojis-list": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q=="
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"loader-utils": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"requires": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
"json5": "^2.1.2"
}
},
"supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
"vue-mugen-scroll": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/vue-mugen-scroll/-/vue-mugen-scroll-0.2.6.tgz",
+4 -4
View File
@@ -33,13 +33,13 @@
"bootstrap-vue": "^2.23.1",
"chai": "^4.3.7",
"core-js": "^3.27.2",
"dompurify": "^2.4.1",
"dompurify": "^2.4.3",
"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.19.5",
"hellojs": "^1.20.0",
"inspectpack": "^4.7.1",
"intro.js": "^6.0.0",
"jquery": "^3.6.3",
@@ -49,13 +49,13 @@
"sass": "^1.34.0",
"sass-loader": "^8.0.2",
"smartbanner.js": "^1.19.1",
"stopword": "^2.0.5",
"stopword": "^2.0.7",
"svg-inline-loader": "^0.8.2",
"svg-url-loader": "^7.1.1",
"svgo": "^1.3.2",
"svgo-loader": "^2.2.1",
"uuid": "^8.3.2",
"validator": "^13.7.0",
"validator": "^13.9.0",
"vue": "^2.7.10",
"vue-cli-plugin-storybook": "2.1.0",
"vue-mugen-scroll": "^0.2.6",
+3
View File
@@ -35,6 +35,7 @@
<sub-canceled-modal v-if="isUserLoaded" />
<bug-report-modal v-if="isUserLoaded" />
<bug-report-success-modal v-if="isUserLoaded" />
<external-link-modal />
<birthday-modal />
<snackbars />
<router-view v-if="!isUserLoggedIn || isStaticPage" />
@@ -175,6 +176,7 @@ import amazonPaymentsModal from '@/components/payments/amazonModal';
import paymentsSuccessModal from '@/components/payments/successModal';
import subCancelModalConfirm from '@/components/payments/cancelModalConfirm';
import subCanceledModal from '@/components/payments/canceledModal';
import externalLinkModal from '@/components/externalLinkModal.vue';
import spellsMixin from '@/mixins/spells';
import {
@@ -210,6 +212,7 @@ export default {
subCanceledModal,
bugReportModal,
bugReportSuccessModal,
externalLinkModal,
},
mixins: [notifications, spellsMixin],
data () {
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

+6 -2
View File
@@ -19,8 +19,12 @@
top: -16px !important;
}
.Pet.Pet-FlyingPig-Veggie, .Pet.Pet-FlyingPig-Dessert, .Pet.Pet-FlyingPig-VirtualPet {
top: -28px !important;
$foolPets: Veggie, Dessert, VirtualPet, TeaShop;
@each $foolPet in $foolPets {
.Pet.Pet-FlyingPig-#{$foolPet} {
top: -28px !important;
}
}
.Pet[class*="Virtual"] {
@@ -50,10 +50,7 @@ h3.markdown {
}
a {
color: $blue-10;
&:hover, &:active, &:focus {
color: $blue-10;
text-decoration: underline;
}
}
+9 -11
View File
@@ -26,19 +26,17 @@ a:not([href]), a:not([href]):hover {
a, a:not([href]):not([tabindex]) {
cursor: pointer;
color: $purple-300;
&.standard-link {
color: $blue-10;
&:hover, &:active, &:focus {
text-decoration: underline;
color: $purple-300;
}
&:hover, &:active, &:focus {
text-decoration: underline;
}
&[disabled="disabled"] {
color: $gray-300;
text-decoration: none;
cursor: default;
}
&[disabled="disabled"] {
color: $gray-300;
text-decoration: none;
cursor: default;
}
&.small-link {
@@ -46,6 +46,10 @@
Perk offset months:
<strong>{{ hero.purchased.plan.consecutive.offset }}</strong>
</div>
<div>
Perk month count:
<strong>{{ hero.purchased.plan.perkMonthCount }}</strong>
</div>
<div>
Next Mystic Hourglass:
<strong>{{ nextHourglassDate }}</strong>
@@ -149,7 +153,7 @@ export default {
nextHourglassDate () {
const currentPlanContext = getPlanContext(this.hero, new Date());
return currentPlanContext.nextHourglassDate.format('MMMM');
return currentPlanContext.nextHourglassDate.format('MMMM YYYY');
},
},
methods: {
+11 -16
View File
@@ -86,6 +86,13 @@
>{{ $t('companyContribute') }}
</a>
</li>
<li>
<a
href="https://translate.habitica.com/"
target="_blank"
>{{ $t('translateHabitica') }}
</a>
</li>
</ul>
</div>
<!-- Support -->
@@ -101,6 +108,7 @@
v-if="user"
>
<a
href=""
target="_blank"
@click.prevent="openBugReportModal()"
>
@@ -205,7 +213,7 @@
</a>
<a
class="social-circle"
href="https://twitter.com/habitica"
href="https://twitter.com/habitica/"
target="_blank"
>
<div
@@ -215,7 +223,7 @@
</a>
<a
class="social-circle"
href="https://www.facebook.com/Habitica"
href="https://www.facebook.com/Habitica/"
target="_blank"
>
<div
@@ -472,10 +480,6 @@ footer {
color: $purple-300;
text-decoration: underline;
}
a:not([href]):not([class]):hover { // needed to make "report a bug"'s hover state correct
color: $purple-300;
text-decoration: underline;
}
column-gap: 1.5rem;
display: grid;
@@ -675,11 +679,6 @@ h3 {
footer {
padding: 24px 16px;
a:not([href]):not([class]):hover { // needed to make "report a bug"'s hover state correct
color: $purple-300;
text-decoration: underline;
}
column-gap: 1.5rem;
display: grid;
grid-template-areas:
@@ -719,10 +718,6 @@ h3 {
@media (max-width: 1024px) and (min-width: 768px) {
footer {
padding: 24px 24px;
a:not([href]):not([class]):hover { // needed to make "report a bug"'s hover state correct
color: $purple-300;
text-decoration: underline;
}
}
.desktop {
@@ -815,7 +810,7 @@ export default {
...mapState({ user: 'user.data' }),
...mapState(['isUserLoaded']),
getDataDisplayToolUrl () {
const base = 'https://oldgods.net/habitrpg/habitrpg_user_data_display.html';
const base = 'https://tools.habitica.com/';
if (!this.user) return null;
return `${base}?uuid=${this.user._id}`;
},
+1 -1
View File
@@ -244,7 +244,7 @@ export default {
petClass () {
if (some(
this.currentEventList,
event => moment().isBetween(event.start, event.end) && event.aprilFools && event.aprilFools === 'virtual',
event => moment().isBetween(event.start, event.end) && event.aprilFools && event.aprilFools === 'teaShop',
)) {
return this.foolPet(this.member.items.currentPet);
}
@@ -159,7 +159,6 @@ label {
}
.cancel-link {
color: $blue-10;
line-height: 1.71;
}
@@ -107,7 +107,6 @@ label {
}
.cancel-link {
color: $blue-10;
line-height: 1.71;
}
@@ -322,6 +322,7 @@ import omit from 'lodash/omit';
import { v4 as uuid } from 'uuid';
import { userStateMixin } from '../../mixins/userState';
import externalLinks from '../../mixins/externalLinks';
import memberSearchDropdown from '@/components/members/memberSearchDropdown';
import closeChallengeModal from './closeChallengeModal';
import Column from '../tasks/column';
@@ -358,7 +359,7 @@ export default {
userLink,
groupLink,
},
mixins: [challengeMemberSearchMixin, userStateMixin],
mixins: [challengeMemberSearchMixin, externalLinks, userStateMixin],
props: ['challengeId'],
data () {
return {
@@ -414,6 +415,10 @@ export default {
mounted () {
if (!this.searchId) this.searchId = this.challengeId;
if (!this.challenge._id) this.loadChallenge();
this.handleExternalLinks();
},
updated () {
this.handleExternalLinks();
},
async beforeRouteUpdate (to, from, next) {
this.searchId = to.params.challengeId;
@@ -120,6 +120,7 @@ import { mapState } from '@/libs/store';
import Sidebar from './sidebar';
import ChallengeItem from './challengeItem';
import challengeModal from './challengeModal';
import externalLinks from '@/mixins/externalLinks';
import challengeUtilities from '@/mixins/challengeUtilities';
import positiveIcon from '@/assets/svg/positive.svg';
@@ -131,7 +132,7 @@ export default {
challengeModal,
MugenScroll,
},
mixins: [challengeUtilities],
mixins: [challengeUtilities, externalLinks],
data () {
return {
loading: true,
@@ -177,6 +178,10 @@ export default {
section: this.$t('challenges'),
});
this.loadChallenges();
this.handleExternalLinks();
},
updated () {
this.handleExternalLinks();
},
methods: {
updateSearch (eventData) {
@@ -81,6 +81,8 @@ import challengeModal from './challengeModal';
import { mapState } from '@/libs/store';
import markdownDirective from '@/directives/markdown';
import externalLinks from '../../mixins/externalLinks';
import challengeItem from './challengeItem';
import challengeIcon from '@/assets/svg/challenge.svg';
@@ -92,6 +94,7 @@ export default {
directives: {
markdown: markdownDirective,
},
mixins: [externalLinks],
props: ['group'],
data () {
return {
@@ -118,6 +121,10 @@ export default {
},
mounted () {
this.loadChallenges();
this.handleExternalLinks();
},
updated () {
this.handleExternalLinks();
},
methods: {
async loadChallenges () {
@@ -145,6 +145,7 @@ import Sidebar from './sidebar';
import ChallengeItem from './challengeItem';
import challengeModal from './challengeModal';
import challengeUtilities from '@/mixins/challengeUtilities';
import externalLinks from '@/mixins/externalLinks';
import challengeIcon from '@/assets/svg/challenge.svg';
import positiveIcon from '@/assets/svg/positive.svg';
@@ -156,7 +157,7 @@ export default {
challengeModal,
MugenScroll,
},
mixins: [challengeUtilities],
mixins: [challengeUtilities, externalLinks],
data () {
return {
icons: Object.freeze({
@@ -203,6 +204,10 @@ export default {
section: this.$t('challenges'),
});
this.loadChallenges();
this.handleExternalLinks();
},
updated () {
this.handleExternalLinks();
},
methods: {
updateSearch (eventData) {
@@ -77,7 +77,6 @@
}
a.cancel-link {
color: $blue-10;
margin-right: .5em;
}
@@ -0,0 +1,209 @@
<template>
<b-modal
id="external-link-modal"
size="md"
>
<!-- HEADER -->
<div slot="modal-header">
<div
class="modal-close"
@click="close()"
>
<div
class="icon-close"
v-html="icons.close"
>
</div>
</div>
<div class="exclamation-container d-flex align-items-center justify-content-center">
<div
v-once
class="svg-icon svg-exclamation"
v-html="icons.exclamation"
></div>
</div>
<h2>
{{ $t('leaveHabitica') }}
</h2>
</div>
<!-- BODY -->
<div
class="row leave-warning-text"
v-html="$t('leaveHabiticaText')"
>
</div>
<div
class="skip-modal"
>
{{ $t('skipExternalLinkModal') }}
</div>
<!-- FOOTER -->
<div slot="modal-footer">
<button
v-once
class="btn btn-primary"
@click="proceed()"
>
{{ $t('continue') }}
</button>
<div
v-once
class="close-link justify-content-center"
@click="close()"
>
{{ $t('cancel') }}
</div>
</div>
</b-modal>
</template>
<style lang="scss">
@import '~@/assets/scss/colors.scss';
#external-link-modal {
&.modal {
display: flex !important;
}
.modal-md {
max-width: 448px;
min-width: 330px;
margin: auto;
.modal-close {
position: absolute;
right: 12px;
top: 12px;
cursor: pointer;
.icon-close {
width: 16px;
height: 16px;
vertical-align: middle;
& svg {
fill: $yellow-1;
opacity: 0.75;
}
& :hover {
fill: $yellow-1;
opacity: 1;
}
}
}
.modal-content {
background: transparent;
}
.modal-header {
justify-content: center;
padding-top: 32px;
padding-bottom: 0px;
background: $yellow-100;
border-top-right-radius: 8px;
border-top-left-radius: 8px;
border-bottom: none;
.exclamation-container {
width: 64px;
height: 64px;
border-radius: 50%;
background: $yellow-1;
margin: 0 auto;
margin-bottom: 16px;
}
.svg-exclamation {
width: 8px;
color: $white;
}
h2 {
color: $yellow-1;
margin-bottom: 16px;
}
}
.modal-body {
padding: 16px 44px 20px 44px;
background: $white;
.leave-warning-text {
font-size: 0.875rem;
line-height: 1.71;
text-align: center;
margin-top:24px;
}
.skip-modal {
color: $gray-100;
font-size: 0.75rem;
text-align: center;
line-height: 1.33;
margin-top: 16px;
// padding-bottom: 24px;
}
}
.modal-footer {
background: $white;
border-bottom-right-radius: 8px;
border-bottom-left-radius: 8px;
justify-content: center;
border-top: none;
padding-top: 0;
}
.close-link {
color: $purple-300;
line-height: 1.71;
font-size: 0.875rem;
cursor: pointer;
margin-top:16px;
margin-bottom: 8px;
text-align: center;
&:hover {
text-decoration: underline;
}
}
}
}
</style>
<script>
import exclamationIcon from '@/assets/svg/exclamation.svg';
import closeIcon from '@/assets/svg/new-close.svg';
export default {
data () {
return {
icons: Object.freeze({
close: closeIcon,
exclamation: exclamationIcon,
}),
url: '',
};
},
mounted () {
this.$root.$on('habitica:external-link', url => {
this.url = url;
this.$root.$emit('bv::show::modal', 'external-link-modal');
});
},
beforeDestroy () {
this.$root.$off('habitica:external-link');
},
methods: {
close () {
this.$root.$emit('bv::hide::modal', 'external-link-modal');
},
proceed () {
window.open(this.url, '_blank').focus();
this.close();
},
},
};
</script>
@@ -87,6 +87,8 @@
<script>
import debounce from 'lodash/debounce';
import externalLinks from '../../mixins/externalLinks';
import autocomplete from '../chat/autoComplete';
import communityGuidelines from './communityGuidelines';
import chatMessage from '../chat/chatMessages';
@@ -103,6 +105,7 @@ export default {
communityGuidelines,
chatMessage,
},
mixins: [externalLinks],
props: ['label', 'group', 'placeholder'],
data () {
return {
@@ -132,6 +135,10 @@ export default {
},
mounted () {
this.textbox = this.$refs['user-entry'];
this.handleExternalLinks();
},
updated () {
this.handleExternalLinks();
},
methods: {
// https://medium.com/@_jh3y/how-to-where-s-the-caret-getting-the-xy-position-of-the-caret-a24ba372990a
@@ -78,7 +78,6 @@
@import '~@/assets/scss/colors.scss';
a:not([href]) {
color: $blue-10;
font-size: 16px;
}
@@ -245,10 +245,6 @@
text-align: center;
color: $gray-100;
a {
color: $blue-10;
}
}
#quest-detail-modal {
@@ -377,11 +377,9 @@
.members-invited {
min-height: 1rem;
color: $blue-10;
margin: 0;
&:hover, &:focus {
color: $blue-10;
text-decoration: underline;
}
}
@@ -340,12 +340,13 @@
<li>
<a
v-once
href="https://oldgods.net/habitrpg/habitrpg_user_data_display.html"
href="https://tools.habitica.com/"
target="_blank"
>{{ $t('dataDisplayTool') }}</a>
</li>
<li>
<a
href=""
target="_blank"
@click.prevent="openBugReportModal()"
>
@@ -521,21 +522,6 @@
margin-left: .5em;
}
// formats the report a bug link to match the others
a:not([href]) {
&:not([role=button]) {
color: #007bff;
text-decoration: none;
}
}
a:not([href]):hover {
&:not([role=button]) {
color: #0056b3;
text-decoration: underline;
}
}
.tier1-icon, .tier2-icon {
width: 11px;
}
@@ -759,6 +745,7 @@
</style>
<script>
import find from 'lodash/find';
import { mapState } from '@/libs/store';
import { goToModForm } from '@/libs/modform';
@@ -835,22 +822,23 @@ export default {
computed: {
...mapState({
user: 'user.data',
currentEvent: 'worldState.data.currentEvent',
currentEventList: 'worldState.data.currentEventList',
}),
questData () {
if (!this.group.quest) return {};
return quests.quests[this.group.quest.key];
},
imageURLs () {
if (!this.currentEvent || !this.currentEvent.season) {
const currentEvent = find(this.currentEventList, event => Boolean(event.season));
if (!currentEvent) {
return {
background: 'url(/static/npc/normal/tavern_background.png)',
npc: 'url(/static/npc/normal/tavern_npc.png)',
};
}
return {
background: `url(/static/npc/${this.currentEvent.season}/tavern_background.png)`,
npc: `url(/static/npc/${this.currentEvent.season}/tavern_npc.png)`,
background: `url(/static/npc/${currentEvent.season}/tavern_background.png)`,
npc: `url(/static/npc/${currentEvent.season}/tavern_npc.png)`,
};
},
},
@@ -5,7 +5,14 @@
:notification="notification"
>
<div slot="content">
<div v-html="$t('invitedToParty', {party: notification.data.name})"></div>
<div
v-html="$t('invitedToPartyBy', {
userId: notification.data.inviter,
userName: invitingUser.auth ? invitingUser.auth.local.username : null,
party: notification.data.name,
})"
>
</div>
<div class="notifications-buttons">
<div
class="btn btn-small btn-success"
@@ -32,10 +39,31 @@ export default {
components: {
BaseNotification,
},
props: ['notification', 'canRemove'],
props: {
notification: {
type: Object,
default (data) {
return data;
},
},
canRemove: {
type: Boolean,
default: true,
},
},
data () {
return {
invitingUser: {},
};
},
computed: {
...mapState({ user: 'user.data' }),
},
async mounted () {
this.invitingUser = await this.$store.dispatch('members:fetchMember', {
memberId: this.notification.data.inviter,
});
},
methods: {
async accept () {
const group = this.notification.data;
@@ -39,7 +39,7 @@
{{ $t('notifications') }}
</h4>
<a
class="small-link standard-link"
class="small-link"
:disabled="notificationsCount === 0"
@click="dismissAll"
>{{ $t('dismissAll') }}</a>
@@ -879,7 +879,7 @@ export default {
return;
}
if (this.user.preferences.suppressModals.raisePet) {
if (this.user.preferences.suppressModals.hatchPet) {
this.hatchPet(pet);
return;
}
@@ -171,8 +171,9 @@ export default {
getPetItemClass () {
if (this.isOwned() && some(
this.currentEventList,
event => moment().isBetween(event.start, event.end) && event.aprilFools && event.aprilFools === 'virtual',
event => moment().isBetween(event.start, event.end) && event.aprilFools && event.aprilFools === 'teaShop',
)) {
if (this.isSpecial()) return `Pet ${this.foolPet(this.item.key)}`;
const petString = `${this.item.eggKey}-${this.item.key}`;
return `Pet ${this.foolPet(petString)}`;
}
@@ -139,6 +139,8 @@
import axios from 'axios';
import moment from 'moment';
import externalLinks from '../../mixins/externalLinks';
import renderWithMentions from '@/libs/renderWithMentions';
import { mapState } from '@/libs/store';
import userLink from '../userLink';
@@ -150,6 +152,7 @@ export default {
components: {
userLink,
},
mixins: [externalLinks],
filters: {
timeAgo (value) {
return moment(value).fromNow();
@@ -179,6 +182,10 @@ export default {
},
mounted () {
this.$emit('message-card-mounted');
this.handleExternalLinks();
},
updated () {
this.handleExternalLinks();
},
methods: {
report () {
@@ -31,7 +31,6 @@
</button>
<a
v-once
class="standard-link"
@click="close()"
>{{ $t('neverMind') }}</a>
</div>
@@ -180,7 +180,6 @@
@import '~@/assets/scss/colors.scss';
a:not([href]) {
color: $blue-10;
font-size: 0.875rem;
line-height: 1.71;
}
+1 -27
View File
@@ -23,33 +23,7 @@
</div>
<div class="section">
<h3>{{ $t('thirdPartyApps') }}</h3>
<ul>
<li>
<a
target="_blank"
href="https://www.beeminder.com/habitica"
>{{ $t('beeminder') }}</a>
<br>
{{ $t('beeminderDesc') }}
</li>
<li>
<div v-html="$t('chatExtension')">
</div>
<span>{{ $t('chatExtensionDesc') }}</span>
</li>
<li>
<a
target="_blank"
:href="`https://oldgods.net/habitica/habitrpg_user_data_display.html?uuid=` + user._id"
>{{ $t('dataDisplayTool') }}</a>
<br>
{{ $t('dataToolDesc') }}
</li>
<li>
<div v-html="$t('otherExtensions')"></div>
<span>{{ $t('otherDesc') }}</span>
</li>
</ul>
<p v-html="$t('thirdPartyTools')"></p>
<hr>
</div>
</div>
@@ -7,6 +7,38 @@
{{ $t('settings') }}
</h1>
<div class="col-sm-6">
<div class="sleep">
<h5>{{ $t('pauseDailies') }}</h5>
<h4>{{ $t('sleepDescription') }}</h4>
<ul>
<li v-once>
{{ $t('sleepBullet1') }}
</li>
<li v-once>
{{ $t('sleepBullet2') }}
</li>
<li v-once>
{{ $t('sleepBullet3') }}
</li>
</ul>
<button
v-if="!user.preferences.sleep"
v-once
class="sleep btn btn-primary btn-block pause-button"
@click="toggleSleep()"
>
{{ $t('pauseDailies') }}
</button>
<button
v-if="user.preferences.sleep"
v-once
class="btn btn-secondary btn-block pause-button"
@click="toggleSleep()"
>
{{ $t('unpauseDailies') }}
</button>
</div>
<hr>
<div class="form-horizontal">
<h5>{{ $t('language') }}</h5>
<select
@@ -517,6 +549,10 @@
width: 100%;
margin-top: 5px;
}
.sleep {
margin-bottom: 16px;
}
</style>
<script>
@@ -651,6 +687,9 @@ export default {
}
},
methods: {
toggleSleep () {
this.$store.dispatch('user:sleep');
},
validateDisplayName: debounce(function checkName (displayName) {
if (displayName.length <= 1 || displayName === this.user.profile.name) {
this.displayNameIssues = [];
@@ -804,7 +804,7 @@ export default {
return currentPlanContext.nextHourglassDate;
},
nextHourGlass () {
const nextHourglassMonth = this.nextHourGlassDate.format('MMM');
const nextHourglassMonth = this.nextHourGlassDate.format('MMM YYYY');
return nextHourglassMonth;
},
@@ -146,6 +146,7 @@
</style>
<script>
import find from 'lodash/find';
import _filter from 'lodash/filter';
import _map from 'lodash/map';
import _throttle from 'lodash/throttle';
@@ -225,7 +226,7 @@ export default {
user: 'user.data',
userStats: 'user.data.stats',
userItems: 'user.data.items',
currentEvent: 'worldState.data.currentEvent',
currentEventList: 'worldState.data.currentEventList',
}),
market () {
return shops.getMarketShop(this.user);
@@ -292,15 +293,16 @@ export default {
return Object.values(this.viewOptions).some(g => g.selected);
},
imageURLs () {
if (!this.currentEvent || !this.currentEvent.season) {
const currentEvent = find(this.currentEventList, event => Boolean(event.season));
if (!currentEvent) {
return {
background: 'url(/static/npc/normal/market_background.png)',
npc: 'url(/static/npc/normal/market_banner_npc.png)',
};
}
return {
background: `url(/static/npc/${this.currentEvent.season}/market_background.png)`,
npc: `url(/static/npc/${this.currentEvent.season}/market_banner_npc.png)`,
background: `url(/static/npc/${currentEvent.season}/market_background.png)`,
npc: `url(/static/npc/${currentEvent.season}/market_banner_npc.png)`,
};
},
},
@@ -397,6 +397,7 @@
</style>
<script>
import find from 'lodash/find';
import _filter from 'lodash/filter';
import _sortBy from 'lodash/sortBy';
import _throttle from 'lodash/throttle';
@@ -512,7 +513,7 @@ export default {
user: 'user.data',
userStats: 'user.data.stats',
userItems: 'user.data.items',
currentEvent: 'worldState.data.currentEvent',
currentEventList: 'worldState.data.currentEventList',
}),
shop () {
return shops.getQuestShop(this.user);
@@ -536,15 +537,16 @@ export default {
return Object.values(this.viewOptions).some(g => g.selected);
},
imageURLs () {
if (!this.currentEvent || !this.currentEvent.season) {
const currentEvent = find(this.currentEventList, event => Boolean(event.season));
if (!currentEvent) {
return {
background: 'url(/static/npc/normal/quest_shop_background.png)',
npc: 'url(/static/npc/normal/quest_shop_npc.png)',
};
}
return {
background: `url(/static/npc/${this.currentEvent.season}/quest_shop_background.png)`,
npc: `url(/static/npc/${this.currentEvent.season}/quest_shop_npc.png)`,
background: `url(/static/npc/${currentEvent.season}/quest_shop_background.png)`,
npc: `url(/static/npc/${currentEvent.season}/quest_shop_npc.png)`,
};
},
},
@@ -2,7 +2,7 @@
<div class="container-fluid">
<h1>{{ $t('communityGuidelines') }}</h1>
<hr>
<p>{{ $t('lastUpdated') }} July 28, 2021</p>
<p>{{ $t('lastUpdated') }} February 8, 2023</p>
<h2 id="welcome">
{{ $t('commGuideHeadingWelcome') }}
</h2>
@@ -21,6 +21,7 @@
<p v-html="$t('commGuidePara016')"></p>
<p v-html="$t('commGuidePara017')"></p>
<ul>
<li v-html="$t('commGuideList01F')"></li>
<li v-html="$t('commGuideList01A')"></li>
<li v-html="$t('commGuideList01B')"></li>
<li v-html="$t('commGuideList01C')"></li>
@@ -32,6 +33,7 @@
<img src="~@/assets/images/community-guidelines/publicSpaces.png">
</div>
<ul>
<li v-html="$t('commGuideList02N')"></li>
<li v-html="$t('commGuideList02A')"></li>
<li v-html="$t('commGuideList02B')"></li>
<li v-html="$t('commGuideList02G')"></li>
@@ -147,10 +149,9 @@
<li>
{{ $t('commGuideList10A') }}
<ul>
<li>{{ $t('commGuideList10A1') }}</li>
<li v-html="$t('commGuideList10A1')"></li>
</ul>
</li>
<li v-html="$t('commGuideList10C')"></li>
<li v-html="$t('commGuideList10D')"></li>
<li v-html="$t('commGuideList10F')"></li>
</ul>
@@ -176,50 +177,53 @@
<h2 id="meet-the-mods">
{{ $t('commGuideHeadingMeet') }}
</h2>
<p v-html="$t('commGuidePara006')"></p>
<p v-html="$t('commGuidePara007')"></p>
<p v-html="$t('commGuidePara008')"></p>
<p v-html="$t('commGuidePara009')"></p>
<div class="media align-items-center">
<img src="~@/assets/images/community-guidelines/staff.png">
<div class="media-body">
<ul>
<li>{{ $t('commGuideAKA', {habitName: 'Viirus', realName: 'Phillip'}) }}</li>
<li>
{{ $t('commGuideAKA', {habitName: 'heyeilatan', realName: 'Natalie'}) }}
({{ $t('commGuideOnGitHub', {gitHubName: 'CuriousMagpie'}) }})
- Web Developer
</li>
<li>
{{ $t('commGuideAKA', {habitName: 'Viirus', realName: 'Phillip'}) }}
- Mobile Developer
</li>
<li>
{{ $t('commGuideAKA', {habitName: 'redphoenix', realName: 'Vicky'}) }}
({{ $t('commGuideOnGitHub', {gitHubName: 'veeeeeee'}) }})
- Co-Founder
</li>
<li>
{{ $t('commGuideAKA', {habitName: 'Beffymaroo', realName: 'Beth'}) }}
- Art, Community Management, Many Hats
</li>
<li>
{{ $t('commGuideAKA', {habitName: 'SabreCat', realName: 'Sabe'}) }}
- Web Developer
</li>
<li>
{{ $t('commGuideAKA', {habitName: 'Apollo', realName: 'Tressley'}) }}
- Designer
</li>
<li>
{{ $t('commGuideAKA', {habitName: 'Piyo', realName: 'Sara'}) }}
- Mobile Designer
</li>
<li>{{ $t('commGuideAKA', {habitName: 'Beffymaroo', realName: 'Beth'}) }}</li>
<li>{{ $t('commGuideAKA', {habitName: 'SabreCat', realName: 'Sabe'}) }}</li>
<li>{{ $t('commGuideAKA', {habitName: 'Apollo', realName: 'Tressley'}) }}</li>
<li>{{ $t('commGuideAKA', {habitName: 'Piyo', realName: 'Sara'}) }}</li>
</ul>
</div>
</div>
<p v-html="$t('commGuidePara010')"></p>
<div class="media align-items-center">
<img src="~@/assets/images/community-guidelines/moderators.png">
<div class="media-body">
<p v-html="$t('commGuidePara011')"></p>
<ul>
<li>Dewines</li>
<li>Nakonana</li>
<li>Cantras</li>
<li>Alys (LadyAlys {{ $t('commGuidePara011c') }})</li>
<li>Fox_town</li>
<li>MaybeSteveRogers</li>
<li>shanaqui</li>
<li>deilann (not yet pictured)</li>
</ul>
</div>
</div>
<p v-html="$t('commGuidePara012')"></p>
<p v-html="$t('commGuidePara013')"></p>
<p>
{{ $t('commGuidePara014') }}<br>
<em>
Lemoness, lefnire, Slappybag, litenull, Shaner, Bobbyroberts99, wc8,
Breadstrings, Megan, Blade, and Daniel the Bard
Breadstrings, Megan, Blade, Daniel the Bard, deilann, shanaqui, Nakonana,
Dewines, Alys, Fox_town, MaybeSteveRogers, and Cantras.
</em>
</p>
<h2 id="final">
@@ -240,6 +244,7 @@
</ul>
<p v-html="$t('commGuidePara069')"></p>
<ul class="list-2col list-unstyled">
<li>Beffymaroo</li>
<li>Breadstrings</li>
<li>Draayder</li>
<li>Kiwibot</li>
@@ -354,6 +354,9 @@
<style lang='scss'>
@import '~@/assets/scss/static.scss';
#front .form-text a {
color: $white !important;
}
</style>
<style lang="scss" scoped>
@@ -362,10 +365,6 @@
@import url('https://fonts.googleapis.com/css?family=Varela+Round');
#front {
.form-text a {
color: $white !important;
}
.container-fluid {
margin: 0;
}
@@ -165,10 +165,6 @@ export default {
question: 'pkQuestion7',
answer: 'pkAnswer7',
},
{
question: 'pkQuestion8',
answer: 'pkAnswer8',
},
],
});
},
@@ -81,7 +81,6 @@
</span>
<a
v-if="assignedUsersCount > 1 && !showStatus"
class="blue-10"
@click="showStatus = !showStatus"
>
{{ $t('viewStatus') }}
@@ -128,10 +127,6 @@
padding-top: 0.25rem;
z-index: 9;
height: 24px;
.blue-10 {
color: $blue-10;
}
}
.completion-row {
@@ -355,6 +355,7 @@ import Task from './task';
import ClearCompletedTodos from './clearCompletedTodos';
import buyMixin from '@/mixins/buy';
import sync from '@/mixins/sync';
import externalLinks from '@/mixins/externalLinks';
import { mapState, mapActions, mapGetters } from '@/libs/store';
import shopItem from '../shops/shopItem';
import BuyQuestModal from '@/components/shops/quests/buyQuestModal.vue';
@@ -384,7 +385,7 @@ export default {
shopItem,
draggable,
},
mixins: [buyMixin, notifications, sync],
mixins: [buyMixin, notifications, sync, externalLinks],
// @TODO Set default values for props
// allows for better control of props values
// allows for better control of where this component is called
@@ -534,6 +535,10 @@ export default {
if (this.activeFilter.label !== 'complete2') return;
this.loadCompletedTodos();
});
this.handleExternalLinks();
},
updated () {
this.handleExternalLinks();
},
beforeDestroy () {
this.$root.$off('buyModal::boughtItem');
@@ -593,7 +593,6 @@
a:not(.dropdown-item) {
font-size: 12px;
line-height: 1.33;
color: $blue-10;
}
.modal-dialog.modal-sm {
@@ -276,7 +276,6 @@
a {
font-size: 12px;
line-height: 1.33;
color: $blue-10;
margin-top: 4px;
&:focus, &:hover, &:active {
@@ -83,6 +83,7 @@
<script>
import moment from 'moment';
import { mapState } from '@/libs/store';
import externalLinks from '@/mixins/externalLinks';
import scoreTask from '@/mixins/scoreTask';
import sync from '@/mixins/sync';
import Task from './task';
@@ -93,7 +94,7 @@ export default {
Task,
LoadingSpinner,
},
mixins: [scoreTask, sync],
mixins: [externalLinks, scoreTask, sync],
props: {
yesterDailies: {
type: Array,
@@ -108,6 +109,9 @@ export default {
dueDate: moment().subtract(1, 'days'),
};
},
updated () {
this.handleExternalLinks();
},
computed: {
...mapState({ user: 'user.data' }),
tasksByType () {
+1 -1
View File
@@ -133,7 +133,7 @@
font-size: 12px;
font-weight: bold;
text-align: center;
color: $gray-400;
color: $white !important;
text-decoration: none !important;
border-bottom: 2px solid transparent;
padding: 0.5rem;
@@ -182,7 +182,6 @@
</table>
</div>
</div>
</div>
</template>
@@ -296,10 +295,6 @@
width: 50%;
}
.challenge-link, .user-link {
color: $blue-10 !important;
}
.entry-action {
b {
text-transform: uppercase;
@@ -759,6 +759,7 @@ import challenge from '@/assets/svg/challenge.svg';
import member from '@/assets/svg/member-icon.svg';
import staff from '@/assets/svg/tier-staff.svg';
import error404 from '../404';
import externalLinks from '../../mixins/externalLinks';
import { userCustomStateMixin } from '../../mixins/userState';
// @TODO: EMAILS.COMMUNITY_MANAGER_EMAIL
const COMMUNITY_MANAGER_EMAIL = 'admin@habitica.com';
@@ -772,7 +773,7 @@ export default {
profileStats,
error404,
},
mixins: [userCustomStateMixin('userLoggedIn')],
mixins: [externalLinks, userCustomStateMixin('userLoggedIn')],
props: ['userId', 'startingPage'],
data () {
return {
@@ -862,8 +863,12 @@ export default {
mounted () {
this.loadUser();
this.oldTitle = this.$store.state.title;
this.handleExternalLinks();
this.selectPage(this.startingPage);
},
updated () {
this.handleExternalLinks();
},
beforeDestroy () {
if (this.oldTitle) {
this.$store.dispatch('common:setTitle', {
+7 -1
View File
@@ -33,9 +33,15 @@ setUpLogging();
setupAnalytics(); // just create queues for analytics, no scripts loaded at this time
const store = getStore();
export default new Vue({
const vueInstance = new Vue({
el: '#app',
router,
store,
render: h => h(AppComponent),
});
export default vueInstance;
window.externalLink = url => {
vueInstance.$root.$emit('habitica:external-link', url);
};
@@ -0,0 +1,35 @@
import some from 'lodash/some';
export default {
methods: {
handleExternalLinks () {
const { TRUSTED_DOMAINS } = process.env;
const allLinks = document.getElementsByTagName('a');
for (let i = 0; i < allLinks.length; i += 1) {
const link = allLinks[i];
let domainIndex = link.href.indexOf('www');
if (domainIndex !== -1 && domainIndex < 9) {
domainIndex += 4;
} else {
domainIndex = link.href.indexOf('//') + 2;
}
if ((link.classList.value.indexOf('external-link') === -1)
&& domainIndex !== 1
&& !some(TRUSTED_DOMAINS.split(','), domain => link.href.indexOf(domain) === domainIndex)) {
link.classList.add('external-link');
link.addEventListener('click', e => {
if (e.ctrlKey || e.metaKey) {
return;
}
e.stopPropagation();
e.preventDefault();
window.externalLink(link.href);
});
}
}
},
},
};
+4 -4
View File
@@ -40,15 +40,15 @@ export default {
'Dragon',
'Cactus',
];
if (!pet) return 'Pet-Cactus-Virtual';
if (!pet) return 'Pet-TigerCub-TeaShop';
if (SPECIAL_PETS.indexOf(pet) !== -1) {
return 'Pet-Wolf-Virtual';
return 'Pet-Dragon-TeaShop';
}
const species = pet.slice(0, pet.indexOf('-'));
if (includes(BASE_PETS, species)) {
return `Pet-${species}-Virtual`;
return `Pet-${species}-TeaShop`;
}
return 'Pet-Fox-Virtual';
return 'Pet-BearCub-TeaShop';
},
},
};
+5 -5
View File
@@ -272,6 +272,11 @@ const router = new VueRouter({
name: 'transactions',
path: 'transactions',
component: Transactions,
meta: {
privilegeNeeded: [
'userSupport',
],
},
},
{
name: 'notifications',
@@ -316,11 +321,6 @@ const router = new VueRouter({
{
name: 'front', path: 'front', component: HomePage, meta: { requiresLogin: false },
},
// Commenting out merch page see
// https://github.com/HabitRPG/habitica/issues/12039
// {
// name: 'merch', path: 'merch', component: MerchPage, meta: { requiresLogin: false },
// },
{
name: 'news', path: 'new-stuff', component: NewsPage, meta: { requiresLogin: false },
},
@@ -1,8 +1,5 @@
import axios from 'axios';
// import omit from 'lodash/omit';
// import findIndex from 'lodash/findIndex';
const apiv4Prefix = '/api/v4';
export async function getGroupMembers (store, payload) {
@@ -117,38 +114,3 @@ export async function getPurchaseHistory (store, payload) {
const response = await axios.get(`${apiv4Prefix}/members/${payload.memberId}/purchase-history`);
return response.data.data;
}
// export async function selectMember (uid) {
// let memberIsReady = _checkIfMemberIsReady(members[uid]);
//
// if (memberIsReady) {
// _prepareMember(members[uid], self);
// return
// } else {
// fetchMember(uid)
// .then(function (response) {
// var member = response.data.data;
// addToMembersList(member); // lazy load for later
// _prepareMember(member, self);
// deferred.resolve();
// });
// }
// }
// function addToMembersList (member) {
// if (member._id) {
// members[member._id] = member;
// }
// }
// function _checkIfMemberIsReady (member) {
// return member && member.items && member.items.weapon;
// }
//
// function _prepareMember(member, self) {
// self.selectedMember = members[member._id];
// }
//
// $rootScope.$on('userUpdated', function(event, user){
// addToMembersList(user);
// })
+1
View File
@@ -27,6 +27,7 @@ const envVars = [
'APPLE_AUTH_CLIENT_ID',
'AMPLITUDE_KEY',
'LOGGLY_CLIENT_TOKEN',
'TRUSTED_DOMAINS',
// TODO necessary? if yes how not to mess up with vue cli? 'NODE_ENV'
];
+5 -2
View File
@@ -140,9 +140,12 @@
"achievementWoodlandWizardText": "لقد فقس جميع الألوان القياسية لمخلوقات الغابة: الغرير، الدب، الغزال، الثعلب، الضفدع، القنفذ، البومة، الأفعى، السنجاب والشجيرة!",
"achievementWoodlandWizardModalText": "لقد جمعت كل حيوانات الغابة الأليفة!",
"achievementPolarPro": "المحترف القطبي",
"achievementPolarProText": "فقست جميع الحيوانات الأليفة القطبية: الدب ، الثعلب ، البطريق ، الحوت ، والذئب!",
"achievementPolarProText": "فقست جميع الحيوانات الأليفة القطبية في الألوان القياسية: الدب ، الثعلب ، البطريق ، الحوت ، والذئب!",
"achievementPolarProModalText": "لقد جمعت كل الحيوانات الأليفة القطبية!",
"achievementBoneToPick": "جامع العظام",
"achievementBoneToPickText": "فقست جميع الحيوانات الأليفة الهيكلية المغامرة والكلاسيكية!",
"achievementBoneToPickModalText": "لقد جمعت كل الحيوانات الأليفة الهيكلية المغامرة والكلاسيكية!"
"achievementBoneToPickModalText": "لقد جمعت كل الحيوانات الأليفة الهيكلية المغامرة والكلاسيكية!",
"achievementPlantParent": "والد النبات",
"achievementPlantParentText": "فقست جميع الحيوانات الأليفة النباتية في الألوان القياسية: الصبار والتريلنج!",
"achievementPlantParentModalText": "لقد جمعت كل الحيوانات الأليفة النباتية!"
}
+216 -2
View File
@@ -411,7 +411,7 @@
"backgroundScribesWorkshopNotes": "Write your next great scroll in a Scribe's Workshop.",
"backgrounds022019": "مجموعة 57: تم إصدارها في فبراير 2019",
"backgroundBirthdayPartyText": "حفلة عيد ميلاد",
"backgrounds012020": "مجموعة 68: تم طرحه في يناير 2020",
"backgrounds012020": "المجموعة 68: صدرت في يناير 2020",
"backgroundMedievalKitchenText": "مطبخ القرون الوسطى",
"backgroundMedievalKitchenNotes": "اطبخ العاصفة في مطبخ القرون الوسطى.",
"backgroundBirthdayPartyNotes": "احتفل بعيد ميلاد ال Habitican المفضل لديك.",
@@ -448,5 +448,219 @@
"backgroundDojoNotes": "تعلم حركات جديدة في دوجو.",
"backgroundSchoolOfFishText": "سرب من الأسماك",
"backgrounds072019": "المجموعة 62: صدرت في يوليو 2019",
"backgroundParkWithStatueNotes": "اتبع مسارًا تصطف على جانبيه الأزهار عبر حديقة بها تمثال."
"backgroundParkWithStatueNotes": "اتبع مسارًا تصطف على جانبيه الأزهار عبر حديقة بها تمثال.",
"backgroundFlyingOverTropicalIslandsText": "التحليق فوق الجزر الاستوائية",
"backgroundFlyingOverTropicalIslandsNotes": "دع المنظر يذهلك وأنت تحلق فوق الجزر الاستوائية.",
"backgrounds082019": "المجموعة 63: صدرت في أغسطس 2019",
"backgroundLakeWithFloatingLanternsNotes": "شاهد النجوم من بحيرة احتفالية عليها فوانيس عائمة.",
"backgroundLakeWithFloatingLanternsText": "بحيرة عليها فوانيس عائمة",
"backgroundTreehouseNotes": "استرخ بمفردك في منزل الشجرة الخاص بك.",
"backgrounds092019": "المجموعة 64: صدرت في سبتمبر 2019",
"backgroundAutumnFlowerGardenText": "حديقة الزهور الخريفية",
"backgroundInAnAncientTombText": "قبر قديم",
"backgroundAmidAncientRuinsNotes": "قف بوقار لماضٍ غامض بين الآثار القديمة.",
"backgroundGiantDandelionsText": "الهندباء العملاقة",
"backgroundAmongGiantAnemonesText": "بين شقائق النعمان العملاقة",
"backgroundInAnAncientTombNotes": "واجه الأسرار من قبر قديم.",
"backgroundAutumnFlowerGardenNotes": "تشمس في دفء حديقة الزهور الخريفية.",
"backgroundTreehouseText": "منزل الشجرة",
"backgroundAmongGiantAnemonesNotes": "استكشف الشعاب المرجانية بينما أنت محمي\\ة من الحيوانات المفترسة البحرية بين شقائق النعمان العملاقة.",
"backgroundAmidAncientRuinsText": "بين الأطلال القديمة",
"backgroundGiantDandelionsNotes": "اقضِ بعض الوقت بين الهندباء العملاقة.",
"backgroundInAClassroomText": "صف",
"backgroundInAClassroomNotes": "اكتسب المعرفة من معلميك في صف.",
"backgrounds102019": "المجموعة 65: صدرت في اكتوبر 2019",
"backgroundFoggyMoorText": "مستنقع ضبابي",
"backgroundFoggyMoorNotes": "كن حذرًا أثناء عبور المستنقع الضبابي.",
"backgroundPumpkinCarriageText": "عربة اليقطين",
"backgroundPumpkinCarriageNotes": "اركب في عربة اليقطين المسحورة قبل وصول منتصف الليل.",
"backgroundMonsterMakersWorkshopText": "ورشة عمل صانع الوحش",
"backgroundMonsterMakersWorkshopNotes": "تجربة مع علوم مشوهة في ورشة عمل صانع الوحش.",
"backgrounds112019": "المجموعة 66: صدرت في نوفمبر 2019",
"backgroundFarmersMarketText": "سوق المزارعين",
"backgroundFarmersMarketNotes": "تسوق للحصول على الطعام الطازج في سوق المزارعين.",
"backgroundFlyingInAThunderstormText": "عاصفة رعدية مضطربة",
"backgroundFlyingInAThunderstormNotes": "تابع عاصفة رعدية مضطربة إذا كنت تجرؤ.",
"backgroundPotionShopNotes": "اعثر على إكسير لأي مرض في متجر الجرعات السحرية.",
"backgroundPotionShopText": "متجر الجرعات السحرية",
"backgrounds122019": "المجموعة 67: صدرت في ديسمبر 2019",
"backgroundWinterNocturneText": "ليلة شتاء",
"backgroundWinterNocturneNotes": "تشمس في ضوء النجوم في ليلة شتاء.",
"backgroundElegantBallroomText": "قاعة رقص أنيقة",
"backgroundDesertWithSnowText": "صحراء ثلجية",
"backgrounds022020": "المجموعة 69: صدرت في فبراير 2020",
"backgroundHallOfHeroesText": "قاعة الأبطال",
"backgrounds032020": "المجموعة 70: صدرت في مارس 2020",
"backgroundButterflyGardenText": "حديقة الفراشات",
"backgroundSnowglobeNotes": "هز كرة ثلجية واستقر في صورة مصغرة لمنظر طبيعي شتوي.",
"backgroundAmongGiantFlowersText": "بين الزهور العملاقة",
"backgroundHallOfHeroesNotes": "اقترب من قاعة الأبطال بتقدير وتقديس.",
"backgroundDesertWithSnowNotes": "شاهد الجمال النادر والهادئ للصحراء الثلجية.",
"backgroundTeaPartyNotes": "شارك في حفلة شاي فاخرة.",
"backgroundAnimalCloudsText": "غيوم على شكل حيوانات",
"backgrounds042020": "المجموعة 71: صدرت في أبريل 2020",
"backgroundAnimalCloudsNotes": "مارس خيالك بالعثور على أشكال حيوانات في الغيوم.",
"backgroundHolidayMarketText": "سوق العطلات",
"backgroundTeaPartyText": "حفلة شاي",
"backgroundElegantBallroomNotes": "ارقص طوال الليل في قاعة رقص أنيقة.",
"backgroundHolidayMarketNotes": "اعثر على الهدايا والزخارف المثالية في سوق العطلات.",
"backgroundSnowglobeText": "كرة الثلج",
"backgroundSucculentGardenNotes": "قدّر جمال حديقة النباتات النضرة.",
"backgroundButterflyGardenNotes": "احتفل مع الملقحات في حديقة الفراشات.",
"backgroundSucculentGardenText": "حديقة النباتات النضرة",
"backgroundHolidayWreathText": "إكليل الصنوبر",
"backgroundHolidayWreathNotes": "تزيين صورتك الرمزية مع إكليل عطر من الصنوبر.",
"backgroundAmongGiantFlowersNotes": "اقض بعض الوقت بين الزهور العملاقة.",
"backgroundHotAirBalloonText": "منطاد الهواء الساخن",
"backgroundRelaxationRiverText": "نهر الاسترخاء",
"backgroundHotAirBalloonNotes": "احلق فوق الأرض في منطاد الهواء الساخن.",
"backgroundStrawberryPatchText": "حقل الفراولة",
"backgroundHeatherFieldNotes": "استمتع برائحة حقل الخلنج.",
"backgroundHabitCityRooftopsText": "أسطح المنازل في مدينة حابيت",
"backgroundHabitCityRooftopsNotes": "خذ قفزات جريئة بين أسطح المنازل في مدينة حابيت.",
"backgroundHeatherFieldText": "حقل الخلنج",
"backgroundRainyBarnyardNotes": "تجول في مزرعة ممطرة.",
"backgroundRainyBarnyardText": "مزرعة ممطرة",
"backgrounds052020": "المجموعة 72: صدرت في مايو 2020",
"backgroundStrawberryPatchNotes": "جمع التوت الطازج من حقل الفراولة.",
"backgrounds062020": "المجموعة 73: صدرت في يونيو 2020",
"backgroundRelaxationRiverNotes": "انجرف ببطء على طول نهر الاسترخاء.",
"backgroundSaltLakeText": "بحيرة مالحة",
"backgroundVikingShipText": "سفينة فايكنغ",
"backgroundSaltLakeNotes": "شاهد التموجات الحمراء المذهلة لبحيرة مالحة.",
"backgroundBeachCabanaNotes": "استرخِ في ظل كوخ الشاطئ.",
"backgroundSwimmingAmongJellyfishText": "السباحة بين قناديل البحر",
"backgrounds072020": "المجموعة 74: صدرت في يوليو 2020",
"backgroundBeachCabanaText": "كوخ الشاطئ",
"backgroundVikingShipNotes": "أبحر على متن سفينة فايكنغ بحثًا عن المغامرة.",
"backgrounds082020": "المجموعة 75: صدرت في أغسطس 2020",
"backgroundSwimmingAmongJellyfishNotes": "اشعر بالجمال والخطر وأنت تسبح بين قناديل البحر.",
"backgroundUnderwaterRuinsText": "أطلال تحت الماء",
"backgroundCampingOutNotes": "استمتع بالهواء الطلق أثناء رحلة التخييم.",
"backgroundUnderwaterRuinsNotes": "اِسْتَكْشِفْ الأطلال تحت الماء التي غرقت منذ فترة طويلة.",
"backgroundCampingOutText": "رحلة تخييم",
"backgroundProductivityPlazaText": "ساحة الإنتاجية",
"backgroundJungleCanopyText": "رؤوس الأشجار الاستوائية",
"backgroundJungleCanopyNotes": "تشمس في الروعة الساخنة في رؤوس الأشجار الاستوائية.",
"backgroundProductivityPlazaNotes": "قم بنزهة ملهمة في ساحة الإنتاجية في مدينة حابيت.",
"backgroundFlyingOverAnAutumnForestNotes": "انظر إلى الألوان الرائعة أسفلك أثناء التحليق فوق الغابة الخريفية.",
"backgroundFlyingOverAnAutumnForestText": "التحليق فوق الغابة الخريفية",
"backgrounds092020": "المجموعة 76: صدرت في سبتمبر 2020",
"backgroundGiantAutumnLeafNotes": "اجثم على ورقة عملاقة قبل أن تسقط.",
"backgroundGiantAutumnLeafText": "ورقة عملاقة",
"backgroundHerdingSheepInAutumnNotes": "اختلط بالقطيع من الأغنام.",
"backgroundHerdingSheepInAutumnText": "قطيع من الأغنام",
"backgrounds102020": "المجموعة 77: صدرت في اكتوبر 2020",
"backgroundGingerbreadHouseText": "بيت كعك الزنجبيل",
"backgroundSpookyScarecrowFieldText": "حقل الفزاعة المخيفة",
"backgroundRiverOfLavaText": "نهر من الحمم البركانية",
"backgroundMysticalObservatoryText": "مرصد باطني",
"backgroundCrescentMoonNotes": "قم بعمل الأحلام وأنت جالس على الهلال.",
"backgroundHauntedForestText": "غابة مسكونة",
"backgroundRiverOfLavaNotes": "تحدى الحمل الحراري وتجول على طول نهر الحمم البركانية.",
"backgroundHauntedForestNotes": "حاول ألا تضيع في الغابة المسكونة.",
"backgroundCrescentMoonText": "هلال",
"backgroundSpookyScarecrowFieldNotes": "أثبت أنك أكثر شجاعة من الطائر بالذهاب إلى حقل الفزاعة المخيفة.",
"backgrounds112020": "المجموعة 78: صدرت في نوفمبر 2020",
"backgroundMysticalObservatoryNotes": "اقرأ مصيرك في النجوم من المرصد الباطني.",
"backgroundRestingInTheInnNotes": "اعمل براحة وأمان في غرفتك أثناء الراحة في النزل.",
"backgroundRestingInTheInnText": "الراحة في النزل",
"backgrounds122020": "المجموعة 79: صدرت في ديسمبر 2020",
"backgroundGingerbreadHouseNotes": "تحيط علما بالمشاهد والروائح و(إن كنت تجرؤ) النكهات بيت كعك الزنجبيل.",
"backgroundIcicleBridgeNotes": "اعبر الجسر الجليدي بحذر.",
"backgroundIcicleBridgeText": "جسر جليدي",
"backgroundInsideAnOrnamentText": "داخل حلية العطلة",
"backgroundWintryCastleNotes": "انظر إلى القلعة الشتوية التي تقع داخل الضباب البارد.",
"backgroundHolidayHearthText": "مدفأة احتفالية",
"backgrounds022021": "المجموعة 81: صدرت في فبراير 2021",
"backgroundFlyingOverGlacierText": "تحلق فوق نهر جليدي",
"backgrounds012021": "المجموعة 80: صدرت في يناير 2021",
"backgroundWintryCastleText": "قلعة شتوية",
"backgroundHotSpringNotes": "تخلص من همومك عن طريق الراحة في ينبوع حار.",
"backgroundHotSpringText": "ينبوع حار",
"backgroundHolidayHearthNotes": "استرخ ، دفئ نفسكَ وجفف نفسك بجانب مدفأة احتفالية.",
"backgroundInsideAnOrnamentNotes": "دع روح العطلة الخاصة بك تتألق من داخل حلية العطلة.",
"backgroundFlyingOverGlacierNotes": "شاهد المشهد المهيب وأنت تحلق فوق نهر جليدي.",
"backgroundHeartShapedBubblesText": "فقاعات على شكل قلب",
"backgroundHeartShapedBubblesNotes": "اطف بمرح بين الفقاعات على شكل قلب.",
"backgrounds032021": "المجموعة 82: صدرت في مارس 2021",
"backgroundThroneRoomText": "غرفة العرش",
"backgroundThroneRoomNotes": "امنح جمهورًا في غرفة العرش الفاخرة الخاصة بك.",
"backgroundInTheArmoryText": "في مستودع الأسلحة",
"backgroundSplashInAPuddleNotes": "استمتع بآثار العاصفة بالرش في بركة.",
"backgroundSpringThawText": "ذوبـان الثلوج في فصل الربيع",
"backgroundSpringThawNotes": "شاهد الشتاء يختفي مع ذوبان الثلوج في فصل الربيع.",
"backgrounds042021": "المجموعة 83: صدرت في أبريل 2021",
"backgroundInTheArmoryNotes": "جهز نفسك في مستودع الأسلحة.",
"backgroundSplashInAPuddleText": "الرش في بركة",
"backgroundAmongCattailsText": "بين القصب",
"backgroundElegantGardenText": "حديقة أنيقة",
"backgroundAmongCattailsNotes": "انظر إلى الحياة البرية في الأراضي الرطبة بين القصب.",
"backgroundCottageConstructionNotes": "ساعد في, أو على الأقل الإشراف على كوخ قيد الإنشاء.",
"backgroundCottageConstructionText": "كوخ قيد الانشاء",
"backgroundForestedLakeshoreText": "شاطئ البحيرة الحرجي",
"backgroundDragonsLairText": "عرين التنين",
"backgroundWaterMillNotes": "شاهد عجلة الطاحونة المائية تدور.",
"backgroundGhostShipText": "سفينة الأشباح",
"backgrounds062021": "المجموعة 85: صدرت في يونيو 2021",
"backgroundWindmillsText": "طواحين الهواء",
"backgroundAfternoonPicnicNotes": "استمتع بنزهة بعد الظهر بمفردك أو مع حيوانك الأليف.",
"backgroundClotheslineText": "حبل الغسيل",
"backgroundUnderwaterAmongKoiNotes": "أبهر وانبهر بالمخلوقات المتلألئة تحت الماء بين أسماك كوي.",
"backgrounds052021": "المجموعة 84: صدرت في مايو 2021",
"backgrounds072021": "المجموعة 86: صدرت في يوليو 2021",
"backgroundGhostShipNotes": "أثبت صحة القصص والأساطير عندما تصعد على متن سفينة الأشباح.",
"backgroundElegantGardenNotes": "تجول على طول المسارات المشذبة الجميلة لحديقة أنيقة.",
"backgroundForestedLakeshoreNotes": "كن موضع حسد فريقك من خلال موقعك المتميز على شاطئ البحيرة الحرجي.",
"backgroundDragonsLairNotes": "حاول ألا تزعج ساكن عرين التنين.",
"backgroundAfternoonPicnicText": "نزهة بعد الظهر",
"backgroundWaterMillText": "طاحونة مائية",
"backgroundClotheslineNotes": "استرخِ بينما تجف الملابس على حبل الغسيل.",
"backgroundWindmillsNotes": "استعد لمحاربة أعداء غير مرئيين في طواحين الهواء.",
"backgroundUnderwaterAmongKoiText": "تحت الماء بين أسماك كوي",
"backgroundRagingRiverText": "نهر هائج",
"backgroundRagingRiverNotes": "قف وسط التيار العظيم لنهر هائج.",
"backgrounds082021": "المجموعة 87: صدرت في أغسطس 2021",
"backgroundStoneTowerText": "برج حجري",
"backgroundStoneTowerNotes": "انظر من حاجز البرج الحجري إلى آخر.",
"backgroundRopeBridgeText": "جسر الحبل",
"backgroundDaytimeMistyForestText": "غابة ضبابية",
"backgroundRopeBridgeNotes": "أظهر للمشككين أن جسر الحبل هذا آمن تمامًا.",
"backgrounds092021": "المجموعة 88: صدرت في سبتمبر 2021",
"backgroundVineyardText": "مزرعة العنب",
"backgroundAutumnPoplarsText": "غابة الحور الخريفية",
"backgroundDaytimeMistyForestNotes": "تشمس بأشعة الضوء المشرقة من خلال الغابة الضبابية.",
"backgroundVineyardNotes": "استكشف مساحة من مزرعة العنب المثمرة.",
"backgroundAutumnLakeshoreText": "شاطئ البحيرة الخريفية",
"backgrounds102021": "المجموعة 89: صدرت في اكتوبر 2021",
"backgroundAutumnLakeshoreNotes": "توقف عند شاطئ البحيرة الخريفية لتقدير انعكاس الغابة على الماء.",
"backgroundAutumnPoplarsNotes": "استمتع بالدرجات اللامعة من اللون البني والذهبي في غابة الحور الخريفية.",
"backgrounds122021": "المجموعة 91: صدرت في ديسمبر 2021",
"backgrounds112021": "المجموعة 90: صدرت في نوفمبر 2021",
"backgroundFortuneTellersShopText": "محل العرافة",
"backgroundFortuneTellersShopNotes": "ابحث عن تلميحات مغرية لمستقبلك في محل العرافة.",
"backgroundInsideAPotionBottleText": "داخل زجاجة الجرعة السحرية",
"backgroundInsideAPotionBottleNotes": "انظر عبر الزجاج بينما تأمل في الإنقاذ من داخل زجاجة الجرعة السحرية.",
"backgroundSpiralStaircaseText": "درج حلزوني",
"backgroundSpiralStaircaseNotes": "اصعد ، انزل ، واذهب حول الدرج الحلزوني.",
"backgroundCrypticCandlesText": "شموع خفية",
"backgroundCrypticCandlesNotes": "استدع قوى غامضة بين الشموع الخفية.",
"backgroundHauntedPhotoText": "صورة مسكونة",
"backgroundHauntedPhotoNotes": "تجد نفسك محاصرًا في عالم أحادي اللون لصورة مسكونة.",
"backgroundUndeadHandsText": "أيدي الزومبي",
"backgroundUndeadHandsNotes": "حاول الهروب من براثن أيدي الزومبي.",
"backgrounds022022": "المجموعة 93: صدرت في فبراير 2022",
"backgroundFrozenPolarWatersText": "المياه القطبية المجمدة",
"backgroundFrozenPolarWatersNotes": "استكشف المياه القطبية المجمدة.",
"backgroundWinterCanyonText": "وادي شتوي",
"backgroundWinterCanyonNotes": "اذهب في مغامرة في وادي شتوي!",
"backgroundIcePalaceText": "قصر الجليد",
"backgrounds012022": "المجموعة 92: صدرت في يناير 2022",
"backgroundSnowyFarmText": "مزرعة ثلجية",
"backgroundMeteorShowerText": "دش النيزك",
"backgroundMeteorShowerNotes": "شاهد العرض الليلي المبهر لدش النيزك.",
"backgroundPalmTreeWithFairyLightsText": "شجرة نخيل مع أضواء زخرفية",
"backgroundSnowyFarmNotes": "تأكد من أن الجميع آمنون ودافئون في مزرعتك الثلجية.",
"backgroundIcePalaceNotes": "احكم في قصر الجليد.",
"backgroundPalmTreeWithFairyLightsNotes": "قف بجانب شجرة نخيل ملفوفة بأضواء زخرفية."
}
@@ -1,5 +1,4 @@
{
"tavernCommunityGuidelinesPlaceholder": "Friendly reminder: this is an all-ages chat, so please keep content and language appropriate! Consult the Community Guidelines in the sidebar if you have questions.",
"lastUpdated": "آخر تحديث:",
"commGuideHeadingWelcome": "أهلاً وسهلاً بك في Habitica!",
@@ -7,7 +6,7 @@
"commGuidePara002": "To help keep everyone safe, happy, and productive in the community, we do have some guidelines. We have carefully crafted them to make them as friendly and easy-to-read as possible. Please take the time to read them before you start chatting.",
"commGuidePara003": "تنطبق هذه القواعد على جميع المساحات الإجتماعية التي نستخدمها، بما في ذلك (ولكن لا تقتصر على) Trello، GitHub، Transifex و Wikia (أي الwiki). في بعض الأحيان، سوف تنشأ حالات غير متوقعة، مثل مصدراً جديداً من الصراع أو ظهور مستحضراً للأرواح الشرية. عندما يحدث ذلك، يجوز للمشرفين تعديل هذه المبادئ التوجيهية للحفاظ على سلامة المجتمع من التهديدات الجديدة. ولكن لا تخف: سيتم إعلامك عن طريق إعلان من الآنسة Bailey إذا تغيرت المبادئ التوجيهية.",
"commGuideHeadingInteractions": "التفاعل في Habitica",
"commGuidePara015": "Habitica has two kinds of social spaces: public, and private. Public spaces include the Tavern, Public Guilds, GitHub, Trello, and the Wiki. Private spaces are Private Guilds, Party chat, and Private Messages. All Display Names must comply with the public space guidelines. To change your Display Name, go on the website to User > Profile and click on the \"Edit\" button.",
"commGuidePara015": "يحتوي Habitica على نوعين من الفضاءات الاجتماعية: العامة والخاصة. تشمل الفضاءات العامة التي يمكن الوصول إليها الحانوت والمنتديات العامة و GitHub و Trello والويكي. الفضاءات الخاصة هي الأندية الخاصة والدردشة الجماعية والرسائل الخاصة. يجب على جميع أسماء العرض وأسماء المستخدمين @ اتباع إرشادات الفضاء العام. لتغيير اسم العرض و / أو اسم المستخدم @ ، انتقل إلى القائمة> الإعدادات> الملف الشخصي على الهاتف المحمول. على الويب ، انتقل إلى المستخدم> الإعدادات.",
"commGuidePara016": "عند التنقل ما بين الأماكن العامة في Habitica، هناك بعض القواعد العامة للحفاظ على سعادة وسلامة الجميع. ستكون هذه القواعد سهلة عليك أيها المغامر!",
"commGuideList02A": "<strong>Respect each other</strong>. Be courteous, kind, friendly, and helpful. Remember: Habiticans come from all backgrounds and have had wildly divergent experiences. This is part of what makes Habitica so cool! Building a community means respecting and celebrating our differences as well as our similarities. Here are some easy ways to respect each other:",
"commGuideList02B": "<strong>التزم بجميع <a href='/static/terms' target='_blank'>الشروط والأحكام</a></strong>.",
+2 -2
View File
@@ -1,11 +1,11 @@
{
"frequentlyAskedQuestions": "الأسئلة الأكثر تكراراً",
"faqQuestion0": "أنا محتار. من أين استطيع أن احصل على نظرة عامة؟",
"iosFaqAnswer0": "First, you'll set up tasks that you want to do in your everyday life. Then, as you complete the tasks in real life and check them off, you'll earn experience and gold. Gold is used to buy equipment and some items, as well as custom rewards. Experience causes your character to level up and unlock content such as Pets, Skills, and Quests! You can customize your character under Menu > Customize Avatar.\n\n Some basic ways to interact: click the (+) in the upper-right-hand corner to add a new task. Tap on an existing task to edit it, and swipe left on a task to delete it. You can sort tasks using Tags in the upper-left-hand corner, and expand and contract checklists by clicking on the checklist bubble.",
"iosFaqAnswer0": "أولاً ، ستقوم بإعداد المهام التي تريد القيام بها في حياتك اليومية. ثم ، بمجرد الانتهاء من المهام في الحياة الحقيقية وتحققها ، ستكسب الخبرة والذهب. يتم استخدام الذهب لشراء المعدات وبعض العناصر ، بالإضافة إلى المكافآت المخصصة. يؤدي الخبرة إلى صعود شخصيتك وفتح محتوى مثل الحيوانات الأليفة والمهارات والمهام! يمكنك تخصيص شخصيتك في القائمة> تخصيص الصورة الرمزية.\n\n بعض الطرق الأساسية للتفاعل: انقر على (+) في الزاوية العلوية اليمنى لإضافة مهمة جديدة. انقر فوق المهمة الموجودة لتحريرها ، واسحب إلى اليسار على المهمة لحذفها. يمكنك فرز المهام باستخدام العلامات في الزاوية العلوية اليسرى ، وتوسيع وطي قوائم الاختيار عن طريق النقر على فقاعة قائمة الاختيارات.",
"androidFaqAnswer0": "First, you'll set up tasks that you want to do in your everyday life. Then, as you complete the tasks in real life and check them off, you'll earn experience and gold. Gold is used to buy equipment and some items, as well as custom rewards. Experience causes your character to level up and unlock content such as Pets, Skills, and Quests! You can customize your character under Menu > [Inventory >] Avatar.\n\n Some basic ways to interact: click the (+) in the lower-right-hand corner to add a new task. Tap on an existing task to edit it, and swipe left on a task to delete it. You can sort tasks using Tags in the upper-right-hand corner, and expand and contract checklists by clicking on the checklist count box.",
"webFaqAnswer0": "First, you'll set up tasks that you want to do in your everyday life. Then, as you complete the tasks in real life and check them off, you'll earn Experience and Gold. Gold is used to buy equipment and some items, as well as custom rewards. Experience causes your character to level up and unlock content such as pets, skills, and quests! For more detail, check out a step-by-step overview of the game at [Help -> Overview for New Users](https://habitica.com/static/overview).",
"faqQuestion1": "كيف أضيف مهماتي؟",
"iosFaqAnswer1": "Good Habits (the ones with a +) are tasks that you can do many times a day, such as eating vegetables. Bad Habits (the ones with a -) are tasks that you should avoid, like biting nails. Habits with a + and a - have a good choice and a bad choice, like taking the stairs vs. taking the elevator. Good Habits award experience and gold. Bad Habits subtract health.\n\n Dailies are tasks that you have to do every day, like brushing your teeth or checking your email. You can adjust the days that a Daily is due by tapping to edit it. If you skip a Daily that is due, your avatar will take damage overnight. Be careful not to add too many Dailies at once!\n\n To-Dos are your To-Do list. Completing a To-Do earns you gold and experience. You never lose health from To-Dos. You can add a due date to a To-Do by tapping to edit.",
"iosFaqAnswer1": "العادات الجيدة (تلك التي تحتوي على علامة \"+\") هي المهام التي يمكنك القيام بها عدة مرات في اليوم، مثل تناول الخضروات. العادات السيئة (تلك التي تحتوي على علامة \"-\") هي المهام التي يجب عليك تجنبها، مثل عض الأظافر. والعادات التي تحتوي على علامة \"+\" و \"-\" لديها خيار جيد وخيار سيئ، مثل استخدام الدرج بدلاً من المصعد.\n\nالعادات الجيدة تمنحك خبرة وذهب. والعادات السيئة تقلل من صحتك.\n\nالمهام اليومية هي المهام التي يجب عليك القيام بها كل يوم، مثل تنظيف أسنانك أو التحقق من بريدك الإلكتروني. يمكنك تعديل تواريخ المهام اليومية بالنقر لتحريرها. إذا تخطيت مهمة يومية محددة، فسيتلقى أفاتارك ضررًا خلال الليل. كن حذرًا من عدم إضافة العديد من المهام اليومية في وقت واحد!\n\nالمهام التي يجب القيام بها هي قائمة المهام الخاصة بك. إكمال المهام يمنحك الذهب والخبرة. لن تفقد أبدًا صحتك بسبب هذه المهام. يمكنك إضافة تاريخ استحقاق للمهام التي يجب القيام بها بالنقر لتحريرها.",
"androidFaqAnswer1": "Good Habits (the ones with a +) are tasks that you can do many times a day, such as eating vegetables. Bad Habits (the ones with a -) are tasks that you should avoid, like biting nails. Habits with a + and a - have a good choice and a bad choice, like taking the stairs vs. taking the elevator. Good Habits award experience and gold. Bad Habits subtract health.\n\n Dailies are tasks that you have to do every day, like brushing your teeth or checking your email. You can adjust the days that a Daily is due by tapping to edit it. If you skip a Daily that is due, your character will take damage overnight. Be careful not to add too many Dailies at once!\n\n To-Dos are your To-Do list. Completing a To-Do earns you gold and experience. You never lose health from To-Dos. You can add a due date to a To-Do by tapping to edit.",
"webFaqAnswer1": "* Good Habits (the ones with a :heavy_plus_sign:) are tasks that you can do many times a day, such as eating vegetables. Bad Habits (the ones with a :heavy_minus_sign:) are tasks that you should avoid, like biting nails. Habits with a :heavy_plus_sign: and a :heavy_minus_sign: have a good choice and a bad choice, like taking the stairs vs. taking the elevator. Good Habits award Experience and Gold. Bad Habits subtract Health.\n* Dailies are tasks that you have to do every day, like brushing your teeth or checking your email. You can adjust the days that a Daily is due by clicking the pencil item to edit it. If you skip a Daily that is due, your avatar will take damage overnight. Be careful not to add too many Dailies at once!\n* To-Dos are your To-Do list. Completing a To-Do earns you Gold and Experience. You never lose Health from To-Dos. You can add a due date to a To-Do by clicking the pencil icon to edit.",
"faqQuestion2": "ما هي أمثلة المهمات؟",
+9 -8
View File
@@ -1,14 +1,14 @@
{
"quests": "التناقيب",
"quest": "تنقيب",
"petQuests": "Pet and Mount Quests",
"unlockableQuests": "Unlockable Quests",
"goldQuests": "Masterclasser Quest Lines",
"quests": "مغامرات",
"quest": "مغامرة",
"petQuests": "مغامرات للحصول على حيوانات الأليفة ومطايا",
"unlockableQuests": "مغامرات غير قابلة للفتح",
"goldQuests": "مغامرات ماستركلاسر",
"questDetails": "تفاصيل المغامرة",
"questDetailsTitle": "Quest Details",
"questDetailsTitle": "تفاصيل المغامرة",
"questDescription": "Quests allow players to focus on long-term, in-game goals with the members of their party.",
"invitations": "الدعوات",
"completed": "\t\nمنتهى!",
"completed": "اكتملت المغامرة!",
"rewardsAllParticipants": "Rewards for all Quest Participants",
"rewardsQuestOwner": "Additional Rewards for Quest Owner",
"inviteParty": "Invite Party to Quest",
@@ -71,5 +71,6 @@
"bossHealth": "<%= currentHealth %> / <%= maxHealth %> Health",
"rageAttack": "Rage Attack:",
"bossRage": "<%= currentRage %> / <%= maxRage %> Rage",
"rageStrikes": "Rage Strikes"
"rageStrikes": "Rage Strikes",
"hatchingPotionQuests": "مغامرات للحصول على جرعات سحرية"
}
+3 -3
View File
@@ -1,11 +1,11 @@
{
"questEvilSantaText": "سانتا الموقع بالفخ",
"questEvilSantaNotes": "You hear agonized roars deep in the icefields. You follow the growls - punctuated by the sound of cackling - to a clearing in the woods, where you see a fully-grown polar bear. She's caged and shackled, fighting for her life. Dancing atop the cage is a malicious little imp wearing a castaway costume. Vanquish Trapper Santa, and save the beast!",
"questEvilSantaNotes": "تسمع زئيرًا متألمة في عمق حقول الجليد. تتبع النموات - المفصولة بصوت الضحك - إلى مساحة صافية في الغابة ، حيث ترى دبًا قطبيًا ناضجًا تمامًا. إنها مسجونة ومقيدة ، تحارب من أجل حياتها. يرقص فوق القفص عفريت صغيرة شريرة ترتدي زي الناجي. اهزم صياد سانتا وانقذ الوحش! <br> <br> <strong> ملاحظة </strong>: \"صياد سانتا\" يمنح إنجازًا قابلًا للتكديس للمهمة ولكنه يعطي جبلًا نادرًا يمكن إضافته إلى طاولة الخيل الخاصة بك مرة واحدة.",
"questEvilSantaCompletion": "Trapper Santa squeals in anger, and bounces off into the night. The grateful she-bear, through roars and growls, tries to tell you something. You take her back to the stables, where Matt Boch the Beast Master listens to her tale with a gasp of horror. She has a cub! He ran off into the icefields when mama bear was captured.",
"questEvilSantaBoss": "سانتا الموقع بالفخ",
"questEvilSantaDropBearCubPolarMount": "دب قطبي (مركب)",
"questEvilSanta2Text": "البحث عن الشبل",
"questEvilSanta2Notes": "When Trapper Santa captured the polar bear mount, her cub ran off into the icefields. You hear twig-snaps and snow crunch through the crystalline sound of the forest. Paw prints! You start racing to follow the trail. Find all the prints and broken twigs, and retrieve the cub!",
"questEvilSanta2Text": "ابحث عن الشبل",
"questEvilSanta2Notes": "عندما اعتقل صياد السانتا الدب القطبي، هرب صغيرها إلى حقول الجليد. تسمع صوت تكسر أغصان الشجر وصوت الثلج يتكسر بينما تجوب الغابة. آثار بصمات الكفوف! تبدأ بالجري لمتابعة الأثر. ابحث عن جميع الأثر والأغصان المكسورة واسترد الصغير!<br><br><strong>ملاحظة</strong>: تمنح \"البحث عن الصغير\" إنجازًا لمهمة يمكن تراكمه ولكن يمنح حيوانًا أليفًا نادرًا يمكن إضافته إلى مستودعك مرة واحدة فقط.",
"questEvilSanta2Completion": "You've found the cub! It will keep you company forever.",
"questEvilSanta2CollectTracks": "مسارات",
"questEvilSanta2CollectBranches": "أغصان مكسورة",
+4 -1
View File
@@ -136,5 +136,8 @@
"cancelSubInfoGoogle": "الرجاء الانتقال إلى \"الحساب\"> قسم \"الاشتراكات\" في متجر Google Play لإلغاء اشتراكك أو لمعرفة تاريخ انتهاء إشتراكك إذا كنت قد ألغيته بالفعل. هذه الشاشة غير قادرة على إظهار ما إذا كان قد تم إلغاء اشتراكك.",
"organization": "منظمة",
"giftASubscription": "إهداء إشتراك",
"viewSubscriptions": "عرض الإشتراكات"
"viewSubscriptions": "عرض الإشتراكات",
"howManyGemsSend": "كم عدد الجواهر التي ترغب في إرسالها؟",
"howManyGemsPurchase": "كم عدد الأحجار الكريمة التي ترغب في شرائها؟",
"needToPurchaseGems": "هل تحتاج إلى شراء جواهر كهدية؟"
}
+6 -6
View File
@@ -1,8 +1,8 @@
{
"achievement": "Achievement",
"onwards": "Onwards!",
"levelup": "By accomplishing your real life goals, you leveled up and are now fully healed!",
"reachedLevel": "You Reached Level <%= level %>",
"achievementLostMasterclasser": "Quest Completionist: Masterclasser Series",
"achievementLostMasterclasserText": "Completed all sixteen quests in the Masterclasser Quest Series and solved the mystery of the Lost Masterclasser!"
"achievement": "Дасягненьне",
"onwards": "Наперад!",
"levelup": "By accomplishing your real life goals, you leveled up and are now fully healed!",
"reachedLevel": "You Reached Level <%= level %>",
"achievementLostMasterclasser": "Quest Completionist: Masterclasser Series",
"achievementLostMasterclasserText": "Completed all sixteen quests in the Masterclasser Quest Series and solved the mystery of the Lost Masterclasser!"
}
+14 -1
View File
@@ -93,5 +93,18 @@
"achievementFreshwaterFriendsText": "Завършили сте мисиите за домашни любимци за аксолотъла, жабата и хипопотама.",
"achievementFreshwaterFriends": "Сладководни приятели",
"yourRewards": "Вашите Награди",
"achievementBoneCollectorModalText": "Събрали сте всичките Скелетни Любимци!"
"achievementBoneCollectorModalText": "Събрали сте всичките Скелетни Любимци!",
"achievementRedLetterDay": "Червен Празник",
"achievementLegendaryBestiary": "Легендарен Бестиарий",
"achievementLegendaryBestiaryText": "Излюпили са всички стандартни цветови разновидности на Митичните животни: Дракон, Летящо прасе, Грифон, Водна змия и Еднорог!",
"achievementLegendaryBestiaryModalText": "Събрали сте всички Митичн любимци!",
"achievementSkeletonCrewModalText": "Събрали сте всички Скелетни животни!",
"achievementSeeingRed": "Виждам червено",
"achievementSkeletonCrew": "Скелетен екипаж",
"achievementSeeingRedText": "Събрали са всичк Червени любимци.",
"achievementRedLetterDayModalText": "Събрали сте всички Червени животни!",
"achievementSeasonalSpecialist": "Сезонен експерт",
"achievementRedLetterDayText": "Са събрали всички Червени животни.",
"achievementSeeingRedModalText": "Събрали сте всички Червени любимци!",
"achievementSkeletonCrewText": "Събрали са всички Скелетни животни."
}
+7 -1
View File
@@ -1 +1,7 @@
{}
{
"achievement": "Kadaugan",
"onwards": "Padayon!",
"levelup": "Sa pagbuhat sa imong tumong sa kinabuhi, mitaas ang imong nibel ug nahanaw ang imong sakit nga gibati.",
"reachedLevel": "Nakamtan mo ang Nibel <%= level %>",
"yourRewards": "Imong Daog"
}
+10 -1
View File
@@ -106,5 +106,14 @@
"achievementLegendaryBestiaryModalText": "Posbíral/a jsi všechny mytické mazlíčky!",
"achievementLegendaryBestiaryText": "Posbíral/a všechny mytické mazlíčky: draka, létající prase, gryfona, mořského hada a jednorožce!",
"achievementLegendaryBestiary": "Legendární bestiář",
"achievementSeasonalSpecialist": "Sezónní specialista"
"achievementSeasonalSpecialist": "Sezónní specialista",
"achievementVioletsAreBlueText": "Posbíral/a všechny mazlíčky z Modré Cukrové Vaty.",
"achievementVioletsAreBlue": "Fialky jsou Modré",
"achievementVioletsAreBlueModalText": "Posbíral/a jsi všechny mazlíčky z Modré Cukrové Vaty.",
"achievementSeasonalSpecialistModalText": "Dokončl/a jsi všechny sezónní úkoly!",
"achievementDomesticatedModalText": "Sesbíral/a jsi všechna domácí zvířata!",
"achievementSeasonalSpecialistText": "Dokončil/a jsi všechny Jarní a Zimní sezónní úkoly: Honba za vajíčky, Pastičkář Santa, a najdi Cuba!",
"achievementWildBlueYonderText": "Ochočil/a všechny zvířata z Modré Cukrové Vaty.",
"achievementWildBlueYonderModalText": "Ochočil/a jsi všechny mazlíčky z Modré Cukrové Vaty!",
"achievementDomesticatedText": "Vylíhl/a všechna standardní zbarvení domácích zvířat: Fretka, morče, kohout, létající prasátko, krysa, králík, kůň a kráva!"
}
+19 -1
View File
@@ -340,5 +340,23 @@
"singleCompletion": "Single - Completes when any assigned user finishes",
"allAssignedCompletion": "All - Completes when all assigned users finish",
"pmReported": "Tak, fordi du rapporterede denne besked.",
"features": "Funktioner"
"features": "Funktioner",
"invitedToPartyBy": "<a href=\"/profile/<%- userId %>\" target=\"_blank\">@<%- userName %></a> har inviteret dig til holdet <span class=\"notification-bold\"><%- party %></span>",
"PMUserDoesNotReceiveMessages": "Denne bruger modtager ikke længere private beskeder",
"blockedToSendToThisUser": "Du kan ikke sende til denne spiller da du har blokeret denne spiller.",
"blockYourself": "Du kan ikke blokere dig selv",
"selectGift": "Vælg Gave",
"sendGiftToWhom": "Hvem vil du gerne sende en gave til?",
"PMDisabled": "Slå Private Beskeder fra",
"editGuild": "Rediger Klan",
"sendGiftTotal": "I alt:",
"usernameOrUserId": "Indtast @brugernavn eller Bruger ID",
"sendGiftLabel": "Vil du gerne sende en gavebesked?",
"giftMessageTooLong": "Maximum længe for gavebeskeden er <%= maxGiftMessageLength %>.",
"userWithUsernameOrUserIdNotFound": "Brugernavn eller Bruger ID findes ikke.",
"editParty": "Rediger Hold",
"leaveGuild": "Forlad Klan",
"joinGuild": "Tilslut Klan",
"PMUnblockUserToSendMessages": "Fjern denne brugers blokering for at sende og modtage beskeder.",
"selectSubscription": "Vælg Abonnement"
}
+4 -1
View File
@@ -141,5 +141,8 @@
"achievementWoodlandWizardText": "Du hast alle Standard-Farben der Waldkreaturen ausgebrütet: Dachs, Bär, Hirsch, Fuchs, Frosch, Igel, Eule, Schnecke, Eichhörnchen und Bäumling!",
"achievementBoneToPickModalText": "Du hast alle klassischen und Quest-Skeletthaustiere gesammelt!",
"achievementBoneToPick": "Ein harter Knochen",
"achievementBoneToPickText": "Hat alle klassischen und Quest-Skeletthaustiere ausgebrütet!"
"achievementBoneToPickText": "Hat alle klassischen und Quest-Skeletthaustiere ausgebrütet!",
"achievementPolarProText": "Hat alle Standardfarben der Polar-Haustiere ausgebrütet: Bär, Fuchs, Pinguin, Wal und Wolf!",
"achievementPolarPro": "Polar-Profi",
"achievementPolarProModalText": "Du hast alle Polar-Haustiere gesammelt!"
}
+12 -1
View File
@@ -745,5 +745,16 @@
"backgroundAutumnBridgeNotes": "Bewundere die Schönheit einer Brücke im Herbst.",
"backgrounds122022": "Set 103: Veröffentlicht im Dezember 2022",
"backgroundBranchesOfAHolidayTreeText": "Äste eines Festtagsbaums",
"backgroundBranchesOfAHolidayTreeNotes": "Baumle auf den Ästen eines Festtagsbaums."
"backgroundBranchesOfAHolidayTreeNotes": "Baumle auf den Ästen eines Festtagsbaums.",
"backgrounds032023": "SET 106: Veröffentlicht im März 2023",
"backgrounds022023": "SET 195: Veröffentlicht im Februar 2023",
"backgroundGoldenBirdcageText": "Goldener Vogelkäfig",
"backgroundGoldenBirdcageNotes": "Verstecken in einem goldenen Vogelkäfig.",
"backgrounds012023": "SET 104: Veröffentlicht Januar 2023",
"backgroundRimeIceText": "Raureif",
"backgroundRimeIceNotes": "Bewundere funkelnden Raureif.",
"backgroundSnowyTempleText": "Verschneiter Tempel",
"backgroundSnowyTempleNotes": "Einen ruhigen verschneiten Tempel anschauen.",
"backgroundSnowyVillageText": "Verschneites Dorf",
"backgroundSnowyVillageNotes": "Ein verschneites Dorf bewundern."
}
@@ -129,5 +129,6 @@
"commGuidePara017": "Hier ist die Kurzfassung, aber wir möchten Dich ermutigen, weiter unten mehr Details zu erfahren:",
"commGuideList02M": "Frage nicht nach oder bettle nicht um Edelsteine, Abonnements oder die Mitgliedschaft in Gruppenplänen. Nachrichten dieser Art sind weder in der Taverne, noch in öffentlichen oder privaten Chaträumen, und auch nicht in Privatnachrichten erlaubt. Wenn Du Nachrichten erhältst, in denen man Dich um bezahlte Artikel fragt, melde sie bitte über das Fähnchen. Wiederholte oder extreme Betteleien nach Edelsteinen oder Abonnements, vor allem nachdem bereits eine Warnung ausgesprochen wurde, können zu einer Kontosperre führen.",
"commGuideList09D": "Entfernung oder Herabstufung des Mitwirkenden-Ranges",
"commGuideList05H": "Schwerwiegende oder wiederholte Versuche, andere Spielende zu betrügen oder zu bedrängen, um an Gegenstände zu kommen, die echtes Geld kosten"
"commGuideList05H": "Schwerwiegende oder wiederholte Versuche, andere Spielende zu betrügen oder zu bedrängen, um an Gegenstände zu kommen, die echtes Geld kosten",
"commGuideList02N": "<strong>Markiere und melde Nachrichten, in denen diese Richtlinien oder die Nutzungsbedingungen nicht eingehalten werden.</strong> Wir werden uns so schnell wie möglich darum kümmern. Alternativ kannst du Mitarbeiter:innen über <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a> benachrichtigen, doch die Markierung ist der schnellste Weg, um Hilfe zu erhalten."
}
+1 -1
View File
@@ -166,7 +166,7 @@
"assignedToUser": "Zugewiesen: <strong>@<%- userName %></strong>",
"assignedToMembers": "<%= userCount %> Mitgliedern",
"assignedToYouAndMembers": "<strong>Dir</strong>, <%= userCount %> Mitgliedern",
"youAreAssigned": "Dir zugewiesen",
"youAreAssigned": "Zugewiesen: <strong>Dir<strong>",
"taskIsUnassigned": "Diese Aufgabe ist niemandem zugewiesen",
"confirmUnClaim": "Bist Du sicher, dass Du diese Aufgabe abgeben möchtest?",
"confirmNeedsWork": "Bist Du sicher, dass Du diese Aufgabe auf \"Benötigt Arbeit\" setzen möchtest?",
+8 -1
View File
@@ -235,5 +235,12 @@
"fall2022HarpyMageSet": "Harpyie (Magier)",
"fall2022WatcherHealerSet": "Beobachter (Heiler)",
"gemSaleHow": "Kauf einfach zwischen <%= eventStartMonth %> <%= eventStartOrdinal %>und <%= eventEndOrdinal %> eines der Edelstein-Pakete wie normal und Deinem Konto werden automatisch die zusätzlichen Edelsteine gutgeschrieben. Das heißt insgesamt mehr Edelsteine zum ausgeben, teilen oder ansparen für zukünftige Veröffentlichungen!",
"gemSaleLimitations": "Dieses Sonderangebot gilt nur während der zeitlich beschränkten Aktion. Die Aktion startet am <%= eventStartOrdinal %>. <%= eventStartMonth %> um 8:00 EDT (12:00 UTC) und endet am <%= eventEndOrdinal %>. <%= eventStartMonth %> um 20:00 PM EDT (00:00 UTC). Das Sonderangebot ist nur verfügbar, wenn Du Edelsteine für Dich selbst kaufst."
"gemSaleLimitations": "Dieses Sonderangebot gilt nur während der zeitlich beschränkten Aktion. Die Aktion startet am <%= eventStartOrdinal %>. <%= eventStartMonth %> um 8:00 EDT (12:00 UTC) und endet am <%= eventEndOrdinal %>. <%= eventStartMonth %> um 20:00 PM EDT (00:00 UTC). Das Sonderangebot ist nur verfügbar, wenn Du Edelsteine für Dich selbst kaufst.",
"winter2023WalrusWarriorSet": "Walross (Krieger)",
"winter2023FairyLightsMageSet": "Feenlichter (Magier)",
"winter2023CardinalHealerSet": "Kardinal (Heiler)",
"dateStartFebruary": "8. Februar",
"anniversaryLimitedDates": "30. Januar bis 8. Februar",
"limitedEvent": "Limitiertes Event",
"winter2023RibbonRogueSet": "Schleife (Schurke)"
}
+2 -1
View File
@@ -113,5 +113,6 @@
"gryphatrice": "Greifatrice",
"tooMuchFood": "Du versuchst zu viel Futter an Dein Haustier zu verfüttern, Aktion abgebrochen",
"notEnoughFood": "Du hast nicht genug Futter",
"invalidAmount": "Ungültige Menge Futter, positiver Integer benötigt"
"invalidAmount": "Ungültige Menge Futter, positiver Integer benötigt",
"jubilantGryphatrice": "Jubelnder Greifatrice"
}
+4 -1
View File
@@ -144,5 +144,8 @@
"achievementBoneToPickModalText": "You collected all the Classic and Quest Skeleton Pets!",
"achievementPolarPro": "Polar Pro",
"achievementPolarProText": "Has hatched all standard colors of Polar pets: Bear, Fox, Penguin, Whale, and Wolf!",
"achievementPolarProModalText": "You collected all the Polar Pets!"
"achievementPolarProModalText": "You collected all the Polar Pets!",
"achievementPlantParent": "Plant Parent",
"achievementPlantParentText": "Has hatched all standard colors of Plant pets: Cactus and Treeling!",
"achievementPlantParentModalText": "You collected all the Plant Pets!"
}
+27 -3
View File
@@ -845,11 +845,35 @@
"backgrounds012023": "SET 104: Released January 2023",
"backgroundRimeIceText": "Rime Ice",
"backgroundRimeIceNotes": "Admire Sparkly Rime Ice.",
"backgroundRimeIceNotes": "Admire sparkly Rime Ice.",
"backgroundSnowyTempleText": "Snowy Temple",
"backgroundSnowyTempleNotes": "View a Serene Snowy Temple.",
"backgroundSnowyTempleNotes": "View a serene Snowy Temple.",
"backgroundWinterLakeWithSwansText": "Winter Lake With Swans",
"backgroundWinterLakeWithSwansNotes": "Enjoy Nature at a Winter Lake With Swans.",
"backgroundWinterLakeWithSwansNotes": "Enjoy nature at a Winter Lake With Swans.",
"backgrounds022023": "SET 105: Released February 2023",
"backgroundInFrontOfFountainText": "In Front of a Fountain",
"backgroundInFrontOfFountainNotes": "Stroll In Front of a Fountain.",
"backgroundGoldenBirdcageText": "Golden Birdcage",
"backgroundGoldenBirdcageNotes": "Hide out in a Golden Birdcage.",
"backgroundFancyBedroomText": "Fancy Bedroom",
"backgroundFancyBedroomNotes": "Luxuriate in a Fancy Bedroom.",
"backgrounds032023": "SET 106: Released March 2023",
"backgroundOldTimeyBasketballCourtText": "Old Timey Basketball Court",
"backgroundOldTimeyBasketballCourtNotes": "Shoot hoops on an Old Timey BasketBall Court.",
"backgroundJungleWateringHoleText": "Jungle Watering Hole",
"backgroundJungleWateringHoleNotes": "Stop for a sip at a Jungle Watering Hole.",
"backgroundMangroveForestText": "Mangrove Forest",
"backgroundMangroveForestNotes": "Explore the edge of the Mangrove Forest.",
"backgrounds042023": "SET 107: Released April 2023",
"backgroundLeafyTreeTunnelText": "Leafy Tree Tunnel",
"backgroundLeafyTreeTunnelNotes": "Wander through a Leafy Tree Tunnel.",
"backgroundSpringtimeShowerText": "Springtime Shower",
"backgroundSpringtimeShowerNotes": "See a Flowery Springtime Shower.",
"backgroundUnderWisteriaText": "Under Wisteria",
"backgroundUnderWisteriaNotes": "Relax Under Wisteria.",
"timeTravelBackgrounds": "Steampunk Backgrounds",
"backgroundAirshipText": "Airship",
@@ -5,53 +5,55 @@
"commGuideHeadingWelcome": "Welcome to Habitica!",
"commGuidePara001": "Greetings, adventurer! Welcome to Habitica, the land of productivity, healthy living, and the occasional rampaging gryphon. We have a cheerful community full of helpful people supporting each other on their way to self-improvement. To fit in, all it takes is a positive attitude, a respectful manner, and the understanding that everyone has different skills and limitations -- including you! Habiticans are patient with one another and try to help whenever they can.",
"commGuidePara002": "To help keep everyone safe, happy, and productive in the community, we do have some guidelines. We have carefully crafted them to make them as friendly and easy-to-read as possible. Please take the time to read them before you start chatting.",
"commGuidePara003": "These rules apply to all of the social spaces we use, including (but not necessarily limited to) Trello, GitHub, Weblate, and the Habitica Wiki on Fandom. As communities grow and change, their rules may adapt from time to time. When there are substantive changes to these Guidelines, you'll hear about it in a Bailey announcement and/or our social media!",
"commGuidePara003": "These rules apply to all of the social spaces we use, including (but not necessarily limited to) Trello, GitHub, Weblate, and the Habitica Wiki on Fandom. As communities grow and change, their rules may adapt from time to time. When there are substantive changes to the community rules listed here, you'll hear about it in a Bailey announcement and/or our social media!",
"commGuideHeadingInteractions": "Interactions in Habitica",
"commGuidePara015": "Habitica has two kinds of social spaces: public, and private. Public spaces include the Tavern, Public Guilds, GitHub, Trello, and the Wiki. Private spaces are Private Guilds, Party chat, and Private Messages. All Display Names and @usernames must comply with the public space guidelines. To change your Display Name and/or @username, on mobile go to Menu > Settings > Profile. On web, go to User > Settings.",
"commGuidePara016": "When navigating the public spaces in Habitica, there are some general rules to keep everyone safe and happy.",
"commGuidePara017": "Here's the quick version, but we encourage you to read in more detail below:",
"commGuideList01F": "Please flag posts that break our Community Guidelines or TOS.",
"commGuideList01A": "Terms & Conditions apply across all spaces, including private guilds, party chat, and messages.",
"commGuideList01B": "Prohibited: Any communication that is violent, threatening, promoting of discrimination etc. including memes, images, and jokes.",
"commGuideList01C": "All discussions must be appropriate for all ages and be free of profanity.",
"commGuideList01D": "Please comply with mod requests.",
"commGuideList01E": "Do not instigate or engage in contentious conversation in the Tavern.",
"commGuideList01D": "Please comply with staff requests.",
"commGuideList01E": "<strong>Do not instigate or engage in contentious conversation in the Tavern.</strong>",
"commGuideList01F": "No begging for paid items, spamming, or large header text/all caps.",
"commGuideList02N": "<strong>Flag and report posts that break these Guidelines or the Terms of Service.</strong> We will handle them as quickly as possible. You may also notify staff via <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a> but flags are the fastest way to get help.",
"commGuideList02A": "<strong>Respect each other</strong>. Be courteous, kind, friendly, and helpful. Remember: Habiticans come from all backgrounds and have had wildly divergent experiences. This is part of what makes Habitica so cool! Building a community means respecting and celebrating our differences as well as our similarities.",
"commGuideList02B": "<strong>Obey all of the <a href='/static/terms' target='_blank'>Terms and Conditions</a></strong> in both public and private spaces.",
"commGuideList02G": "<strong>Comply immediately with any Mod request.</strong> This could include, but is not limited to, requesting you limit your posts in a particular space, editing your profile to remove unsuitable content, asking you to move your discussion to a more suitable space, etc. Do not argue with moderators. If you have concerns or comments about moderation, email <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a> to contact our community manager.",
"commGuideList02B": "<strong>Obey all of the <a href='https://habitica.com/static/terms' target='_blank'>Terms and Conditions</a></strong> in both public and private spaces.",
"commGuideList02G": "<strong>Comply immediately with any Staff request.</strong> This could include, but is not limited to, requesting you limit your posts in a particular space, editing your profile to remove unsuitable content, asking you to move your discussion to a more suitable space, etc. Do not argue with staff. If you have concerns or comments about staff actions, email <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a> to contact our community manager.",
"commGuideList02C": "<strong>Do not post images or text that are violent, threatening, or sexually explicit/suggestive, or that promote discrimination, bigotry, racism, sexism, hatred, harassment or harm against any individual or group</strong>. Not even as a joke or meme. This includes slurs as well as statements. Not everyone has the same sense of humor, and so something that you consider a joke may be hurtful to another.",
"commGuideList02D": "<strong>Keep discussions appropriate for all ages</strong>. This means avoiding adult topics in public spaces. We have many young Habiticans who use the site, and people come from all walks of life. We want our community to be as comfortable and inclusive as possible.",
"commGuideList02E": "<strong>Avoid profanity. This includes milder, religious-based oaths that may be acceptable elsewhere and abbreviated or obscured profanity.</strong> We have people from all religious and cultural backgrounds, and we want to make sure that all of them feel comfortable in public spaces. <strong>If a moderator or staff member tells you that a term is disallowed on Habitica, even if it is a term that you did not realize was problematic, that decision is final.</strong> Additionally, slurs will be dealt with very severely, as they are also a violation of the Terms of Service.",
"commGuideList02F": "Avoid extended discussions of divisive topics in the Tavern and where it would be off-topic. If someone mentions something that is allowed by the guidelines but which is hurtful to you, it's okay to politely let them know that. If someone tells you you've made them uncomfortable, take time to reflect instead of responding in anger. But if you feel that a conversation is getting heated, overly emotional, or hurtful, <strong>cease to engage. Instead, report the posts to let us know about it.</strong> Moderators will respond as quickly as possible. You may also email <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a> and include screenshots if they may be helpful.",
"commGuideList02E": "<strong>Avoid profanity. This includes abbreviated or obscured profanity.</strong> We have people from all religious and cultural backgrounds, and we want to make sure that all of them feel comfortable in public spaces. <strong>If a staff member tells you that a term is disallowed on Habitica, even if it is a term that you did not realize was problematic, that decision is final.</strong> Additionally, slurs will be dealt with very severely, as they are also a violation of the Terms of Service.",
"commGuideList02F": "Avoid extended discussions of divisive topics in the Tavern and where it would be off-topic. If someone mentions something that is allowed by the guidelines but which is hurtful to you, it's okay to politely let them know that. If someone tells you you've made them uncomfortable, take time to reflect instead of responding in anger. But if you feel that a conversation is getting heated, overly emotional, or hurtful, <strong>cease to engage. Instead, report the posts to let us know about it. </strong>Staff will respond as quickly as possible. You may also email <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a> and include screenshots if they may be helpful.",
"commGuideList02M": "Do not ask or beg for gems, subscriptions or membership in Group Plans. This is not allowed in the Tavern, public or private chat spaces, or in PMs. If you receive messages asking for paid items, please report them by flagging. Repeated or severe gem or subscription begging, especially after a warning, may result in an account ban.",
"commGuideList02J": "<strong>Do not spam</strong>. Spamming may include, but is not limited to: posting the same comment or query in multiple places, <strong>posting links without explanation or context</strong>, posting nonsensical messages, posting multiple promotional messages about a Guild, Party or Challenge, or posting many messages in a row. If people clicking on a link will result in any benefit to you, you need to disclose that in the text of your message or that will also be considered spam. Mods may decide what constitutes spam at their discretion.",
"commGuideList02J": "<strong>Do not spam</strong>. Spamming may include, but is not limited to: posting the same comment or query in multiple places, <strong>posting links without explanation or context</strong>, posting nonsensical messages, posting multiple promotional messages about a Guild, Party or Challenge, or posting many messages in a row. If people clicking on a link will result in any benefit to you, you need to disclose that in the text of your message or that will also be considered spam. Staff may decide what constitutes spam at their discretion.",
"commGuideList02K": "<strong>Avoid posting large header text in the public chat spaces, particularly the Tavern</strong>. Much like ALL CAPS, it reads as if you were yelling, and interferes with the comfortable atmosphere.",
"commGuideList02L": "<strong>We highly discourage the exchange of personal information -- particularly information that can be used to identify you -- in public chat spaces</strong>. Identifying information can include but is not limited to: your address, your email address, and your API token/password. This is for your safety! Staff or moderators may remove such posts at their discretion. If you are asked for personal information in a private Guild, Party, or PM, we highly recommend that you politely refuse and alert the staff and moderators by either 1) flagging the message, or 2) emailing <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a> and including screenshots.",
"commGuideList02L": "<strong>We highly discourage the exchange of personal information -- particularly information that can be used to identify you -- in public chat spaces</strong>. Identifying information can include but is not limited to: your address, your email address, and your API token/password. This is for your safety! Staff may remove such posts at their discretion. If you are asked for personal information in a private Guild, Party, or PM, we highly recommend that you politely refuse and alert the staff by either 1) flagging the message, or 2) emailing <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a> and including screenshots.",
"commGuidePara019": "<strong>In private spaces</strong>, users have more freedom to discuss whatever topics they would like, but they still may not violate the Terms and Conditions, including posting slurs or any discriminatory, violent, or threatening content. Note that, because Challenge names appear in the winner's public profile, ALL Challenge names must obey the public space guidelines, even if they appear in a private space.",
"commGuidePara020": "<strong>Private Messages (PMs)</strong> have some additional guidelines. If someone has blocked you, do not contact them elsewhere to ask them to unblock you. Additionally, you should not send PMs to someone asking for support (since public answers to support questions are helpful to the community). Finally, do not send anyone PMs begging for paid content of any kind.",
"commGuidePara020A": "<strong>If you see a post or private message that you believe is in violation of the public space guidelines outlined above, or if you see a post or private message that concerns you or makes you uncomfortable, you can bring it to the attention of Moderators and Staff by clicking the flag icon to report it</strong>. A Staff member or Moderator will respond to the situation as soon as possible. Please note that intentionally reporting innocent posts is an infraction of these Guidelines (see below in \"Infractions\"). You can also contact the Mods by emailing <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a> You may want to do this if there are multiple problematic posts by the same person in different Guilds, or if the situation requires some explanation. You may contact us in your native language if that is easier for you: we may have to use Google Translate, but we want you to feel comfortable about contacting us if you have a problem.",
"commGuidePara020A": "<strong>If you see a post or private message that you believe is in violation of the public space guidelines outlined above, or if you see a post or private message that concerns you or makes you uncomfortable, you can bring it to the attention of Staff by clicking the flag icon to report it</strong>. A Staff member will respond to the situation as soon as possible. Please note that intentionally reporting innocent posts is an infraction of these Guidelines (see below in \"Infractions\"). You can also contact the Staff by emailing <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a> You may want to do this if there are multiple problematic posts by the same person in different Guilds, or if the situation requires some explanation. You may contact us in your native language if that is easier for you: we may have to use Google Translate, but we want you to feel comfortable about contacting us if you have a problem.",
"commGuidePara021": "Furthermore, some public spaces in Habitica have additional guidelines.",
"commGuideHeadingTavern": "The Tavern",
"commGuidePara022": "The Tavern is the main spot for Habiticans to mingle. Daniel the Innkeeper keeps the place spic-and-span, and Lemoness will happily conjure up some lemonade while you sit and chat. Just keep in mind…",
"commGuidePara023": "<strong>Conversation tends to revolve around casual chatting and productivity or life improvement tips</strong>. Because the Tavern chat can only hold 200 messages, <strong>it isn't a good place for prolonged conversations on topics, especially sensitive ones</strong> (ex. politics, religion, depression, whether or not goblin-hunting should be banned, etc.). These conversations should be taken to an applicable Guild. A Mod may direct you to a suitable Guild, but it is ultimately your responsibility to find and post in the appropriate place.",
"commGuidePara023": "<strong>Conversation tends to revolve around casual chatting and productivity or life improvement tips</strong>. Because the Tavern chat can only hold 200 messages, <strong>it isn't a good place for prolonged conversations on topics, especially sensitive or contentious ones</strong> (ex. politics, religion, depression, whether or not goblin-hunting should be banned, etc.). These conversations should be taken to an applicable Guild. Staff may direct you to a suitable Guild, but it is ultimately your responsibility to find and post in the appropriate place.",
"commGuidePara024": "<strong>Don't discuss anything addictive in the Tavern</strong>. Many people use Habitica to try to quit their bad Habits. Hearing people talk about addictive/illegal substances may make this much harder for them! Respect your fellow Tavern-goers and take this into consideration. This includes, but is not exclusive to: smoking, alcohol, pornography, gambling, and drug use/abuse.",
"commGuideHeadingPublicGuilds": "Public Guilds",
"commGuidePara029": "<strong>Public Guilds are much like the Tavern, except that instead of being centered around general conversation, they have a focused theme</strong>. Public Guild chat should focus on this theme. For example, members of the Wordsmiths Guild might be cross if the conversation is suddenly focusing on gardening instead of writing, and a Dragon-Fanciers Guild might not have any interest in deciphering ancient runes. Some Guilds are more lax about this than others, but in general, <strong>try to stay on topic</strong>!",
"commGuidePara031": "Some public Guilds will contain sensitive topics such as depression, religion, politics, etc. This is fine as long as the conversations therein do not violate any of the Terms and Conditions or Public Space Rules, and as long as they stay on topic.",
"commGuidePara033": "<strong>Public Guilds may NOT contain 18+ content. If they plan to regularly discuss sensitive content, they should say so in the Guild description</strong>. This is to keep Habitica safe and comfortable for everyone.",
"commGuidePara035": "<strong>If the Guild in question has different kinds of sensitive issues, it is respectful to your fellow Habiticans to place your comment behind a warning (ex. \"Warning: references self-harm\")</strong>. These may be characterized as trigger warnings and/or content notes, and Guilds may have their own rules in addition to those given here. If possible, please use <a href='https://habitica.fandom.com/wiki/Markdown_Cheat_Sheet' target='_blank'>markdown</a> to hide the potentially sensitive content below line breaks so that those who may wish to avoid reading it can scroll past it without seeing the content. Habitica staff and moderators may still remove this material at their discretion.",
"commGuidePara035": "<strong>If the Guild in question has different kinds of sensitive issues, it is respectful to your fellow Habiticans to include a warning (ex. \"Warning: references self-harm\")</strong>. These may be characterized as trigger warnings and/or content notes, and Guilds may have their own rules in addition to those given here. Habitica staff may still remove this material at their discretion.",
"commGuidePara036": "Additionally, the sensitive material should be topical -- bringing up self-harm in a Guild focused on fighting depression may make sense, but is probably less appropriate in a music Guild. If you see someone who is repeatedly violating this guideline, especially after several requests, please report the posts.",
"commGuidePara037": "<strong>No Guilds, Public or Private, should be created for the purpose of attacking any group or individual</strong>. Creating such a Guild is grounds for an instant ban. Fight bad habits, not your fellow adventurers!",
"commGuidePara038": "<strong>All Tavern Challenges and Public Guild Challenges must comply with these rules as well</strong>.",
"commGuideHeadingInfractionsEtc": "Infractions, Consequences, and Restoration",
"commGuideHeadingInfractions": "Infractions",
"commGuidePara050": "Overwhelmingly, Habiticans assist each other, are respectful, and work to make the whole community fun and friendly. However, once in a blue moon, something that a Habitican does may violate one of the above guidelines. When this happens, the Mods will take whatever actions they deem necessary to keep Habitica safe and comfortable for everyone.",
"commGuidePara051": "<strong>There are a variety of infractions, and they are dealt with depending on their severity</strong>. These are not comprehensive lists, and the Mods can make decisions on topics not covered here at their own discretion. The Mods will take context into account when evaluating infractions.",
"commGuidePara050": "Overwhelmingly, Habiticans assist each other, are respectful, and work to make the whole community fun and friendly. However, once in a blue moon, something that a Habitican does may violate one of the above guidelines. When this happens, the Staff will take whatever actions they deem necessary to keep Habitica safe and comfortable for everyone.",
"commGuidePara051": "<strong>There are a variety of infractions, and they are dealt with depending on their severity</strong>. These are not comprehensive lists, and the Staff can make decisions on topics not covered here at their own discretion. The Staff will take context into account when evaluating infractions.",
"commGuideHeadingSevereInfractions": "Severe Infractions",
"commGuidePara052": "Severe infractions greatly harm the safety of Habitica's community and users, and therefore have severe consequences as a result.",
@@ -59,16 +61,16 @@
"commGuideList05A": "Violation of Terms and Conditions",
"commGuideList05B": "Hate Speech/Images, Harassment/Stalking, Cyber-Bullying, Flaming, and Trolling",
"commGuideList05C": "Violation of Probation",
"commGuideList05D": "Impersonation of Staff or Moderators - this includes claiming user-created spaces not affiliated with Habitica are official and/or moderated by Habitica or its Mods/staff",
"commGuideList05D": "Impersonation of Staff - this includes claiming user-created spaces not affiliated with Habitica are official and/or moderated by Habitica or its Staff",
"commGuideList05E": "Repeated Moderate Infractions",
"commGuideList05F": "Creation of a duplicate account to avoid consequences (for example, making a new account to chat after having chat privileges revoked)",
"commGuideList05G": "Intentional deception of Staff or Moderators in order to avoid consequences or to get another user in trouble",
"commGuideList05G": "Intentional deception of Staff in order to avoid consequences or to get another user in trouble",
"commGuideList05H": "Severe or repeated attempts to defraud or pressure other players for real-money items",
"commGuideHeadingModerateInfractions": "Moderate Infractions",
"commGuidePara054": "Moderate infractions do not make our community unsafe, but they do make it unpleasant. These infractions will have moderate consequences. When in conjunction with multiple infractions, the consequences may grow more severe.",
"commGuidePara055": "The following are some examples of Moderate Infractions. This is not a comprehensive list.",
"commGuideList06A": "Ignoring, disrespecting or arguing with a Mod. This includes publicly complaining about moderators or other users, publicly glorifying or defending banned users, or debating whether or not a moderator action was appropriate. If you are concerned about one of the rules or the behaviour of the Mods, please contact the staff via email (<a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a>).",
"commGuideList06A": "<strong>Ignoring, disrespecting or arguing with Staff.</strong> This includes publicly complaining about staff or other users, publicly glorifying or defending banned users, or debating whether or not a staff action was appropriate. If you are concerned about one of the rules or the behavior of the Staff, please contact us via email (<a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a>).",
"commGuideList06B": "Backseat Modding. To quickly clarify a relevant point: A friendly mention of the rules is fine. Backseat modding consists of telling, demanding, and/or strongly implying that someone must take an action that you describe to correct a mistake. You can alert someone to the fact that they have committed a transgression, but please do not demand an action -- for example, saying, \"Just so you know, profanity is discouraged in the Tavern, so you may want to delete that,\" would be better than saying, \"I'm going to have to ask you to delete that post.\"",
"commGuideList06C": "Intentionally flagging innocent posts.",
"commGuideList06D": "Repeatedly Violating Public Space Guidelines",
@@ -78,14 +80,14 @@
"commGuidePara056": "Minor Infractions, while discouraged, still have minor consequences. If they continue to occur, they can lead to more severe consequences over time.",
"commGuidePara057": "The following are some examples of Minor Infractions. This is not a comprehensive list.",
"commGuideList07A": "First-time violation of Public Space Guidelines",
"commGuideList07B": "Any statements or actions that trigger a \"Please Don't\" from a Mod. When you are asked not to do something publicly, this in itself can be a consequence. If Mods have to issue many of these corrections to the same person, it may count as a larger infraction",
"commGuideList07B": "Any statements or actions that trigger a \"Please Don't\" from a Staff member. When you are asked not to do something publicly, this in itself can be a consequence. If Staff have to issue many of these corrections to the same person, it may count as a larger infraction",
"commGuidePara057A": "Some posts may be hidden because they contain sensitive information or might give people the wrong idea. Typically this does not count as an infraction, particularly not the first time it happens!",
"commGuideHeadingConsequences": "Consequences",
"commGuidePara058": "In Habitica -- as in real life -- every action has a consequence, whether it is getting fit because you've been running, getting cavities because you've been eating too much sugar, or passing a class because you've been studying.",
"commGuidePara059": "<strong>Similarly, all infractions have direct consequences.</strong> Some sample consequences are outlined below.",
"commGuidePara060": "<strong>If your infraction has a moderate or severe consequence, there will be a post from a staff member or moderator in the forum in which the infraction occurred explaining</strong>:",
"commGuidePara060": "<strong>If your infraction has a moderate or severe consequence, if appropriate for the circumstances, there will be a post from a staff member in the forum in which the infraction occurred explaining</strong>:",
"commGuideList08A": "what your infraction was",
"commGuideList08B": "what the consequence is",
"commGuideList08C": "what to do to correct the situation and restore your status, if possible.",
@@ -97,35 +99,29 @@
"commGuideList09D": "Removal or demotion of Contributor Tiers",
"commGuideHeadingModerateConsequences": "Examples of Moderate Consequences",
"commGuideList10A": "Restricted public and/or private chat privileges",
"commGuideList10A1": "If your actions result in revocation of your chat privileges, a Moderator or Staff member will PM you and/or post in the forum in which you were muted to notify you of the reason for your muting and the length of time for which you will be muted and/or the action required for reinstatement. You will be reinstated if you comply politely with the actions required and agree to abide by the Community Guidelines and ToS",
"commGuideList10C": "Restricted Guild/Challenge creation privileges",
"commGuideList10A1": "If your actions result in revocation of your chat privileges, you must email <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a>. You may be reinstated at staff discretion if you comply politely with the actions required and agree to abide by the Community Guidelines and ToS",
"commGuideList10D": "Temporarily disabling (\"freezing\") progression through Contributor Tiers",
"commGuideList10F": "Putting users on \"Probation\"",
"commGuideHeadingMinorConsequences": "Examples of Minor Consequences",
"commGuideList11A": "Reminders of Public Space Guidelines",
"commGuideList11B": "Warnings",
"commGuideList11C": "Requests",
"commGuideList11D": "Deletions (Mods/Staff may delete problematic content)",
"commGuideList11E": "Edits (Mods/Staff may edit problematic content)",
"commGuideList11D": "Deletions (Staff may delete problematic content)",
"commGuideList11E": "Edits (Staff may edit problematic content)",
"commGuideHeadingRestoration": "Restoration",
"commGuidePara061": "Habitica is a land devoted to self-improvement, and we believe in second chances. <strong>If you commit an infraction and receive a consequence, view it as a chance to evaluate your actions and strive to be a better member of the community</strong>.",
"commGuidePara062": "The announcement, message, and/or email that you receive explaining the consequences of your actions is a good source of information. Cooperate with any restrictions which have been imposed, and endeavor to meet the requirements to have any penalties lifted.",
"commGuidePara063": "If you do not understand your consequences, or the nature of your infraction, ask the Staff/Moderators for help so you can avoid committing infractions in the future. If you feel a particular decision was unfair, you can contact the staff to discuss it at <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a>.",
"commGuidePara063": "If you do not understand your consequences, or the nature of your infraction, ask the Staff for help so you can avoid committing infractions in the future. If you feel a particular decision was unfair, you can contact the staff to discuss it at <a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a>.",
"commGuideHeadingMeet": "Meet the Staff and Mods!",
"commGuidePara006": "Habitica has some tireless knights-errant who join forces with the staff members to keep the community calm, contented, and free of trolls. Each has a specific domain, but will sometimes be called to serve in other social spheres.",
"commGuidePara007": "Staff have purple tags marked with crowns. Their title is \"Heroic\".",
"commGuidePara008": "Mods have dark blue tags marked with stars. Their title is \"Guardian\".",
"commGuideHeadingMeet": "Meet the Staff",
"commGuidePara007": "The Habitica Staff keep the app and sites running and can act as chat moderators. They have purple tags marked with crowns. Their title is \"Heroic\".",
"commGuidePara009": "The current Staff Members are (from left to right):",
"commGuideAKA": "<%= habitName %> aka <%= realName %>",
"commGuideOnGitHub": "<%= gitHubName %> on GitHub",
"commGuidePara010": "There are also several Moderators who assist the staff members. They were selected carefully, so please give them your respect and listen to their suggestions.",
"commGuidePara011": "The current Moderators are (from left to right):",
"commGuidePara011b": "on GitHub/Fandom",
"commGuidePara011c": "on the Wiki",
"commGuidePara011d": "on GitHub",
"commGuidePara012": "If you have an issue or concern about a particular Mod, please send an email to our Staff (<a href='mailto:admin@habitica.com' target='_blank'>admin@habitica.com</a>).",
"commGuidePara013": "In a community as big as Habitica, users come and go, and sometimes a staff member or moderator needs to lay down their noble mantle and relax. The following are Staff and Moderators Emeritus. They no longer act with the power of a Staff member or Moderator, but we would still like to honor their work!",
"commGuidePara014": "Staff and Moderators Emeritus:",
+2
View File
@@ -310,6 +310,8 @@
"hatchingPotionOnyx": "Onyx",
"hatchingPotionVirtualPet": "Virtual Pet",
"hatchingPotionPorcelain": "Porcelain",
"hatchingPotionPinkMarble": "Pink Marble",
"hatchingPotionTeaShop": "Tea Shop",
"hatchingPotionNotes": "Pour this on an egg, and it will hatch as a <%= potText(locale) %> pet.",
"premiumPotionAddlNotes": "Not usable on quest pet eggs. Available for purchase until <%= date(locale) %>.",
+3 -2
View File
@@ -65,7 +65,7 @@
"pkQuestion1": "What inspired Habitica? How did it start?",
"pkAnswer1": "If youve ever invested time in leveling up a character in a game, its hard not to wonder how great your life would be if you put all of that effort into improving your real-life self instead of your avatar. We starting building Habitica to address that question. <br /> Habitica officially launched with a Kickstarter in 2013, and the idea really took off. Since then, its grown into a huge project, supported by our awesome open-source volunteers and our generous users.",
"pkQuestion2": "Why does Habitica work?",
"pkAnswer2": "Forming a new habit is hard because people really need that obvious, instant reward. For example, its tough to start flossing, because even though our dentist tells us that it's healthier in the long run, in the immediate moment it just makes your gums hurt. <br /> Habitica's gamification adds a sense of instant gratification to everyday objectives by rewarding a tough task with experience, gold… and maybe even a random prize, like a dragon egg! This helps keep people motivated even when the task itself doesn't have an intrinsic reward, and we've seen people turn their lives around as a result. You can check out success stories here: https://habitversary.tumblr.com",
"pkAnswer2": "Forming a new habit is hard because people really need that obvious, instant reward. For example, its tough to start flossing, because even though our dentist tells us that it's healthier in the long run, in the immediate moment it just makes your gums hurt. <br /> Habitica's gamification adds a sense of instant gratification to everyday objectives by rewarding a tough task with experience, gold… and maybe even a random prize, like a dragon egg! This helps keep people motivated even when the task itself doesn't have an intrinsic reward, and we've seen people turn their lives around as a result.",
"pkQuestion3": "Why did you add social features?",
"pkAnswer3": "Social pressure is a huge motivating factor for a lot of people, so we knew that we wanted to have a strong community that would hold each other accountable for their goals and cheer for their successes. Luckily, one of the things that multiplayer video games do best is foster a sense of community among their users! Habiticas community structure borrows from these types of games; you can form a small Party of close friends, but you can also join a larger, shared-interest groups known as a Guild. Although some users choose to play solo, most decide to form a support network that encourages social accountability through features such as Quests, where Party members pool their productivity to battle monsters together.",
"pkQuestion4": "Why does skipping tasks remove your avatars health?",
@@ -179,5 +179,6 @@
"signup": "Sign Up",
"getStarted": "Get Started!",
"mobileApps": "Mobile Apps",
"learnMore": "Learn More"
"learnMore": "Learn More",
"translateHabitica": "Translate Habitica"
}
+56 -3
View File
@@ -460,7 +460,7 @@
"weaponSpecialFall2022HealerNotes": "To claim victory, hold it forth and utter the words of command: 'Eye One!' Increases Intelligence by <%= int %>. Limited Edition 2022 Fall Gear.",
"weaponSpecialWinter2023RogueText": "Green Satin Sash",
"weaponSpecialWinter2023RogueNotes": "Legends tell of Rogues who snare their opponents' weapons, disarm them, then gift the item back just to be cute. Incrases Strength by <%= str %>. Limited Edition 2022-2023 Winter Gear.",
"weaponSpecialWinter2023RogueNotes": "Legends tell of Rogues who snare their opponents' weapons, disarm them, then gift the item back just to be cute. Increases Strength by <%= str %>. Limited Edition 2022-2023 Winter Gear.",
"weaponSpecialWinter2023WarriorText": "Tusk Spear",
"weaponSpecialWinter2023WarriorNotes": "The two prongs of this spear are shaped like walrus tusks but are twice as powerful. Jab at doubts and at silly poems until they back off! Increases Strength by <%= str %>. Limited Edition 2022-2023 Winter Gear.",
"weaponSpecialWinter2023MageText": "Foxfire",
@@ -468,6 +468,15 @@
"weaponSpecialWinter2023HealerText": "Throwing Wreath",
"weaponSpecialWinter2023HealerNotes": "Watch this festive, prickly wreath spin through the air toward your enemy or obstacles and return to you like a boomerang for another throw. Increases Intelligence by <%= int %>. Limited Edition 2022-2023 Winter Gear.",
"weaponSpecialSpring2023RogueText": "Nibbled Leaf",
"weaponSpecialSpring2023RogueNotes": "Slash! Swat! Snack! Get strong and ready for your coming metamorphosis. Increases Strength by <%= str %>. Limited Edition 2023 Spring Gear.",
"weaponSpecialSpring2023WarriorText": "Hummingbird Foil",
"weaponSpecialSpring2023WarriorNotes": "En garde! Fend off foes from your flowers with this foil! Increases Strength by <%= str %>. Limited Edition 2023 Spring Gear.",
"weaponSpecialSpring2023MageText": "Moonstone Magic",
"weaponSpecialSpring2023MageNotes": "The greater their glow, the more potent is their power. Increases Intelligence by <%= int %>. Limited Edition 2023 Spring Gear.",
"weaponSpecialSpring2023HealerText": "Lilium Pollen",
"weaponSpecialSpring2023HealerNotes": "With a puff and a sparkle, you deploy new growth, joy, and color. Increases Intelligence by <%= int %>. Limited Edition 2023 Spring Gear.",
"weaponMystery201411Text": "Pitchfork of Feasting",
"weaponMystery201411Notes": "Stab your enemies or dig in to your favorite foods - this versatile pitchfork does it all! Confers no benefit. November 2014 Subscriber Item.",
"weaponMystery201502Text": "Shimmery Winged Staff of Love and Also Truth",
@@ -1131,6 +1140,15 @@
"armorSpecialWinter2023HealerText": "Cardinal Suit",
"armorSpecialWinter2023HealerNotes": "This bright cardinal suit is perfect for flying high above your problems. Increases Constitution by <%= con %>. Limited Edition 2022-2023 Winter Gear.",
"armorSpecialSpring2023RogueText": "Caterpillar Cape",
"armorSpecialSpring2023RogueNotes": "You may only have four limbs to work with, but you can climb and crawl with the greatest of grubs. Increases Perception by <%= per %>. Limited Edition 2023 Spring Gear.",
"armorSpecialSpring2023WarriorText": "Hummingbird Armor",
"armorSpecialSpring2023WarriorNotes": "That humming sound you hear is your wings beating faster than you can imagine. Increases Constitution by <%= con %>. Limited Edition 2023 Spring Gear.",
"armorSpecialSpring2023MageText": "Moonstone Suit",
"armorSpecialSpring2023MageNotes": "This snazzy spring suit magnifies moonstone magic. Increases Intelligence by <%= int %>. Limited Edition 2023 Spring Gear.",
"armorSpecialSpring2023HealerText": "Lily Leaf Gown",
"armorSpecialSpring2023HealerNotes": "A sweep of verdant glory to make you the envy of the Party. Increases Constitution by <%= con %>. Limited Edition 2023 Spring Gear.",
"armorMystery201402Text": "Messenger Robes",
"armorMystery201402Notes": "Shimmering and strong, these robes have many pockets to carry letters. Confers no benefit. February 2014 Subscriber Item.",
"armorMystery201403Text": "Forest Walker Armor",
@@ -1245,6 +1263,9 @@
"armorMystery202210Notes": "Try slithering for a change, you may find it's quite an efficient mode of transportation! Confers no benefit. October 2022 Subscriber Item.",
"armorMystery202212Text": "Glacial Dress",
"armorMystery202212Notes": "The universe can be cold, but this charming dress will keep you cozy as you fly. Confers no benefit. December 2022 Subscriber Item.",
"armorMystery202304Text": "Tiptop Teapot Armor",
"armorMystery202304Notes": "Here is your handle and here is your spout! Confers no benefit. April 2023 Subscriber Item.",
"armorMystery301404Text": "Steampunk Suit",
"armorMystery301404Notes": "Dapper and dashing, wot! Confers no benefit. February 3015 Subscriber Item.",
"armorMystery301703Text": "Steampunk Peacock Gown",
@@ -1428,7 +1449,11 @@
"armorArmoireJewelersApronNotes": "This heavy-duty apron is just the thing to wear when you feel creative. Best of all, there are dozens of small pockets to hold everything you need. Increases Intelligence by <%= int %>. Enchanted Armoire: Jeweler Set (Item 1 of 4).",
"armorArmoireShawlCollarCoatText": "Shawl-Collar Coat",
"armorArmoireShawlCollarCoatNotes": "A wise wizard once said theres nothing better than being both cozy and productive! Wear this warm and stylish coat as you conquer the years challenges. Increases Constitution by <%= con %>. Enchanted Armoire: Independent Item.",
"armorArmoireTeaGownText": "Tea Party Gown",
"armorArmoireTeaGownNotes": "Youre resilient, creative, brilliant, and so fashionable! Increases Strength and Intelligence by <%= attrs %> each. Enchanted Armoire: Tea Party Set (Item 1 of 3).",
"armorArmoireBasketballUniformText": "Basketball Uniform",
"armorArmoireBasketballUniformNotes": "Wondering whats printed on the back of this uniform? Its your lucky number, of course! Increases Perception by <% per %>. Enchanted Armoire: Old Timey Basketball Set (Item 1 of 2).",
"headgear": "helm",
"headgearCapitalized": "Headgear",
@@ -1869,6 +1894,15 @@
"headSpecialWinter2023HealerText": "Cardinal Helm",
"headSpecialWinter2023HealerNotes": "This cardinal helm is perfect for whistling and singing to herald the winter season. Increases Intelligence by <%= int %>. Limited Edition 2022-2023 Winter Gear.",
"headSpecialSpring2023RogueText": "Caterpillar Cowl",
"headSpecialSpring2023RogueNotes": "Be sure to tuck in those tempting antennae when birds are hunting overhead! Increases Perception by <%= per %>. Limited Edition 2023 Spring Gear.",
"headSpecialSpring2023WarriorText": "Hummingbird Helmet",
"headSpecialSpring2023WarriorNotes": "Cover your visage in iridescent feathers when you fly into battle. Increases Strength by <%= str %>. Limited Edition 2023 Spring Gear.",
"headSpecialSpring2023MageText": "Moonstone Visor",
"headSpecialSpring2023MageNotes": "Youll want to wear these glasses at night so you can see clearly by the light of the moon. Increases Perception by <%= per %>. Limited Edition 2023 Spring Gear.",
"headSpecialSpring2023HealerText": "Lily Bloom",
"headSpecialSpring2023HealerNotes": "This brilliant and colorful display shares a color scheme with the Orb of Rebirth! How symbolic! Increases Intelligence by <%= int %>. Limited Edition 2023 Spring Gear.",
"headSpecialGaymerxText": "Rainbow Warrior Helm",
"headSpecialGaymerxNotes": "In celebration of the GaymerX Conference, this special helmet is decorated with a radiant, colorful rainbow pattern! GaymerX is a game convention celebrating LGTBQ and gaming and is open to everyone.",
@@ -2014,6 +2048,11 @@
"headMystery202211Notes": "Be careful with this powerful hat, its effect on admirers can be quite shocking! Confers no benefit. November 2022 Subscriber Item.",
"headMystery202301Text": "Valiant Vulpine Ears",
"headMystery202301Notes": "Your hearing will be so sharp you'll hear the dawn breaking and the dew sparkling. Confers no benefit. January 2023 Subscriber Item.",
"headMystery202303Text": "Mane Character Hair",
"headMystery202303Notes": "What better way to let everyone know youre the star of this tale than to have blue and improbably spiky hair? Confers no benefit. March 2023 Subscriber Item.",
"headMystery202304Text": "Tiptop Teapot Lid",
"headMystery202304Notes": "Wear this helm for your own safe-tea. Confers no benefit. April 2023 Subscriber Item.",
"headMystery301404Text": "Fancy Top Hat",
"headMystery301404Notes": "A fancy top hat for the finest of gentlefolk! January 3015 Subscriber Item. Confers no benefit.",
"headMystery301405Text": "Basic Top Hat",
@@ -2189,6 +2228,10 @@
"headArmoireStrawRainHatNotes": "Youll be able to spot every obstacle in your path when you wear this water-resistant, conical hat. Increases Perception by <%= per %>. Enchanted Armoire: Straw Raincoat Set (Item 2 of 2).",
"headArmoireFancyPirateHatText": "Fancy Pirate Hat",
"headArmoireFancyPirateHatNotes": "Be protected from the sun and any seagulls flying overhead as you drink tea on the deck of your ship. Increases Perception by <%= per %>. Enchanted Armoire: Fancy Pirate Set (Item 2 of 3).",
"headArmoireTeaHatText": "Tea Party Hat",
"headArmoireTeaHatNotes": "This elegant hat is both fancy and functional. Increases Perception by <%= per %>. Enchanted Armoire: Tea Party Set (Item 2 of 3).",
"headArmoireBeaniePropellerHatText": "Beanie Propeller Hat",
"headArmoireBeaniePropellerHatNotes": "This isnt the time to keep your feet on the ground! Spin this little propeller and rise as high as your ambitions will take you. Increases all stats by <%= attrs %>. Enchanted Armoire: Independent Item.",
"offhand": "off-hand item",
"offHandCapitalized": "Off-Hand Item",
@@ -2436,6 +2479,11 @@
"shieldSpecialWinter2023HealerText": "Cool Jams",
"shieldSpecialWinter2023HealerNotes": "Your song of frost and snow will soothe the spirits of all who hear. Increases Constitution by <%= con %>. Limited Edition 2022-2023 Winter Gear.",
"shieldSpecialSpring2023WarriorText": "Flower Bunch",
"shieldSpecialSpring2023WarriorNotes": "Collect the springs best flowers into this brightly colored floral bunch. Increases Constitution by <%= con %>. Limited Edition 2023 Spring Gear.",
"shieldSpecialSpring2023HealerText": "Lily Corsage",
"shieldSpecialSpring2023HealerNotes": "An accent for a healing visit, or part of a ritual for attending a springtime dance! Increases Constitution by <%= con %>. Limited Edition 2023 Spring Gear.",
"shieldMystery201601Text": "Resolution Slayer",
"shieldMystery201601Notes": "This blade can be used to parry away all distractions. Confers no benefit. January 2016 Subscriber Item.",
"shieldMystery201701Text": "Time-Freezer Shield",
@@ -2595,7 +2643,10 @@
"shieldArmoireBubblingCauldronNotes": "The perfect cauldron for brewing up a productivity potion or cooking a savory soup. In fact, there is little difference between the two! Increases Constitution by <%= con %>. Enchanted Armoire: Cooking Implements Set (Item 2 of 2).",
"shieldArmoireJewelersPliersText": "Jeweler's Pliers",
"shieldArmoireJewelersPliersNotes": "They cut, twist, pinch, and more. This tool can help you create whatever you can imagine. Increases Strength by <%= str %>. Enchanted Armoire: Jeweler Set (Item 3 of 4).",
"shieldArmoireTeaKettleText": "Tea Kettle",
"shieldArmoireTeaKettleNotes": "All your favorite, flavorful teas can be brewed in this kettle. Are you in the mood for black tea, green tea, oolong, or perhaps an herbal infusion? Increases Constitution by <%= con %>. Enchanted Armoire: Tea Party Set (Item 3 of 3).",
"shieldArmoireBasketballText": "Basketball",
"shieldArmoireBasketballNotes": "Swish! Whenever you shoot this magic basketball, there will be nothing but net. Increases Constitution and Strength by <%= attrs %> each. Enchanted Armoire: Old Timey Basketball Set (Item 2 of 2).",
"back": "Back Accessory",
"backBase0Text": "No Back Accessory",
@@ -2965,6 +3016,8 @@
"eyewearMystery202204BNotes": "What's your mood today? Express yourself with these fun screens. Confers no benefit. April 2022 Subscriber Item.",
"eyewearMystery202208Text": "Sparkly Eyes",
"eyewearMystery202208Notes": "Lull your enemies into a false sense of security with these terrifyingly cute peepers. Confers no benefit. August 2022 Subscriber Item.",
"eyewearMystery202303Text": "Dreamy Eyes",
"eyewearMystery202303Notes": "Let your nonchalant expression lure your enemies into a false sense of security. Confers no benefit. March 2023 Subscriber Item.",
"eyewearMystery301404Text": "Eyewear Goggles",
"eyewearMystery301404Notes": "No eyewear could be fancier than a pair of goggles - except, perhaps, for a monocle. Confers no benefit. April 3015 Subscriber Item.",
"eyewearMystery301405Text": "Monocle",
+4 -1
View File
@@ -212,5 +212,8 @@
"contactForm": "Contact the Moderation Team",
"loadEarlierMessages": "Load Earlier Messages",
"askQuestion": "Ask a Question",
"emptyReportBugMessage": "Report Bug Message missing"
"emptyReportBugMessage": "Report Bug Message missing",
"leaveHabitica": "You are about to leave Habitica.com",
"leaveHabiticaText": "Habitica is not responsible for the content of any linked website that is not owned or operated by HabitRPG.<br>Please note that these websites' practices may differ from Habiticas community guidelines.",
"skipExternalLinkModal": "Hold CTRL (Windows) or Command (Mac) when clicking a link to skip this modal."
}
+2 -1
View File
@@ -25,6 +25,7 @@
"invite": "Invite",
"leave": "Leave",
"invitedToParty": "You were invited to join the Party <span class=\"notification-bold\"><%- party %></span>",
"invitedToPartyBy": "<a href=\"/profile/<%- userId %>\" target=\"_blank\">@<%- userName %></a> has invited you to join the Party <span class=\"notification-bold\"><%- party %></span>",
"invitedToPrivateGuild": "You were invited to join the private Guild <span class=\"notification-bold\"><%- guild %></span>",
"invitedToPublicGuild": "You were invited to join the Guild <span class=\"notification-bold-blue\"><%- guild %></span>",
"invitationAcceptedHeader": "Your Invitation has been Accepted",
@@ -334,7 +335,7 @@
"teamBasedTasksList": "Team-Based Task List",
"teamBasedTasksListDesc": "Set up an easily-viewed shared task list for the group. Assign tasks to your fellow group members, or let them claim their own tasks to make it clear what everyone is working on!",
"groupManagementControls": "Group Management Controls",
"groupManagementControlsDesc": "Use task approvals to verify that a task that was really completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
"groupManagementControlsDesc": "View task status to verify that a task that was completed, add Group Managers to share responsibilities, and enjoy a private group chat for all team members.",
"inGameBenefits": "In-Game Benefits",
"inGameBenefitsDesc": "Group members get an exclusive Jackalope Mount, as well as full subscription benefits, including special monthly equipment sets and the ability to buy gems with gold.",
"inspireYourParty": "Inspire your party, gamify life together.",
+5 -1
View File
@@ -194,7 +194,11 @@
"winter2023WalrusWarriorSet": "Walrus (Warrior)",
"winter2023FairyLightsMageSet": "Fairy Lights (Mage)",
"winter2023CardinalHealerSet": "Cardinal (Healer)",
"winter2023RibbonRogueSet": "Ribbon (Rogue)",
"winter2023RibbonRogueSet": "Ribbon (Rogue)",
"spring2023CaterpillarRogueSet": "Caterpillar (Rogue)",
"spring2023HummingbirdWarriorSet": "Hummingbird (Warrior)",
"spring2023MoonstoneMageSet": "Moonstone (Mage)",
"spring2023LilyHealerSet": "Lily (Healer)",
"eventAvailability": "Available for purchase until <%= date(locale) %>.",
"eventAvailabilityReturning": "Available for purchase until <%= availableDate(locale) %>. This potion was last available in <%= previousDate(locale) %>.",
"dateEndJanuary": "January 31",
+11 -1
View File
@@ -877,5 +877,15 @@
"questVirtualPetRageDescription": "This bar fills when you don't complete your Dailies. When it is full, the Wotchimon will take away some of your party's pending damage!",
"questVirtualPetRageEffect": "`Wotchimon uses Bothersome Beep!` Wotchimon sounds a bothersome beep, and its happiness bar suddenly disappears! Pending damage reduced.",
"questVirtualPetDropVirtualPetPotion": "Virtual Pet Hatching Potion",
"questVirtualPetUnlockText": "Unlocks Virtual Pet Hatching Potion for purchase in the Market"
"questVirtualPetUnlockText": "Unlocks Virtual Pet Hatching Potion for purchase in the Market",
"questPinkMarbleText": "Calm the Corrupted Cupid",
"questPinkMarbleNotes": "After hearing rumors about a cave in the Meandering Mountains that has pink rocks and dust shooting out of it, your party starts to investigate. As you approach the cave, there is indeed a huge pink dust cloud and strangely, you hear a tiny voice's battle cry, followed by the sound of shattering rock.<br><br>@Empress42 accidentally inhales some of the dust and suddenly feels dreamy and less productive. “Same here!” says @QuartzFox, “I'm suddenly fantasizing about a person that I barely know!”<br><br>@a_diamond peeks into the cave and finds a little being zipping around and smashing pink marbled rock to dust. “Take cover! This Cupid has been corrupted and is using his magic to cause limerence and unrealistic infatuations! We have to subdue him!”",
"questPinkMarbleCompletion": "You manage to pin the little guy down at last he was much tougher and faster than expected. Before he stirs again, you take away his quiver of glowing arrows. He blinks and suddenly looks around in surprise. “To escape my own sorrow and heartbreak for a while I pricked myself with one of my arrows… I don't remember anything after that!”<br><br>He is just about to flee the cave, notices that @Loremi has taken a sample of the marble dust and grins. “Try using some of this pink marble dust in a potion! Nurture the pets that hatch from it and you will find that real relationships are born from communication, mutual trust and care. I wish you luck, and I wish you love!”",
"questPinkMarbleBoss": "Cupido",
"questPinkMarbleRageTitle": "Pink Punch",
"questPinkMarbleRageDescription": "This bar fills when you don't complete your Dailies. When it is full, Cupido will take away some of your party's pending damage!",
"questPinkMarbleRageEffect": "`Cupido uses Pink Punch!` That wasn't affectionate at all! Your partymates are taken aback. Pending damage reduced.",
"questPinkMarbleDropPinkMarblePotion": "Pink Marble Hatching Potion",
"QuestPinkMarbleUnlockText": "Unlocks Pink Marble Hatching Potions for purchase in the Market."
}
+1
View File
@@ -75,6 +75,7 @@
"chatExtensionDesc": "The Chat Extension for Habitica adds an intuitive chat box to all of habitica.com. It allows users to chat in the Tavern, their party, and any guilds they are in.",
"otherExtensions": "<a target='blank' href='https://habitica.fandom.com/wiki/Extensions,_Add-Ons,_and_Customizations'>Other Extensions</a>",
"otherDesc": "Find other apps, extensions, and tools on the Habitica wiki.",
"thirdPartyTools": "Find third party apps, extensions, and all kinds of other tools you can use with your account on the <a href='https://habitica.fandom.com/wiki/Extensions,_Add-Ons,_and_Customizations' target='_blank'>Habitica wiki</a>.",
"resetDo": "Do it, reset my account!",
"resetComplete": "Reset complete!",
"fixValues": "Fix Values",
@@ -147,6 +147,8 @@
"mysterySet202212": "Glacial Guardian Set",
"mysterySet202301": "Valiant Vulpine Set",
"mysterySet202302": "Trickster Tabby Set",
"mysterySet202303": "Mane Character Set",
"mysterySet202304": "Tiptop Teapot Set",
"mysterySet301404": "Steampunk Standard Set",
"mysterySet301405": "Steampunk Accessories Set",
"mysterySet301703": "Peacock Steampunk Set",
+10 -1
View File
@@ -138,5 +138,14 @@
"achievementReptacularRumble": "Rumble reptacular",
"achievementWoodlandWizard": "Mago del bosque",
"achievementWoodlandWizardModalText": "¡Has recogido todas las mascotas del bosque!",
"achievementWoodlandWizardText": "Ha incubado todos los colores estándar de las criaturas del bosque: Tejón, Oso, Ciervo, Zorro, Rana, Erizo, Búho, Caracol, Ardilla y Treeling!"
"achievementWoodlandWizardText": "Ha incubado todos los colores estándar de las criaturas del bosque: Tejón, Oso, Ciervo, Zorro, Rana, Erizo, Búho, Caracol, Ardilla y Treeling!",
"achievementBoneToPick": "Hueso para recoger",
"achievementBoneToPickText": "¡Ha eclosionado todas las mascotas Clásicas y de Misión Esqueléticas!",
"achievementPolarPro": "Experto Polar",
"achievementPolarProModalText": "¡Has coleccionado todas las mascotas Polares!",
"achievementBoneToPickModalText": "¡Has coleccionado todas las mascotas clásicas y de misiones esqueléticas!",
"achievementPolarProText": "¡Ha eclosionado todos los colores estándar para mascotas Polares: Osos, Zorros, Pinguinos, Ballenas y Lobos!",
"achievementPlantParent": "Progenitor de las Plantas",
"achievementPlantParentText": "¡Ha eclosionado todos los colores estándar para las mascotas Planta: Cáctus y Esqueje de árbol!",
"achievementPlantParentModalText": "¡Has coleccionado todas las Mascotas Planta!"
}
+50 -7
View File
@@ -7,8 +7,8 @@
"backgrounds062014": "1.ª serie: publicada en junio de 2014",
"backgroundBeachText": "Playa",
"backgroundBeachNotes": "Relájate en una cálida playa.",
"backgroundFairyRingText": "Anillo de hada",
"backgroundFairyRingNotes": "Baila en un anillo de hada.",
"backgroundFairyRingText": "Anillo de hadas",
"backgroundFairyRingNotes": "Baila en un anillo de hadas.",
"backgroundForestText": "Bosque",
"backgroundForestNotes": "Pasea por un bosque estival.",
"backgrounds072014": "2.ª serie: publicada en julio de 2014",
@@ -17,7 +17,7 @@
"backgroundOpenWatersText": "Aguas abiertas",
"backgroundOpenWatersNotes": "Disfruta de las aguas abiertas.",
"backgroundSeafarerShipText": "Bajel de marineros",
"backgroundSeafarerShipNotes": "Navega a bordo de un barco de marineros.",
"backgroundSeafarerShipNotes": "Navega a bordo de un barco marinero.",
"backgrounds082014": "3.ª serie: publicada en agosto de 2014",
"backgroundCloudsText": "Nubes",
"backgroundCloudsNotes": "Planea entre las nubes.",
@@ -27,7 +27,7 @@
"backgroundVolcanoNotes": "Entra en calor dentro de un volcán.",
"backgrounds092014": "4.ª serie: publicada en septiembre de 2014",
"backgroundThunderstormText": "Tormenta eléctrica",
"backgroundThunderstormNotes": "Dirige un rayo en la tormenta eléctrica.",
"backgroundThunderstormNotes": "Conduce rayos en la tormenta eléctrica.",
"backgroundAutumnForestText": "Bosque otoñal",
"backgroundAutumnForestNotes": "Pasea por un bosque otoñal.",
"backgroundHarvestFieldsText": "Campos de cultivo",
@@ -675,7 +675,7 @@
"backgroundOrangeGroveText": "Naranjal",
"backgroundOrangeGroveNotes": "Deambula por un naranjal fragante.",
"backgrounds022022": "93.ª serie: publicada en febrero de 2022",
"backgrounds032022": "94.ª serie: publiccada en marzo de 2022",
"backgrounds032022": "94.ª serie: publicada en marzo de 2022",
"backgroundBrickWallWithIvyText": "Pared de Ladrillo con Hiedra",
"backgroundBrickWallWithIvyNotes": "Admira una Pared de Ladrillo con Hiedra.",
"backgrounds042022": "95ª. serie: publicada en abril de 2022",
@@ -689,7 +689,7 @@
"backgroundFloweringPrairieText": "Pradera floreciente",
"backgroundSpringtimeLakeText": "Lago de Primavera",
"backgroundSpringtimeLakeNotes": "Disfruta las vistas a orillas de un Lago de Primavera.",
"hideLockedBackgrounds": "Esconde fondos cerrados",
"hideLockedBackgrounds": "Ocultar fondos bloqueados",
"backgroundBioluminescentWavesText": "Olas Bioluminiscentes",
"backgroundBioluminescentWavesNotes": "Admira el resplandor de Olas Bioluminiscentes.",
"backgroundUnderwaterCaveNotes": "Explora una Cueva Subacuática.",
@@ -724,5 +724,48 @@
"backgroundAutumnPicnicText": "Picnic otoñal",
"backgroundAutumnPicnicNotes": "Disfruta un picnic otoñal.",
"backgroundOldPhotoText": "Foto antigua",
"backgroundOldPhotoNotes": "Posa en una foto antigua."
"backgroundOldPhotoNotes": "Posa en una foto antigua.",
"backgrounds022023": "105ª serie: publicada en febrero del 2023",
"backgroundInFrontOfFountainText": "Frente a una fuente",
"backgroundInFrontOfFountainNotes": "Pasea frente a una fuente.",
"backgroundGoldenBirdcageText": "Jaula de pájaros dorada",
"backgroundFancyBedroomText": "Dormitorio elegante",
"backgroundFancyBedroomNotes": "Deléitate con un dormitorio elegante.",
"backgroundGoldenBirdcageNotes": "Escóndete en una jaula de pájaros dorada.",
"backgrounds012023": "104ª serie: publicada en enero del 2023",
"backgroundRimeIceText": "Hielo escarchado",
"backgroundRimeIceNotes": "Admira el brillante hielo escarchado.",
"backgroundSnowyTempleText": "Templo nevado",
"backgroundSnowyTempleNotes": "Contempla un sereno templo nevado.",
"backgroundWinterLakeWithSwansText": "Lago invernal con cisnes",
"backgroundWinterLakeWithSwansNotes": "Disfruta de la naturaleza en un lago invernal con cisnes.",
"eventBackgrounds": "Fondos de Evento",
"backgroundBirthdayBashText": "Fiesta de cumpleaños",
"backgroundBirthdayBashNotes": "Habitica está celebrando una fiesta de cumpleaños, ¡y todos están invitados!",
"backgroundMistyAutumnForestText": "Bosque otoñal brumoso",
"backgroundMistyAutumnForestNotes": "Camina a través de un brumoso bosque otoñal.",
"backgroundAutumnBridgeText": "Puente en otoño",
"backgroundAutumnBridgeNotes": "Admira la belleza de un puente en otoño.",
"backgrounds102022": "101ª serie: publicada en octubre de 2022",
"backgroundSpookyRuinsText": "Ruinas espeluznantes",
"backgroundMaskMakersWorkshopNotes": "Prueba una nueva cara en el taller del fabricante de máscaras.",
"backgroundMaskMakersWorkshopText": "Taller del fabricante de máscaras",
"backgroundCemeteryGateText": "Puerta del cementerio",
"backgroundCemeteryGateNotes": "Ronda la puerta del cementerio.",
"backgrounds122022": "103ª serie: publicada en diciembre del 2022",
"backgroundBranchesOfAHolidayTreeText": "Ramas de un árbol navideño",
"backgroundBranchesOfAHolidayTreeNotes": "Retoza en las ramas de un árbol navideño.",
"backgroundInsideACrystalText": "Dentro de un cristal",
"backgroundInsideACrystalNotes": "Asómate desde el interior desde un cristal.",
"backgroundSnowyVillageText": "Pueblo nevado",
"backgroundSpookyRuinsNotes": "Explora unas ruinas espeluznantes.",
"backgrounds112022": "102ª serie: publicada en noviembre del 2022",
"backgroundAmongGiantMushroomsText": "Entre setas gigantes",
"backgroundAmongGiantMushroomsNotes": "Maravillate con las setas gigantes.",
"backgroundSnowyVillageNotes": "Admira un pueblo nevado.",
"backgroundOldTimeyBasketballCourtNotes": "Echa unas canastas en una cancha de baloncesto antigua.",
"backgroundMangroveForestText": "Bosque de Manglares",
"backgroundMangroveForestNotes": "Explora las lindes del Bosque de Manglares.",
"backgrounds032023": "106.ª serie: publicada en marzo de 2023",
"backgroundOldTimeyBasketballCourtText": "Cancha de Baloncesto Antigua"
}

Some files were not shown because too many files have changed in this diff Show More