{{i18n "patreon.group"}} | 17 |{{i18n "patreon.rewards"}} | 18 |19 | |
---|---|---|
{{rule.group}} | 26 |{{rule.rewards}} | 27 |
28 |
29 |
37 | |
38 |
57 |
58 |
65 | |
66 |
{{i18n "patreon.help_text"}}
71 | 72 |هل يعجبك موقعنا؟ هل ترغب في التبرع لصالح قضية جيدة؟
49 | 50 |51 | إذا كنت تجد موقعنا مفيدًا وتستمتع بالمجتمع الذي أنشأناه، فسنسعد كثيرًا بتبرعك لموقعنا. 52 | تحافظ التبرعات على تشغيل خدماتنا بسلاسة وتضمن استمرار مجتمعنا في العمل لسنوات قادمة. 53 | كل دولار يصنع الفارق وسيتم توظيفه جيدًا. 54 |
55 | 56 |شكرًا لك على دعمك!
57 | 58 |
59 | انضم إلى الرعاة 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.be.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | be: 8 | js: 9 | patreon: 10 | group: 'Група' 11 | filter: 'Filter' 12 | edit: 'Рэдагаваць' 13 | delete: 'Выдаліць' 14 | save: 'Захаваць' 15 | field: 16 | email: "электронная пошта" 17 | -------------------------------------------------------------------------------- /config/locales/client.bg.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | bg: 8 | js: 9 | patreon: 10 | group: 'Група' 11 | filter: 'Филтер' 12 | edit: 'Редактирай' 13 | delete: 'Изтрий' 14 | save: 'Запази' 15 | field: 16 | email: "Имейл" 17 | -------------------------------------------------------------------------------- /config/locales/client.bs_BA.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | bs_BA: 8 | js: 9 | patreon: 10 | group: 'Grupa' 11 | filter: 'Filter' 12 | edit: 'Izmijeni' 13 | delete: 'Delete' 14 | save: 'Sačuvaj' 15 | field: 16 | email: "Email" 17 | -------------------------------------------------------------------------------- /config/locales/client.ca.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ca: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Filtres' 16 | group: 'Grup' 17 | rewards: 'Recompenses' 18 | filter: 'Filtre' 19 | help_text: 'Podeu sincronitzar un grup de Discourse amb un o més nivells de recompensa de Patreon.' 20 | last_synced: 'Última sincronització' 21 | edit: 'Edita' 22 | delete: 'Suprimeix' 23 | save: 'Desa' 24 | update_data: 'Actualitza les dades de Patreon i sincronitza els grups' 25 | refresh_page: 'S''han descarregat dades noves de l''API de Patreon. Actualitzeu la pàgina.' 26 | field: 27 | id: "Id" 28 | email: "Correu electrònic" 29 | amount_cents: "Quantitat (en cèntims)" 30 | rewards: "Recompenses" 31 | declined_since: "Compromís refusat des de" 32 | more_details: 33 | label: "Pagaments i més detalls" 34 | help_text: 35 | email_available: "Aneu a la part inferior dreta de la pàgina per a veure l'historial de compromís de Patreon." 36 | email_not_available: "Seleccioneu el membre de Patreon i aneu a la part inferior dreta de la pàgina per a veure l'historial de compromisos." 37 | -------------------------------------------------------------------------------- /config/locales/client.cs.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | cs: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Filtry' 16 | group: 'Skupina' 17 | rewards: 'Odměny' 18 | filter: 'Filtr' 19 | edit: 'Upravit' 20 | delete: 'Smazat' 21 | save: 'Uložit' 22 | field: 23 | email: "Email" 24 | rewards: "Odměny" 25 | -------------------------------------------------------------------------------- /config/locales/client.da.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | da: 8 | js: 9 | patreon: 10 | group: 'Gruppe' 11 | filter: 'Filter' 12 | edit: 'Rediger' 13 | delete: 'Slet' 14 | save: 'Gem' 15 | field: 16 | email: "Email" 17 | -------------------------------------------------------------------------------- /config/locales/client.de.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | de: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Discourse – Patreon" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: Mit Patreon anmelden 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: 'Filter' 22 | group: 'Gruppe' 23 | rewards: 'Belohnungen' 24 | filter: 'Filter' 25 | help_text: 'Du kannst eine Discourse-Gruppe mit einer oder mehreren Patreon-Belohnungsstufen synchronisieren.' 26 | last_synced: 'Zuletzt synchronisiert' 27 | edit: 'Bearbeiten' 28 | delete: 'Löschen' 29 | save: 'Speichern' 30 | update_data: 'Patreon-Daten aktualisieren und Gruppen synchronisieren' 31 | refresh_page: 'Neue Daten wurden über die Patreon-API heruntergeladen. Bitte lade die Seite neu.' 32 | select_group: 'Gruppe auswählen' 33 | field: 34 | id: "ID" 35 | email: "E-Mail" 36 | amount_cents: "Betrag (in Cent)" 37 | rewards: "Belohnungen" 38 | declined_since: "Spende abgelehnt seit" 39 | more_details: 40 | label: "Zahlungen und weitere Details" 41 | help_text: 42 | email_available: "Gehe nach unten rechts auf der Seite, um den Verlauf der Patreon-Spenden zu sehen." 43 | email_not_available: "Wähle das Patreon-Mitglied aus und gehe auf der Seite nach unten rechts, um den Verlauf der Patreon-Spenden zu sehen." 44 | donation_prompt: 45 | body: | 46 |Gefällt dir unsere Website? Möchtest du einen Beitrag zu einem guten Zweck leisten?
49 | 50 |51 | Wenn du unsere Website hilfreich findest und dir die Community gefällt, die wir geschaffen haben, würden wir uns freuen, wenn du für unsere Website spendest. 52 | Spenden sorgen dafür, dass unsere Dienste reibungslos funktionieren und dass unsere Community auch in den nächsten Jahren weiterbestehen kann. 53 | Jeder Euro zählt und wird sinnvoll eingesetzt. 54 |
55 | 56 |Dankeschön für deine Unterstützung!
57 | 58 |
59 | Patron werden 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.el.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | el: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Φίλτρα' 16 | group: 'Ομάδα' 17 | rewards: 'Ανταμοιβές' 18 | filter: 'Φίλτρο' 19 | help_text: 'Μπορείτε να συγχρονίσετε μια ομάδα Discourse με ένα ή περισσότερα επίπεδα ανταμοιβής Patreon.' 20 | edit: 'Επεξεργασία' 21 | delete: 'Σβήσιμο' 22 | save: 'Αποθήκευση' 23 | field: 24 | email: "Διεύθυνση Email" 25 | amount_cents: "Ποσό (σε λεπτά)" 26 | rewards: "Ανταμοιβές" 27 | -------------------------------------------------------------------------------- /config/locales/client.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | admin_js: 3 | admin: 4 | site_settings: 5 | categories: 6 | discourse_patreon: "Discourse Patreon" 7 | js: 8 | login: 9 | patreon: 10 | name: Patreon 11 | title: Log in with Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Filters' 16 | group: 'Group' 17 | rewards: 'Rewards' 18 | filter: 'Filter' 19 | help_text: 'You can sync a Discourse group with one or more Patreon reward tiers.' 20 | last_synced: 'Last Synced' 21 | edit: 'Edit' 22 | delete: 'Delete' 23 | save: 'Save' 24 | update_data: 'Update Patreon Data & Sync Groups' 25 | refresh_page: 'New data has been downloaded from Patreon API. Please refresh the page.' 26 | select_group: 'Select a group' 27 | field: 28 | id: "Id" 29 | email: "Email" 30 | amount_cents: "Amount (in cents)" 31 | rewards: "Rewards" 32 | declined_since: "Pledge Declined Since" 33 | more_details: 34 | label: "Payments & More Details" 35 | help_text: 36 | email_available: "Reach bottom right of the page to see this Patreon's pledge history." 37 | email_not_available: "Select the Patreon member and reach bottom right of the page to see the pledge history." 38 | donation_prompt: 39 | body: | 40 |Do you like our website? Would you like to contribute to a good cause?
43 | 44 |45 | If find our website helpful and enjoy the community we've created, we would love if you donated to our website. 46 | Donations keep our services running smoothly and ensures that our community will be operational for years to come. 47 | Every dollar counts and will be put to good use. 48 |
49 | 50 |Thank you for your support!
51 | 52 |
53 | Become a Patron 54 |
55 | -------------------------------------------------------------------------------- /config/locales/client.en_GB.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | en_GB: 8 | -------------------------------------------------------------------------------- /config/locales/client.es.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | es: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Patreon de Discourse" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: Iniciar sesión con Patreon 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: 'Filtros' 22 | group: 'Grupo' 23 | rewards: 'Recompensas' 24 | filter: 'Filtro' 25 | help_text: 'Puedes sincronizar un grupo de Discourse con uno o varios niveles de recompensa Patreon.' 26 | last_synced: 'Última sincronización' 27 | edit: 'Editar' 28 | delete: 'Eliminar' 29 | save: 'Guardar' 30 | update_data: 'Actualizar datos de Patreon y sincronizar grupos' 31 | refresh_page: 'Se han descargado nuevos datos desde la API de Patreon. Actualiza la página.' 32 | select_group: 'Selecciona un grupo' 33 | field: 34 | id: "ID" 35 | email: "Correo electrónico" 36 | amount_cents: "Cantidad (en céntimos)" 37 | rewards: "Recompensas" 38 | declined_since: "Promesa rechazada desde" 39 | more_details: 40 | label: "Pagos y más detalles" 41 | help_text: 42 | email_available: "Ve a la parte inferior derecha de la página para ver el historial de promesas de Patreon." 43 | email_not_available: "Selecciona el miembro de Patreon y ve a la parte inferior derecha de la página para ver el historial de promesas." 44 | donation_prompt: 45 | body: | 46 |¿Te gusta nuestro sitio web? ¿Quieres contribuir a una buena causa?
49 | 50 |51 | Si nuestro sitio web te resulta útil y disfrutas de la comunidad que hemos creado, nos encantaría que hicieras una donación a nuestro sitio web. 52 | Las donaciones mantienen nuestros servicios en funcionamiento y garantizan que nuestra comunidad esté operativa durante años. 53 | Cada dólar cuenta y se le dará un buen uso. 54 |
55 | 56 |¡Gracias por tu apoyo!
57 | 58 |
59 | Hazte mecenas 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.et.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | et: 8 | js: 9 | patreon: 10 | header: 11 | rules: 'Filtrid' 12 | group: 'Grupp' 13 | rewards: 'Autasud' 14 | filter: 'Filter' 15 | last_synced: 'Viimati sünkroonitud' 16 | edit: 'Muuda' 17 | delete: 'Kustuta' 18 | save: 'Salvesta' 19 | field: 20 | id: "D" 21 | email: "E-post" 22 | rewards: "Autasud" 23 | -------------------------------------------------------------------------------- /config/locales/client.fa_IR.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | fa_IR: 8 | js: 9 | login: 10 | patreon: 11 | name: پاترئون 12 | patreon: 13 | title: 'پاترون' 14 | header: 15 | rules: 'فیلترها' 16 | group: 'گروه' 17 | rewards: 'پاداش' 18 | filter: 'فیلتر' 19 | edit: 'ویرایش' 20 | delete: 'حذف' 21 | save: 'ذخیره' 22 | select_group: 'یک گروه را انتخاب کنید' 23 | field: 24 | id: "شناسه" 25 | email: "ایمیل" 26 | amount_cents: "مقدار (به سنت)" 27 | rewards: "پاداش" 28 | more_details: 29 | label: "پرداختها و جزئیات بیشتر" 30 | -------------------------------------------------------------------------------- /config/locales/client.fi.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | fi: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Discourse Patreon" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: Kirjaudu Patreonilla 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: 'Suodattimet' 22 | group: 'Ryhmä' 23 | rewards: 'Palkinnot' 24 | filter: 'Suodatin' 25 | help_text: 'Voit synkronoida Discourse-ryhmän yhteen tai useampaan Patreon-palkintotasoon.' 26 | last_synced: 'Viimeksi synkronisoitu' 27 | edit: 'Muokkaa' 28 | delete: 'Poista' 29 | save: 'Tallenna' 30 | update_data: 'Päivitä Patreonin tiedot ja synkronoi ryhmät' 31 | refresh_page: 'Uusia tietoja on ladattu Patreonin APIsta. Päivitä sivu.' 32 | select_group: 'Valitse ryhmä' 33 | field: 34 | id: "Tunnus" 35 | email: "Sähköposti" 36 | amount_cents: "Määrä (senteissä)" 37 | rewards: "Palkinnot" 38 | declined_since: "Lahjoituslupaus peruttu alkaen" 39 | more_details: 40 | label: "Maksut ja muita tietoja" 41 | help_text: 42 | email_available: "Selaa oikeaan alareunaan nähdäksesi tämän Patreonin lahjoituslupaushistoria." 43 | email_not_available: "Valitse Patreon-jäsen ja selaa oikeaan alakulmaan nähdäksesi lahjoituslupaushistorian." 44 | donation_prompt: 45 | body: | 46 |Pidätkö verkkosivustostamme? Haluaisitko osallistua hyvään tarkoitukseen?
49 | 50 |51 | Jos verkkosivustomme on mielestäsi hyödyllinen ja pidät luomastamme yhteisöstä, olisimme iloisia, jos antaisit lahjoituksen verkkosivustollemme. 52 | Lahjoitukset pitävät palvelumme käynnissä ja varmistavat, että yhteisömme jatkaa toimintaansa tulevina vuosina. 53 | Jokainen dollari on tärkeä ja laitetaan hyvään käyttöön. 54 |
55 | 56 |Kiitos tuestasi!
57 | 58 |
59 | Ryhdy tukijaksi 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.fr.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | fr: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Patreon de Discourse" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: Se connecter avec Patreon 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: 'Filtres' 22 | group: 'Groupe' 23 | rewards: 'Récompenses' 24 | filter: 'Filtre' 25 | help_text: 'Vous pouvez synchroniser un groupe Discourse avec un ou plusieurs niveaux de récompense Patreon.' 26 | last_synced: 'Dernière synchronisation' 27 | edit: 'Modifier' 28 | delete: 'Supprimer' 29 | save: 'Enregistrer' 30 | update_data: 'Mettre à jour les données Patreon et synchroniser les groupes' 31 | refresh_page: 'Des nouvelles données ont été téléchargées depuis l''API Patreon. Veuillez actualiser la page.' 32 | select_group: 'Sélectionner un groupe' 33 | field: 34 | id: "ID" 35 | email: "E-mail" 36 | amount_cents: "Montant (en cents)" 37 | rewards: "Récompenses" 38 | declined_since: "Promesse de don refusée depuis le" 39 | more_details: 40 | label: "Paiements et autres détails" 41 | help_text: 42 | email_available: "Vous trouverez l'historique des promesses de don de ce Patreon en bas à droite de cette page." 43 | email_not_available: "Sélectionnez le membre Patreon et accédez à l'historique des promesses de dons en bas à droite de la page." 44 | donation_prompt: 45 | body: | 46 |Appréciez-vous notre site ? Souhaitez-vous soutenir une bonne cause ?
49 | 50 |51 | Si vous trouvez ce site utile et appréciez la communauté que nous avons formée, nous serions ravis de recevoir vos dons. 52 | Les donations permettent le bon fonctionnement de notre service et garantissent que notre communauté reste active pour les années à venir. 53 | Chaque montant est important et sera utilisé à bon escient. 54 |
55 | 56 |Merci pour votre soutien !
57 | 58 |
59 | Devenir mécène 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.gl.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | gl: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreón 12 | patreon: 13 | title: 'Patreón' 14 | header: 15 | rules: 'Filtros' 16 | group: 'Grupo' 17 | rewards: 'Recompensas' 18 | filter: 'Filtro' 19 | help_text: 'Pode sincronizar un grupo de Discourse cun ou máis niveis de recompensa de Patreon.' 20 | last_synced: 'Última sincronización' 21 | edit: 'Editar' 22 | delete: 'Eliminar' 23 | save: 'Gardar' 24 | update_data: 'Actualizar os datos de Patreon e sincronizar os grupos' 25 | refresh_page: 'Descargáronse novos datos da API de Patreon. Actualice a páxina.' 26 | select_group: 'Seleccione un grupo' 27 | field: 28 | id: "Id" 29 | email: "Correo electrónico" 30 | amount_cents: "Cantidade (en céntimos)" 31 | rewards: "Recompensas" 32 | declined_since: "Compromiso rexeitado dende" 33 | more_details: 34 | label: "Pagamentos e máis detalles" 35 | help_text: 36 | email_available: "Acceda á parte inferior dereita da páxina para ver o historial de compromisos deste Patreon." 37 | email_not_available: "Seleccione o membro de Patreon e acceda co botón da parte inferior dereita da páxina para ver o historial de promesas." 38 | donation_prompt: 39 | body: | 40 |Gústalle o noso sitio? Gustaríalle contribuír a unha boa causa?
43 | 44 |45 | Se atopa de utilidade o sitio e lle resulta atractiva a comunidade que fomos creando, estariamos encantados se doase ao noso sitio. 46 | As doazóns manteñen o noso servizo funcionando normalmente e asegura que a nosa comunidade estará operativa nos vindeiros anos. 47 | Cada moeda conta e faremos bo uso delas. 48 |
49 | 50 |Grazas polo seu apoio!
51 | 52 |
53 | Fágase Patron 54 |
55 | -------------------------------------------------------------------------------- /config/locales/client.he.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | he: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Discourse Patreon" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: כניסה עם פטראון 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: 'מסננים' 22 | group: 'קבוצה' 23 | rewards: 'פרסים' 24 | filter: 'מסנן' 25 | help_text: 'ניתן לסנכרן קבוצת Discourse עם שכבה אחת או יותר של פרסים מ־Patreon.' 26 | last_synced: 'נסכרון אחרון' 27 | edit: 'עריכה' 28 | delete: 'מחיקה' 29 | save: 'שמירה' 30 | update_data: 'עדכון הנתונים של Patreon וסנכרון הקבוצות' 31 | refresh_page: 'התקבלו נתונים חדשים מה־API של Patreon. נא לרענן את העמוד.' 32 | select_group: 'בחירת קבוצה' 33 | field: 34 | id: "מזהה" 35 | email: "דוא״ל" 36 | amount_cents: "כמות (בסנטים)" 37 | rewards: "פרסים" 38 | declined_since: "ההבטחה נדחתה מאז" 39 | more_details: 40 | label: "תשלומים ופרטים נוספים" 41 | help_text: 42 | email_available: "ניתן להגיע לפינה הימנית התחתונה של העמוד כדי לצפות בהיסטוריית ההבטחות של ה־Patreon הזה." 43 | email_not_available: "נא לבחור בחבר ב־Patreon ולהגיע לפינה הימנית התחתונה של העמוד כדי לצפות בהיסטוריית ההבטחות." 44 | donation_prompt: 45 | body: | 46 |איך האתר שלנו? מעניין אותך לתרום למטרה טובה?
49 | 50 |51 | אם לדעתך האתר שלנו מועיל והקהילה שבנינו נאה בעיניך, נשמח לבקש ממך לתרום לאתר שלנו. 52 | התרומות דואגות לכך שהשירותים ימשיכו לפעול בצורה איכותית ויעילה ומבטיחה את פעילות הקהילה שלנו גם לשנים הבאות. 53 | כל דולר נחשב והוא ישמש למטרה טובה. 54 |
55 | 56 |תודה על תמיכתך!
57 | 58 |
59 | הפיכה ל־Patreon 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.hr.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | hr: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Filteri' 16 | group: 'Grupa' 17 | rewards: 'Nagrade' 18 | filter: 'Filter' 19 | help_text: 'Grupu na Discourseu možete sinkronizirati s jednim ili više rangova nagrada na Patreonu' 20 | last_synced: 'Posljednji put sinkronizirano' 21 | edit: 'Izmijeni' 22 | delete: 'Pobriši' 23 | save: 'Spremi' 24 | update_data: 'Ažuriraj podatke Patreona i sinkroniziraj grupe' 25 | refresh_page: 'Novi podaci prezueti su s Pateron API-ja. Molimo osvježite stranicu.' 26 | field: 27 | id: "Id" 28 | email: "Email" 29 | amount_cents: "Iznos (u centima)" 30 | rewards: "Nagrade" 31 | declined_since: "Zalog odbijen od" 32 | more_details: 33 | label: "Plaćanja i detalji" 34 | help_text: 35 | email_available: "Navigirajte do dna ove stranice kako bi vidjeli povijest Patreon zaloga." 36 | email_not_available: "Odaberite Pateron člana i navigirajte do dna stranice kako bi pregledali povijest zaloga." 37 | -------------------------------------------------------------------------------- /config/locales/client.hu.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | hu: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Szűrők' 16 | group: 'Csoport' 17 | rewards: 'Jutalmak' 18 | filter: 'Szűr' 19 | last_synced: 'Utoljára szinkronizálva' 20 | edit: 'Szerkeszt' 21 | delete: 'Töröl' 22 | save: 'Mentés' 23 | field: 24 | id: "Id" 25 | email: "Email" 26 | rewards: "Jutalmak" 27 | -------------------------------------------------------------------------------- /config/locales/client.hy.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | hy: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Ֆիլտրներ' 16 | group: 'Խմբավորել' 17 | rewards: 'Պարգևատրումներ' 18 | filter: 'Ֆիլտրել' 19 | help_text: 'Դուք կարող եք համաժամանակեցնել Discourse խումբ մեկ կամ ավելի Patreon պարգևատրման աստիճանների հետ:' 20 | last_synced: 'Վերջին անգամ Համաժամանակեցվել է' 21 | edit: 'Խմբագրել' 22 | delete: 'Ջնջել' 23 | save: 'Պահպանել' 24 | update_data: 'Թարմացնել Patreon -ի Տվյալները և Համաժամանակեցնել Խմբերը' 25 | refresh_page: 'Patreon API -ից ներբեռնվել են նոր տվյալներ: Խնդրում ենք թարմացնել էջը:' 26 | field: 27 | id: "Id" 28 | email: "Էլ. հասցե" 29 | amount_cents: "Քանակ (ցենտով)" 30 | rewards: "Պարգևատրումներ" 31 | declined_since: "Երաշխիքի Մերժման Պատճառ՝" 32 | more_details: 33 | label: "Վճարումներ և Մանրամասն Տեղեկություններ" 34 | help_text: 35 | email_available: "Իջեք դեպի էջի ներքևի աջ կողմ՝ այս Patreon-ի երաշխիքի պատմությունը դիտելու համար" 36 | email_not_available: "Ընտրել Patreon անդամի և իջնել դեպի էջի ներքևի աջ կողմ՝ երաշխիքի պատմությունը դիտելու համար:" 37 | -------------------------------------------------------------------------------- /config/locales/client.id.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | id: 8 | js: 9 | patreon: 10 | filter: 'Filter' 11 | edit: 'Ubah' 12 | delete: 'Hapus' 13 | save: 'Simpan' 14 | field: 15 | email: "Email" 16 | -------------------------------------------------------------------------------- /config/locales/client.it.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | it: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Discourse Patreon" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: Accedi con Patreon 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: 'Filtri' 22 | group: 'Gruppo' 23 | rewards: 'Ricompense' 24 | filter: 'Filtro' 25 | help_text: 'Puoi sincronizzare un gruppo Discourse con uno o più livelli di ricompense di Patreon.' 26 | last_synced: 'Ultima Sincronizzazione' 27 | edit: 'Modifica' 28 | delete: 'Cancella' 29 | save: 'Salva' 30 | update_data: 'Aggiorna Dati Patreon & Sincronizza Gruppi' 31 | refresh_page: 'Nuovi dati sono stati scaricati dall''API Patreon. Si prega di aggiornare la pagina.' 32 | select_group: 'Seleziona un gruppo' 33 | field: 34 | id: "Id" 35 | email: "Email" 36 | amount_cents: "Importo (in centesimi)" 37 | rewards: "Ricompense" 38 | declined_since: "Promessa di donazione rifiutata dal" 39 | more_details: 40 | label: "Pagamenti e altri dettagli" 41 | help_text: 42 | email_available: "Raggiungi la parte in basso a destra della pagina per vedere la cronologia delle donazioni di Patreon." 43 | email_not_available: "Seleziona il membro Patreon e raggiungi la parte in basso a destra della pagina per vedere la cronologia delle donazioni." 44 | donation_prompt: 45 | body: | 46 |Ti piace il nostro sito web? Vuoi contribuire a una buona causa?
49 | 50 |51 | Se trovi utile il nostro sito web e ti piace la community che abbiamo creato, ti saremmo molto grati se tu volessi fare una donazione al nostro sito web. 52 | Le donazioni garantiscono il buon funzionamento dei nostri servizi e assicurano l'operatività della nostra community negli anni a venire. 53 | Anche la più piccola somma è importante e sarà messa a frutto. 54 |
55 | 56 |Grazie per il tuo sostegno!
57 | 58 |
59 | Diventa un nostro sostenitore 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.ja.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ja: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Discourse Patreon" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: Patreon でログイン 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: 'フィルター' 22 | group: 'グループ' 23 | rewards: '報酬' 24 | filter: 'フィルター' 25 | help_text: 'Discourse グループを 1 つ以上の Patreon 報酬ランクと同期できます。' 26 | last_synced: '最終同期' 27 | edit: '編集' 28 | delete: '削除' 29 | save: '保存' 30 | update_data: 'Patreon データを更新してグループを同期' 31 | refresh_page: 'Patreon API から新しいデータがダウンロードされました。ページを更新してください。' 32 | select_group: 'グループを選択' 33 | field: 34 | id: "ID" 35 | email: "メールアドレス" 36 | amount_cents: "金額(セント単位)" 37 | rewards: "報酬" 38 | declined_since: "誓約拒否" 39 | more_details: 40 | label: "支払いとその他の詳細" 41 | help_text: 42 | email_available: "ページの右下に移動し、この Patreon の誓約履歴を確認してください。" 43 | email_not_available: "Patreon メンバーを選択し、ページの右下に移動して、誓約履歴を確認してください。" 44 | donation_prompt: 45 | body: | 46 |私たちのウェブサイトを気に入っていただけていますでしょうか?慈善活動に貢献したいと思いませんか?
49 | 50 |51 | 私たちのウェブサイトがあなたの役に立っており、コミュニティーをお楽しみいただいているのであれば、このウェブサイトに寄付していただければ幸いです。 52 | 今後数年に渡って、私たちのサービスとコミュニティーの運営を円滑に維持していくには、皆さんからの寄付が必要です。 53 | 皆さんからの 1 円 1 円を大切に利用させていただきます。 54 |
55 | 56 |皆さんのご支援をお待ちしております!
57 | 58 |
59 | パトロンになる 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.ko.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ko: 8 | js: 9 | login: 10 | patreon: 11 | name: 파트 레온 12 | patreon: 13 | title: '파트 레온' 14 | header: 15 | rules: '필터' 16 | group: '그룹' 17 | rewards: '보상' 18 | filter: '필터' 19 | help_text: 'Discourse 그룹을 하나 이상의 Patreon 보상 계층과 동기화 할 수 있습니다.' 20 | last_synced: '마지막 동기화' 21 | edit: '수정' 22 | delete: '삭제' 23 | save: '저장' 24 | update_data: 'Patreon 데이터 및 동기화 그룹 업데이트' 25 | refresh_page: 'Patreon API에서 새 데이터가 다운로드되었습니다. 페이지를 새로 고침하십시오.' 26 | select_group: '그룹을 선택하세요' 27 | field: 28 | id: "신분증" 29 | email: "이메일" 30 | amount_cents: "금액 (센트)" 31 | rewards: "보상" 32 | declined_since: "이후 거부 된 서약" 33 | more_details: 34 | label: "지불 및 자세한 내용" 35 | help_text: 36 | email_available: "이 Patreon의 서약 내역을 보려면 페이지 오른쪽 하단에 도달하십시오." 37 | email_not_available: "Patreon 회원을 선택하고 페이지 오른쪽 하단에 도달하여 서약 내역을 확인하십시오." 38 | -------------------------------------------------------------------------------- /config/locales/client.lt.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | lt: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Filtrai' 16 | group: 'Grupė' 17 | filter: 'Filtruoti' 18 | edit: 'Redaguoti' 19 | delete: 'Pašalinti' 20 | save: 'Saugoti' 21 | field: 22 | email: "Epaštas" 23 | -------------------------------------------------------------------------------- /config/locales/client.lv.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | lv: 8 | js: 9 | patreon: 10 | group: 'Grupa' 11 | filter: 'Filtrs' 12 | edit: 'Labot' 13 | delete: 'Dzēst' 14 | save: 'Saglabāt' 15 | field: 16 | email: "E-pasts" 17 | -------------------------------------------------------------------------------- /config/locales/client.nb_NO.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | nb_NO: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Filter' 16 | group: 'Gruppe' 17 | rewards: 'Belønninger' 18 | filter: 'Filter' 19 | help_text: 'Du kan synkronisere en Discourse-gruppe med én eller flere Patreon-belønningsnivåer.' 20 | edit: 'Rediger' 21 | delete: 'Slett' 22 | save: 'Lagre' 23 | update_data: 'Oppdater Patreon-data og synkroniser grupper' 24 | field: 25 | email: "E-post" 26 | rewards: "Belønninger" 27 | -------------------------------------------------------------------------------- /config/locales/client.nl.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | nl: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Discourse Patreon" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: Inloggen met Patreon 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: 'Filters' 22 | group: 'Groep' 23 | rewards: 'Beloningen' 24 | filter: 'Filter' 25 | help_text: 'Je kunt een Discourse-groep met een of meer Patreon-beloningsniveaus synchroniseren.' 26 | last_synced: 'Laatst gesynchroniseerd' 27 | edit: 'Bewerken' 28 | delete: 'Verwijderen' 29 | save: 'Opslaan' 30 | update_data: 'Patreon-gegevens bijwerken en groepen synchroniseren' 31 | refresh_page: 'Er zijn nieuwe gegevens gedownload via de Patreon-API. Vernieuw de pagina.' 32 | select_group: 'Selecteer een groep' 33 | field: 34 | id: "ID" 35 | email: "E-mailadres" 36 | amount_cents: "Bedrag (in centen)" 37 | rewards: "Beloningen" 38 | declined_since: "Donatie geweigerd sinds" 39 | more_details: 40 | label: "Betalingen en meer details" 41 | help_text: 42 | email_available: "Bekijk de pagina rechtsonder om de donatiegeschiedenis van deze Patreon te zien." 43 | email_not_available: "Selecteer het Patreon-lid en bekijk de pagina rechtsonder om de donatiegeschiedenis te zien." 44 | donation_prompt: 45 | body: | 46 |Bevalt onze website? Wil je bijdragen aan een goed doel?
49 | 50 |51 | Als je onze website nuttig vindt en geniet van de community die we hebben gecreëerd, zouden we het fijn vinden als je doneert aan onze website. 52 | Donaties zorgen ervoor dat onze services soepel blijven werken en dat onze community nog jarenlang operationeel blijft. 53 | Elke cent telt en wordt goed gebruikt. 54 |
55 | 56 |Bedankt voor je steun!
57 | 58 |
59 | Patron worden 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.pl_PL.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | pl_PL: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Filtry' 16 | group: 'Grupa' 17 | rewards: 'Nagrody' 18 | filter: 'Filtr' 19 | help_text: 'Możesz zsynchronizować grupę Discourse’a z jednym lub większą liczbą progów Patreona.' 20 | last_synced: 'Ostatnio zsynchronizowane' 21 | edit: 'Edytuj' 22 | delete: 'Usuń' 23 | save: 'Zapisz' 24 | update_data: 'Zaktualizuj dane Patreona i zsynchronizuj grupy' 25 | refresh_page: 'Nowe dane są pobierane przez API Patreona. Odśwież stronę.' 26 | field: 27 | id: "ID" 28 | email: "Email" 29 | amount_cents: "Liczba (w centach)" 30 | rewards: "Nagrody" 31 | declined_since: "Wpłata odrzucona od" 32 | more_details: 33 | label: "Płatność i szczegóły" 34 | help_text: 35 | email_available: "Sprawdź prawą dolną część strony, by zobaczyć historię wpłat Patreona." 36 | email_not_available: "Wybierz użytkownika Patreona i sprawdź prawą dolną część strony, by zobaczyć historię wpłat." 37 | -------------------------------------------------------------------------------- /config/locales/client.pt.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | pt: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Filtros' 16 | group: 'Grupo' 17 | rewards: 'Recompensas' 18 | filter: 'Filtrar' 19 | help_text: 'Pode sincronizar um grupo do Discourse com uma ou mais camadas de recompensa do Patreon.' 20 | edit: 'Editar' 21 | delete: 'Eliminar' 22 | save: 'Guardar' 23 | update_data: 'Atualizar Dados de Patreon e Sincronizar Grupos' 24 | refresh_page: 'Foram transferidos novos dados da API do Patreon. Por favor, atualize a página.' 25 | field: 26 | email: "E-mail" 27 | amount_cents: "Valor (em cent.)" 28 | rewards: "Recompensas" 29 | -------------------------------------------------------------------------------- /config/locales/client.pt_BR.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | pt_BR: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Patreon no Discourse" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: Entrar com o Patreon 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: 'Filtros' 22 | group: 'Grupo' 23 | rewards: 'Recompensas' 24 | filter: 'Filtro' 25 | help_text: 'Você pode sincronizar um grupo do Discourse com um ou mais níveis de recompensa do Patreon.' 26 | last_synced: 'Último Sincronizado' 27 | edit: 'Editar' 28 | delete: 'Excluir' 29 | save: 'Salvar' 30 | update_data: 'Atualizar dados do Patreon e sincronizar grupos' 31 | refresh_page: 'Novos dados foram baixados da API do Patreon. Atualize a página.' 32 | select_group: 'Selecione um grupo' 33 | field: 34 | id: "Id" 35 | email: "E-mail" 36 | amount_cents: "Valor (em centavos)" 37 | rewards: "Recompensas" 38 | declined_since: "Compromisso Recusado Desde" 39 | more_details: 40 | label: "Pagamentos e mais detalhes" 41 | help_text: 42 | email_available: "Vá para o canto inferior direito da página para ver este histórico de compromissos do Patreon." 43 | email_not_available: "Selecione o membro Patreon e vá para o canto inferior direito da página para ver o histórico de compromissos." 44 | donation_prompt: 45 | body: | 46 |Você gosta do nosso site? Gostaria de contribuir para uma boa causa?
49 | 50 |51 | Se achar nosso site útil e gosta da comunidade que criamos, nós adoraríamos que fizesse uma doação para nosso site. 52 | Doações mantêm nossos serviços funcionando sem problemas e garantem que nossa comunidade estará operacional por muitos anos. 53 | Cada dólar conta e será bem utilizado. 54 |
55 | 56 |Obrigado pelo seu apoio!
57 | 58 |
59 | Torne-se um(a) Patrono(a) 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.ro.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ro: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Discourse Patreon" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: Conectare cu Pateron 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: 'Filtre' 22 | group: 'Grup' 23 | rewards: 'Recompense' 24 | filter: 'Filtru' 25 | help_text: 'Poți sincroniza un grup Discourse cu unul sau mai multe niveluri de recompensă Patreon.' 26 | last_synced: 'Ultima sincronizare' 27 | edit: 'Editează' 28 | delete: 'Șterge' 29 | save: 'Salvează' 30 | update_data: 'Actualizează date Patreon și sincronizează grupuri' 31 | refresh_page: 'Date noi au fost descărcate din API-ul Patreon. Te rugăm să reîmprospătezi pagina.' 32 | select_group: 'Selectează un grup' 33 | field: 34 | id: "ID" 35 | email: "Email" 36 | amount_cents: "Sumă (în cenți)" 37 | rewards: "Recompense" 38 | declined_since: "Angajament refuzat din" 39 | more_details: 40 | label: "Plăți și mai multe detalii" 41 | help_text: 42 | email_available: "Ajungi în dreapta jos a paginii pentru a vedea istoricul angajamentului acestui Patreon." 43 | email_not_available: "Selectează membrul Patreon și ajungi în dreapta jos a paginii pentru a vedea istoricul angajamentului." 44 | donation_prompt: 45 | body: | 46 |Îți place site-ul nostru? Vrei să contribui la o cauză bună?
49 | 50 |51 | Dacă găsești site-ul nostru util și te bucuri de comunitatea pe care am creat-o, ne-ar plăcea dacă ai dona pentru site-ul nostru web. 52 | Donațiile mențin serviciile noastre funcționale fără probleme și asigură operaționalitatea comunitatății noastre în anii următori. 53 | Fiecare dolar contează și va fi folosit în scopuri bune. 54 |
55 | 56 |Îți mulțumim pentru sprijin!
57 | 58 |
59 | Devino un Patron 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.ru.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ru: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Patreon для Discourse" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: Войти через Patreon 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: 'Фильтры' 22 | group: 'Группа' 23 | rewards: 'Награда' 24 | filter: 'Фильтр' 25 | help_text: 'Вы можете синхронизировать группу Discourse с одним или несколькими уровнями вознаграждений Patreon.' 26 | last_synced: 'Последняя синхронизация' 27 | edit: 'Изменить' 28 | delete: 'Удалить' 29 | save: 'Сохранить' 30 | update_data: 'Обновить данные на Patreon и синхронизировать группы' 31 | refresh_page: 'Новые данные были загружены из Patreon API. Пожалуйста, обновите страницу.' 32 | select_group: 'Выберите группу' 33 | field: 34 | id: "Id" 35 | email: "Email" 36 | amount_cents: "Сумма (в центах)" 37 | rewards: "Награда" 38 | declined_since: "Подписка отклонена с" 39 | more_details: 40 | label: "Платежи и более подробная информация" 41 | help_text: 42 | email_available: "Дойдите до правого нижнего края страницы Patreon, чтобы увидеть историю подписок." 43 | email_not_available: "Выберите участника Patreon и дойдите до правого нижнего края страницы, чтобы увидеть историю подписок." 44 | donation_prompt: 45 | body: | 46 |Вам нравится наш сайт? Хотели бы вы внести свой вклад в благое дело?
49 | 50 |51 | Если наш веб-сайт окажется полезным, и вам понравится созданное нами сообщество, мы будем рады, если вы сделаете пожертвование. 52 | Пожертвования обеспечивают бесперебойную работу наших служб и гарантируют, что наше сообщество будет функционировать в течение многих лет. 53 | Каждый доллар имеет значение и будет полезен. 54 |
55 | 56 |Спасибо за Вашу поддержку!
57 | 58 |
59 | Стать покровителем 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.sk.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sk: 8 | js: 9 | patreon: 10 | header: 11 | rules: 'Filtre' 12 | group: 'Skupina' 13 | rewards: 'Odmeny' 14 | filter: 'Filter' 15 | edit: 'Upraviť' 16 | delete: 'Odstrániť' 17 | save: 'Uložiť' 18 | field: 19 | id: "Id" 20 | email: "Email" 21 | rewards: "Odmena" 22 | -------------------------------------------------------------------------------- /config/locales/client.sl.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sl: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Filtri' 16 | group: 'Skupina' 17 | rewards: 'Nagrade' 18 | filter: 'Filter' 19 | help_text: 'Discourse skupino lahko sinhronizirate z eno ali več nagradnimi stopnjami v Patreonu.' 20 | last_synced: 'Nazadnje sinhronizirano' 21 | edit: 'Uredi' 22 | delete: 'Izbriši' 23 | save: 'Shrani' 24 | update_data: 'Posodobi Patreon podatke & sinhroniziraj skupine' 25 | field: 26 | id: "Id" 27 | email: "Email" 28 | amount_cents: "Vrednost (v centih)" 29 | rewards: "Nagrade" 30 | more_details: 31 | label: "Plačila & več podatkov" 32 | -------------------------------------------------------------------------------- /config/locales/client.sq.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sq: 8 | js: 9 | patreon: 10 | group: 'Grupi' 11 | filter: 'Filtro' 12 | edit: 'Redakto' 13 | delete: 'Fshij' 14 | save: 'Ruaj' 15 | field: 16 | email: "Email" 17 | -------------------------------------------------------------------------------- /config/locales/client.sr.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sr: 8 | js: 9 | patreon: 10 | group: 'Grupa' 11 | filter: 'Filter' 12 | edit: 'Izmeni' 13 | delete: 'Obriši' 14 | save: 'Sačuvaj' 15 | field: 16 | email: "E-mail" 17 | -------------------------------------------------------------------------------- /config/locales/client.sv.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sv: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Filter' 16 | group: 'Grupp' 17 | rewards: 'Belöningar' 18 | filter: 'Filter' 19 | help_text: 'Du kan synkronisera en Discourse-grupp med en eller flera Patreon-belöningsnivåer.' 20 | last_synced: 'Senast synkroniserad' 21 | edit: 'Redigera' 22 | delete: 'Radera' 23 | save: 'Spara' 24 | update_data: 'Uppdatera Patreon-data och synkronisera grupper' 25 | refresh_page: 'Ny data har laddats ner från Patreon-API:n. Uppdatera sidan.' 26 | select_group: 'Välj en grupp' 27 | field: 28 | id: "ID" 29 | email: "E-post" 30 | amount_cents: "Belopp (i cent)" 31 | rewards: "Belöningar" 32 | declined_since: "Donation nekad sedan" 33 | more_details: 34 | label: "Betalningar och mer detaljer" 35 | help_text: 36 | email_available: "Längst ner till höger på sidan ser du den här Patreonens donationshistorik." 37 | email_not_available: "Välj Patreon-medlemmen och gå längst ner till höger på sidan för att se donationshistoriken." 38 | donation_prompt: 39 | body: | 40 |Gillar du vår webbplats? Vill du bidra till ett gott ändamål?
43 | 44 |45 | Om du tycker att vår webbplats är till nytta, och använder dig av det forum som vi har skapat, skulle vi bli glada om du donerade till webbplatsen. 46 | Donationer är det som ser till att våra tjänster fungerar smidigt och säkerställer att vårt forum fungerar under många år framöver. 47 | Varje krona räknas och kommer till god användning. 48 |
49 | 50 |Tack för ditt stöd!
51 | 52 |
53 | Bli Patreon 54 |
55 | -------------------------------------------------------------------------------- /config/locales/client.sw.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sw: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: 'Inachujwa' 16 | group: 'Kikundi' 17 | rewards: 'Tuzo' 18 | filter: 'Ichujwe' 19 | last_synced: 'Mara ya mwisho Ulandanishi umefanyika' 20 | edit: 'Hariri' 21 | delete: 'Futa' 22 | save: 'Hifadhi' 23 | field: 24 | id: "Utambulisho" 25 | email: "Barua Pepe" 26 | amount_cents: "Kiasi (kwenye senti)" 27 | rewards: "Tuzo" 28 | declined_since: "Ombi Limekataliwa Tangia" 29 | -------------------------------------------------------------------------------- /config/locales/client.te.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | te: 8 | js: 9 | patreon: 10 | group: 'సమూహం' 11 | filter: 'జల్లెడ' 12 | edit: 'సవరించు' 13 | delete: 'తొలగించు' 14 | save: 'భద్రపరచు' 15 | field: 16 | email: "ఈమెయిల్" 17 | -------------------------------------------------------------------------------- /config/locales/client.th.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | th: 8 | js: 9 | patreon: 10 | group: 'กลุ่ม' 11 | edit: 'แก้ไข' 12 | delete: 'ลบ' 13 | save: 'บันทึก' 14 | field: 15 | email: "อีเมล" 16 | -------------------------------------------------------------------------------- /config/locales/client.tr_TR.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | tr_TR: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Discourse Patreon" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: Patreon ile giriş yapın 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: 'Filtreler' 22 | group: 'Grup' 23 | rewards: 'Ödüller' 24 | filter: 'Filtre' 25 | help_text: 'Bir Discourse grubunu bir veya daha fazla Patreon ödül kademesiyle senkronize edebilirsiniz.' 26 | last_synced: 'Son senkronize' 27 | edit: 'Düzenle' 28 | delete: 'Sil' 29 | save: 'Kaydet' 30 | update_data: 'Patreon Verilerini Güncelle ve Grupları Senkronize Et' 31 | refresh_page: 'Patreon API''den yeni veriler indirildi. Lütfen sayfayı yenileyin.' 32 | select_group: 'Grup seçin' 33 | field: 34 | id: "Kimlik" 35 | email: "E-posta" 36 | amount_cents: "Miktar (sent cinsinden)" 37 | rewards: "Ödüller" 38 | declined_since: "O Zamandan Bu Yana Bağış Azaldı" 39 | more_details: 40 | label: "Ödemeler ve Daha Fazla Ayrıntı" 41 | help_text: 42 | email_available: "Bu Patreon'un bağış geçmişini görmek için sayfanın sağ alt kısmına ulaşın." 43 | email_not_available: "Bağış geçmişini görmek için Patreon üyesini seçin ve sayfanın sağ alt kısmına ulaşın." 44 | donation_prompt: 45 | body: | 46 |Web sitemizi beğendiniz mi? İyi bir amaca katkıda bulunmak ister misiniz?
49 | 50 |51 | Web sitemizi yararlı buluyor ve oluşturduğumuz topluluktan hoşlanıyorsanız web sitemize bağışta bulunursanız çok seviniriz. 52 | Bağışlar, hizmetlerimizin sorunsuz bir şekilde devam etmesini ve topluluğumuzun yıllarca faaliyette kalmasını sağlar. 53 | Her miktar önemli ve iyi bir şekilde kullanılacak. 54 |
55 | 56 |Desteğiniz için teşekkür ederiz!
57 | 58 |
59 | Hami Olun 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.ug.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ug: 8 | js: 9 | patreon: 10 | group: 'گۇرۇپپا' 11 | filter: 'سۈزگۈچ' 12 | edit: 'تەھرىر' 13 | delete: 'ئۆچۈر' 14 | save: 'ساقلا' 15 | field: 16 | email: "ئېلخەت" 17 | -------------------------------------------------------------------------------- /config/locales/client.uk.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | uk: 8 | js: 9 | patreon: 10 | group: 'Група' 11 | filter: 'Filter' 12 | edit: 'Редагувати' 13 | delete: 'Видалити' 14 | save: 'Зберегти' 15 | field: 16 | email: "Електронна пошта" 17 | -------------------------------------------------------------------------------- /config/locales/client.ur.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ur: 8 | js: 9 | login: 10 | patreon: 11 | name: پَیٹریئون 12 | patreon: 13 | title: 'پَیٹریئون' 14 | header: 15 | rules: 'فِلٹر' 16 | group: 'گروپ' 17 | rewards: 'انعامات' 18 | filter: 'فِلٹر' 19 | help_text: 'آپ کسی ڈسکورس گروپ کو ایک یا ایک سے زیادہ پَیٹریئون کے انعامات والے زمروں کے ساتھ مطابقت پذیر بنا سکتے ہیں۔' 20 | last_synced: 'آخری دفعہ سینک کیا گیا' 21 | edit: 'ترمیم کریں' 22 | delete: 'حذف کریں' 23 | save: 'محفوظ کریں' 24 | update_data: 'پَیٹریئون ڈیٹا اَپ ڈیٹ کریں اور گروپس کو مطابقت پذیر بنائیں' 25 | refresh_page: 'پَیٹریئون API سے نیا ڈیٹا ڈاؤن لوڈ کیا گیا ہے۔ براہ کرم صفحہ ریفریش کریں۔' 26 | field: 27 | id: "آئی ڈی" 28 | email: "اِی میل" 29 | amount_cents: "رقم (سینٹ میں)" 30 | rewards: "انعامات" 31 | declined_since: "سے پلِج انکار کیا گیا" 32 | more_details: 33 | label: "ادائیگیاں اور مزید تفصیلات" 34 | help_text: 35 | email_available: "اِس پَیٹریئون کی پلَیج ہِسٹری دیکھنے کیلئے صفحے کے نچلے دائیں حصہ تک پہنچیں۔" 36 | email_not_available: "پلَیج ہِسٹری دیکھنے کیلئے پَیٹریئون رکن کو منتخب کریں اور صفحے کے نچلے دائیں حصہ تک پہنچیں۔" 37 | -------------------------------------------------------------------------------- /config/locales/client.vi.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | vi: 8 | js: 9 | patreon: 10 | group: 'Nhóm' 11 | filter: 'Lọc' 12 | edit: 'Sửa' 13 | delete: 'Xóa' 14 | save: 'Lưu' 15 | field: 16 | email: "Email" 17 | -------------------------------------------------------------------------------- /config/locales/client.zh_CN.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | zh_CN: 8 | admin_js: 9 | admin: 10 | site_settings: 11 | categories: 12 | discourse_patreon: "Discourse Patreon" 13 | js: 14 | login: 15 | patreon: 16 | name: Patreon 17 | title: 使用 Patreon 登录 18 | patreon: 19 | title: 'Patreon' 20 | header: 21 | rules: '筛选器' 22 | group: '群组' 23 | rewards: '奖励' 24 | filter: '筛选器' 25 | help_text: '您可以将 Discourse 群组与一个或多个 Patreon 奖励等级同步。' 26 | last_synced: '最后同步' 27 | edit: '编辑' 28 | delete: '删除' 29 | save: '保存' 30 | update_data: '更新 Patreon 数据并同步群组' 31 | refresh_page: '新数据已从 Patreon API 下载。请刷新页面。' 32 | select_group: '选择一个群组' 33 | field: 34 | id: "ID" 35 | email: "电子邮件" 36 | amount_cents: "金额(以美分为单位)" 37 | rewards: "奖励" 38 | declined_since: "承诺拒绝自" 39 | more_details: 40 | label: "付款和更多详细信息" 41 | help_text: 42 | email_available: "在页面右下角查看 Patreon 的承诺历史。" 43 | email_not_available: "选择 Patreon 成员并在页面右下角查看承诺历史。" 44 | donation_prompt: 45 | body: | 46 |您喜欢我们的网站吗?您是否愿意为公益事业做出贡献?
49 | 50 |51 | 如果您认为我们的网站有所帮助并且喜欢我们创建的社区,我们将十分感激您能捐助我们的网站。 52 | 捐助可以帮助我们的服务保持稳定运行,并确保我们的社区在未来几年内仍可正常运营。 53 | 每一元的捐助都十分重要并会被妥当利用。 54 |
55 | 56 |感谢您的支持!
57 | 58 |
59 | 成为赞助人 60 |
61 | -------------------------------------------------------------------------------- /config/locales/client.zh_TW.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | zh_TW: 8 | js: 9 | login: 10 | patreon: 11 | name: Patreon 12 | patreon: 13 | title: 'Patreon' 14 | header: 15 | rules: '過濾器' 16 | group: '群組' 17 | rewards: '獎勵' 18 | filter: '過濾器' 19 | help_text: '您可以將 Discourse 群組與一個或多個 Patreon 獎勵等級同步。' 20 | edit: '編輯' 21 | delete: '刪除' 22 | save: '儲存' 23 | update_data: '更新 Patreon 資料與同步群組' 24 | field: 25 | email: "電子信箱" 26 | rewards: "獎勵" 27 | -------------------------------------------------------------------------------- /config/locales/server.ar.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ar: 8 | site_settings: 9 | patreon_enabled: 'تفعيل المكوِّن الإضافي discourse-patreon' 10 | patreon_login_enabled: 'تفعيل تسجيل الدخول إلى Patreon بحساب تواصل اجتماعي' 11 | patreon_client_id: 'مُعرِّف عميل Patreon الذي تم إنشاؤه' 12 | patreon_client_secret: 'سر عمل Patreon الذي تم إنشاؤه' 13 | patreon_webhook_secret: 'سر خطاف ويب Patreon الذي تم إنشاؤه' 14 | patreon_creator_discourse_username: "اسم مستخدم حساب Discourse المستخدم لتسجيل الدخول من خلال أحد حسابات منشئي المحتوى على Patreon باستخدام 'تسجيل الدخول إلى Patreon بحساب تواصل اجتماعي'" 15 | patreon_creator_access_token: "رمز وصول منشئ Patreon الذي تم إنشاؤه" 16 | patreon_creator_refresh_token: "رمز تحديث منشئ Patreon الذي تم إنشاؤه" 17 | patreon_declined_pledges_grace_period_days: "فترة السماح (بالأيام) قبل رفض التبرع تمامًا." 18 | max_patreon_api_reqs_per_hr: "أقصى عدد لطلبات Patreon API في الساعة" 19 | max_patreon_api_reqs_per_day: "أقصى عدد لطلبات Patreon API في اليوم" 20 | patreon_verbose_log: 'تفعيل التسجيل المطوَّل لحمولة Patreon' 21 | patreon_donation_prompt_enabled: "هل تريد تفعيل أمر التبرع؟" 22 | patreon_donation_prompt_show_after_topics: "عرض أمر التبرع بعد N من الموضوعات" 23 | patreon_donation_prompt_campaign_url: "عنوان URL لحملة أوامر التبرع" 24 | errors: 25 | patreon_creator_username_not_set: "أنت بحاجة إلى ضبط إعداد اسم مستخدم Discourse لمنشئي المحتوى على Patreon قبل تفعيل تسجيل الدخول باستخدام Patreon." 26 | dashboard: 27 | problem: 28 | access_token_invalid: "قيم رمز الوصول والتحديث لمُنشئ Patreon غير صحيحة. يجب عليك نسخ ولصق الرموز الجديدة من موقع Patreon على الويب إلى إعدادات الموقع." 29 | patreon: 30 | error: 31 | invalid_response: "استجابة غير صالحة من Patreon API" 32 | -------------------------------------------------------------------------------- /config/locales/server.be.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | be: 8 | -------------------------------------------------------------------------------- /config/locales/server.bg.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | bg: 8 | -------------------------------------------------------------------------------- /config/locales/server.bs_BA.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | bs_BA: 8 | -------------------------------------------------------------------------------- /config/locales/server.ca.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ca: 8 | site_settings: 9 | patreon_enabled: 'Habilita el connector Discourse-Patreon' 10 | patreon_login_enabled: 'Habilita la connexió social de Patreon' 11 | patreon_client_id: 'ID generat de client Patreon ' 12 | patreon_client_secret: 'Secret de client generat de Patreon' 13 | patreon_webhook_secret: 'Secret generat de Patreon Webhook' 14 | patreon_creator_discourse_username: "Nom d'usuari del compte de Discourse que s'utilitza per a iniciar sessió mitjançant el compte de creador de Patreon fent servir 'Patreon Social Login'." 15 | patreon_creator_access_token: "Testimoni d'accés generat de creador de Patreon" 16 | patreon_creator_refresh_token: "Testimoni de refresc generat de creador de Patreon" 17 | patreon_declined_pledges_grace_period_days: "Període de gràcia (en dies) abans que es denegui completament el compromís." 18 | max_patreon_api_reqs_per_hr: "Nombre màxim de sol·licituds API de Patreon per hora" 19 | max_patreon_api_reqs_per_day: "Nombre màxim de sol·licituds API de Patreon per dia" 20 | patreon_verbose_log: 'habilita el registre detallat de la càrrega útil del Patreon' 21 | patreon_donation_prompt_enabled: "Voleu activar la sol·licitud de donació?" 22 | patreon_donation_prompt_show_after_topics: "Mostra el missatge de donació després de n temes" 23 | patreon: 24 | error: 25 | invalid_response: "Resposta no vàlida de l'API de Patreon" 26 | -------------------------------------------------------------------------------- /config/locales/server.cs.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | cs: 8 | -------------------------------------------------------------------------------- /config/locales/server.da.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | da: 8 | -------------------------------------------------------------------------------- /config/locales/server.de.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | de: 8 | site_settings: 9 | patreon_enabled: 'Aktiviere das discourse-patreon-Plug-in' 10 | patreon_login_enabled: 'Aktiviere das Patreon-Social-Log-in' 11 | patreon_client_id: 'Generierte Patreon-Client-ID' 12 | patreon_client_secret: 'Generiertes Patreon-Client-Geheimnis' 13 | patreon_webhook_secret: 'Generiertes Patreon-Webhook-Geheimnis' 14 | patreon_creator_discourse_username: "Benutzername des Discourse-Kontos, das für die Anmeldung über das Patreon-Ersteller-Konto mit „Patreon-Social-Log-in“ verwendet wird" 15 | patreon_creator_access_token: "Generiertes Patreon-Ersteller-Zugriffstoken" 16 | patreon_creator_refresh_token: "Generiertes Patreon-Ersteller-Aktualisierungstoken" 17 | patreon_declined_pledges_grace_period_days: "Frist (in Tagen), bevor eine Spende vollständig abgelehnt wird." 18 | max_patreon_api_reqs_per_hr: "Maximale Anzahl an Patreon-API-Anfragen pro Stunde" 19 | max_patreon_api_reqs_per_day: "Maximale Anzahl von Patreon-API-Anfragen pro Tag" 20 | patreon_verbose_log: 'aktiviert die ausführliche Protokollierung des Patreon-Payload' 21 | patreon_donation_prompt_enabled: "Spendenaufforderung aktivieren?" 22 | patreon_donation_prompt_show_after_topics: "Zeige Spendenaufforderung nach n Themen an" 23 | patreon_donation_prompt_campaign_url: "URL der Spendenaufforderungskampagne" 24 | errors: 25 | patreon_creator_username_not_set: "Bevor du das Patreon-Log-in aktivieren kannst, musst du den Patreon-Ersteller-Discourse-Benutzernamen einstellen." 26 | dashboard: 27 | problem: 28 | access_token_invalid: "Die Werte für die Zugangs- und Aktualisierungs-Token des Patreon-Erstellers sind falsch. Du musst neue Token von der Patreon-Website kopieren und in die Website-Einstellungen einfügen." 29 | patreon: 30 | error: 31 | invalid_response: "Ungültige Antwort der Patreon-API" 32 | -------------------------------------------------------------------------------- /config/locales/server.el.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | el: 8 | -------------------------------------------------------------------------------- /config/locales/server.en.yml: -------------------------------------------------------------------------------- 1 | en: 2 | site_settings: 3 | patreon_enabled: 'Enable the discourse-patreon plugin' 4 | patreon_login_enabled: 'Enable Patreon Social Login' 5 | patreon_client_id: 'Generated Patreon Client ID' 6 | patreon_client_secret: 'Generated Patreon Client Secret' 7 | patreon_webhook_secret: 'Generated Patreon Webhook Secret' 8 | patreon_creator_discourse_username: "Username of the Discourse account which is used to login through Patreon creator account using 'Patreon Social Login'" 9 | patreon_creator_access_token: "Generated Patreon Creator's Access Token" 10 | patreon_creator_refresh_token: "Generated Patreon Creator's Refesh Token" 11 | patreon_declined_pledges_grace_period_days: "Grace period (in days) before a pledge is declined completely." 12 | max_patreon_api_reqs_per_hr: "Maximum number of Patreon API requests per hour" 13 | max_patreon_api_reqs_per_day: "Maximum number of Patreon API requests per day" 14 | patreon_verbose_log: 'enable verbose logging of patreon payload' 15 | patreon_donation_prompt_enabled: "Enable donation prompt?" 16 | patreon_donation_prompt_show_after_topics: "Show donation prompt after n topics" 17 | patreon_donation_prompt_campaign_url: "Donation prompt campaign URL" 18 | errors: 19 | patreon_creator_username_not_set: "You need to set the Patreon Creator Discourse Username setting before enabling Patreon Login." 20 | dashboard: 21 | problem: 22 | access_token_invalid: "Patreon Creator's access and refresh token values are incorrect. You must copy-paste new tokens from Patreon website to site settings." 23 | patreon: 24 | error: 25 | invalid_response: "Invalid response from Patreon API" 26 | -------------------------------------------------------------------------------- /config/locales/server.en_GB.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | en_GB: 8 | -------------------------------------------------------------------------------- /config/locales/server.es.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | es: 8 | site_settings: 9 | patreon_enabled: 'Habilitar el complemento discourse-patreon' 10 | patreon_login_enabled: 'Habilitar el inicio de sesión a través de Patreon' 11 | patreon_client_id: 'ID de cliente de Patreon generada' 12 | patreon_client_secret: 'Secreto de cliente de Patreon generado' 13 | patreon_webhook_secret: 'Secreto de webhook de Patreon generado' 14 | patreon_creator_discourse_username: "Nombre de usuario de la cuenta de Discourse que se usa para iniciar sesión mediante la cuenta de creador de Patreon usando el «inicio de sesión a través de Patreon»" 15 | patreon_creator_access_token: "Token de acceso de creador de Patreon generado" 16 | patreon_creator_refresh_token: "Token de actualización de creador de Patreon generado" 17 | patreon_declined_pledges_grace_period_days: "Período de gracia (en días) antes de que una promesa se rechace por completo." 18 | max_patreon_api_reqs_per_hr: "Número máximo de solicitudes del API de Patreon por hora" 19 | max_patreon_api_reqs_per_day: "Número máximo de solicitudes del API de Patreon por día" 20 | patreon_verbose_log: 'habilitar el registro detallado de la carga útil de Patreon' 21 | patreon_donation_prompt_enabled: "¿Activar el aviso de donación?" 22 | patreon_donation_prompt_show_after_topics: "Mostrar aviso de donación después de n temas" 23 | patreon_donation_prompt_campaign_url: "URL de la campaña de donación" 24 | errors: 25 | patreon_creator_username_not_set: "Tienes que establecer la configuración del Nombre de usuario de Discourse para Patreon Creator antes de activar el inicio de sesión de Patreon." 26 | dashboard: 27 | problem: 28 | access_token_invalid: "Los valores de los tokens de acceso y actualización de Patreon Creator son incorrectos. Debes copiar y pegar los nuevos tokens del sitio web de Patreon a los ajustes del sitio." 29 | patreon: 30 | error: 31 | invalid_response: "Respuesta no válida de la API de Patreon" 32 | -------------------------------------------------------------------------------- /config/locales/server.et.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | et: 8 | -------------------------------------------------------------------------------- /config/locales/server.fa_IR.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | fa_IR: 8 | -------------------------------------------------------------------------------- /config/locales/server.fi.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | fi: 8 | site_settings: 9 | patreon_enabled: 'Ota discourse-patreon-lisäosa käyttöön' 10 | patreon_login_enabled: 'Ota käyttöön yhteisökirjautuminen Patreonilla' 11 | patreon_client_id: 'Luotu Patreonin asiakastunnus (client ID)' 12 | patreon_client_secret: 'Luotu Patreonin asiakkaan salatunnus (client secret)' 13 | patreon_webhook_secret: 'Luotu Patreonin webhook-salausavain (webhook secret)' 14 | patreon_creator_discourse_username: "Sen Discourse-tilin käyttäjätunnus, jota käytetään kirjauduttaessa Patreon-tuottajatilin (engl. creator account) kautta Patreonin yhteisökirjautumisen kautta" 15 | patreon_creator_access_token: "Luotu Patreonin tuottajan tunnistusväline (creator's access token)" 16 | patreon_creator_refresh_token: "Luotu Patreonin tuottajan päivitysväline (creator's refresh token)" 17 | patreon_declined_pledges_grace_period_days: "Varoaika (päivinä), kunnes lahjoituslupaus hylätään lopullisesti." 18 | max_patreon_api_reqs_per_hr: "Patreon API-pyyntöjen enimmäismäärä per tunti" 19 | max_patreon_api_reqs_per_day: "Patreon API-pyyntöjen päivittäinen enimmäismäärä" 20 | patreon_verbose_log: 'salli patreon-tietosisällön monikirjaus' 21 | patreon_donation_prompt_enabled: "Otetaanko lahjoituskehotus käyttöön?" 22 | patreon_donation_prompt_show_after_topics: "Näytä lahjoituskehotus n ketjun jälkeen" 23 | patreon_donation_prompt_campaign_url: "Lahjoituskehotuskampanjan URL" 24 | errors: 25 | patreon_creator_username_not_set: "Sinun täytyy määrittää Patreon Creator Discourse -käyttäjätunnusasetus ennen kuin otat Patreon-kirjautumisen käyttöön." 26 | dashboard: 27 | problem: 28 | access_token_invalid: "Patreonin tuottajan tunnistus- ja päivitysvälineiden arvot ovat virheellisiä. Sinun täytyy kopioida ja liittää uudet välineet Patreonin verkkosivustolta sivuston asetuksiin." 29 | patreon: 30 | error: 31 | invalid_response: "Virheellinen vastaus Patreonin APIsta" 32 | -------------------------------------------------------------------------------- /config/locales/server.fr.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | fr: 8 | site_settings: 9 | patreon_enabled: 'Activer l''extension discourse-patreon' 10 | patreon_login_enabled: 'Activer la connexion de réseau social Patreon' 11 | patreon_client_id: 'ID de client Patreon généré' 12 | patreon_client_secret: 'Secret du client Patreon généré' 13 | patreon_webhook_secret: 'Secret du Webhook Patreon généré' 14 | patreon_creator_discourse_username: "Nom d'utilisateur du compte Discourse qui est utilisé pour se connecter via le compte de créateur Patreon à l'aide de « Connexion de réseau social Patreon »" 15 | patreon_creator_access_token: "Jeton d'accès de créateur Patreon généré" 16 | patreon_creator_refresh_token: "Jeton d'actualisation de créateur Patreon généré" 17 | patreon_declined_pledges_grace_period_days: "Période de grâce (en jours) avant que la promesse de don soit définitivement refusée." 18 | max_patreon_api_reqs_per_hr: "Nombre maximal de requêtes d'API Patreon par heure" 19 | max_patreon_api_reqs_per_day: "Nombre maximal de requêtes d'API Patreon par jour" 20 | patreon_verbose_log: 'activer la journalisation détaillée des données Patreon' 21 | patreon_donation_prompt_enabled: "Activer l'invite de donation ?" 22 | patreon_donation_prompt_show_after_topics: "Afficher l'invite de donation après n sujets" 23 | patreon_donation_prompt_campaign_url: "URL de la campagne d'incitation aux donations" 24 | errors: 25 | patreon_creator_username_not_set: "Vous devez définir le paramètre Patreon Creator Discourse Username avant d'activer la connexion Patreon." 26 | dashboard: 27 | problem: 28 | access_token_invalid: "Les valeurs des jetons d'accès et d'actualisation du créateur Patreon sont incorrectes. Vous devez copier-coller les nouveaux jetons à partir du site Web de Patreon vers les paramètres du site." 29 | patreon: 30 | error: 31 | invalid_response: "Réponse invalide de l'API Patreon" 32 | -------------------------------------------------------------------------------- /config/locales/server.gl.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | gl: 8 | -------------------------------------------------------------------------------- /config/locales/server.he.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | he: 8 | site_settings: 9 | patreon_enabled: 'הפעלת התוסף discourse-patreon' 10 | patreon_login_enabled: 'הפעלת כניסה ל־Patreon דרך רשת חברתית' 11 | patreon_client_id: 'נוצר מזהה לקוח Patreon' 12 | patreon_client_secret: 'נוצר סוד לקוח Patreon' 13 | patreon_webhook_secret: 'נוצרה התליית סוד של Patreon' 14 | patreon_creator_discourse_username: "שם המשתמש של חשבון ה־Discourse שמשמש לכניסה באמצעות חשבון יוצר ב־Patreon עם ‚כניסה ל־Patreon דרך רשת חברתית’" 15 | patreon_creator_access_token: "נוצר אסימון גישה ליוצר ב־Patreon" 16 | patreon_creator_refresh_token: "נוצר אסימון רענון ליוצר ב־Patreon" 17 | patreon_declined_pledges_grace_period_days: "תקופת חסד (בימים) לפני שההבטחה תידחה לחלוטין." 18 | max_patreon_api_reqs_per_hr: "מספר הבקשות המרבי ל־API של Patreon בשעה" 19 | max_patreon_api_reqs_per_day: "מספר הבקשות המרבי ל־API של Patreon ביום" 20 | patreon_verbose_log: 'הפעלת תיעוד מפורט ביומן של התעבורה מול patreon' 21 | patreon_donation_prompt_enabled: "להפעיל הודעת בקשת תרומה?" 22 | patreon_donation_prompt_show_after_topics: "הצגת הודעת בקשה תרומה לאחר n נושאים" 23 | patreon_donation_prompt_campaign_url: "כתובת בקשב לתרומה במסע פרסום" 24 | errors: 25 | patreon_creator_username_not_set: "עליך להגדיר את שם המשתמש ב־Discourse ליוצר Patreon בטרם הפעלת כניסה עם Patreon." 26 | patreon: 27 | error: 28 | invalid_response: "תגובה שגויה מה־API של Patreon" 29 | -------------------------------------------------------------------------------- /config/locales/server.hr.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | hr: 8 | site_settings: 9 | patreon_enabled: 'Omogućite discourse-pateron dodatak' 10 | patreon_login_enabled: 'Omogućite Pateron Social Login' 11 | patreon_client_id: 'Generirani Pateron Client ID' 12 | patreon_client_secret: 'Generirani Patreon Client Secret' 13 | patreon_webhook_secret: 'Generirani Patreon Webhook Secret' 14 | patreon_creator_discourse_username: "Korisničko ime Discourse računa kojim se prijavljuje na Pateron creator račun koristeći 'Patreon Social Login'" 15 | patreon_creator_access_token: "Generirani Patreon Creator's Access Token" 16 | patreon_creator_refresh_token: "Generirani Pateron Creator's Refresh Token" 17 | patreon_declined_pledges_grace_period_days: "Razdoblje počeka (u danima) prije potpunog odbijanja zaloga." 18 | max_patreon_api_reqs_per_hr: "Maksimalni broj Patreon API zahtjeva u jednom satu" 19 | max_patreon_api_reqs_per_day: "Maksimalni broj Pateron API zahtjeva u jednom danu" 20 | patreon_verbose_log: 'omogućite opširno logiranje patreon podataka' 21 | patreon: 22 | error: 23 | invalid_response: "Nevažeći odgovor Patreon API-ja" 24 | -------------------------------------------------------------------------------- /config/locales/server.hu.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | hu: 8 | -------------------------------------------------------------------------------- /config/locales/server.hy.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | hy: 8 | site_settings: 9 | patreon_enabled: 'Միացնել discourse-patreon պլագինը' 10 | patreon_login_enabled: 'Միացնել Patreon Սոցիալակա կայքով Մուտքը' 11 | patreon_client_id: 'Գեներացված Patreon Հաճախորդի ID' 12 | patreon_client_secret: 'Գեներացված Patreon Հաճախորդի Գաղտնիք' 13 | patreon_webhook_secret: 'Գեներացված Patreon Webhook Գաղտնիք' 14 | patreon_creator_discourse_username: "Discourse հաշվի օգտանուն, որը օգտագործվում է Patreon ստեղծողի հաշվի միջոցով մուտք գործելու ժամանակ՝ օգտագործելով 'Patreon Սոցիալական կայքով Մուտքը'" 15 | patreon_creator_access_token: "Գեներացված Patreon Ստեղծողի հասանելիության տոկեն" 16 | patreon_creator_refresh_token: "Գեներացված Patreon Creator's Refesh TokenՍտեղծողի Թարմացման Տոկեն" 17 | patreon_declined_pledges_grace_period_days: "Արտոնյալ ժամկետը (օրերով) , որից հետո երաշխիքը ամբողջությամբ մերժվում է:" 18 | max_patreon_api_reqs_per_hr: "Patreon API հարցումների առավելագույն քանակը մեկ ժամում" 19 | max_patreon_api_reqs_per_day: "Patreon API հարցումների առավելագույն քանակը մեկ օրում" 20 | patreon_verbose_log: 'միացնել patreon տվյալների ուղարկման բառային մուտքագրումը' 21 | patreon: 22 | error: 23 | invalid_response: "Անվավեր արձագանք Patreon API -ից" 24 | -------------------------------------------------------------------------------- /config/locales/server.id.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | id: 8 | -------------------------------------------------------------------------------- /config/locales/server.it.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | it: 8 | site_settings: 9 | patreon_enabled: 'Abilita il plugin discourse-patreon' 10 | patreon_login_enabled: 'Abilita l''accesso social di Patreon' 11 | patreon_client_id: 'ID client di Patreon generato' 12 | patreon_client_secret: 'Segreto client di Patreon generato' 13 | patreon_webhook_secret: 'Segreto webhook di Patreon generato' 14 | patreon_creator_discourse_username: "Nome utente dell'account Discourse che viene utilizzato per accedere tramite l'account di Patreon creator utilizzando l'\"Accesso Social di Patreon\"" 15 | patreon_creator_access_token: "Token di accesso a Patreon Creator generato" 16 | patreon_creator_refresh_token: "Token di aggiornamento per Patreon Creator generato" 17 | patreon_declined_pledges_grace_period_days: "Il periodo di tolleranza (in giorni) prima che una promessa di donazione sia completamente rifiutata." 18 | max_patreon_api_reqs_per_hr: "Numero massimo di richieste API Patreon all'ora" 19 | max_patreon_api_reqs_per_day: "Numero massimo di richieste API Patreon al giorno" 20 | patreon_verbose_log: 'abilita la diagnostica dettagliata del payload di patreon' 21 | patreon_donation_prompt_enabled: "Abilitare la richiesta di donazione?" 22 | patreon_donation_prompt_show_after_topics: "Mostra la richiesta di donazione dopo n argomenti" 23 | patreon_donation_prompt_campaign_url: "URL della campagna per la richiesta di donazioni" 24 | errors: 25 | patreon_creator_username_not_set: "Devi impostare il nome utente di Patreon Creator Discourse prima di abilitare l'accesso a Patreon." 26 | dashboard: 27 | problem: 28 | access_token_invalid: "I valori dei token di accesso e aggiornamento di Patreon Creator sono errati. Devi copiare e incollare i nuovi token dal sito web Patreon alle impostazioni del sito." 29 | patreon: 30 | error: 31 | invalid_response: "Risposta non valida dall'API Patreon" 32 | -------------------------------------------------------------------------------- /config/locales/server.ja.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ja: 8 | site_settings: 9 | patreon_enabled: 'discourse-patreon プラグインを有効にする' 10 | patreon_login_enabled: 'Patreon ソーシャルログインを有効にする' 11 | patreon_client_id: '生成された Patreon クライアント ID' 12 | patreon_client_secret: '生成された Patreon クライアントシークレット' 13 | patreon_webhook_secret: '生成された Patreon Webhook シークレット' 14 | patreon_creator_discourse_username: "「Patreon ソーシャルログイン」でPatreon クリエーターアカウントを通じてログインするために使用する Discourse アカウントのユーザー名" 15 | patreon_creator_access_token: "生成された Patreon クリエーターのアクセストークン" 16 | patreon_creator_refresh_token: "生成された Patreon クリエーターのリフレッシュトークン" 17 | patreon_declined_pledges_grace_period_days: "誓約が完全に拒否されるまでの猶予期間(日数)。" 18 | max_patreon_api_reqs_per_hr: "1 時間当たりの Patreon API の最大リクエスト数" 19 | max_patreon_api_reqs_per_day: "1 日当たりの Patreon API リクエストの最大数" 20 | patreon_verbose_log: 'Patreon ペイロードの詳細なロギングを有効にする' 21 | patreon_donation_prompt_enabled: "寄付プロンプトを有効にしますか?" 22 | patreon_donation_prompt_show_after_topics: "トピック n 件ごとに寄付プロンプトを表示する" 23 | patreon_donation_prompt_campaign_url: "寄付プロンプトのキャンペーン URL" 24 | errors: 25 | patreon_creator_username_not_set: "Patreon ログインを有効にする前に、Patreon クリエーターの Discourse ユーザー名設定を設定する必要があります。" 26 | dashboard: 27 | problem: 28 | access_token_invalid: "Patreon Creator のアクセストークンとリフレッシュトークンの値が間違っています。Patreon ウェブサイトから新しいトークンをコピーしてサイト設定に貼り付ける必要があります。" 29 | patreon: 30 | error: 31 | invalid_response: "Patreon API からの無効な応答" 32 | -------------------------------------------------------------------------------- /config/locales/server.ko.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ko: 8 | site_settings: 9 | patreon_enabled: '담화 패턴 플러그인 활성화' 10 | patreon_login_enabled: 'Patreon 소셜 로그인 활성화' 11 | patreon_client_id: '생성 된 Patreon 클라이언트 ID' 12 | patreon_client_secret: '생성 된 Patreon 클라이언트 시크릿' 13 | patreon_webhook_secret: '생성 된 Patreon Webhook Secret' 14 | patreon_creator_discourse_username: "'Patreon Social Login'을 사용하여 Patreon 제작자 계정을 통해 로그인하는 데 사용되는 담화 계정의 사용자 이름" 15 | patreon_creator_access_token: "Patreon Creator의 액세스 토큰 생성" 16 | patreon_creator_refresh_token: "생성 된 Patreon Creator의 Refesh Token" 17 | patreon_declined_pledges_grace_period_days: "서약이 완전히 거절되기 전의 유예 기간 (일)." 18 | max_patreon_api_reqs_per_hr: "시간당 최대 Patreon API 요청 수" 19 | max_patreon_api_reqs_per_day: "하루 최대 Patreon API 요청 수" 20 | patreon_verbose_log: 'patreon 페이로드에 대한 자세한 로깅 사용' 21 | patreon_donation_prompt_enabled: "기부 프롬프트를 사용 하시겠습니까?" 22 | patreon_donation_prompt_show_after_topics: "n 개의 주제 다음에 기부 프롬프트 표시" 23 | patreon_donation_prompt_campaign_url: "기부 프롬프트 캠페인 URL" 24 | patreon: 25 | error: 26 | invalid_response: "Patreon API의 잘못된 응답" 27 | -------------------------------------------------------------------------------- /config/locales/server.lt.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | lt: 8 | site_settings: 9 | patreon_login_enabled: 'Įgalinti Patreon prisijungimą' 10 | -------------------------------------------------------------------------------- /config/locales/server.lv.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | lv: 8 | -------------------------------------------------------------------------------- /config/locales/server.nb_NO.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | nb_NO: 8 | -------------------------------------------------------------------------------- /config/locales/server.nl.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | nl: 8 | site_settings: 9 | patreon_enabled: 'Discourse-Patreon-plug-in inschakelen' 10 | patreon_login_enabled: 'Sociale aanmelding voor Patreon inschakelen' 11 | patreon_client_id: 'Gegenereerde Patreon-client-ID' 12 | patreon_client_secret: 'Gegenereerd Patreon-clientgeheim' 13 | patreon_webhook_secret: 'Gegenereerd Patreon-webhookgeheim' 14 | patreon_creator_discourse_username: "Gebruikersnaam van het Discourse-account dat wordt gebruikt voor aanmelding via een Patreon-makersaccount met behulp van 'Sociale aanmelding voor Patreon'" 15 | patreon_creator_access_token: "Gegenereerd toegangstoken van Patreon-maker" 16 | patreon_creator_refresh_token: "Gegenereerd vernieuwingstoken van Patreon-maker" 17 | patreon_declined_pledges_grace_period_days: "Respijtperiode (in dagen) voordat een donatie volledig wordt geweigerd." 18 | max_patreon_api_reqs_per_hr: "Maximaal aantal Patreon-API-verzoeken per uur" 19 | max_patreon_api_reqs_per_day: "Maximaal aantal Patreon-API-verzoeken per dag" 20 | patreon_verbose_log: 'Uitgebreide logging van Patreon-payload inschakelen' 21 | patreon_donation_prompt_enabled: "Donatievraag inschakelen?" 22 | patreon_donation_prompt_show_after_topics: "Donatievraag weergeven na n topics" 23 | patreon_donation_prompt_campaign_url: "Campagne-URL voor donatievraag" 24 | errors: 25 | patreon_creator_username_not_set: "Je moet de instelling Discourse-gebruikersnaam Patreon-maker instellen voordat je Patreon-aanmelding inschakelt." 26 | dashboard: 27 | problem: 28 | access_token_invalid: "Het toegangs- en het verversingstoken van Patreon Creator zijn onjuist. Je moet nieuwe tokens kopiëren en plakken vanaf de Patreon-website naar de site-instellingen." 29 | patreon: 30 | error: 31 | invalid_response: "Ongeldig antwoord van Patreon-API" 32 | -------------------------------------------------------------------------------- /config/locales/server.pl_PL.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | pl_PL: 8 | site_settings: 9 | patreon_enabled: 'Włącz wtyczkę discourse‐patreon' 10 | patreon_login_enabled: 'Włącz logowanie za pomocą Patreona' 11 | patreon_client_id: 'Wygenerowane Client ID Patreona' 12 | patreon_client_secret: 'Wygenerowany Patreon Client Secret' 13 | patreon_webhook_secret: 'Wygenerowany Patreon Webhook Secret' 14 | patreon_creator_discourse_username: "Nazwa konta do zalogowania przez konto kreatora Patreon przy użyciu \"logowania za pomocą Patreona\"" 15 | patreon_creator_access_token: "Wygenerowany klucz dostępu kreatora Patreon" 16 | patreon_creator_refresh_token: "Wygenerowany token odświeżania kreatora Patreon" 17 | patreon_declined_pledges_grace_period_days: "Okres karencji (w dniach) przed całkowitym odrzuceniem wpłaty." 18 | max_patreon_api_reqs_per_hr: "Maksymalna liczba zapytań o API Patreona na godzinę" 19 | max_patreon_api_reqs_per_day: "Maksymalna liczba zapytań o API Patreona na dzień" 20 | patreon_verbose_log: 'aktywuj pełne logowanie do ładunku Patreona' 21 | patreon_donation_prompt_enabled: "Włączyć zachętę do dotacji?" 22 | patreon_donation_prompt_show_after_topics: "Pokaż zachętę do dotacji po n tematach." 23 | patreon_donation_prompt_campaign_url: "URL kampanii zachęcającej do dotacji" 24 | patreon: 25 | error: 26 | invalid_response: "Nieprawidłowa odpowiedź z API Patreona" 27 | -------------------------------------------------------------------------------- /config/locales/server.pt.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | pt: 8 | site_settings: 9 | patreon_enabled: 'Ativar o ''''plug-in'''' de discourse-patreon' 10 | patreon_login_enabled: 'Ativar Credencial Social de Patreon' 11 | patreon_client_id: 'Gerada Id. do Cliente Patreon' 12 | patreon_client_secret: 'Gerado Segredo de Cliente Patreon' 13 | patreon_webhook_secret: 'Gerado Segredo de Patreon Webhook Patreon' 14 | patreon_creator_discourse_username: "Nome de utilizador da conta Discourse que é utilizada para iniciar a sessão na conta do criador Patreon utilizando a 'Credencial Social do Patreon'" 15 | patreon_creator_access_token: "Gerado Código de Acesso do Criador Patreon" 16 | -------------------------------------------------------------------------------- /config/locales/server.pt_BR.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | pt_BR: 8 | site_settings: 9 | patreon_enabled: 'Ativar o plugin discourse-patreon' 10 | patreon_login_enabled: 'Ativar Login Social do Patreon' 11 | patreon_client_id: 'ID do cliente Patreon gerado' 12 | patreon_client_secret: 'Segredo do cliente Patreon gerado' 13 | patreon_webhook_secret: 'Segredo do Webhook do Patreon gerado' 14 | patreon_creator_discourse_username: "Nome do(a) usuário(a) da conta do Discourse que é usado para entrar pela conta do(a) criador(a) do Patreon com o \"Login Social do Patreon\"" 15 | patreon_creator_access_token: "Token de acesso do criador do Patreon gerado" 16 | patreon_creator_refresh_token: "Token de atualização do(a) criador(a) do Patreon gerado" 17 | patreon_declined_pledges_grace_period_days: "Período de carência (em dias) antes que um compromisso seja recusado completamente." 18 | max_patreon_api_reqs_per_hr: "Número máximo de solicitações da API do Patreon por hora" 19 | max_patreon_api_reqs_per_day: "Número máximo de solicitações da API do Patreon por dia" 20 | patreon_verbose_log: 'ativar registro prolixo do conteúdo do Patreon' 21 | patreon_donation_prompt_enabled: "Ativar solicitação de doação?" 22 | patreon_donation_prompt_show_after_topics: "Mostrar solicitação de doação após n tópicos" 23 | patreon_donation_prompt_campaign_url: "URL da campanha de solicitação de doação" 24 | errors: 25 | patreon_creator_username_not_set: "Você precisa definir a configuração do nome do(a) usuário(a) do Discourse do(a) criador(a) do Patreon antes de ativar o login do Patreon." 26 | dashboard: 27 | problem: 28 | access_token_invalid: "Os valores dos tokens de atualização e acesso do Patreon Creator estão incorretos. É preciso copiar e colar os novos tokens de Patreon website para as configurações do site." 29 | patreon: 30 | error: 31 | invalid_response: "Resposta inválida da API do Patreon" 32 | -------------------------------------------------------------------------------- /config/locales/server.ro.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ro: 8 | site_settings: 9 | patreon_enabled: 'Activează modulul discourse-patreon' 10 | patreon_login_enabled: 'Activează conectarea socială Patreon' 11 | patreon_client_id: 'ID client Patreon generat' 12 | patreon_client_secret: 'Secret client Patreon generat' 13 | dashboard: 14 | problem: 15 | access_token_invalid: "Valorile jetoanelor de acces și de reîmprospătare ale Creatorului Patreon sunt incorecte. Trebuie să copiezi și să lipești noile jetoane de pe site-ul Patreon în setările site-ului." 16 | -------------------------------------------------------------------------------- /config/locales/server.ru.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ru: 8 | site_settings: 9 | patreon_enabled: 'Включить плагин discourse-patreon' 10 | patreon_login_enabled: 'Включить Patreon Social Login' 11 | patreon_client_id: 'Сгенерированный Patreon Client ID' 12 | patreon_client_secret: 'Сгенерированный Patreon Client Secret' 13 | patreon_webhook_secret: 'Сгенерированный Patreon Webhook Secret' 14 | patreon_creator_discourse_username: "Имя пользователя Discourse, которое используется для входа через учётную запись Patreon с помощью 'Patreon Social Login'" 15 | patreon_creator_access_token: "Сгенерированный access-токен от Patreon" 16 | patreon_creator_refresh_token: "Сгенерированный refesh-токен от Patreon" 17 | patreon_declined_pledges_grace_period_days: "Период ожидания (в днях) до полного отказа от подписки." 18 | max_patreon_api_reqs_per_hr: "Максимальное количество запросов Patreon API в час" 19 | max_patreon_api_reqs_per_day: "Максимальное количество запросов Patreon API в день" 20 | patreon_verbose_log: 'Добавлять в журнал подробную информацию при работе с Patreon' 21 | patreon_donation_prompt_enabled: "Включить запрос на пожертвование?" 22 | patreon_donation_prompt_show_after_topics: "Показывать приглашение к пожертвованию после указанного здесь количества тем" 23 | patreon_donation_prompt_campaign_url: "URL рекламной кампании для пожертвований" 24 | errors: 25 | patreon_creator_username_not_set: "Перед включением входа через Patreon необходимо установить настройку имени пользователя в Patreon Creator Discourse." 26 | dashboard: 27 | problem: 28 | access_token_invalid: "Значения токенов доступа и обновления Patreon Creator неверны. Вам нужно скопировать и вставить новые токены с сайта Patreon в , настройки сайта." 29 | patreon: 30 | error: 31 | invalid_response: "Неверный ответ от Patreon API" 32 | -------------------------------------------------------------------------------- /config/locales/server.sk.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sk: 8 | -------------------------------------------------------------------------------- /config/locales/server.sl.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sl: 8 | site_settings: 9 | patreon_enabled: 'Vključi discourse-patreon vtičnik' 10 | -------------------------------------------------------------------------------- /config/locales/server.sq.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sq: 8 | -------------------------------------------------------------------------------- /config/locales/server.sr.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sr: 8 | -------------------------------------------------------------------------------- /config/locales/server.sv.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sv: 8 | site_settings: 9 | patreon_enabled: 'Aktivera discourse-patreon-tillägget' 10 | patreon_login_enabled: 'Aktivera Patreon Social Login' 11 | patreon_client_id: 'Genererade Patreon-klient-ID' 12 | patreon_client_secret: 'Genererade Patreon-klienthemlighet' 13 | patreon_webhook_secret: 'Genererade Patreon Webhook-hemlighet' 14 | patreon_creator_discourse_username: "Användarnamn på det Discourse-konto som används för att logga in via Patreon-skaparkonto med 'Patreon Social Login'" 15 | patreon_creator_access_token: "Genererade Patreon Creator-åtkomstbevis" 16 | patreon_creator_refresh_token: "Genererade Patreon Creator-uppdateringsbevis" 17 | patreon_declined_pledges_grace_period_days: "Nådefrist (i dagar) innan en donation nekas helt." 18 | max_patreon_api_reqs_per_hr: "Maximalt antal Patreon API-förfrågningar per timme" 19 | max_patreon_api_reqs_per_day: "Maximalt antal Patreon API-förfrågningar per dag" 20 | patreon_verbose_log: 'aktivera utförlig loggning av Patreon-nyttolast' 21 | patreon_donation_prompt_enabled: "Aktivera donationsuppmaning?" 22 | patreon_donation_prompt_show_after_topics: "Visa donationsuppmaning efter n ämnen" 23 | patreon_donation_prompt_campaign_url: "Donationsuppmaningskampanj-URL" 24 | errors: 25 | patreon_creator_username_not_set: "Du måste ange inställningen för Patreon-skaparens Discourse-användarnamn innan du aktiverar Patreon-inloggning." 26 | patreon: 27 | error: 28 | invalid_response: "Ogiltigt svar från Patreon-API" 29 | -------------------------------------------------------------------------------- /config/locales/server.sw.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | sw: 8 | site_settings: 9 | patreon_enabled: 'Ruhusu plugin ya discourse-patreon ' 10 | patreon_login_enabled: 'Ruhusu watu kuingia kupitia Patreon' 11 | patreon_client_id: 'Utambulisho wa Mteja wa Patreon Uliotengenezwa' 12 | patreon_creator_discourse_username: "Jina la mtumiaji kutoka kwenye Akaunti ya Discourse ambalo limetumika kutengeneza akaunti ya Patreon kupitia 'Patreon Social Login'" 13 | patreon_declined_pledges_grace_period_days: "Mda fulani (siku) kabla ya ombi kukataliwa kabisa." 14 | max_patreon_api_reqs_per_day: "Kiwango cha juu cha maombi kwa Patreon API kwa siku" 15 | -------------------------------------------------------------------------------- /config/locales/server.te.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | te: 8 | -------------------------------------------------------------------------------- /config/locales/server.th.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | th: 8 | -------------------------------------------------------------------------------- /config/locales/server.tr_TR.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | tr_TR: 8 | site_settings: 9 | patreon_enabled: 'Discourse-patreon eklentisini etkinleştir' 10 | patreon_login_enabled: 'Patreon Sosyal Girişini Etkinleştir' 11 | patreon_client_id: 'Oluşturulan Patreon İstemci Kimliği' 12 | patreon_client_secret: 'Oluşturulan Patreon İstemcisi Gizliliği' 13 | patreon_webhook_secret: 'Oluşturulan Patreon Web Kancası Sırrı' 14 | patreon_creator_discourse_username: "\"Patreon Sosyal Girişi\" kullanılarak Patreon oluşturucu hesabı üzerinden giriş yapmak için kullanılan Discourse hesabının kullanıcı adı" 15 | patreon_creator_access_token: "Oluşturulan Patreon Oluşturucusunun Erişim Token'ı" 16 | patreon_creator_refresh_token: "Oluşturulan Patreon Oluşturucusunun Refesh Token'ı" 17 | patreon_declined_pledges_grace_period_days: "Bir bağış tamamen reddedilmeden önceki bekleme süresi (gün cinsinden)." 18 | max_patreon_api_reqs_per_hr: "Saat başına maksimum Patreon API isteği sayısı" 19 | max_patreon_api_reqs_per_day: "Günlük maksimum Patreon API isteği sayısı" 20 | patreon_verbose_log: 'patreon yükünün ayrıntılı günlük kaydını etkinleştirin' 21 | patreon_donation_prompt_enabled: "Bağış istemi etkinleştirilsin mi?" 22 | patreon_donation_prompt_show_after_topics: "N konudan sonra bağış istemini göster" 23 | patreon_donation_prompt_campaign_url: "Bağış istemi kampanyasının URL'si" 24 | errors: 25 | patreon_creator_username_not_set: "Patreon Girişini etkinleştirmeden önce Patreon Üreticisi Discourse Kullanıcı Adı ayarını yapmanız gerekir." 26 | dashboard: 27 | problem: 28 | access_token_invalid: "Patreon Creator'ın erişim ve yenileme token değerleri yanlış. Yeni token'ları Patreon web sitesinden kopyalayıp site ayarlarına yapıştırmalısınız." 29 | patreon: 30 | error: 31 | invalid_response: "Patreon API'den geçersiz yanıt" 32 | -------------------------------------------------------------------------------- /config/locales/server.ug.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ug: 8 | -------------------------------------------------------------------------------- /config/locales/server.uk.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | uk: 8 | site_settings: 9 | patreon_enabled: 'Увімкніть discourse-patreon плагін' 10 | patreon_login_enabled: 'Увімкнути соціальний вхід з Patreon' 11 | patreon_client_id: 'Створений Patreon Client ID' 12 | patreon_client_secret: 'Створений Patreon Client Secret' 13 | patreon_webhook_secret: 'Створений Patreon Webhook Secret' 14 | patreon_creator_discourse_username: "Ім’я користувача облікового запису «Discourse», який використовується для входу через обліковий запис Patreon, використовуючи «Patreon Social Login»" 15 | max_patreon_api_reqs_per_hr: "Максимальна кількість запитів Patreon API на годину" 16 | max_patreon_api_reqs_per_day: "Максимальна кількість запитів Patreon API на день" 17 | patreon_verbose_log: 'увімкнути детальний журнал оплат Patreon' 18 | patreon_donation_prompt_enabled: "Увімкнути підказку про пожертвування?" 19 | patreon_donation_prompt_show_after_topics: "Показати запит на пожертвування після n тем" 20 | patreon_donation_prompt_campaign_url: "URL-адреса кампанії з швидким пожертвуванням" 21 | patreon: 22 | error: 23 | invalid_response: "Неправильна відповідь від API Patreon" 24 | -------------------------------------------------------------------------------- /config/locales/server.ur.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | ur: 8 | site_settings: 9 | patreon_enabled: 'ڈسکورس-پَیٹریئون پلگ اِن کو فعال کریں' 10 | patreon_login_enabled: 'پَیٹریئون سوشل لاگ اِن کو فعال کریں' 11 | patreon_client_id: 'پَیٹریئون کلائنٹ ID تیار کرلی گئی' 12 | patreon_client_secret: 'پَیٹریئون کلائنٹ سیکرٹ تیار کرلیا گیا' 13 | patreon_webhook_secret: 'پَیٹریئون وَیب ہوک سیکرٹ تیار کرلیا گیا' 14 | patreon_creator_discourse_username: "ڈسکورس اکاؤنٹ کا صارف نام جسے 'پَیٹریئون سماجی لاگ اِن' کا استعمال کرتے ہوئے پَیٹریئون کرِییٹر اکاؤنٹ کے ذریعہ لاگ ان کرنے کے لئے استعمال کیا جاتا ہے۔" 15 | patreon_creator_access_token: "پَیٹریئون کرِییٹر اِکسس ٹوکن تیار کرلیا گیا" 16 | patreon_creator_refresh_token: "پَیٹریئون کرِییٹر ریفریش ٹوکن تیار کرلیا گیا" 17 | patreon_declined_pledges_grace_period_days: "رعایتی مدت (دنوں میں) اِس سے پہلے کہ وعدہ مکمل طور پر رد کر دیا جائے۔" 18 | max_patreon_api_reqs_per_hr: "فی گھنٹہ پَیٹریئون API درخواستوں کی زیادہ سے زیادہ تعداد" 19 | max_patreon_api_reqs_per_day: "فی دن پَیٹریئون API درخواستوں کی زیادہ سے زیادہ تعداد" 20 | patreon_verbose_log: 'پَیٹریئون پَیلوڈ کیلئے تفصیلی لاگِنگ فعال کریں' 21 | patreon: 22 | error: 23 | invalid_response: "پَیٹریئون API کی طرف سے غلط جواب" 24 | -------------------------------------------------------------------------------- /config/locales/server.vi.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | vi: 8 | site_settings: 9 | patreon_login_enabled: 'Kích hoạt đăng nhập xã hội Patreon' 10 | patreon_creator_discourse_username: "Tên người dùng của tài khoản Discourse được sử dụng để đăng nhập thông qua tài khoản người tạo Patreon bằng cách sử dụng 'Đăng nhập xã hội Patreon'" 11 | -------------------------------------------------------------------------------- /config/locales/server.zh_CN.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | zh_CN: 8 | site_settings: 9 | patreon_enabled: '启用 discourse-patreon 插件' 10 | patreon_login_enabled: '启用 Patreon 社交登录' 11 | patreon_client_id: '生成的 Patreon 客户端 ID' 12 | patreon_client_secret: '生成的 Patreon 客户端密钥' 13 | patreon_webhook_secret: '生成的 Patreon 网络钩子密钥' 14 | patreon_creator_discourse_username: "Discourse 帐户的用户名,用于使用“Patreon 社交登录”通过 Patreon 创作者帐户登录" 15 | patreon_creator_access_token: "生成的 Patreon 创作者的访问令牌" 16 | patreon_creator_refresh_token: "生成的 Patreon 创作者的刷新令牌" 17 | patreon_declined_pledges_grace_period_days: "承诺被完全拒绝之前的宽限期(以天为单位)。" 18 | max_patreon_api_reqs_per_hr: "每小时最大 Patreon API 请求数量" 19 | max_patreon_api_reqs_per_day: "每天最大 Patreon API 请求数量" 20 | patreon_verbose_log: '启用 Patreon 有效负载的详细日志记录' 21 | patreon_donation_prompt_enabled: "启用捐助提示?" 22 | patreon_donation_prompt_show_after_topics: "在 n 个话题后显示捐助提示" 23 | patreon_donation_prompt_campaign_url: "捐助提示活动 URL" 24 | errors: 25 | patreon_creator_username_not_set: "在启用 Patreon 登录之前,您需要设置 Patreon 创作者 Discourse 用户名设置。" 26 | dashboard: 27 | problem: 28 | access_token_invalid: "Patreon 创作者的访问和刷新令牌值不正确。您必须将新的令牌从 Patreon 网站复制粘贴到网站设置。" 29 | patreon: 30 | error: 31 | invalid_response: "Patreon API 的响应无效" 32 | -------------------------------------------------------------------------------- /config/locales/server.zh_TW.yml: -------------------------------------------------------------------------------- 1 | # WARNING: Never edit this file. 2 | # It will be overwritten when translations are pulled from Crowdin. 3 | # 4 | # To work with us on translations, join this project: 5 | # https://translate.discourse.org/ 6 | 7 | zh_TW: 8 | -------------------------------------------------------------------------------- /config/settings.yml: -------------------------------------------------------------------------------- 1 | discourse_patreon: 2 | patreon_enabled: 3 | default: false 4 | client: true 5 | patreon_login_enabled: 6 | default: false 7 | client: true 8 | validator: 'PatreonLoginEnabledValidator' 9 | patreon_client_id: 10 | default: '' 11 | patreon_client_secret: 12 | default: '' 13 | secret: true 14 | patreon_webhook_secret: 15 | default: '' 16 | secret: true 17 | patreon_creator_discourse_username: 18 | default: '' 19 | type: username 20 | patreon_creator_access_token: 21 | default: '' 22 | secret: true 23 | patreon_creator_refresh_token: 24 | default: '' 25 | secret: true 26 | patreon_declined_pledges_grace_period_days: 27 | default: 7 28 | max_patreon_api_reqs_per_hr: 29 | default: 100 30 | max_patreon_api_reqs_per_day: 31 | default: 1000 32 | patreon_verbose_log: 33 | default: false 34 | patreon_login_ignore_state: 35 | default: false 36 | hidden: true 37 | patreon_donation_prompt_enabled: 38 | default: false 39 | client: true 40 | patreon_donation_prompt_show_after_topics: 41 | default: 20 42 | client: true 43 | min: 0 44 | patreon_donation_prompt_campaign_url: 45 | default: "" 46 | client: true 47 | regex: "^https?:\\/\\/.+[^\\/]$" 48 | -------------------------------------------------------------------------------- /db/migrate/20211230151700_migrate_patreon_user_info.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class MigratePatreonUserInfo < ActiveRecord::Migration[6.1] 4 | def up 5 | execute <<~SQL 6 | INSERT INTO user_associated_accounts ( 7 | provider_name, 8 | provider_uid, 9 | user_id, 10 | info, 11 | last_used, 12 | created_at, 13 | updated_at 14 | ) SELECT 15 | 'patreon', 16 | uid, 17 | user_id, 18 | json_build_object('email', email, 'name', name), 19 | updated_at, 20 | created_at, 21 | updated_at 22 | FROM oauth2_user_infos 23 | WHERE provider = 'patreon' 24 | ON CONFLICT DO NOTHING 25 | SQL 26 | end 27 | 28 | def down 29 | raise ActiveRecord::IrreversibleMigration 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /db/migrate/20221025153038_deactivate_unverified_email_patreon_accounts.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DeactivateUnverifiedEmailPatreonAccounts < ActiveRecord::Migration[6.1] 4 | def up 5 | execute <<~SQL 6 | UPDATE users SET active = false 7 | WHERE users.id IN ( 8 | SELECT user_id FROM user_associated_accounts 9 | WHERE provider_name = 'patreon' 10 | AND extra -> 'raw_info' -> 'data' -> 'attributes' ->> 'is_email_verified' = 'false' 11 | ) 12 | SQL 13 | end 14 | 15 | def down 16 | # noop 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /db/migrate/20221026043851_delete_unverified_patreon_user_info.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class DeleteUnverifiedPatreonUserInfo < ActiveRecord::Migration[6.1] 4 | def up 5 | execute <<~SQL 6 | DELETE FROM user_auth_tokens 7 | WHERE user_id IN ( 8 | SELECT user_id 9 | FROM user_associated_accounts 10 | WHERE provider_name = 'patreon' 11 | AND COALESCE(JSON_EXTRACT_PATH(extra::json, 'raw_info', 'data', 'attributes', 'is_email_verified')::text, 'false') <> 'true' 12 | ) 13 | SQL 14 | 15 | execute <<~SQL 16 | UPDATE user_api_keys 17 | SET revoked_at = NOW() 18 | WHERE user_id IN ( 19 | SELECT user_id 20 | FROM user_associated_accounts 21 | WHERE provider_name = 'patreon' 22 | AND COALESCE(JSON_EXTRACT_PATH(extra::json, 'raw_info', 'data', 'attributes', 'is_email_verified')::text, 'false') <> 'true' 23 | ) 24 | SQL 25 | 26 | execute <<~SQL 27 | UPDATE api_keys 28 | SET revoked_at = NOW() 29 | WHERE created_by_id IN ( 30 | SELECT user_id 31 | FROM user_associated_accounts 32 | WHERE provider_name = 'patreon' 33 | AND COALESCE(JSON_EXTRACT_PATH(extra::json, 'raw_info', 'data', 'attributes', 'is_email_verified')::text, 'false') <> 'true' 34 | ) 35 | SQL 36 | 37 | execute <<~SQL 38 | DELETE FROM user_associated_accounts 39 | WHERE provider_name = 'patreon' 40 | AND COALESCE(JSON_EXTRACT_PATH(extra::json, 'raw_info', 'data', 'attributes', 'is_email_verified')::text, 'false') <> 'true' 41 | SQL 42 | end 43 | 44 | def down 45 | # noop 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /eslint.config.mjs: -------------------------------------------------------------------------------- 1 | import DiscourseRecommended from "@discourse/lint-configs/eslint"; 2 | 3 | export default [...DiscourseRecommended]; 4 | -------------------------------------------------------------------------------- /lib/api.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "json" 4 | 5 | module ::Patreon 6 | class InvalidApiResponse < ::StandardError 7 | end 8 | 9 | class Api 10 | ACCESS_TOKEN_INVALID = "dashboard.patreon.access_token_invalid".freeze 11 | INVALID_RESPONSE = "patreon.error.invalid_response".freeze 12 | 13 | def self.campaign_data 14 | get( 15 | "/oauth2/api/current_user/campaigns?include=rewards,creator,goals,pledges&page[count]=100", 16 | ) 17 | end 18 | 19 | def self.get(uri) 20 | limiter_hr = 21 | RateLimiter.new(nil, "patreon_api_hr", SiteSetting.max_patreon_api_reqs_per_hr, 1.hour) 22 | limiter_day = 23 | RateLimiter.new(nil, "patreon_api_day", SiteSetting.max_patreon_api_reqs_per_day, 1.day) 24 | 25 | limiter_hr.performed! unless limiter_hr.can_perform? 26 | 27 | limiter_day.performed! unless limiter_day.can_perform? 28 | 29 | response = 30 | Faraday.new( 31 | url: "https://api.patreon.com", 32 | headers: { 33 | "Authorization" => "Bearer #{SiteSetting.patreon_creator_access_token}", 34 | }, 35 | ).get(uri) 36 | 37 | limiter_hr.performed! 38 | limiter_day.performed! 39 | 40 | case response.status 41 | when 200 42 | return JSON.parse response.body 43 | when 401 44 | ProblemCheckTracker[:access_token_invalid].problem! 45 | else 46 | e = ::Patreon::InvalidApiResponse.new(response.body.presence || "") 47 | e.set_backtrace(caller) 48 | Discourse.warn_exception(e, message: I18n.t(INVALID_RESPONSE), env: { api_uri: uri }) 49 | end 50 | 51 | { error: I18n.t(INVALID_RESPONSE) } 52 | end 53 | end 54 | end 55 | -------------------------------------------------------------------------------- /lib/campaign.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "json" 4 | 5 | module ::Patreon 6 | class Campaign 7 | def self.update! 8 | rewards = {} 9 | campaign_rewards = [] 10 | pledges_uris = [] 11 | 12 | response = ::Patreon::Api.campaign_data 13 | 14 | return false if response.blank? || response["data"].blank? 15 | 16 | response["data"].map do |campaign| 17 | uri = campaign["relationships"]["pledges"]["links"]["first"] 18 | pledges_uris << uri.sub("page%5Bcount%5D=20", "page%5Bcount%5D=100") 19 | 20 | campaign["relationships"]["rewards"]["data"].each do |entry| 21 | campaign_rewards << entry["id"] 22 | end 23 | end 24 | 25 | response["included"].each do |entry| 26 | id = entry["id"] 27 | if entry["type"] == "reward" && campaign_rewards.include?(id) 28 | rewards[id] = entry["attributes"] 29 | rewards[id]["id"] = id 30 | end 31 | end 32 | 33 | # Special catch all patrons virtual reward 34 | rewards["0"] ||= {} 35 | rewards["0"]["title"] = "All Patrons" 36 | rewards["0"]["amount_cents"] = 0 37 | 38 | Patreon.set("rewards", rewards) 39 | 40 | Patreon::Pledge.pull!(pledges_uris) 41 | 42 | # Sets all patrons to the seed group by default on first run 43 | filters = Patreon.get("filters") 44 | Patreon::Seed.seed_content! if filters.blank? 45 | 46 | true 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/patron.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "json" 4 | 5 | module ::Patreon 6 | class Patron 7 | def self.update! 8 | return unless Patreon::Campaign.update! 9 | sync_groups 10 | 11 | rewards = Patreon.get("rewards") 12 | ::MessageBus.publish "/patreon/background_sync", rewards 13 | end 14 | 15 | def self.sync_groups 16 | filters = Patreon.get("filters") || {} 17 | return if filters.blank? 18 | 19 | local_users = get_local_users 20 | reward_users = Patreon::RewardUser.all 21 | declined_users = Patreon::Pledge::Decline.all 22 | declined_pledges_grace_period_days = SiteSetting.patreon_declined_pledges_grace_period_days 23 | 24 | filters.each_pair do |group_id, rewards| 25 | group = Group.find_by(id: group_id) 26 | 27 | next if group.nil? 28 | 29 | patron_ids = rewards.map { |id| reward_users[id] }.compact.flatten.uniq 30 | 31 | next if patron_ids.blank? 32 | 33 | user_ids = 34 | local_users 35 | .select do |_, patreon_id| 36 | is_declined = false 37 | declined_since = declined_users[patreon_id] 38 | 39 | if declined_since.present? 40 | declined_days_count = Time.now.to_date - declined_since.to_date 41 | is_declined = declined_days_count > declined_pledges_grace_period_days 42 | end 43 | 44 | patreon_id.present? && patron_ids.include?(patreon_id) && !is_declined 45 | end 46 | .pluck(0) 47 | 48 | group_user_ids = GroupUser.where(group: group).pluck(:user_id) 49 | 50 | User.where(id: (user_ids - group_user_ids)).each { |user| group.add user } 51 | 52 | User.where(id: (group_user_ids - user_ids)).each { |user| group.remove user } 53 | end 54 | end 55 | 56 | def self.sync_groups_by(patreon_id:) 57 | filters = Patreon.get("filters") || {} 58 | return if filters.blank? 59 | 60 | user = get_local_user(patreon_id) 61 | return if user.blank? 62 | 63 | reward_users = Patreon::RewardUser.all 64 | declined_since = Patreon::Pledge::Decline.all[patreon_id] 65 | declined_pledges_grace_period_days = SiteSetting.patreon_declined_pledges_grace_period_days 66 | is_member = true 67 | 68 | if declined_since.present? 69 | declined_days_count = Time.now.to_date - declined_since.to_date 70 | is_member = false if declined_days_count > declined_pledges_grace_period_days 71 | end 72 | 73 | filters.each_pair do |group_id, rewards| 74 | group = Group.find_by(id: group_id) 75 | next if group.blank? 76 | 77 | if is_member 78 | patron_ids = rewards.map { |id| reward_users[id] }.compact.flatten.uniq 79 | next if patron_ids.blank? 80 | 81 | is_member = false if patron_ids.exclude?(patreon_id) 82 | end 83 | 84 | is_existing_member = GroupUser.exists?(group: group, user: user) 85 | 86 | if is_member && !is_existing_member 87 | group.add user 88 | elsif !is_member && is_existing_member 89 | group.remove user 90 | end 91 | end 92 | end 93 | 94 | def self.all 95 | Patreon.get("users") || {} 96 | end 97 | 98 | def self.update_local_user(user, patreon_id, skip_save = false) 99 | return if user.blank? 100 | 101 | user.custom_fields["patreon_id"] = patreon_id 102 | user.save_custom_fields unless skip_save || user.custom_fields_clean? 103 | 104 | user 105 | end 106 | 107 | def self.attr(name, user) 108 | id = user.custom_fields["patreon_id"] 109 | return if id.blank? 110 | 111 | case name 112 | when "email" 113 | all[id] 114 | when "amount_cents" 115 | Patreon::Pledge.all[id] 116 | when "rewards" 117 | reward_users = Patreon::RewardUser.all 118 | Patreon::Reward 119 | .all 120 | .map { |i, r| r["title"] if reward_users[i].include?(id) } 121 | .compact 122 | .join(", ") 123 | when "declined_since" 124 | Patreon::Pledge::Decline.all[id] 125 | else 126 | id 127 | end 128 | end 129 | 130 | def self.get_local_users 131 | users = 132 | User.joins( 133 | "INNER JOIN user_custom_fields cf ON cf.user_id = users.id AND cf.name = 'patreon_id'", 134 | ).pluck("users.id, cf.value") 135 | patrons = all.slice!(*users.pluck(1)) 136 | 137 | oauth_users = UserAssociatedAccount.includes(:user).where(provider_name: "patreon") 138 | oauth_users = oauth_users.where("provider_uid IN (?)", patrons.keys) if patrons.present? 139 | 140 | users += 141 | oauth_users.map do |o| 142 | patrons = patrons.slice!(o.provider_uid) 143 | update_local_user(o.user, o.provider_uid) 144 | [o.user_id, o.provider_uid] 145 | end 146 | 147 | emails = patrons.values.map { |e| e.downcase } 148 | users += 149 | UserEmail 150 | .includes(:user) 151 | .where(email: emails) 152 | .map do |u| 153 | patreon_id = patrons.key(u.email) 154 | update_local_user(u.user, patreon_id) 155 | [u.user_id, patreon_id] 156 | end 157 | 158 | users.compact 159 | end 160 | 161 | def self.get_local_user(patreon_id) 162 | user = 163 | User.joins(:_custom_fields).find_by( 164 | user_custom_fields: { 165 | name: "patreon_id", 166 | value: patreon_id, 167 | }, 168 | ) 169 | return user if user.present? 170 | 171 | user = 172 | User.joins(:user_associated_accounts).find_by( 173 | user_associated_accounts: { 174 | provider_name: "patreon", 175 | provider_uid: patreon_id, 176 | }, 177 | ) 178 | user ||= User.joins(:user_emails).find_by(user_emails: { email: all[patreon_id] }) 179 | return if user.blank? 180 | 181 | update_local_user(user, patreon_id) 182 | end 183 | end 184 | end 185 | -------------------------------------------------------------------------------- /lib/pledge.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ::Patreon 4 | class Pledge 5 | def self.create!(pledge_data) 6 | save!([pledge_data], true) 7 | end 8 | 9 | def self.update!(pledge_data) 10 | delete!(pledge_data) 11 | create!(pledge_data) 12 | end 13 | 14 | def self.delete!(pledge_data) 15 | entry = pledge_data["data"] 16 | rel = entry["relationships"] 17 | reward_users = Patreon::RewardUser.all 18 | 19 | if entry["type"] == "pledge" 20 | patron_id = rel["patron"]["data"]["id"] 21 | reward_id = rel["reward"]["data"]["id"] if rel["reward"]["data"].present? 22 | 23 | reward_users[reward_id].reject! { |i| i == patron_id } if reward_id.present? 24 | elsif entry["type"] == "member" 25 | patron_id = rel["user"]["data"]["id"] 26 | 27 | (rel["currently_entitled_tiers"]["data"] || []).each do |tier| 28 | (reward_users[tier["id"]] || []).reject! { |i| i == patron_id } 29 | end 30 | end 31 | 32 | Patreon.set("pledges", all.except(patron_id)) 33 | Decline.set(Decline.all.except(patron_id)) 34 | Patreon.set("users", Patreon::Patron.all.except(patron_id)) 35 | Patreon.set("reward-users", reward_users) 36 | end 37 | 38 | def self.pull!(uris) 39 | pledges_data = [] 40 | 41 | uris.each do |uri| 42 | pledge_data = ::Patreon::Api.get(uri) 43 | 44 | # get next page if necessary and add to the current loop 45 | if pledge_data["links"] && pledge_data["links"]["next"] 46 | next_page_uri = pledge_data["links"]["next"] 47 | uris << next_page_uri if next_page_uri.present? 48 | end 49 | 50 | pledges_data << pledge_data if pledge_data.present? 51 | end 52 | 53 | save!(pledges_data) 54 | end 55 | 56 | def self.save!(pledges_data, is_append = false) 57 | pledges = is_append ? all : {} 58 | reward_users = is_append ? Patreon::RewardUser.all : {} 59 | users = is_append ? Patreon::Patron.all : {} 60 | declines = is_append ? Decline.all : {} 61 | 62 | pledges_data.each do |pledge_data| 63 | new_pledges, new_declines, new_reward_users, new_users = extract(pledge_data) 64 | 65 | pledges.merge!(new_pledges) 66 | declines.merge!(new_declines) 67 | users.merge!(new_users) 68 | 69 | Patreon::Reward.all.keys.each do |key| 70 | reward_users[key] = (reward_users[key] || []) + (new_reward_users[key] || []) 71 | end 72 | end 73 | 74 | reward_users["0"] = pledges.keys 75 | 76 | Patreon.set("pledges", pledges) 77 | Decline.set(declines) 78 | Patreon.set("reward-users", reward_users) 79 | Patreon.set("users", users) 80 | end 81 | 82 | def self.extract(pledge_data) 83 | pledges, declines, reward_users, users = {}, {}, {}, {} 84 | 85 | if pledge_data && pledge_data["data"].present? 86 | pledge_data["data"] = [pledge_data["data"]] unless pledge_data["data"].kind_of?(Array) 87 | 88 | # get pledges info 89 | pledge_data["data"].each do |entry| 90 | if entry["type"] == "pledge" 91 | patron_id = entry["relationships"]["patron"]["data"]["id"] 92 | attrs = entry["attributes"] 93 | 94 | ( 95 | reward_users[entry["relationships"]["reward"]["data"]["id"]] ||= [] 96 | ) << patron_id unless entry["relationships"]["reward"]["data"].nil? 97 | pledges[patron_id] = attrs["amount_cents"] 98 | declines[patron_id] = attrs["declined_since"] if attrs["declined_since"].present? 99 | elsif entry["type"] == "member" 100 | patron_id = entry["relationships"]["user"]["data"]["id"] 101 | attrs = entry["attributes"] 102 | 103 | currently_entitled_tiers = entry["relationships"]["currently_entitled_tiers"] || {} 104 | (currently_entitled_tiers["data"] || []).each do |tier| 105 | (reward_users[tier["id"]] ||= []) << patron_id 106 | end 107 | pledges[patron_id] = attrs["pledge_amount_cents"] 108 | declines[patron_id] = attrs["last_charge_date"] if attrs["last_charge_status"] == 109 | "Declined" 110 | end 111 | end 112 | 113 | # get user list too 114 | pledge_data["included"].each do |entry| 115 | case entry["type"] 116 | when "user" 117 | if entry["attributes"]["email"].present? 118 | users[entry["id"]] = entry["attributes"]["email"].downcase 119 | end 120 | end 121 | end 122 | end 123 | 124 | [pledges, declines, reward_users, users] 125 | end 126 | 127 | def self.all 128 | Patreon.get("pledges") || {} 129 | end 130 | 131 | def self.get_patreon_id(pledge_data) 132 | data = pledge_data["data"] 133 | key = data["type"] == "member" ? "user" : "patron" 134 | data["relationships"][key]["data"]["id"] 135 | end 136 | 137 | class Decline 138 | KEY = "pledge-declines".freeze 139 | 140 | def self.all 141 | Patreon.get(KEY) || {} 142 | end 143 | 144 | def self.set(value) 145 | Patreon.set(KEY, value) 146 | end 147 | end 148 | end 149 | end 150 | -------------------------------------------------------------------------------- /lib/seed.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module ::Patreon 4 | class Seed 5 | def self.seed_content! 6 | flair = 7 | File.open( 8 | "#{Rails.root}/plugins/discourse-patreon/public/images/patreon-logomark-color-on-white.png", 9 | ) 10 | flair_upload = 11 | UploadCreator.new(flair, "patreon-flair.png").create_for(Discourse.system_user.id) 12 | 13 | default_group = 14 | Group.where(name: "patrons").first_or_initialize( 15 | visibility_level: Group.visibility_levels[:public], 16 | primary_group: true, 17 | title: "Patron", 18 | flair_upload_id: flair_upload.id, 19 | bio_raw: 20 | "To get access to this group go to our [Patreon page](https://www.patreon.com/) and add your pledge.", 21 | full_name: "Our Patreon supporters", 22 | ) 23 | default_group.save! 24 | 25 | badge = 26 | Badge.where(name: "Patron").first_or_initialize( 27 | description: "Active Patron", 28 | badge_type_id: 1, 29 | listable: true, 30 | target_posts: false, 31 | query: 32 | "select user_id, created_at granted_at, NULL post_id from group_users where group_id = ( select g.id from groups g where g.name = 'patrons' )", 33 | enabled: true, 34 | auto_revoke: true, 35 | badge_grouping_id: 2, 36 | trigger: 0, 37 | show_posts: false, 38 | system: false, 39 | image_upload_id: flair_upload.id, 40 | long_description: 41 | 'To get access to this badge go to our Patreon page and add your pledge.', 42 | ) 43 | badge.save! 44 | 45 | basic_filter = { default_group.id.to_s => ["0"] } 46 | ::Patreon.set("filters", basic_filter) 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/tokens.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "json" 4 | 5 | module ::Patreon 6 | class Tokens 7 | def self.update! 8 | conn = Faraday.new(url: "https://api.patreon.com") 9 | 10 | response = 11 | conn.post( 12 | "/oauth2/token", 13 | grant_type: "refresh_token", 14 | refresh_token: SiteSetting.patreon_creator_refresh_token, 15 | client_id: SiteSetting.patreon_client_id, 16 | client_secret: SiteSetting.patreon_client_secret, 17 | ) 18 | 19 | if response.status == 200 20 | tokens = JSON.parse response.body 21 | SiteSetting.patreon_creator_access_token = tokens["access_token"] 22 | SiteSetting.patreon_creator_refresh_token = tokens["refresh_token"] 23 | else 24 | Rails.logger.warn( 25 | "Patreon token refresh failed with status: #{response.status}.\n\n #{response.body}", 26 | ) 27 | end 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /lib/validators/patreon_login_enabled_validator.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | class PatreonLoginEnabledValidator 4 | def initialize(opts = {}) 5 | @opts = opts 6 | end 7 | 8 | def valid_value?(val) 9 | return true if val == "f" 10 | return false if SiteSetting.patreon_creator_discourse_username.blank? 11 | true 12 | end 13 | 14 | def error_message 15 | I18n.t("site_settings.errors.patreon_creator_username_not_set") 16 | end 17 | end 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "devDependencies": { 4 | "@discourse/lint-configs": "2.23.0", 5 | "ember-template-lint": "7.7.0", 6 | "eslint": "9.28.0", 7 | "prettier": "3.5.3", 8 | "stylelint": "16.20.0" 9 | }, 10 | "engines": { 11 | "node": ">= 22", 12 | "npm": "please-use-pnpm", 13 | "yarn": "please-use-pnpm", 14 | "pnpm": "9.x" 15 | }, 16 | "packageManager": "pnpm@9.15.5" 17 | } 18 | -------------------------------------------------------------------------------- /public/images/patreon-logomark-color-on-navy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discourse/discourse-patreon/d034a1c50421bbd89092fe64729c863e1f5c8439/public/images/patreon-logomark-color-on-navy.png -------------------------------------------------------------------------------- /public/images/patreon-logomark-color-on-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discourse/discourse-patreon/d034a1c50421bbd89092fe64729c863e1f5c8439/public/images/patreon-logomark-color-on-white.png -------------------------------------------------------------------------------- /public/images/patreon-wordmark-navy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/discourse/discourse-patreon/d034a1c50421bbd89092fe64729c863e1f5c8439/public/images/patreon-wordmark-navy.png -------------------------------------------------------------------------------- /spec/fixtures/campaigns.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [{ 3 | "attributes": { 4 | "created_at": "2017-10-20T21:39:01+00:00", 5 | "creation_count": 0, 6 | "creation_name": "Documentation", 7 | "discord_server_id": null, 8 | "display_patron_goals": false, 9 | "earnings_visibility": "public", 10 | "image_small_url": null, 11 | "image_url": null, 12 | "is_charged_immediately": false, 13 | "is_monthly": false, 14 | "is_nsfw": false, 15 | "is_plural": false, 16 | "main_video_embed": null, 17 | "main_video_url": null, 18 | "one_liner": null, 19 | "outstanding_payment_amount_cents": 0, 20 | "patron_count": 0, 21 | "pay_per_name": null, 22 | "pledge_sum": 0, 23 | "pledge_url": "/bePatron?c=0000000", 24 | "published_at": "2017-10-20T21:49:31+00:00", 25 | "summary": null, 26 | "thanks_embed": null, 27 | "thanks_msg": null, 28 | "thanks_video_url": null 29 | }, 30 | "id": "0000000", 31 | "relationships": { 32 | "creator": { 33 | "data": { 34 | "id": "1111111", 35 | "type": "user" 36 | }, 37 | "links": { 38 | "related": "https://www.patreon.com/api/user/1111111" 39 | } 40 | }, 41 | "goals": { 42 | "data": [] 43 | }, 44 | "rewards": { 45 | "data": [{ 46 | "id": "-1", 47 | "type": "reward" 48 | }, 49 | { 50 | "id": "0", 51 | "type": "reward" 52 | }, 53 | { 54 | "id": "999997", 55 | "type": "reward" 56 | }, 57 | { 58 | "id": "999998", 59 | "type": "reward" 60 | }, 61 | { 62 | "id": "999999", 63 | "type": "reward" 64 | } 65 | ] 66 | }, 67 | "pledges": { 68 | "links": { 69 | "first": "https://www.patreon.com/api/oauth2/api/campaigns/70261/pledges?page%5Bcount%5D=20&sort=created", 70 | "next": "https://www.patreon.com/api/oauth2/api/campaigns/70261/pledges?page%5Bcount%5D=20&sort=created&page%5Bcursor%5D=2017-08-21T20%3A16%3A49.258893%2B00%3A00" 71 | } 72 | } 73 | }, 74 | "type": "campaign" 75 | }], 76 | "included": [{ 77 | "attributes": { 78 | "about": null, 79 | "created": "2017-10-20T21:36:23+00:00", 80 | "discord_id": null, 81 | "email": "corgi@patreon.com", 82 | "facebook": null, 83 | "facebook_id": null, 84 | "first_name": "Corgi", 85 | "full_name": "Corgi The Dev", 86 | "gender": 0, 87 | "has_password": true, 88 | "image_url": "https://c8.patreon.com/2/400/1111111", 89 | "is_deleted": false, 90 | "is_email_verified": false, 91 | "is_nuked": false, 92 | "is_suspended": false, 93 | "last_name": "The Dev", 94 | "social_connections": { 95 | "deviantart": null, 96 | "discord": null, 97 | "facebook": null, 98 | "spotify": null, 99 | "twitch": null, 100 | "twitter": null, 101 | "youtube": null 102 | }, 103 | "thumb_url": "https://c8.patreon.com/2/100/1111111", 104 | "twitch": null, 105 | "twitter": null, 106 | "url": "https://www.patreon.com/drkthedev", 107 | "vanity": "drkthedev", 108 | "youtube": null 109 | }, 110 | "id": "1111111", 111 | "relationships": { 112 | "campaign": { 113 | "data": { 114 | "id": "0000000", 115 | "type": "campaign" 116 | }, 117 | "links": { 118 | "related": "https://www.patreon.com/api/campaigns/0000000" 119 | } 120 | } 121 | }, 122 | "type": "user" 123 | }, 124 | { 125 | "attributes": { 126 | "amount": 0, 127 | "amount_cents": 0, 128 | "created_at": null, 129 | "description": "Everyone", 130 | "id": "-1", 131 | "remaining": 0, 132 | "requires_shipping": false, 133 | "type": "reward", 134 | "url": null, 135 | "user_limit": null 136 | }, 137 | "id": "-1", 138 | "relationships": { 139 | "creator": { 140 | "data": { 141 | "id": "1111111", 142 | "type": "user" 143 | }, 144 | "links": { 145 | "related": "https://www.patreon.com/api/user/1111111" 146 | } 147 | } 148 | }, 149 | "type": "reward" 150 | }, 151 | { 152 | "attributes": { 153 | "amount": 1, 154 | "amount_cents": 1, 155 | "created_at": null, 156 | "description": "Patrons Only", 157 | "id": "0", 158 | "remaining": 0, 159 | "requires_shipping": false, 160 | "type": "reward", 161 | "url": null, 162 | "user_limit": null 163 | }, 164 | "id": "0", 165 | "relationships": { 166 | "creator": { 167 | "data": { 168 | "id": "1111111", 169 | "type": "user" 170 | }, 171 | "links": { 172 | "related": "https://www.patreon.com/api/user/1111111" 173 | } 174 | } 175 | }, 176 | "type": "reward" 177 | }, 178 | { 179 | "attributes": { 180 | "amount": 10, 181 | "amount_cents": 10, 182 | "created_at": null, 183 | "description": "Standard", 184 | "id": "0", 185 | "remaining": 0, 186 | "requires_shipping": false, 187 | "type": "reward", 188 | "url": null, 189 | "user_limit": null 190 | }, 191 | "id": "999997", 192 | "relationships": { 193 | "creator": { 194 | "data": { 195 | "id": "1111111", 196 | "type": "user" 197 | }, 198 | "links": { 199 | "related": "https://www.patreon.com/api/user/1111111" 200 | } 201 | } 202 | }, 203 | "type": "reward" 204 | }, 205 | { 206 | "attributes": { 207 | "amount": 100, 208 | "amount_cents": 100, 209 | "created_at": null, 210 | "description": "Pro", 211 | "id": "0", 212 | "remaining": 0, 213 | "requires_shipping": false, 214 | "type": "reward", 215 | "url": null, 216 | "user_limit": null 217 | }, 218 | "id": "999998", 219 | "relationships": { 220 | "creator": { 221 | "data": { 222 | "id": "1111111", 223 | "type": "user" 224 | }, 225 | "links": { 226 | "related": "https://www.patreon.com/api/user/1111111" 227 | } 228 | } 229 | }, 230 | "type": "reward" 231 | }, 232 | { 233 | "attributes": { 234 | "amount": 1000, 235 | "amount_cents": 1000, 236 | "created_at": null, 237 | "description": "Premium", 238 | "id": "0", 239 | "remaining": 0, 240 | "requires_shipping": false, 241 | "type": "reward", 242 | "url": null, 243 | "user_limit": null 244 | }, 245 | "id": "999999", 246 | "relationships": { 247 | "creator": { 248 | "data": { 249 | "id": "1111111", 250 | "type": "user" 251 | }, 252 | "links": { 253 | "related": "https://www.patreon.com/api/user/1111111" 254 | } 255 | } 256 | }, 257 | "type": "reward" 258 | } 259 | ] 260 | } 261 | -------------------------------------------------------------------------------- /spec/fixtures/member.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "attributes": { 4 | "currently_entitled_amount_cents": null, 5 | "full_name": "Platform", 6 | "is_follower": true, 7 | "last_charge_date": null, 8 | "last_charge_status": null, 9 | "lifetime_support_cents": 0, 10 | "note": "", 11 | "patron_status": null, 12 | "pledge_relationship_start": null 13 | }, 14 | "id": "d485d5ac-6c82-42c6-9c08-c50cf01b73d7", 15 | "relationships": { 16 | "address": { 17 | "data": null 18 | }, 19 | "campaign": { 20 | "data": { 21 | "id": "123456", 22 | "type": "campaign" 23 | } 24 | }, 25 | "currently_entitled_tiers": { 26 | "data": [] 27 | }, 28 | "user": { 29 | "data": { 30 | "id": "987654321", 31 | "type": "user" 32 | } 33 | } 34 | }, 35 | "type": "member" 36 | }, 37 | "included": [ 38 | { 39 | "attributes": { 40 | "about": "sample text about", 41 | "created": "2015-01-15T07:25:51+00:00", 42 | "email": "roo@aar.com", 43 | "facebook": null, 44 | "first_name": "Roo", 45 | "full_name": "Roo Aar", 46 | "gender": 1, 47 | "image_url": "", 48 | "is_email_verified": true, 49 | "last_name": "Aar", 50 | "social_connections": { 51 | "deviantart": null, 52 | "discord": null, 53 | "facebook": null, 54 | "spotify": null, 55 | "twitch": null, 56 | "twitter": null, 57 | "youtube": null 58 | }, 59 | "thumb_url": "", 60 | "twitch": null, 61 | "twitter": "roo", 62 | "url": "https://www.patreon.com/foo", 63 | "vanity": "roo", 64 | "youtube": null 65 | }, 66 | "id": "987654321", 67 | "type": "user" 68 | }, 69 | { 70 | "attributes": { 71 | "amount": 1, 72 | "amount_cents": 1, 73 | "created_at": null, 74 | "description": "Patrons Only", 75 | "id": "999999", 76 | "remaining": 0, 77 | "requires_shipping": false, 78 | "type": "reward", 79 | "url": null, 80 | "user_limit": null 81 | }, 82 | "id": "999999", 83 | "relationships": { 84 | "creator": { 85 | "data": { 86 | "id": "1111111", 87 | "type": "user" 88 | }, 89 | "links": { 90 | "related": "https://www.patreon.com/api/user/1111111" 91 | } 92 | } 93 | }, 94 | "type": "reward" 95 | } 96 | ] 97 | } 98 | -------------------------------------------------------------------------------- /spec/fixtures/pledge.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "attributes": { 4 | "amount_cents": 250, 5 | "created_at": "2015-05-18T23:50:42+00:00", 6 | "declined_since": null, 7 | "patron_pays_fees": false, 8 | "pledge_cap_cents": null 9 | }, 10 | "id": "1", 11 | "relationships": { 12 | "address": { 13 | "data": null 14 | }, 15 | "card": { 16 | "data": null 17 | }, 18 | "creator": { 19 | "data": { 20 | "id": "3024102", 21 | "type": "user" 22 | }, 23 | "links": { 24 | "related": "https://www.patreon.com/api/user/3024102" 25 | } 26 | }, 27 | "patron": { 28 | "data": { 29 | "id": "32187", 30 | "type": "user" 31 | }, 32 | "links": { 33 | "related": "https://www.patreon.com/api/user/32187" 34 | } 35 | }, 36 | "reward": { 37 | "data": { 38 | "id": "999999", 39 | "type": "reward" 40 | }, 41 | "links": { 42 | "related": "https://www.patreon.com/api/rewards/599336" 43 | } 44 | } 45 | }, 46 | "type": "pledge" 47 | }, 48 | "included": [{ 49 | "attributes": { 50 | "about": "sample text about", 51 | "created": "2015-01-15T07:25:51+00:00", 52 | "email": "roo@aar.com", 53 | "facebook": null, 54 | "first_name": "Roo", 55 | "full_name": "Roo Aar", 56 | "gender": 1, 57 | "image_url": "", 58 | "is_email_verified": true, 59 | "last_name": "Aar", 60 | "social_connections": { 61 | "deviantart": null, 62 | "discord": null, 63 | "facebook": null, 64 | "spotify": null, 65 | "twitch": null, 66 | "twitter": null, 67 | "youtube": null 68 | }, 69 | "thumb_url": "", 70 | "twitch": null, 71 | "twitter": "roo", 72 | "url": "https://www.patreon.com/foo", 73 | "vanity": "roo", 74 | "youtube": null 75 | }, 76 | "id": "32187", 77 | "type": "user" 78 | }, 79 | { 80 | "attributes": { 81 | "amount": 1, 82 | "amount_cents": 1, 83 | "created_at": null, 84 | "description": "Patrons Only", 85 | "id": "999999", 86 | "remaining": 0, 87 | "requires_shipping": false, 88 | "type": "reward", 89 | "url": null, 90 | "user_limit": null 91 | }, 92 | "id": "999999", 93 | "relationships": { 94 | "creator": { 95 | "data": { 96 | "id": "1111111", 97 | "type": "user" 98 | }, 99 | "links": { 100 | "related": "https://www.patreon.com/api/user/1111111" 101 | } 102 | } 103 | }, 104 | "type": "reward" 105 | } 106 | ] 107 | } 108 | -------------------------------------------------------------------------------- /spec/fixtures/pledges.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "attributes": { 5 | "amount_cents": 0, 6 | "created_at": "2016-07-25T20:59:52+00:00", 7 | "declined_since": null, 8 | "patron_pays_fees": false, 9 | "pledge_cap_cents": null 10 | }, 11 | "id": "2745627", 12 | "relationships": { 13 | "patron": { 14 | "data": { 15 | "id": "111111", 16 | "type": "user" 17 | }, 18 | "links": { 19 | "related": "https://www.patreon.com/api/user/111111" 20 | } 21 | }, 22 | "reward": { 23 | "data": { 24 | "id": "999999" 25 | } 26 | } 27 | }, 28 | "type": "pledge" 29 | }, 30 | { 31 | "attributes": { 32 | "amount_cents": 100, 33 | "created_at": "2016-08-25T20:59:52+00:00", 34 | "declined_since": "2017-11-07T20:59:52+00:00", 35 | "patron_pays_fees": false, 36 | "pledge_cap_cents": null 37 | }, 38 | "id": "2745628", 39 | "relationships": { 40 | "patron": { 41 | "data": { 42 | "id": "111112", 43 | "type": "user" 44 | }, 45 | "links": { 46 | "related": "https://www.patreon.com/api/user/111112" 47 | } 48 | }, 49 | "reward": { 50 | "data": { 51 | "id": "999998" 52 | } 53 | } 54 | }, 55 | "type": "pledge" 56 | }, 57 | { 58 | "attributes": { 59 | "amount_cents": 200, 60 | "created_at": "2017-01-15T20:59:52+00:00", 61 | "declined_since": "2017-11-10T20:59:52+00:00", 62 | "patron_pays_fees": false, 63 | "pledge_cap_cents": null 64 | }, 65 | "id": "2745629", 66 | "relationships": { 67 | "patron": { 68 | "data": { 69 | "id": "111113", 70 | "type": "user" 71 | }, 72 | "links": { 73 | "related": "https://www.patreon.com/api/user/111113" 74 | } 75 | }, 76 | "reward": { 77 | "data": { 78 | "id": "999997" 79 | } 80 | } 81 | }, 82 | "type": "pledge" 83 | } 84 | ], 85 | "included": [ 86 | { 87 | "attributes": { 88 | "about": "sample about text", 89 | "created": "2015-01-15T07:25:51+00:00", 90 | "email": "foo@bar.com", 91 | "facebook": null, 92 | "first_name": "Foo", 93 | "full_name": "Foo Bar", 94 | "gender": 1, 95 | "image_url": "", 96 | "is_email_verified": true, 97 | "last_name": "Bar", 98 | "social_connections": { 99 | "deviantart": null, 100 | "discord": null, 101 | "facebook": null, 102 | "spotify": null, 103 | "twitch": null, 104 | "twitter": null, 105 | "youtube": null 106 | }, 107 | "thumb_url": "", 108 | "twitch": null, 109 | "twitter": "foo", 110 | "url": "https://www.patreon.com/foo", 111 | "vanity": "foo", 112 | "youtube": null 113 | }, 114 | "id": "111111", 115 | "type": "user" 116 | }, 117 | { 118 | "attributes": { 119 | "about": "about text sample", 120 | "created": "2015-01-15T07:25:51+00:00", 121 | "email": "boo@far.com", 122 | "facebook": null, 123 | "first_name": "Boo", 124 | "full_name": "Boo Far", 125 | "gender": 1, 126 | "image_url": "", 127 | "is_email_verified": true, 128 | "last_name": "Far", 129 | "social_connections": { 130 | "deviantart": null, 131 | "discord": null, 132 | "facebook": null, 133 | "spotify": null, 134 | "twitch": null, 135 | "twitter": null, 136 | "youtube": null 137 | }, 138 | "thumb_url": "", 139 | "twitch": null, 140 | "twitter": "boo", 141 | "url": "https://www.patreon.com/boo", 142 | "vanity": "boo", 143 | "youtube": null 144 | }, 145 | "id": "111112", 146 | "type": "user" 147 | }, 148 | { 149 | "attributes": { 150 | "about": "sample text about", 151 | "created": "2015-01-15T07:25:51+00:00", 152 | "email": "roo@aar.com", 153 | "facebook": null, 154 | "first_name": "Roo", 155 | "full_name": "Roo Aar", 156 | "gender": 1, 157 | "image_url": "", 158 | "is_email_verified": true, 159 | "last_name": "Aar", 160 | "social_connections": { 161 | "deviantart": null, 162 | "discord": null, 163 | "facebook": null, 164 | "spotify": null, 165 | "twitch": null, 166 | "twitter": null, 167 | "youtube": null 168 | }, 169 | "thumb_url": "", 170 | "twitch": null, 171 | "twitter": "roo", 172 | "url": "https://www.patreon.com/foo", 173 | "vanity": "roo", 174 | "youtube": null 175 | }, 176 | "id": "111113", 177 | "type": "user" 178 | } 179 | ], 180 | "meta": { 181 | "count": 18 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /spec/fixtures/tokens.json: -------------------------------------------------------------------------------- 1 | { 2 | "access_token": "ACCESS TOKEN", 3 | "refresh_token": "REFRESH TOKEN", 4 | "expires_in": "TOKEN LIFETIME DURATION", 5 | "scope": "TOKEN SCOPES", 6 | "token_type": "Bearer" 7 | } 8 | -------------------------------------------------------------------------------- /spec/integration/patreon_auth_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | describe "Patreon Oauth2" do 4 | let(:access_token) { "patreon_access_token_448" } 5 | let(:client_id) { "abcdef11223344" } 6 | let(:client_secret) { "adddcccdddd99922" } 7 | let(:temp_code) { "patreon_temp_code_544254" } 8 | 9 | fab!(:user1) { Fabricate(:user) } 10 | fab!(:user2) { Fabricate(:user) } 11 | 12 | def setup_patreon_emails_stub(email:, verified:) 13 | stub_request(:get, "https://api.patreon.com/oauth2/api/current_user").with( 14 | headers: { 15 | "Authorization" => "Bearer #{access_token}", 16 | }, 17 | ).to_return( 18 | status: 200, 19 | body: 20 | JSON.dump( 21 | data: { 22 | id: "493290423324", 23 | attributes: { 24 | email: email, 25 | full_name: "Patron", 26 | is_email_verified: verified, 27 | }, 28 | }, 29 | ), 30 | headers: { 31 | "Content-Type" => "application/json", 32 | }, 33 | ) 34 | end 35 | 36 | before do 37 | SiteSetting.patreon_creator_discourse_username = user2.username 38 | SiteSetting.patreon_login_enabled = true 39 | SiteSetting.patreon_client_id = client_id 40 | SiteSetting.patreon_client_secret = client_secret 41 | 42 | stub_request(:post, "https://api.patreon.com/oauth2/token").with( 43 | body: 44 | hash_including( 45 | "client_id" => client_id, 46 | "client_secret" => client_secret, 47 | "code" => temp_code, 48 | "grant_type" => "authorization_code", 49 | "redirect_uri" => "http://test.localhost/auth/patreon/callback", 50 | ), 51 | ).to_return( 52 | status: 200, 53 | body: Rack::Utils.build_query(access_token: access_token), 54 | headers: { 55 | "Content-Type" => "application/x-www-form-urlencoded", 56 | }, 57 | ) 58 | end 59 | 60 | it "doesn't sign in the user if the email from patreon is not verified" do 61 | post "/auth/patreon" 62 | expect(response.status).to eq(302) 63 | expect(response.location).to start_with("https://www.patreon.com/oauth2/authorize") 64 | 65 | setup_patreon_emails_stub(email: user1.email, verified: false) 66 | 67 | post "/auth/patreon/callback", params: { state: session["omniauth.state"], code: temp_code } 68 | expect(response.status).to eq(302) 69 | expect(response.location).to eq("http://test.localhost/") 70 | expect(session[:current_user_id]).to be_blank 71 | end 72 | 73 | it "signs in the user if the email from patreon is verified" do 74 | post "/auth/patreon" 75 | expect(response.status).to eq(302) 76 | expect(response.location).to start_with("https://www.patreon.com/oauth2/authorize") 77 | 78 | setup_patreon_emails_stub(email: user1.email, verified: true) 79 | 80 | post "/auth/patreon/callback", params: { state: session["omniauth.state"], code: temp_code } 81 | expect(response.status).to eq(302) 82 | expect(response.location).to eq("http://test.localhost/") 83 | expect(session[:current_user_id]).to eq(user1.id) 84 | end 85 | end 86 | -------------------------------------------------------------------------------- /spec/integration/patreon_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | 5 | RSpec.describe ::Patreon do 6 | let(:user1) { Fabricate(:user) } 7 | let(:user2) { Fabricate(:user) } 8 | let(:group) { Fabricate(:group) } 9 | let(:filters) { { group.id.to_s => [] } } 10 | 11 | before do 12 | described_class.set("filters", filters) 13 | group.add(user1) 14 | end 15 | 16 | context "with donation prompt enabled" do 17 | before { SiteSetting.patreon_donation_prompt_enabled = true } 18 | 19 | it "should not show donation prompt to patrons" do 20 | expect(described_class.show_donation_prompt_to_user?(user1)).to eq(false) 21 | end 22 | 23 | it "should show donation prompt to non-patrons" do 24 | expect(described_class.show_donation_prompt_to_user?(user2)).to eq(true) 25 | end 26 | end 27 | 28 | context "with donation prompt disabled" do 29 | before { SiteSetting.patreon_donation_prompt_enabled = false } 30 | 31 | it "should show donation prompt to non-patrons" do 32 | expect(described_class.show_donation_prompt_to_user?(user2)).to eq(false) 33 | end 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /spec/jobs/patreon_update_tokens_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | require_relative "../spec_helper" 5 | 6 | RSpec.describe Jobs::PatreonUpdateTokens do 7 | before do 8 | SiteSetting.patreon_enabled = true 9 | 10 | stub_request(:post, "https://api.patreon.com/oauth2/token").with( 11 | body: { 12 | "client_id" => SiteSetting.patreon_client_id, 13 | "client_secret" => SiteSetting.patreon_client_secret, 14 | "grant_type" => "refresh_token", 15 | "refresh_token" => SiteSetting.patreon_creator_refresh_token, 16 | }, 17 | ).to_return(status: 200, body: get_patreon_response("tokens.json")) 18 | end 19 | 20 | it "should update both access and refresh tokens from Patreon" do 21 | described_class.new.execute({}) 22 | 23 | expect(SiteSetting.patreon_creator_access_token).to eq("ACCESS TOKEN") 24 | expect(SiteSetting.patreon_creator_refresh_token).to eq("REFRESH TOKEN") 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /spec/lib/api_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | 5 | RSpec.describe ::Patreon::Api do 6 | let(:url) do 7 | "https://api.patreon.com/oauth2/api/current_user/campaigns?include=rewards,creator,goals,pledges&page%5Bcount%5D=100" 8 | end 9 | 10 | def stub(status) 11 | content = { status: status, headers: { "Content-Type" => "application/json" }, body: "{}" } 12 | 13 | stub_request(:get, url).to_return(content) 14 | end 15 | 16 | before { SiteSetting.stubs(patreon_enabled: true) } 17 | 18 | it "should add admin warning message for invalid api response" do 19 | stub(401) 20 | 21 | described_class.get(url) 22 | 23 | expect(ProblemCheckTracker[:access_token_invalid].blips).to eq(1) 24 | expect(AdminNotice.find_by(identifier: :access_token_invalid).message).to eq( 25 | I18n.t("dashboard.problem.access_token_invalid", base_path: Discourse.base_path), 26 | ) 27 | end 28 | 29 | it "should not add admin warning message for valid api response" do 30 | stub(200) 31 | 32 | expect(ProblemCheckTracker[:access_token_invalid].blips).to eq(0) 33 | end 34 | 35 | it "should add warning log" do 36 | stub(500) 37 | 38 | Discourse.expects(:warn_exception).once 39 | expect(described_class.get(url)).to eq(error: I18n.t(described_class::INVALID_RESPONSE)) 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /spec/lib/campaign_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | require_relative "../spec_helper" 5 | 6 | RSpec.describe ::Patreon::Campaign do 7 | before do 8 | campaigns_url = 9 | "https://api.patreon.com/oauth2/api/current_user/campaigns?include=rewards,creator,goals,pledges&page%5Bcount%5D=100" 10 | pledges_url = 11 | "https://www.patreon.com/api/oauth2/api/campaigns/70261/pledges?page%5Bcount%5D=100&sort=created" 12 | content = { status: 200, headers: { "Content-Type" => "application/json" } } 13 | 14 | campaigns = content.merge(body: get_patreon_response("campaigns.json")) 15 | pledges = content.merge(body: get_patreon_response("pledges.json")) 16 | 17 | stub_request(:get, campaigns_url).to_return(campaigns) 18 | stub_request(:get, pledges_url).to_return(pledges) 19 | SiteSetting.patreon_enabled = true 20 | SiteSetting.patreon_declined_pledges_grace_period_days = 7 21 | end 22 | 23 | it "should update campaigns and group users data" do 24 | expect { described_class.update! }.to change { Group.count }.by(1).and change { 25 | Badge.count 26 | }.by(1) 27 | 28 | expect(Patreon.get("pledges").count).to eq(3) 29 | expect(Patreon::Pledge::Decline.all.count).to eq(2) 30 | expect(Patreon.get("rewards").count).to eq(5) 31 | expect(Patreon.get("users").count).to eq(3) 32 | expect(Patreon.get("reward-users")["0"].count).to eq(3) 33 | expect(Patreon.get("filters").count).to eq(1) 34 | 35 | # To check `add_model_callback(User, :after_commit, on: :create)` in plugin.rb 36 | expect { 37 | Patreon 38 | .get("users") 39 | .each do |id, email| 40 | cf = Fabricate(:user, email: email).custom_fields 41 | expect(cf["patreon_id"]).to eq(id) 42 | end 43 | }.to change { GroupUser.count }.by(3) 44 | end 45 | end 46 | -------------------------------------------------------------------------------- /spec/lib/patron_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | 5 | RSpec.describe ::Patreon::Patron do 6 | Fabricator(:patreon_user_info, class_name: :user_associated_account) do 7 | provider_name "patreon" 8 | user 9 | end 10 | 11 | let(:patrons) do 12 | { "111111" => "foo@bar.com", "111112" => "boo@far.com", "111113" => "roo@aar.com" } 13 | end 14 | let(:pledges) { { "111111" => "100", "111112" => "500" } } 15 | let(:rewards) do 16 | { 17 | "0" => { 18 | title: "All Patrons", 19 | amount_cents: "0", 20 | }, 21 | "4589" => { 22 | title: "Sponsers", 23 | amount_cents: "1000", 24 | }, 25 | } 26 | end 27 | let(:reward_users) { { "0" => %w[111111 111112], "4589" => ["111112"] } } 28 | let(:titles) { { "111111" => "All Patrons", "111112" => "All Patrons, Sponsers" } } 29 | 30 | before do 31 | Patreon.set("users", patrons) 32 | Patreon.set("pledges", pledges) 33 | Patreon.set("rewards", rewards) 34 | Patreon.set("reward-users", reward_users) 35 | end 36 | 37 | it "should find local users matching Patreon user info" do 38 | Fabricate(:user, email: "foo@bar.com") 39 | Fabricate(:patreon_user_info, provider_uid: "111112") 40 | 41 | local_users = described_class.get_local_users 42 | expect(local_users.count).to eq(2) 43 | 44 | local_users.each do |user_id, patreon_id| 45 | user = User.find(user_id) 46 | expect(described_class.attr("email", user)).to eq(patrons[patreon_id]) 47 | expect(described_class.attr("amount_cents", user)).to eq(pledges[patreon_id]) 48 | expect(described_class.attr("rewards", user)).to eq(titles[patreon_id]) 49 | end 50 | end 51 | 52 | it "should find local users matching email address without case-sensitivity" do 53 | patrons["111111"] = "Foo@bar.com" 54 | Patreon.set("users", patrons) 55 | Fabricate(:user, email: "foo@bar.com") 56 | 57 | local_users = described_class.get_local_users 58 | expect(local_users.count).to eq(1) 59 | end 60 | 61 | describe "sync groups" do 62 | let(:ouser) { Fabricate(:patreon_user_info, provider_uid: "111112") } 63 | let(:group1) { Fabricate(:group) } 64 | let(:group2) { Fabricate(:group) } 65 | 66 | before do 67 | filters = { group1.id.to_s => ["0"], group2.id.to_s => ["4589"] } 68 | Patreon.set("filters", filters) 69 | end 70 | 71 | it "should sync all Patreon users" do 72 | user = Fabricate(:user, email: "foo@bar.com") 73 | described_class.sync_groups 74 | expect(group1.users.to_a - [ouser.user, user]).to eq([]) 75 | expect(group2.users.to_a - [ouser.user]).to eq([]) 76 | end 77 | 78 | it "should sync by Patreon id" do 79 | described_class.sync_groups_by(patreon_id: ouser.provider_uid) 80 | expect(group1.users.to_a).to eq([ouser.user]) 81 | expect(group2.users.to_a).to eq([ouser.user]) 82 | end 83 | end 84 | end 85 | -------------------------------------------------------------------------------- /spec/lib/seed_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | 5 | RSpec.describe ::Patreon::Seed do 6 | it "should seed contents correctly" do 7 | described_class.seed_content! 8 | group = Group.last 9 | expect(group.name).to eq("patrons") 10 | expect(group.flair_upload).to be_present 11 | expect(Badge.last.name).to eq("Patron") 12 | expect(::Patreon.get("filters")).to eq(group.id.to_s => ["0"]) 13 | end 14 | 15 | it "should not raise error if group already exists" do 16 | group = Fabricate(:group, name: "patrons") 17 | described_class.seed_content! 18 | expect(::Patreon.get("filters")).to eq(group.id.to_s => ["0"]) 19 | end 20 | 21 | it "should not raise error if badge already exists" do 22 | Fabricate(:badge, name: "Patron") 23 | described_class.seed_content! 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /spec/requests/patreon_admin_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | 5 | describe Patreon::PatreonAdminController do 6 | describe "#list" do 7 | let(:group1) { Fabricate(:group) } 8 | let(:group2) { Fabricate(:group) } 9 | let(:admin) { Fabricate(:admin) } 10 | let(:filters) { { group1.id.to_s => ["0"], group2.id.to_s => ["208"], "777" => ["888"] } } 11 | let(:rewards) { { "1": { sample: "reward" }, "2": { another: "one" } } } 12 | 13 | before do 14 | sign_in(admin) 15 | SiteSetting.patreon_enabled = true 16 | SiteSetting.patreon_creator_access_token = "TOKEN" 17 | SiteSetting.patreon_creator_refresh_token = "TOKEN" 18 | Patreon.set("filters", filters) 19 | Patreon.set("rewards", rewards) 20 | end 21 | 22 | it "should display list of patreon groups" do 23 | get "/patreon/list.json" 24 | 25 | result = JSON.parse(response.body) 26 | expect(result["filters"].count).to eq(2) 27 | expect(result["rewards"].count).to eq(2) 28 | end 29 | 30 | it "should display list of rewards" do 31 | get "/patreon/rewards.json" 32 | 33 | rewards = JSON.parse(response.body) 34 | expect(rewards.count).to eq(2) 35 | end 36 | 37 | it "should update existing filter" do 38 | ids = %w[1 2] 39 | 40 | post "/patreon/list.json", params: { rewards_ids: ids, group_id: group1.id } 41 | 42 | expect(Patreon.get("filters")[group1.id.to_s]).to eq(ids) 43 | end 44 | 45 | it "should delete an filter" do 46 | expect { delete "/patreon/list.json", params: { group_id: group1.id } }.to change { 47 | Patreon.get("filters").count 48 | }.by(-1) 49 | expect(Patreon.get("filters")[group1.id.to_s]).to eq(nil) 50 | end 51 | 52 | it "should sync patreon groups" do 53 | Patreon::Patron.expects(:sync_groups) 54 | post "/patreon/sync_groups.json" 55 | end 56 | 57 | it "should enqueue job to sync patrons and groups" do 58 | expect_enqueued_with(job: :patreon_sync_patrons_to_groups) do 59 | post "/patreon/update_data.json" 60 | end 61 | 62 | expect(response.status).to eq(200) 63 | end 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /spec/requests/patreon_webhook_controller_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require "rails_helper" 4 | require "openssl" 5 | require "json" 6 | require_relative "../spec_helper" 7 | 8 | RSpec.describe ::Patreon::PatreonWebhookController do 9 | before do 10 | SiteSetting.patreon_enabled = true 11 | SiteSetting.login_required = true 12 | Jobs.run_immediately! 13 | end 14 | 15 | describe "index" do 16 | describe "header checking" do 17 | it "returns a 403 error without header params" do 18 | expect_not_enqueued_with(job: :patreon_sync_patrons_to_groups) { post "/patreon/webhook" } 19 | 20 | expect(response.status).to eq(403) 21 | expect(response.parsed_body["errors"]).to contain_exactly("Missing event header") 22 | end 23 | 24 | it "returns a 403 error with unknown event" do 25 | expect_not_enqueued_with(job: :patreon_sync_patrons_to_groups) do 26 | post "/patreon/webhook", 27 | headers: { 28 | "X-Patreon-Event": "foo:bar", 29 | "X-Patreon-Signature": "foo", 30 | } 31 | end 32 | 33 | expect(response.status).to eq(403) 34 | expect(response.parsed_body["errors"]).to contain_exactly("Unknown event: foo:bar") 35 | end 36 | 37 | it "returns a 403 error with invalid signature" do 38 | expect_not_enqueued_with(job: :patreon_sync_patrons_to_groups) do 39 | post "/patreon/webhook", 40 | headers: { 41 | "X-Patreon-Event": "pledges:create", 42 | "X-Patreon-Signature": "foo", 43 | } 44 | end 45 | 46 | expect(response.status).to eq(403) 47 | expect(response.parsed_body["errors"]).to contain_exactly("Invalid signature") 48 | end 49 | end 50 | 51 | describe "enqueue job" do 52 | let(:body) { get_patreon_response("pledge.json") } 53 | let(:digest) { OpenSSL::Digest.new("MD5") } 54 | let(:secret) { SiteSetting.patreon_webhook_secret = "WEBHOOK SECRET" } 55 | 56 | before do 57 | Patreon.set( 58 | "rewards", 59 | "0": { 60 | title: "All Patrons", 61 | amount_cents: 0, 62 | }, 63 | "999999": { 64 | title: "Premium", 65 | amount_cents: 1000, 66 | }, 67 | ) 68 | end 69 | 70 | def add_pledge 71 | pledge_data = JSON.parse(body) 72 | Patreon::Pledge.create!(pledge_data.dup) 73 | 74 | pledge_data 75 | end 76 | 77 | def post_request(body, event, type = "pledges") 78 | post "/patreon/webhook", 79 | params: body, 80 | headers: { 81 | "X-Patreon-Event": "#{type}:#{event}", 82 | "X-Patreon-Signature": OpenSSL::HMAC.hexdigest(digest, secret, body), 83 | } 84 | end 85 | 86 | it "for event pledge:create" do 87 | user = Fabricate(:user, email: "roo@aar.com") 88 | group = Fabricate(:group) 89 | Patreon.set("filters", group.id.to_s => ["0"]) 90 | 91 | expect { post_request(body, "create") }.to change { Patreon::Pledge.all.keys.count }.by( 92 | 1, 93 | ).and change { Patreon::Patron.all.keys.count }.by(1).and change { 94 | Patreon::RewardUser.all.keys.count 95 | }.by(2) 96 | 97 | expect(group.users).to include(user) 98 | end 99 | 100 | it "for event members:pledge:create" do 101 | body = get_patreon_response("member.json") 102 | user = Fabricate(:user, email: "roo@aar.com") 103 | group = Fabricate(:group) 104 | Patreon.set("filters", group.id.to_s => ["0"]) 105 | 106 | expect { post_request(body, "create", "members:pledge") }.to change { 107 | Patreon::Pledge.all.keys.count 108 | }.by(1).and change { Patreon::Patron.all.keys.count }.by(1).and change { 109 | Patreon::RewardUser.all.keys.count 110 | }.by(2) 111 | 112 | expect(group.users).to include(user) 113 | end 114 | 115 | it "for event pledge:update" do 116 | pledge_data = add_pledge 117 | pledge = pledge_data["data"] 118 | pledge["attributes"]["amount_cents"] = 987 119 | patron_id = pledge["relationships"]["patron"]["data"]["id"] 120 | pledge_data = JSON.pretty_generate(pledge_data) 121 | 122 | expect(Patreon.get("pledges")[patron_id]).to eq(250) 123 | post_request(pledge_data, "update") 124 | expect(Patreon.get("pledges")[patron_id]).to eq(987) 125 | end 126 | 127 | it "for event pledge:delete" do 128 | pledge_data = add_pledge 129 | patron_id = pledge_data["data"]["relationships"]["patron"]["data"]["id"] 130 | reward_id = pledge_data["data"]["relationships"]["reward"]["data"]["id"] 131 | 132 | expect { post_request(body, "delete") }.to change { Patreon::Pledge.all.keys.count }.by( 133 | -1, 134 | ).and change { Patreon::Patron.all.keys.count }.by(-1).and change { 135 | Patreon::RewardUser.all[reward_id].count 136 | }.by(-1) 137 | end 138 | end 139 | end 140 | end 141 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | module Helpers 4 | def get_patreon_response(filename) 5 | FileUtils.mkdir_p("#{Rails.root}/tmp/spec") unless Dir.exist?("#{Rails.root}/tmp/spec") 6 | FileUtils.cp( 7 | "#{Rails.root}/plugins/discourse-patreon/spec/fixtures/#{filename}", 8 | "#{Rails.root}/tmp/spec/#{filename}", 9 | ) 10 | File.new("#{Rails.root}/tmp/spec/#{filename}").read 11 | end 12 | end 13 | 14 | RSpec.configure { |config| config.include Helpers } 15 | -------------------------------------------------------------------------------- /spec/system/core_features_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | RSpec.describe "Core features", type: :system do 4 | before { enable_current_plugin } 5 | 6 | it_behaves_like "having working core features" 7 | end 8 | -------------------------------------------------------------------------------- /stylelint.config.mjs: -------------------------------------------------------------------------------- 1 | export default { 2 | extends: ["@discourse/lint-configs/stylelint"], 3 | }; 4 | -------------------------------------------------------------------------------- /svg-icons/sprite.svg: -------------------------------------------------------------------------------- 1 | 2 | 9 | -------------------------------------------------------------------------------- /translator.yml: -------------------------------------------------------------------------------- 1 | # Configuration file for discourse-translator-bot 2 | 3 | files: 4 | - source_path: config/locales/client.en.yml 5 | destination_path: client.yml 6 | - source_path: config/locales/server.en.yml 7 | destination_path: server.yml 8 | --------------------------------------------------------------------------------