Improve payload format of Web Push API now that it's open (#7521)

> Good lord what is happening in there

Previously the contents of the Web Push API payloads closely resembled the structure of JavaScript's [Notification](https://developer.mozilla.org/en-US/docs/Web/API/Notification). But now that the API is open to non-browser apps, and given that there is no required coupling between contents of the payload and a Notification object, here is how I changed the payload:

```json
{ 
  "access_token": "...",
  "preferred_locale": "en",
  "notification_id": "12345",
  "notification_type": "follow",
  "title": "So and so followed you",
  "body": "This is my bio",
  "icon": "https://example.com/avatar.png"
}
```

The title, body and icon attributes are included as a fallback so you can construct a minimal notification if you cannot perform a network request to the API to get more data.
This commit is contained in:
Eugen Rochko 2018-05-19 14:46:47 +02:00 committed by GitHub
parent 1951ff41b3
commit 4b94e9c65e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
76 changed files with 217 additions and 623 deletions

View file

@ -22,6 +22,7 @@ export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP';
defineMessages({ defineMessages({
mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' }, mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' },
group: { id: 'notifications.group', defaultMessage: '{count} notifications' },
}); });
const fetchRelatedRelationships = (dispatch, notifications) => { const fetchRelatedRelationships = (dispatch, notifications) => {

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "الترقيّات:", "notifications.column_settings.reblog": "الترقيّات:",
"notifications.column_settings.show": "إعرِضها في عمود", "notifications.column_settings.show": "إعرِضها في عمود",
"notifications.column_settings.sound": "أصدر صوتا", "notifications.column_settings.sound": "أصدر صوتا",
"notifications.group": "{count} notifications",
"onboarding.done": "تم", "onboarding.done": "تم",
"onboarding.next": "التالي", "onboarding.next": "التالي",
"onboarding.page_five.public_timelines": "تُعرَض في الخيط الزمني المحلي المشاركات العامة المحررة من طرف جميع المسجلين في {domain}. أما في الخيط الزمني الموحد ، فإنه يتم عرض جميع المشاركات العامة المنشورة من طرف جميع الأشخاص المتابَعين من طرف أعضاء {domain}. هذه هي الخيوط الزمنية العامة، وهي طريقة رائعة للتعرف أشخاص جدد.", "onboarding.page_five.public_timelines": "تُعرَض في الخيط الزمني المحلي المشاركات العامة المحررة من طرف جميع المسجلين في {domain}. أما في الخيط الزمني الموحد ، فإنه يتم عرض جميع المشاركات العامة المنشورة من طرف جميع الأشخاص المتابَعين من طرف أعضاء {domain}. هذه هي الخيوط الزمنية العامة، وهي طريقة رائعة للتعرف أشخاص جدد.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Споделяния:", "notifications.column_settings.reblog": "Споделяния:",
"notifications.column_settings.show": "Покажи в колона", "notifications.column_settings.show": "Покажи в колона",
"notifications.column_settings.sound": "Play sound", "notifications.column_settings.sound": "Play sound",
"notifications.group": "{count} notifications",
"onboarding.done": "Done", "onboarding.done": "Done",
"onboarding.next": "Next", "onboarding.next": "Next",
"onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.", "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Impulsos:", "notifications.column_settings.reblog": "Impulsos:",
"notifications.column_settings.show": "Mostrar en la columna", "notifications.column_settings.show": "Mostrar en la columna",
"notifications.column_settings.sound": "Reproduïr so", "notifications.column_settings.sound": "Reproduïr so",
"notifications.group": "{count} notifications",
"onboarding.done": "Fet", "onboarding.done": "Fet",
"onboarding.next": "Següent", "onboarding.next": "Següent",
"onboarding.page_five.public_timelines": "La línia de temps local mostra missatges públics de tothom de {domain}. La línia de temps federada mostra els missatges públics de tothom que la gent de {domain} segueix. Aquests són les línies de temps Públiques, una bona manera de descobrir noves persones.", "onboarding.page_five.public_timelines": "La línia de temps local mostra missatges públics de tothom de {domain}. La línia de temps federada mostra els missatges públics de tothom que la gent de {domain} segueix. Aquests són les línies de temps Públiques, una bona manera de descobrir noves persones.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Spartere:", "notifications.column_settings.reblog": "Spartere:",
"notifications.column_settings.show": "Mustrà indè a colonna", "notifications.column_settings.show": "Mustrà indè a colonna",
"notifications.column_settings.sound": "Sunà", "notifications.column_settings.sound": "Sunà",
"notifications.group": "{count} notifications",
"onboarding.done": "Fatta", "onboarding.done": "Fatta",
"onboarding.next": "Siguente", "onboarding.next": "Siguente",
"onboarding.page_five.public_timelines": "A linea pubblica lucale mostra statuti pubblichi da tuttu u mondu nant'à {domain}. A linea pubblica glubale mostra ancu quelli di a ghjente seguitata da l'utilizatori di {domain}. Quesse sò una bona manera d'incuntrà nove parsone.", "onboarding.page_five.public_timelines": "A linea pubblica lucale mostra statuti pubblichi da tuttu u mondu nant'à {domain}. A linea pubblica glubale mostra ancu quelli di a ghjente seguitata da l'utilizatori di {domain}. Quesse sò una bona manera d'incuntrà nove parsone.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Geteilte Beiträge:", "notifications.column_settings.reblog": "Geteilte Beiträge:",
"notifications.column_settings.show": "In der Spalte anzeigen", "notifications.column_settings.show": "In der Spalte anzeigen",
"notifications.column_settings.sound": "Ton abspielen", "notifications.column_settings.sound": "Ton abspielen",
"notifications.group": "{count} notifications",
"onboarding.done": "Fertig", "onboarding.done": "Fertig",
"onboarding.next": "Weiter", "onboarding.next": "Weiter",
"onboarding.page_five.public_timelines": "Die lokale Zeitleiste zeigt alle Beiträge von Leuten, die auch auf {domain} sind. Das gesamte bekannte Netz zeigt Beiträge von allen, denen von Leuten auf {domain} gefolgt wird. Zusammen sind sie die öffentlichen Zeitleisten, ein guter Weg, um neue Leute zu finden.", "onboarding.page_five.public_timelines": "Die lokale Zeitleiste zeigt alle Beiträge von Leuten, die auch auf {domain} sind. Das gesamte bekannte Netz zeigt Beiträge von allen, denen von Leuten auf {domain} gefolgt wird. Zusammen sind sie die öffentlichen Zeitleisten, ein guter Weg, um neue Leute zu finden.",

View file

@ -17,6 +17,10 @@
{ {
"defaultMessage": "{name} mentioned you", "defaultMessage": "{name} mentioned you",
"id": "notification.mention" "id": "notification.mention"
},
{
"defaultMessage": "{count} notifications",
"id": "notifications.group"
} }
], ],
"path": "app/javascript/mastodon/actions/notifications.json" "path": "app/javascript/mastodon/actions/notifications.json"
@ -870,7 +874,7 @@
"id": "compose_form.hashtag_warning" "id": "compose_form.hashtag_warning"
}, },
{ {
"defaultMessage": "This toot will only be visible to all the mentioned users.", "defaultMessage": "This toot will only be sent to all the mentioned users. However, the operators of your instance and any receiving instances may see this message.",
"id": "compose_form.direct_message_warning" "id": "compose_form.direct_message_warning"
} }
], ],

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.reblog": "Boosts:",
"notifications.column_settings.show": "Show in column", "notifications.column_settings.show": "Show in column",
"notifications.column_settings.sound": "Play sound", "notifications.column_settings.sound": "Play sound",
"notifications.group": "{count} notifications",
"onboarding.done": "Done", "onboarding.done": "Done",
"onboarding.next": "Next", "onboarding.next": "Next",
"onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.", "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.reblog": "Boosts:",
"notifications.column_settings.show": "Show in column", "notifications.column_settings.show": "Show in column",
"notifications.column_settings.sound": "Play sound", "notifications.column_settings.sound": "Play sound",
"notifications.group": "{count} notifications",
"onboarding.done": "Done", "onboarding.done": "Done",
"onboarding.next": "Next", "onboarding.next": "Next",
"onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.", "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Diskonigoj:", "notifications.column_settings.reblog": "Diskonigoj:",
"notifications.column_settings.show": "Montri en kolumno", "notifications.column_settings.show": "Montri en kolumno",
"notifications.column_settings.sound": "Eligi sonon", "notifications.column_settings.sound": "Eligi sonon",
"notifications.group": "{count} notifications",
"onboarding.done": "Farita", "onboarding.done": "Farita",
"onboarding.next": "Sekva", "onboarding.next": "Sekva",
"onboarding.page_five.public_timelines": "La loka tempolinio montras publikajn mesaĝojn de ĉiuj en {domain}. La fratara tempolinio montras publikajn mesaĝojn de ĉiuj, kiuj estas sekvataj de homoj en {domain}. Tio estas la publikaj tempolinioj, kio estas bona maniero por malkovri novajn homojn.", "onboarding.page_five.public_timelines": "La loka tempolinio montras publikajn mesaĝojn de ĉiuj en {domain}. La fratara tempolinio montras publikajn mesaĝojn de ĉiuj, kiuj estas sekvataj de homoj en {domain}. Tio estas la publikaj tempolinioj, kio estas bona maniero por malkovri novajn homojn.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Retoots:", "notifications.column_settings.reblog": "Retoots:",
"notifications.column_settings.show": "Mostrar en columna", "notifications.column_settings.show": "Mostrar en columna",
"notifications.column_settings.sound": "Reproducir sonido", "notifications.column_settings.sound": "Reproducir sonido",
"notifications.group": "{count} notifications",
"onboarding.done": "Listo", "onboarding.done": "Listo",
"onboarding.next": "Siguiente", "onboarding.next": "Siguiente",
"onboarding.page_five.public_timelines": "La línea de tiempo local muestra toots públicos de todos en {domain}. La línea de tiempo federada muestra toots públicos de cualquiera a quien la gente de {domain} siga. Estas son las líneas de tiempo públicas, una buena forma de conocer gente nueva.", "onboarding.page_five.public_timelines": "La línea de tiempo local muestra toots públicos de todos en {domain}. La línea de tiempo federada muestra toots públicos de cualquiera a quien la gente de {domain} siga. Estas son las líneas de tiempo públicas, una buena forma de conocer gente nueva.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.reblog": "Boosts:",
"notifications.column_settings.show": "Show in column", "notifications.column_settings.show": "Show in column",
"notifications.column_settings.sound": "Play sound", "notifications.column_settings.sound": "Play sound",
"notifications.group": "{count} notifications",
"onboarding.done": "Done", "onboarding.done": "Done",
"onboarding.next": "Next", "onboarding.next": "Next",
"onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.", "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "بازبوق‌ها:", "notifications.column_settings.reblog": "بازبوق‌ها:",
"notifications.column_settings.show": "نمایش در ستون", "notifications.column_settings.show": "نمایش در ستون",
"notifications.column_settings.sound": "پخش صدا", "notifications.column_settings.sound": "پخش صدا",
"notifications.group": "{count} notifications",
"onboarding.done": "پایان", "onboarding.done": "پایان",
"onboarding.next": "بعدی", "onboarding.next": "بعدی",
"onboarding.page_five.public_timelines": "نوشته‌های محلی یعنی نوشته‌های همهٔ کاربران {domain}. نوشته‌های همه‌جا یعنی نوشته‌های همهٔ کسانی که کاربران {domain} آن‌ها را پی می‌گیرند. این فهرست‌های عمومی راه خوبی برای یافتن کاربران تازه هستند.", "onboarding.page_five.public_timelines": "نوشته‌های محلی یعنی نوشته‌های همهٔ کاربران {domain}. نوشته‌های همه‌جا یعنی نوشته‌های همهٔ کسانی که کاربران {domain} آن‌ها را پی می‌گیرند. این فهرست‌های عمومی راه خوبی برای یافتن کاربران تازه هستند.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Buustit:", "notifications.column_settings.reblog": "Buustit:",
"notifications.column_settings.show": "Näytä sarakkeessa", "notifications.column_settings.show": "Näytä sarakkeessa",
"notifications.column_settings.sound": "Äänimerkki", "notifications.column_settings.sound": "Äänimerkki",
"notifications.group": "{count} notifications",
"onboarding.done": "Valmis", "onboarding.done": "Valmis",
"onboarding.next": "Seuraava", "onboarding.next": "Seuraava",
"onboarding.page_five.public_timelines": "Paikallisella aikajanalla näytetään instanssin {domain} kaikkien käyttäjien julkiset julkaisut. Yleisellä aikajanalla näytetään kaikkien instanssin {domain} käyttäjien seuraamien käyttäjien julkiset julkaisut. Nämä julkiset aikajanat ovat loistavia paikkoja löytää uusia ihmisiä.", "onboarding.page_five.public_timelines": "Paikallisella aikajanalla näytetään instanssin {domain} kaikkien käyttäjien julkiset julkaisut. Yleisellä aikajanalla näytetään kaikkien instanssin {domain} käyttäjien seuraamien käyttäjien julkiset julkaisut. Nämä julkiset aikajanat ovat loistavia paikkoja löytää uusia ihmisiä.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Partages:", "notifications.column_settings.reblog": "Partages:",
"notifications.column_settings.show": "Afficher dans la colonne", "notifications.column_settings.show": "Afficher dans la colonne",
"notifications.column_settings.sound": "Émettre un son", "notifications.column_settings.sound": "Émettre un son",
"notifications.group": "{count} notifications",
"onboarding.done": "Effectué", "onboarding.done": "Effectué",
"onboarding.next": "Suivant", "onboarding.next": "Suivant",
"onboarding.page_five.public_timelines": "Le fil public global affiche les messages de toutes les personnes suivies par les membres de {domain}. Le fil public local est identique, mais se limite aux membres de {domain}.", "onboarding.page_five.public_timelines": "Le fil public global affiche les messages de toutes les personnes suivies par les membres de {domain}. Le fil public local est identique, mais se limite aux membres de {domain}.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Promocións:", "notifications.column_settings.reblog": "Promocións:",
"notifications.column_settings.show": "Mostrar en columna", "notifications.column_settings.show": "Mostrar en columna",
"notifications.column_settings.sound": "Reproducir son", "notifications.column_settings.sound": "Reproducir son",
"notifications.group": "{count} notifications",
"onboarding.done": "Feito", "onboarding.done": "Feito",
"onboarding.next": "Seguinte", "onboarding.next": "Seguinte",
"onboarding.page_five.public_timelines": "A liña de tempo local mostra as publicacións públicas de todos en {domain}. A liña de tempo federada mostra as publicacións públicas de todos os que as persoas en {domain} seguen. Estas son as Liñas de tempo públicas, unha boa forma de descubrir novas persoas.", "onboarding.page_five.public_timelines": "A liña de tempo local mostra as publicacións públicas de todos en {domain}. A liña de tempo federada mostra as publicacións públicas de todos os que as persoas en {domain} seguen. Estas son as Liñas de tempo públicas, unha boa forma de descubrir novas persoas.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "הדהודים:", "notifications.column_settings.reblog": "הדהודים:",
"notifications.column_settings.show": "הצגה בטור", "notifications.column_settings.show": "הצגה בטור",
"notifications.column_settings.sound": "שמע מופעל", "notifications.column_settings.sound": "שמע מופעל",
"notifications.group": "{count} notifications",
"onboarding.done": "יציאה", "onboarding.done": "יציאה",
"onboarding.next": "הלאה", "onboarding.next": "הלאה",
"onboarding.page_five.public_timelines": "ציר הזמן המקומי מראה הודעות פומביות מכל באי קהילת {domain}. ציר הזמן העולמי מראה הודעות פומביות מאת כי מי שבאי קהילת {domain} עוקבים אחריו. אלו צירי הזמן הפומביים, דרך נהדרת לגלות אנשים חדשים.", "onboarding.page_five.public_timelines": "ציר הזמן המקומי מראה הודעות פומביות מכל באי קהילת {domain}. ציר הזמן העולמי מראה הודעות פומביות מאת כי מי שבאי קהילת {domain} עוקבים אחריו. אלו צירי הזמן הפומביים, דרך נהדרת לגלות אנשים חדשים.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Boostovi:", "notifications.column_settings.reblog": "Boostovi:",
"notifications.column_settings.show": "Prikaži u stupcu", "notifications.column_settings.show": "Prikaži u stupcu",
"notifications.column_settings.sound": "Sviraj zvuk", "notifications.column_settings.sound": "Sviraj zvuk",
"notifications.group": "{count} notifications",
"onboarding.done": "Učinjeno", "onboarding.done": "Učinjeno",
"onboarding.next": "Sljedeće", "onboarding.next": "Sljedeće",
"onboarding.page_five.public_timelines": "Lokalni timeline prikazuje javne postove sviju od svakog na {domain}. Federalni timeline prikazuje javne postove svakog koga ljudi na {domain} slijede. To su Javni Timelineovi, sjajan način za otkriti nove ljude.", "onboarding.page_five.public_timelines": "Lokalni timeline prikazuje javne postove sviju od svakog na {domain}. Federalni timeline prikazuje javne postove svakog koga ljudi na {domain} slijede. To su Javni Timelineovi, sjajan način za otkriti nove ljude.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Rebloggolások:", "notifications.column_settings.reblog": "Rebloggolások:",
"notifications.column_settings.show": "Oszlopban mutatás", "notifications.column_settings.show": "Oszlopban mutatás",
"notifications.column_settings.sound": "Hang lejátszása", "notifications.column_settings.sound": "Hang lejátszása",
"notifications.group": "{count} notifications",
"onboarding.done": "Befejezve", "onboarding.done": "Befejezve",
"onboarding.next": "Következő", "onboarding.next": "Következő",
"onboarding.page_five.public_timelines": "A helyi idővonal mindenkinek a publikus posztját mutatja a(z) {domain}-n. A federált idővonal mindenki publikus posztját mutatja akit {domain} felhasználói követnek. Ezek a publikus idővonalak, nagyszerű mód új emberek megismerésére.", "onboarding.page_five.public_timelines": "A helyi idővonal mindenkinek a publikus posztját mutatja a(z) {domain}-n. A federált idővonal mindenki publikus posztját mutatja akit {domain} felhasználói követnek. Ezek a publikus idővonalak, nagyszerű mód új emberek megismerésére.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Տարածածներից՝", "notifications.column_settings.reblog": "Տարածածներից՝",
"notifications.column_settings.show": "Ցուցադրել սյունում", "notifications.column_settings.show": "Ցուցադրել սյունում",
"notifications.column_settings.sound": "Ձայն հանել", "notifications.column_settings.sound": "Ձայն հանել",
"notifications.group": "{count} notifications",
"onboarding.done": "Պատրաստ է", "onboarding.done": "Պատրաստ է",
"onboarding.next": "Հաջորդ", "onboarding.next": "Հաջորդ",
"onboarding.page_five.public_timelines": "Տեղական հոսքը ցույց է տալիս {domain} տիրույթից բոլորի հրապարակային թթերը։ Դաշնային հոսքը ցույց է տալիս հրապարակային թթերը բոլորից, ում {domain} տիրույթի մարդիկ հետեւում են։ Սրանք Հրապարակային հոսքերն են՝ նոր մարդկանց բացահայտելու հրաշալի միջոց։", "onboarding.page_five.public_timelines": "Տեղական հոսքը ցույց է տալիս {domain} տիրույթից բոլորի հրապարակային թթերը։ Դաշնային հոսքը ցույց է տալիս հրապարակային թթերը բոլորից, ում {domain} տիրույթի մարդիկ հետեւում են։ Սրանք Հրապարակային հոսքերն են՝ նոր մարդկանց բացահայտելու հրաշալի միջոց։",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Boost:", "notifications.column_settings.reblog": "Boost:",
"notifications.column_settings.show": "Tampilkan dalam kolom", "notifications.column_settings.show": "Tampilkan dalam kolom",
"notifications.column_settings.sound": "Mainkan suara", "notifications.column_settings.sound": "Mainkan suara",
"notifications.group": "{count} notifications",
"onboarding.done": "Selesei", "onboarding.done": "Selesei",
"onboarding.next": "Selanjutnya", "onboarding.next": "Selanjutnya",
"onboarding.page_five.public_timelines": "Linimasa lokal menampilkan semua postingan publik dari semua orang di {domain}. Linimasa gabungan menampilkan postingan publik dari semua orang yang diikuti oleh {domain}. Ini semua adalah Linimasa Publik, cara terbaik untuk bertemu orang lain.", "onboarding.page_five.public_timelines": "Linimasa lokal menampilkan semua postingan publik dari semua orang di {domain}. Linimasa gabungan menampilkan postingan publik dari semua orang yang diikuti oleh {domain}. Ini semua adalah Linimasa Publik, cara terbaik untuk bertemu orang lain.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Repeti:", "notifications.column_settings.reblog": "Repeti:",
"notifications.column_settings.show": "Montrar en kolumno", "notifications.column_settings.show": "Montrar en kolumno",
"notifications.column_settings.sound": "Plear sono", "notifications.column_settings.sound": "Plear sono",
"notifications.group": "{count} notifications",
"onboarding.done": "Done", "onboarding.done": "Done",
"onboarding.next": "Next", "onboarding.next": "Next",
"onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.", "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Post condivisi:", "notifications.column_settings.reblog": "Post condivisi:",
"notifications.column_settings.show": "Mostra in colonna", "notifications.column_settings.show": "Mostra in colonna",
"notifications.column_settings.sound": "Riproduci suono", "notifications.column_settings.sound": "Riproduci suono",
"notifications.group": "{count} notifications",
"onboarding.done": "Fatto", "onboarding.done": "Fatto",
"onboarding.next": "Prossimo", "onboarding.next": "Prossimo",
"onboarding.page_five.public_timelines": "La timeline locale mostra i post pubblici di tutti gli utenti di {domain}. La timeline federata mostra i post pubblici di tutti gli utenti seguiti da quelli di {domain}. Queste sono le timeline pubbliche, che vi danno grandi possibilità di scoprire nuovi utenti.", "onboarding.page_five.public_timelines": "La timeline locale mostra i post pubblici di tutti gli utenti di {domain}. La timeline federata mostra i post pubblici di tutti gli utenti seguiti da quelli di {domain}. Queste sono le timeline pubbliche, che vi danno grandi possibilità di scoprire nuovi utenti.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "ブースト:", "notifications.column_settings.reblog": "ブースト:",
"notifications.column_settings.show": "カラムに表示", "notifications.column_settings.show": "カラムに表示",
"notifications.column_settings.sound": "通知音を再生", "notifications.column_settings.sound": "通知音を再生",
"notifications.group": "{count} notifications",
"onboarding.done": "完了", "onboarding.done": "完了",
"onboarding.next": "次へ", "onboarding.next": "次へ",
"onboarding.page_five.public_timelines": "連合タイムラインでは{domain}の人がフォローしているMastodon全体での公開投稿を表示します。同じくローカルタイムラインでは{domain}のみの公開投稿を表示します。", "onboarding.page_five.public_timelines": "連合タイムラインでは{domain}の人がフォローしているMastodon全体での公開投稿を表示します。同じくローカルタイムラインでは{domain}のみの公開投稿を表示します。",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "부스트:", "notifications.column_settings.reblog": "부스트:",
"notifications.column_settings.show": "컬럼에 표시", "notifications.column_settings.show": "컬럼에 표시",
"notifications.column_settings.sound": "효과음 재생", "notifications.column_settings.sound": "효과음 재생",
"notifications.group": "{count} notifications",
"onboarding.done": "완료", "onboarding.done": "완료",
"onboarding.next": "다음", "onboarding.next": "다음",
"onboarding.page_five.public_timelines": "연합 타임라인에서는 {domain}의 사람들이 팔로우 중인 Mastodon 전체 인스턴스의 공개 포스트를 표시합니다. 로컬 타임라인에서는 {domain} 만의 공개 포스트를 표시합니다.", "onboarding.page_five.public_timelines": "연합 타임라인에서는 {domain}의 사람들이 팔로우 중인 Mastodon 전체 인스턴스의 공개 포스트를 표시합니다. 로컬 타임라인에서는 {domain} 만의 공개 포스트를 표시합니다.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.reblog": "Boosts:",
"notifications.column_settings.show": "In kolom tonen", "notifications.column_settings.show": "In kolom tonen",
"notifications.column_settings.sound": "Geluid afspelen", "notifications.column_settings.sound": "Geluid afspelen",
"notifications.group": "{count} notifications",
"onboarding.done": "Klaar", "onboarding.done": "Klaar",
"onboarding.next": "Volgende", "onboarding.next": "Volgende",
"onboarding.page_five.public_timelines": "De lokale tijdlijn toont openbare toots van iedereen op {domain}. De globale tijdlijn toont openbare toots van iedereen die door gebruikers van {domain} worden gevolgd, dus ook mensen van andere Mastodonservers. Dit zijn de openbare tijdlijnen en vormen een uitstekende manier om nieuwe mensen te leren kennen.", "onboarding.page_five.public_timelines": "De lokale tijdlijn toont openbare toots van iedereen op {domain}. De globale tijdlijn toont openbare toots van iedereen die door gebruikers van {domain} worden gevolgd, dus ook mensen van andere Mastodonservers. Dit zijn de openbare tijdlijnen en vormen een uitstekende manier om nieuwe mensen te leren kennen.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Fremhevet:", "notifications.column_settings.reblog": "Fremhevet:",
"notifications.column_settings.show": "Vis i kolonne", "notifications.column_settings.show": "Vis i kolonne",
"notifications.column_settings.sound": "Spill lyd", "notifications.column_settings.sound": "Spill lyd",
"notifications.group": "{count} notifications",
"onboarding.done": "Ferdig", "onboarding.done": "Ferdig",
"onboarding.next": "Neste", "onboarding.next": "Neste",
"onboarding.page_five.public_timelines": "Den lokale tidslinjen viser offentlige poster fra alle på {domain}. Felles tidslinje viser offentlige poster fra alle som brukere på {domain} følger. Dette er de offentlige tidslinjene, et fint sted å oppdage nye brukere.", "onboarding.page_five.public_timelines": "Den lokale tidslinjen viser offentlige poster fra alle på {domain}. Felles tidslinje viser offentlige poster fra alle som brukere på {domain} følger. Dette er de offentlige tidslinjene, et fint sted å oppdage nye brukere.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Partatges:", "notifications.column_settings.reblog": "Partatges:",
"notifications.column_settings.show": "Mostrar dins la colomna", "notifications.column_settings.show": "Mostrar dins la colomna",
"notifications.column_settings.sound": "Emetre un son", "notifications.column_settings.sound": "Emetre un son",
"notifications.group": "{count} notifications",
"onboarding.done": "Sortir", "onboarding.done": "Sortir",
"onboarding.next": "Seguent", "onboarding.next": "Seguent",
"onboarding.page_five.public_timelines": "Lo flux local mòstra los estatuts publics del monde de vòstra instància, aquí {domain}. Lo flux federat mòstra los estatuts publics de la gent que los de {domain} sègon. Son los fluxes publics, un bon biais de trobar de mond.", "onboarding.page_five.public_timelines": "Lo flux local mòstra los estatuts publics del monde de vòstra instància, aquí {domain}. Lo flux federat mòstra los estatuts publics de la gent que los de {domain} sègon. Son los fluxes publics, un bon biais de trobar de mond.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Podbicia:", "notifications.column_settings.reblog": "Podbicia:",
"notifications.column_settings.show": "Pokaż w kolumnie", "notifications.column_settings.show": "Pokaż w kolumnie",
"notifications.column_settings.sound": "Odtwarzaj dźwięk", "notifications.column_settings.sound": "Odtwarzaj dźwięk",
"notifications.group": "{count} notifications",
"onboarding.done": "Gotowe", "onboarding.done": "Gotowe",
"onboarding.next": "Dalej", "onboarding.next": "Dalej",
"onboarding.page_five.public_timelines": "Lokalna oś czasu zawiera wszystkie publiczne wpisy z {domain}. Globalna oś czasu wyświetla publiczne wpisy śledzonych przez członków {domain}. Są to publiczne osie czasu najlepszy sposób na poznanie nowych osób.", "onboarding.page_five.public_timelines": "Lokalna oś czasu zawiera wszystkie publiczne wpisy z {domain}. Globalna oś czasu wyświetla publiczne wpisy śledzonych przez członków {domain}. Są to publiczne osie czasu najlepszy sposób na poznanie nowych osób.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Compartilhamento:", "notifications.column_settings.reblog": "Compartilhamento:",
"notifications.column_settings.show": "Mostrar nas colunas", "notifications.column_settings.show": "Mostrar nas colunas",
"notifications.column_settings.sound": "Reproduzir som", "notifications.column_settings.sound": "Reproduzir som",
"notifications.group": "{count} notifications",
"onboarding.done": "Pronto", "onboarding.done": "Pronto",
"onboarding.next": "Próximo", "onboarding.next": "Próximo",
"onboarding.page_five.public_timelines": "A timeline local mostra postagens públicas de todos os usuários no {domain}. A timeline federada mostra todas as postagens de todas as pessoas que pessoas no {domain} seguem. Estas são as timelines públicas, uma ótima maneira de conhecer novas pessoas.", "onboarding.page_five.public_timelines": "A timeline local mostra postagens públicas de todos os usuários no {domain}. A timeline federada mostra todas as postagens de todas as pessoas que pessoas no {domain} seguem. Estas são as timelines públicas, uma ótima maneira de conhecer novas pessoas.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Partilhas:", "notifications.column_settings.reblog": "Partilhas:",
"notifications.column_settings.show": "Mostrar nas colunas", "notifications.column_settings.show": "Mostrar nas colunas",
"notifications.column_settings.sound": "Reproduzir som", "notifications.column_settings.sound": "Reproduzir som",
"notifications.group": "{count} notifications",
"onboarding.done": "Pronto", "onboarding.done": "Pronto",
"onboarding.next": "Próximo", "onboarding.next": "Próximo",
"onboarding.page_five.public_timelines": "A timeline local mostra as publicações de todos os utilizadores em {domain}. A timeline global mostra as publicações de todas as pessoas que pessoas em {domain} seguem. Estas são as timelines públicas, uma óptima forma de conhecer novas pessoas.", "onboarding.page_five.public_timelines": "A timeline local mostra as publicações de todos os utilizadores em {domain}. A timeline global mostra as publicações de todas as pessoas que pessoas em {domain} seguem. Estas são as timelines públicas, uma óptima forma de conhecer novas pessoas.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Продвижения:", "notifications.column_settings.reblog": "Продвижения:",
"notifications.column_settings.show": "Показывать в колонке", "notifications.column_settings.show": "Показывать в колонке",
"notifications.column_settings.sound": "Проигрывать звук", "notifications.column_settings.sound": "Проигрывать звук",
"notifications.group": "{count} notifications",
"onboarding.done": "Готово", "onboarding.done": "Готово",
"onboarding.next": "Далее", "onboarding.next": "Далее",
"onboarding.page_five.public_timelines": "Локальная лента показывает публичные посты всех пользователей {domain}. Глобальная лента показывает публичные посты всех людей, на которых подписаны пользователи {domain}. Это - публичные ленты, отличный способ найти новые знакомства.", "onboarding.page_five.public_timelines": "Локальная лента показывает публичные посты всех пользователей {domain}. Глобальная лента показывает публичные посты всех людей, на которых подписаны пользователи {domain}. Это - публичные ленты, отличный способ найти новые знакомства.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Boosty:", "notifications.column_settings.reblog": "Boosty:",
"notifications.column_settings.show": "Zobraziť v stĺpci", "notifications.column_settings.show": "Zobraziť v stĺpci",
"notifications.column_settings.sound": "Prehrať zvuk", "notifications.column_settings.sound": "Prehrať zvuk",
"notifications.group": "{count} notifications",
"onboarding.done": "Koniec", "onboarding.done": "Koniec",
"onboarding.next": "Ďalej", "onboarding.next": "Ďalej",
"onboarding.page_five.public_timelines": "Lokálna časová os zobrazuje verejné správy od všetkých na {domain}. Federovaná časová os zobrazuje verejné správy od všetkých tých, čo následujú užívatrľov {domain} z iných serverov. Tieto sú takzvané Verejné Časové Osi, výborná možnosť ako nájsť a spoznať nových ľudí.", "onboarding.page_five.public_timelines": "Lokálna časová os zobrazuje verejné správy od všetkých na {domain}. Federovaná časová os zobrazuje verejné správy od všetkých tých, čo následujú užívatrľov {domain} z iných serverov. Tieto sú takzvané Verejné Časové Osi, výborná možnosť ako nájsť a spoznať nových ľudí.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.reblog": "Boosts:",
"notifications.column_settings.show": "Show in column", "notifications.column_settings.show": "Show in column",
"notifications.column_settings.sound": "Play sound", "notifications.column_settings.sound": "Play sound",
"notifications.group": "{count} notifications",
"onboarding.done": "Done", "onboarding.done": "Done",
"onboarding.next": "Next", "onboarding.next": "Next",
"onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.", "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Podrški:", "notifications.column_settings.reblog": "Podrški:",
"notifications.column_settings.show": "Prikaži u koloni", "notifications.column_settings.show": "Prikaži u koloni",
"notifications.column_settings.sound": "Puštaj zvuk", "notifications.column_settings.sound": "Puštaj zvuk",
"notifications.group": "{count} notifications",
"onboarding.done": "Gotovo", "onboarding.done": "Gotovo",
"onboarding.next": "Sledeće", "onboarding.next": "Sledeće",
"onboarding.page_five.public_timelines": "Lokalna lajna prikazuje sve javne statuse od svih na domenu {domain}. Federisana lajna prikazuje javne statuse od svih ljudi koje prate korisnici sa domena {domain}. Ovo su javne lajne, sjajan način da otkrijete nove ljude.", "onboarding.page_five.public_timelines": "Lokalna lajna prikazuje sve javne statuse od svih na domenu {domain}. Federisana lajna prikazuje javne statuse od svih ljudi koje prate korisnici sa domena {domain}. Ovo su javne lajne, sjajan način da otkrijete nove ljude.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Подршки:", "notifications.column_settings.reblog": "Подршки:",
"notifications.column_settings.show": "Прикажи у колони", "notifications.column_settings.show": "Прикажи у колони",
"notifications.column_settings.sound": "Пуштај звук", "notifications.column_settings.sound": "Пуштај звук",
"notifications.group": "{count} notifications",
"onboarding.done": "Готово", "onboarding.done": "Готово",
"onboarding.next": "Следеће", "onboarding.next": "Следеће",
"onboarding.page_five.public_timelines": "Локална лајна приказује све јавне статусе од свих на домену {domain}. Федерисана лајна приказује јавне статусе од свих људи које прате корисници са домена {domain}. Ово су јавне лајне, сјајан начин да откријете нове људе.", "onboarding.page_five.public_timelines": "Локална лајна приказује све јавне статусе од свих на домену {domain}. Федерисана лајна приказује јавне статусе од свих људи које прате корисници са домена {domain}. Ово су јавне лајне, сјајан начин да откријете нове људе.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Knuffar:", "notifications.column_settings.reblog": "Knuffar:",
"notifications.column_settings.show": "Visa i kolumnen", "notifications.column_settings.show": "Visa i kolumnen",
"notifications.column_settings.sound": "Spela upp ljud", "notifications.column_settings.sound": "Spela upp ljud",
"notifications.group": "{count} notifications",
"onboarding.done": "Klart", "onboarding.done": "Klart",
"onboarding.next": "Nästa", "onboarding.next": "Nästa",
"onboarding.page_five.public_timelines": "Den lokala tidslinjen visar offentliga inlägg från alla på {domain}. Den förenade tidslinjen visar offentliga inlägg från alla personer på {domain} som följer. Dom här offentliga tidslinjerna är ett bra sätt att upptäcka nya människor.", "onboarding.page_five.public_timelines": "Den lokala tidslinjen visar offentliga inlägg från alla på {domain}. Den förenade tidslinjen visar offentliga inlägg från alla personer på {domain} som följer. Dom här offentliga tidslinjerna är ett bra sätt att upptäcka nya människor.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.reblog": "Boosts:",
"notifications.column_settings.show": "Show in column", "notifications.column_settings.show": "Show in column",
"notifications.column_settings.sound": "Play sound", "notifications.column_settings.sound": "Play sound",
"notifications.group": "{count} notifications",
"onboarding.done": "Done", "onboarding.done": "Done",
"onboarding.next": "Next", "onboarding.next": "Next",
"onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.", "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Boosts:", "notifications.column_settings.reblog": "Boosts:",
"notifications.column_settings.show": "Show in column", "notifications.column_settings.show": "Show in column",
"notifications.column_settings.sound": "Play sound", "notifications.column_settings.sound": "Play sound",
"notifications.group": "{count} notifications",
"onboarding.done": "Done", "onboarding.done": "Done",
"onboarding.next": "Next", "onboarding.next": "Next",
"onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.", "onboarding.page_five.public_timelines": "The local timeline shows public posts from everyone on {domain}. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new people.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Boostlar:", "notifications.column_settings.reblog": "Boostlar:",
"notifications.column_settings.show": "Bildirimlerde göster", "notifications.column_settings.show": "Bildirimlerde göster",
"notifications.column_settings.sound": "Ses çal", "notifications.column_settings.sound": "Ses çal",
"notifications.group": "{count} notifications",
"onboarding.done": "Tamam", "onboarding.done": "Tamam",
"onboarding.next": "Sıradaki", "onboarding.next": "Sıradaki",
"onboarding.page_five.public_timelines": "Yerel zaman tüneli, bu sunucudaki herkesten gelen gönderileri gösterir.Federe zaman tüneli, kullanıcıların diğer sunuculardan takip ettiği kişilerin herkese açık gönderilerini gösterir. Bunlar herkese açık zaman tünelleridir ve yeni insanlarla tanışmak için harika yerlerdir. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new ", "onboarding.page_five.public_timelines": "Yerel zaman tüneli, bu sunucudaki herkesten gelen gönderileri gösterir.Federe zaman tüneli, kullanıcıların diğer sunuculardan takip ettiği kişilerin herkese açık gönderilerini gösterir. Bunlar herkese açık zaman tünelleridir ve yeni insanlarla tanışmak için harika yerlerdir. The federated timeline shows public posts from everyone who people on {domain} follow. These are the Public Timelines, a great way to discover new ",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "Передмухи:", "notifications.column_settings.reblog": "Передмухи:",
"notifications.column_settings.show": "Показати в колонці", "notifications.column_settings.show": "Показати в колонці",
"notifications.column_settings.sound": "Відтворювати звук", "notifications.column_settings.sound": "Відтворювати звук",
"notifications.group": "{count} notifications",
"onboarding.done": "Готово", "onboarding.done": "Готово",
"onboarding.next": "Далі", "onboarding.next": "Далі",
"onboarding.page_five.public_timelines": "Локальна стрічка показує публічні пости усіх користувачів {domain}. Глобальна стрічка показує публічні пости усіх людей, на яких підписані користувачі {domain}. Це публичні стрічки, відмінний спосіб знайти нових людей.", "onboarding.page_five.public_timelines": "Локальна стрічка показує публічні пости усіх користувачів {domain}. Глобальна стрічка показує публічні пости усіх людей, на яких підписані користувачі {domain}. Це публичні стрічки, відмінний спосіб знайти нових людей.",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "当有人转嘟了你的嘟文时:", "notifications.column_settings.reblog": "当有人转嘟了你的嘟文时:",
"notifications.column_settings.show": "在通知栏显示", "notifications.column_settings.show": "在通知栏显示",
"notifications.column_settings.sound": "播放音效", "notifications.column_settings.sound": "播放音效",
"notifications.group": "{count} notifications",
"onboarding.done": "出发!", "onboarding.done": "出发!",
"onboarding.next": "下一步", "onboarding.next": "下一步",
"onboarding.page_five.public_timelines": "“本站时间轴”显示的是由本站({domain})用户发布的所有公开嘟文。“跨站公共时间轴”显示的的是由本站用户关注对象所发布的所有公开嘟文。这些就是寻人好去处的公共时间轴啦。", "onboarding.page_five.public_timelines": "“本站时间轴”显示的是由本站({domain})用户发布的所有公开嘟文。“跨站公共时间轴”显示的的是由本站用户关注对象所发布的所有公开嘟文。这些就是寻人好去处的公共时间轴啦。",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "轉推你的文章:", "notifications.column_settings.reblog": "轉推你的文章:",
"notifications.column_settings.show": "在通知欄顯示", "notifications.column_settings.show": "在通知欄顯示",
"notifications.column_settings.sound": "播放音效", "notifications.column_settings.sound": "播放音效",
"notifications.group": "{count} notifications",
"onboarding.done": "開始使用", "onboarding.done": "開始使用",
"onboarding.next": "繼續", "onboarding.next": "繼續",
"onboarding.page_five.public_timelines": "「本站時間軸」顯示在 {domain} 各用戶的公開文章。「跨站時間軸」顯示在 {domain} 各人關注的所有用戶(包括其他服務站)的公開文章。這些都是「公共時間軸」,是認識新朋友的好地方。", "onboarding.page_five.public_timelines": "「本站時間軸」顯示在 {domain} 各用戶的公開文章。「跨站時間軸」顯示在 {domain} 各人關注的所有用戶(包括其他服務站)的公開文章。這些都是「公共時間軸」,是認識新朋友的好地方。",

View file

@ -186,6 +186,7 @@
"notifications.column_settings.reblog": "轉推:", "notifications.column_settings.reblog": "轉推:",
"notifications.column_settings.show": "顯示在欄位中", "notifications.column_settings.show": "顯示在欄位中",
"notifications.column_settings.sound": "播放音效", "notifications.column_settings.sound": "播放音效",
"notifications.group": "{count} notifications",
"onboarding.done": "完成", "onboarding.done": "完成",
"onboarding.next": "下一步", "onboarding.next": "下一步",
"onboarding.page_five.public_timelines": "本地時間軸顯示 {domain} 上所有人的公開貼文。聯盟時間軸顯示 {domain} 上所有人關注的公開貼文。這就是公開時間軸,發現新朋友的好地方。", "onboarding.page_five.public_timelines": "本地時間軸顯示 {domain} 上所有人的公開貼文。聯盟時間軸顯示 {domain} 上所有人關注的公開貼文。這就是公開時間軸,發現新朋友的好地方。",

View file

@ -0,0 +1,30 @@
/* @preval */
const fs = require('fs');
const path = require('path');
const filtered = {};
const filenames = fs.readdirSync(path.resolve(__dirname, '../locales'));
filenames.forEach(filename => {
if (!filename.match(/\.json$/) || filename.match(/defaultMessages|whitelist/)) return;
const content = fs.readFileSync(path.resolve(__dirname, `../locales/${filename}`), 'utf-8');
const full = JSON.parse(content);
const locale = filename.split('.')[0];
filtered[locale] = {
'notification.favourite': full['notification.favourite'] || '',
'notification.follow': full['notification.follow'] || '',
'notification.mention': full['notification.mention'] || '',
'notification.reblog': full['notification.reblog'] || '',
'status.show_more': full['status.show_more'] || '',
'status.reblog': full['status.reblog'] || '',
'status.favourite': full['status.favourite'] || '',
'notifications.group': full['notifications.group'] || '',
};
});
module.exports = JSON.parse(JSON.stringify(filtered));

View file

@ -1,36 +1,32 @@
import IntlMessageFormat from 'intl-messageformat';
import locales from './web_push_locales';
const MAX_NOTIFICATIONS = 5; const MAX_NOTIFICATIONS = 5;
const GROUP_TAG = 'tag'; const GROUP_TAG = 'tag';
// Avoid loading intl-messageformat and dealing with locales in the ServiceWorker
const formatGroupTitle = (message, count) => message.replace('%{count}', count);
const notify = options => const notify = options =>
self.registration.getNotifications().then(notifications => { self.registration.getNotifications().then(notifications => {
if (notifications.length === MAX_NOTIFICATIONS) { if (notifications.length >= MAX_NOTIFICATIONS) { // Reached the maximum number of notifications, proceed with grouping
// Reached the maximum number of notifications, proceed with grouping
const group = { const group = {
title: formatGroupTitle(options.data.message, notifications.length + 1), title: formatMessage('notifications.group', options.data.preferred_locale, { count: notifications.length + 1 }),
body: notifications body: notifications.sort((n1, n2) => n1.timestamp < n2.timestamp).map(notification => notification.title).join('\n'),
.sort((n1, n2) => n1.timestamp < n2.timestamp)
.map(notification => notification.title).join('\n'),
badge: '/badge.png', badge: '/badge.png',
icon: '/android-chrome-192x192.png', icon: '/android-chrome-192x192.png',
tag: GROUP_TAG, tag: GROUP_TAG,
data: { data: {
url: (new URL('/web/notifications', self.location)).href, url: (new URL('/web/notifications', self.location)).href,
count: notifications.length + 1, count: notifications.length + 1,
message: options.data.message, preferred_locale: options.data.preferred_locale,
}, },
}; };
notifications.forEach(notification => notification.close()); notifications.forEach(notification => notification.close());
return self.registration.showNotification(group.title, group); return self.registration.showNotification(group.title, group);
} else if (notifications.length === 1 && notifications[0].tag === GROUP_TAG) { } else if (notifications.length === 1 && notifications[0].tag === GROUP_TAG) { // Already grouped, proceed with appending the notification to the group
// Already grouped, proceed with appending the notification to the group const group = { ...notifications[0] };
const group = cloneNotification(notifications[0]);
group.title = formatGroupTitle(group.data.message, group.data.count + 1); group.title = formatMessage('notifications.group', options.data.preferred_locale, { count: group.data.count + 1 });
group.body = `${options.title}\n${group.body}`; group.body = `${options.title}\n${group.body}`;
group.data = { ...group.data, count: group.data.count + 1 }; group.data = { ...group.data, count: group.data.count + 1 };
@ -40,57 +36,87 @@ const notify = options =>
return self.registration.showNotification(options.title, options); return self.registration.showNotification(options.title, options);
}); });
const handlePush = (event) => { const fetchFromApi = (path, method, accessToken) => {
const options = event.data.json(); const url = (new URL(path, self.location)).href;
options.body = options.data.nsfw || options.data.content; return fetch(url, {
options.dir = options.data.dir;
options.image = options.image || undefined; // Null results in a network request (404)
options.timestamp = options.timestamp && new Date(options.timestamp);
const expandAction = options.data.actions.find(action => action.todo === 'expand');
if (expandAction) {
options.actions = [expandAction];
options.hiddenActions = options.data.actions.filter(action => action !== expandAction);
options.data.hiddenImage = options.image;
options.image = undefined;
} else {
options.actions = options.data.actions;
}
event.waitUntil(notify(options));
};
const cloneNotification = (notification) => {
const clone = { };
for(var k in notification) {
clone[k] = notification[k];
}
return clone;
};
const expandNotification = (notification) => {
const nextNotification = cloneNotification(notification);
nextNotification.body = notification.data.content;
nextNotification.image = notification.data.hiddenImage;
nextNotification.actions = notification.data.actions.filter(action => action.todo !== 'expand');
return self.registration.showNotification(nextNotification.title, nextNotification);
};
const makeRequest = (notification, action) =>
fetch(action.action, {
headers: { headers: {
'Authorization': `Bearer ${notification.data.access_token}`, 'Authorization': `Bearer ${accessToken}`,
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
method: action.method,
method: method,
credentials: 'include', credentials: 'include',
}); }).then(res => {
if (res.ok) {
return res;
} else {
throw new Error(res.status);
}
}).then(res => res.json());
};
const formatMessage = (messageId, locale, values = {}) =>
(new IntlMessageFormat(locales[locale][messageId], locale)).format(values);
const handlePush = (event) => {
const { access_token, notification_id, preferred_locale, title, body, icon } = event.data.json();
// Placeholder until more information can be loaded
event.waitUntil(
notify({
title,
body,
icon,
tag: notification_id,
timestamp: new Date(),
badge: '/badge.png',
data: { access_token, preferred_locale, url: '/web/notifications' },
}).then(() => fetchFromApi(`/api/v1/notifications/${notification_id}`, 'get', access_token)).then(notification => {
const options = {};
options.title = formatMessage(`notification.${notification.type}`, preferred_locale, { name: notification.account.display_name.length > 0 ? notification.account.display_name : notification.account.username });
options.body = notification.status && notification.status.content;
options.icon = notification.account.avatar_static;
options.timestamp = notification.created_at && new Date(notification.created_at);
options.tag = notification.id;
options.badge = '/badge.png';
options.image = notification.status && notification.status.media_attachments.length > 0 && notification.status.media_attachments[0].preview_url || undefined;
options.data = { access_token, preferred_locale, id: notification.status ? notification.status.id : notification.account.id, url: notification.status ? `/web/statuses/${notification.status.id}` : `/web/accounts/${notification.account.id}` };
if (notification.status && notification.status.sensitive) {
options.data.hiddenBody = notification.status.content;
options.data.hiddenImage = notification.status.media_attachments.length > 0 && notification.status.media_attachments[0].preview_url;
options.body = undefined;
options.image = undefined;
options.actions = [actionExpand(preferred_locale)];
} else if (notification.status) {
options.actions = [actionReblog(preferred_locale), actionFavourite(preferred_locale)];
}
return notify(options);
})
);
};
const actionExpand = preferred_locale => ({
action: 'expand',
icon: '/web-push-icon_expand.png',
title: formatMessage('status.show_more', preferred_locale),
});
const actionReblog = preferred_locale => ({
action: 'reblog',
icon: '/web-push-icon_reblog.png',
title: formatMessage('status.reblog', preferred_locale),
});
const actionFavourite = preferred_locale => ({
action: 'favourite',
icon: '/web-push-icon_favourite.png',
title: formatMessage('status.favourite', preferred_locale),
});
const findBestClient = clients => { const findBestClient = clients => {
const focusedClient = clients.find(client => client.focused); const focusedClient = clients.find(client => client.focused);
@ -99,6 +125,24 @@ const findBestClient = clients => {
return focusedClient || visibleClient || clients[0]; return focusedClient || visibleClient || clients[0];
}; };
const expandNotification = notification => {
const newNotification = { ...notification };
newNotification.body = newNotification.data.hiddenBody;
newNotification.image = newNotification.data.hiddenImage;
newNotification.actions = [actionReblog(notification.data.preferred_locale), actionFavourite(notification.data.preferred_locale)];
return self.registration.showNotification(newNotification.title, newNotification);
};
const removeActionFromNotification = (notification, action) => {
const newNotification = { ...notification };
newNotification.actions = newNotification.actions.filter(item => item.action !== action);
return self.registration.showNotification(newNotification.title, newNotification);
};
const openUrl = url => const openUrl = url =>
self.clients.matchAll({ type: 'window' }).then(clientList => { self.clients.matchAll({ type: 'window' }).then(clientList => {
if (clientList.length !== 0) { if (clientList.length !== 0) {
@ -124,27 +168,19 @@ const openUrl = url =>
return self.clients.openWindow(url); return self.clients.openWindow(url);
}); });
const removeActionFromNotification = (notification, action) => {
const actions = notification.actions.filter(act => act.action !== action.action);
const nextNotification = cloneNotification(notification);
nextNotification.actions = actions;
return self.registration.showNotification(nextNotification.title, nextNotification);
};
const handleNotificationClick = (event) => { const handleNotificationClick = (event) => {
const reactToNotificationClick = new Promise((resolve, reject) => { const reactToNotificationClick = new Promise((resolve, reject) => {
if (event.action) { if (event.action) {
const action = event.notification.data.actions.find(({ action }) => action === event.action); if (event.action === 'expand') {
if (action.todo === 'expand') {
resolve(expandNotification(event.notification)); resolve(expandNotification(event.notification));
} else if (action.todo === 'request') { } else if (event.action === 'reblog') {
resolve(makeRequest(event.notification, action) const { data } = event.notification;
.then(() => removeActionFromNotification(event.notification, action))); resolve(fetchFromApi(`/api/v1/statuses/${data.id}/reblog`, 'post', data.access_token).then(() => removeActionFromNotification(event.notification, 'reblog')));
} else if (event.action === 'favourite') {
const { data } = event.notification;
resolve(fetchFromApi(`/api/v1/statuses/${data.id}/favourite`, 'post', data.access_token).then(() => removeActionFromNotification(event.notification, 'favourite')));
} else { } else {
reject(`Unknown action: ${action.todo}`); reject(`Unknown action: ${event.action}`);
} }
} else { } else {
event.notification.close(); event.notification.close();

View file

@ -21,8 +21,8 @@ class Web::PushSubscription < ApplicationRecord
has_one :session_activation has_one :session_activation
def push(notification) def push(notification)
I18n.with_locale(associated_user.locale || I18n.default_locale) do I18n.with_locale(associated_user&.locale || I18n.default_locale) do
push_payload(message_from(notification), 48.hours.seconds) push_payload(payload_for_notification(notification), 48.hours.seconds)
end end
end end
@ -46,16 +46,13 @@ class Web::PushSubscription < ApplicationRecord
@associated_access_token = if access_token_id.nil? @associated_access_token = if access_token_id.nil?
find_or_create_access_token.token find_or_create_access_token.token
else else
access_token access_token.token
end end
end end
private private
def push_payload(message, ttl = 5.minutes.seconds) def push_payload(message, ttl = 5.minutes.seconds)
# TODO: Make sure that the payload does not
# exceed 4KB - Webpush::PayloadTooLarge
Webpush.payload_send( Webpush.payload_send(
message: Oj.dump(message), message: Oj.dump(message),
endpoint: endpoint, endpoint: endpoint,
@ -70,16 +67,20 @@ class Web::PushSubscription < ApplicationRecord
) )
end end
def message_from(notification) def payload_for_notification(notification)
serializable_resource = ActiveModelSerializers::SerializableResource.new(notification, serializer: Web::NotificationSerializer, scope: self, scope_name: :current_push_subscription) ActiveModelSerializers::SerializableResource.new(
serializable_resource.as_json notification,
serializer: Web::NotificationSerializer,
scope: self,
scope_name: :current_push_subscription
).as_json
end end
def find_or_create_access_token def find_or_create_access_token
Doorkeeper::AccessToken.find_or_create_for( Doorkeeper::AccessToken.find_or_create_for(
Doorkeeper::Application.find_by(superapp: true), Doorkeeper::Application.find_by(superapp: true),
session_activation.user_id, session_activation.user_id,
Doorkeeper::OAuth::Scopes.from_string('read write follow'), Doorkeeper::OAuth::Scopes.from_string('read write follow push'),
Doorkeeper.configuration.access_token_expires_in, Doorkeeper.configuration.access_token_expires_in,
Doorkeeper.configuration.refresh_token_enabled? Doorkeeper.configuration.refresh_token_enabled?
) )

View file

@ -2,168 +2,37 @@
class Web::NotificationSerializer < ActiveModel::Serializer class Web::NotificationSerializer < ActiveModel::Serializer
include RoutingHelper include RoutingHelper
include StreamEntriesHelper include ActionView::Helpers::TextHelper
include ActionView::Helpers::SanitizeHelper
class DataSerializer < ActiveModel::Serializer attributes :access_token, :preferred_locale, :notification_id,
include RoutingHelper :notification_type, :icon, :title, :body
include StreamEntriesHelper
include ActionView::Helpers::SanitizeHelper
attributes :content, :nsfw, :url, :actions, def access_token
:access_token, :message, :dir current_push_subscription.associated_access_token
def content
decoder.decode(strip_tags(body))
end
def dir
rtl?(body) ? 'rtl' : 'ltr'
end
def nsfw
return if object.target_status.nil?
object.target_status.spoiler_text.presence
end
def url
case object.type
when :mention
web_url("statuses/#{object.target_status.id}")
when :follow
web_url("accounts/#{object.from_account.id}")
when :favourite
web_url("statuses/#{object.target_status.id}")
when :reblog
web_url("statuses/#{object.target_status.id}")
end
end
def actions
return @actions if defined?(@actions)
@actions = []
if object.type == :mention
@actions << expand_action if collapsed?
@actions << favourite_action
@actions << reblog_action if rebloggable?
end
@actions
end
def access_token
return if actions.empty?
current_push_subscription.associated_access_token
end
def message
I18n.t('push_notifications.group.title')
end
private
def body
case object.type
when :mention
object.target_status.text
when :follow
object.from_account.note
when :favourite
object.target_status.text
when :reblog
object.target_status.text
end
end
def decoder
@decoder ||= HTMLEntities.new
end
def expand_action
{
title: I18n.t('push_notifications.mention.action_expand'),
icon: full_asset_url('web-push-icon_expand.png', skip_pipeline: true),
todo: 'expand',
action: 'expand',
}
end
def favourite_action
{
title: I18n.t('push_notifications.mention.action_favourite'),
icon: full_asset_url('web-push-icon_favourite.png', skip_pipeline: true),
todo: 'request',
method: 'POST',
action: "/api/v1/statuses/#{object.target_status.id}/favourite",
}
end
def reblog_action
{
title: I18n.t('push_notifications.mention.action_boost'),
icon: full_asset_url('web-push-icon_reblog.png', skip_pipeline: true),
todo: 'request',
method: 'POST',
action: "/api/v1/statuses/#{object.target_status.id}/reblog",
}
end
def collapsed?
!object.target_status.nil? && (object.target_status.sensitive? || object.target_status.spoiler_text.present?)
end
def rebloggable?
!object.target_status.nil? && !object.target_status.hidden?
end
end end
attributes :title, :image, :badge, :tag, def preferred_locale
:timestamp, :icon current_push_subscription.associated_user&.locale || I18n.default_locale
has_one :data, serializer: DataSerializer
def title
case object.type
when :mention
I18n.t('push_notifications.mention.title', name: name)
when :follow
I18n.t('push_notifications.follow.title', name: name)
when :favourite
I18n.t('push_notifications.favourite.title', name: name)
when :reblog
I18n.t('push_notifications.reblog.title', name: name)
end
end end
def image def notification_id
return if object.target_status.nil? || object.target_status.media_attachments.empty?
full_asset_url(object.target_status.media_attachments.first.file.url(:small))
end
def badge
full_asset_url('badge.png', skip_pipeline: true)
end
def tag
object.id object.id
end end
def timestamp def notification_type
object.created_at object.type
end end
def icon def icon
object.from_account.avatar_static_url full_asset_url(object.from_account.avatar_static_url)
end end
def data def title
object I18n.t("notification_mailer.#{object.type}.subject", name: object.from_account.display_name.presence || object.from_account.username)
end end
private def body
truncate(strip_tags(object.target_status&.spoiler_text&.presence || object.target_status&.text || object.from_account.note), length: 140)
def name
display_name(object.from_account)
end end
end end

View file

@ -576,19 +576,6 @@ ar:
other: إعدادات أخرى other: إعدادات أخرى
publishing: النشر publishing: النشر
web: الويب web: الويب
push_notifications:
favourite:
title: أعجب %{name} بمنشورك
follow:
title: "%{name} من متتبعيك الآن"
group:
title: "%{count} إخطارات"
mention:
action_boost: ترقية
action_expand: عرض المزيد
title: أشار إليك %{name}
reblog:
title: قام %{name} بترقية منشورك
remote_follow: remote_follow:
acct: قم بإدخال عنوان حسابك username@domain الذي من خلاله تود المتابعة acct: قم بإدخال عنوان حسابك username@domain الذي من خلاله تود المتابعة
missing_resource: تعذر العثور على رابط التحويل المطلوب الخاص بحسابك missing_resource: تعذر العثور على رابط التحويل المطلوب الخاص بحسابك

View file

@ -594,20 +594,6 @@ ca:
other: Altre other: Altre
publishing: Publicació publishing: Publicació
web: Web web: Web
push_notifications:
favourite:
title: "%{name} ha marcat com a preferit el teu estat"
follow:
title: "%{name} ara et segueix"
group:
title: "%{count} notificacions"
mention:
action_boost: Retooteja
action_expand: Mostra'n més
action_favourite: Preferit
title: "%{name} t'ha mencionat"
reblog:
title: "%{name} t'ha retootejat"
remote_follow: remote_follow:
acct: Escriu el teu usuari@domini des del qual vols seguir acct: Escriu el teu usuari@domini des del qual vols seguir
missing_resource: No s'ha pogut trobar la URL de redirecció necessaria per al compte missing_resource: No s'ha pogut trobar la URL de redirecció necessaria per al compte

View file

@ -593,20 +593,6 @@ co:
other: Altre other: Altre
publishing: Pubblicazione publishing: Pubblicazione
web: Web web: Web
push_notifications:
favourite:
title: "%{name} hà aghjuntu u vostru statutu à i so favuriti"
follow:
title: "%{name} vi seguita"
group:
title: "%{count} nutificazioni"
mention:
action_boost: Sparte
action_expand: Vede di più
action_favourite: Aghjunghje à i favuriti
title: "%{name} vhà mintuvatu·a"
reblog:
title: "%{name} hà spartutu u vostru statutu"
remote_follow: remote_follow:
acct: Entrate u vostru cugnome@istanza da induve vulete siguità stu contu acct: Entrate u vostru cugnome@istanza da induve vulete siguità stu contu
missing_resource: Ùn avemu pussutu à truvà lindirizzu di ridirezzione missing_resource: Ùn avemu pussutu à truvà lindirizzu di ridirezzione

View file

@ -594,20 +594,6 @@ de:
other: Weiteres other: Weiteres
publishing: Beiträge publishing: Beiträge
web: Web web: Web
push_notifications:
favourite:
title: "%{name} hat deinen Beitrag favorisiert"
follow:
title: "%{name} folgt dir nun"
group:
title: "%{count} Benachrichtigungen"
mention:
action_boost: Teilen
action_expand: Mehr anzeigen
action_favourite: Favorisieren
title: "%{name} hat dich erwähnt"
reblog:
title: "%{name} hat deinen Beitrag geteilt"
remote_follow: remote_follow:
acct: Profilname@Domain, von wo aus du dieser Person folgen möchtest acct: Profilname@Domain, von wo aus du dieser Person folgen möchtest
missing_resource: Die erforderliche Weiterleitungs-URL für dein Konto konnte nicht gefunden werden missing_resource: Die erforderliche Weiterleitungs-URL für dein Konto konnte nicht gefunden werden

View file

@ -595,20 +595,6 @@ en:
other: Other other: Other
publishing: Publishing publishing: Publishing
web: Web web: Web
push_notifications:
favourite:
title: "%{name} favourited your status"
follow:
title: "%{name} is now following you"
group:
title: "%{count} notifications"
mention:
action_boost: Boost
action_expand: Show more
action_favourite: Favourite
title: "%{name} mentioned you"
reblog:
title: "%{name} boosted your status"
remote_follow: remote_follow:
acct: Enter your username@domain you want to follow from acct: Enter your username@domain you want to follow from
missing_resource: Could not find the required redirect URL for your account missing_resource: Could not find the required redirect URL for your account

View file

@ -596,20 +596,6 @@ eo:
other: Aliaj aferoj other: Aliaj aferoj
publishing: Publikado publishing: Publikado
web: Reto web: Reto
push_notifications:
favourite:
title: "%{name} stelumis vian mesaĝon"
follow:
title: "%{name} eksekvis vin"
group:
title: "%{count} sciigoj"
mention:
action_boost: Diskonigi
action_expand: Montri pli
action_favourite: Stelumi
title: "%{name} menciis vin"
reblog:
title: "%{name} diskonigis vian mesaĝon"
remote_follow: remote_follow:
acct: Enmetu vian uzantnomo@domajno de kie vi volas sekvi acct: Enmetu vian uzantnomo@domajno de kie vi volas sekvi
missing_resource: La URL de plusendado ne estis trovita missing_resource: La URL de plusendado ne estis trovita

View file

@ -593,20 +593,6 @@ es:
other: Otros other: Otros
publishing: Publicación publishing: Publicación
web: Web web: Web
push_notifications:
favourite:
title: "%A {name} le gustó tu estado"
follow:
title: "%{name} te ha empezado a seguir"
group:
title: "%{count} notificaciones"
mention:
action_boost: Retoot
action_expand: Mostrar más
action_favourite: Me Gusta
title: "%{name} te mencionó"
reblog:
title: "%{name} boosteó tu estado"
remote_follow: remote_follow:
acct: Ingesa tu usuario@dominio desde el que quieres seguir acct: Ingesa tu usuario@dominio desde el que quieres seguir
missing_resource: No se pudo encontrar la URL de redirección requerida para tu cuenta missing_resource: No se pudo encontrar la URL de redirección requerida para tu cuenta

View file

@ -593,20 +593,6 @@ fa:
other: سایر other: سایر
publishing: انتشار publishing: انتشار
web: وب web: وب
push_notifications:
favourite:
title: "%{name} نوشتهٔ شما را پسندید"
follow:
title: "%{name} هم‌اینک پیگیر شماست"
group:
title: "%{count} اعلان"
mention:
action_boost: بازبوق
action_expand: نمایش بیشتر
action_favourite: پسندیدن
title: "%{name} از شما نام برد"
reblog:
title: "%{name} نوشتهٔ شما را بازبوقید"
remote_follow: remote_follow:
acct: نشانی حساب username@domain خود را این‌جا بنویسید acct: نشانی حساب username@domain خود را این‌جا بنویسید
missing_resource: نشانی اینترنتی برای رسیدن به حساب شما پیدا نشد missing_resource: نشانی اینترنتی برای رسیدن به حساب شما پیدا نشد

View file

@ -590,20 +590,6 @@ fi:
other: Muut other: Muut
publishing: Julkaiseminen publishing: Julkaiseminen
web: Web web: Web
push_notifications:
favourite:
title: "%{name} tykkäsi tilastasi"
follow:
title: "%{name} seuraa nyt sinua"
group:
title: "%{count} ilmoitusta"
mention:
action_boost: Buustaa
action_expand: Näytä lisää
action_favourite: Tykkää
title: "%{nimi} mainitsi sinut"
reblog:
title: "%{name} buustasi tilaasi"
remote_follow: remote_follow:
acct: Syötä se käyttäjätunnus@verkkotunnus, josta haluat seurata acct: Syötä se käyttäjätunnus@verkkotunnus, josta haluat seurata
missing_resource: Vaadittavaa uudelleenohjaus-URL:ää tiliisi ei löytynyt missing_resource: Vaadittavaa uudelleenohjaus-URL:ää tiliisi ei löytynyt

View file

@ -594,20 +594,6 @@ fr:
other: Autre other: Autre
publishing: Publication publishing: Publication
web: Web web: Web
push_notifications:
favourite:
title: "%{name} a mis votre statut en favori"
follow:
title: "%{name} vous suit"
group:
title: "%{count} notifications"
mention:
action_boost: Partager
action_expand: Montrer plus
action_favourite: Ajouter aux favoris
title: "%{name} vous a mentionné·e"
reblog:
title: "%{name} a partagé votre statut"
remote_follow: remote_follow:
acct: Entrez votre pseudo@instance depuis lequel vous voulez suivre cet·te utilisateur⋅ice acct: Entrez votre pseudo@instance depuis lequel vous voulez suivre cet·te utilisateur⋅ice
missing_resource: LURL de redirection na pas pu être trouvée missing_resource: LURL de redirection na pas pu être trouvée

View file

@ -594,20 +594,6 @@ gl:
other: Outro other: Outro
publishing: Publicando publishing: Publicando
web: Web web: Web
push_notifications:
favourite:
title: "%{name} marcou favorito o seu estado"
follow:
title: "%{name} agora está a seguila"
group:
title: "%{count} notificacións"
mention:
action_boost: Promover
action_expand: Mostar máis
action_favourite: Favorito
title: "%{name} mencionouna"
reblog:
title: "%{name} promoveu un dos seus estados"
remote_follow: remote_follow:
acct: Introduza o seu nomedeusuaria@dominio desde onde quere facer seguimento acct: Introduza o seu nomedeusuaria@dominio desde onde quere facer seguimento
missing_resource: Non se puido atopar o URL de redirecionamento requerido para a súa conta missing_resource: Non se puido atopar o URL de redirecionamento requerido para a súa conta

View file

@ -531,20 +531,6 @@ hu:
other: Egyéb other: Egyéb
publishing: Közzététel publishing: Közzététel
web: Web web: Web
push_notifications:
favourite:
title: "%{name} a kedvenceihez adta a tülköd"
follow:
title: "%{name} mostantól követ téged"
group:
title: "%{count} értesítés"
mention:
action_boost: Reblog
action_expand: Mutass többet
action_favourite: Kedvencekhez adás
title: "%{name} megemlített téged"
reblog:
title: "%{name} reblogolta a tülköd"
remote_follow: remote_follow:
acct: Írd be a felhasználódat, amelyről követni szeretnéd felhasznalonev@domain formátumban acct: Írd be a felhasználódat, amelyről követni szeretnéd felhasznalonev@domain formátumban
missing_resource: A fiókodnál nem található a szükséges átirányítási URL missing_resource: A fiókodnál nem található a szükséges átirányítási URL

View file

@ -506,18 +506,6 @@ it:
other: Altro other: Altro
publishing: Pubblicazione publishing: Pubblicazione
web: Web web: Web
push_notifications:
favourite:
title: "%{name} ha segnato il tuo status come apprezzato"
follow:
title: "%{name} ha iniziato a seguirti"
group:
title: "%{count} notifiche"
mention:
action_expand: Mostra altro
action_favourite: Apprezzato
reblog:
title: "%{name} ha condiviso il tuo status"
remote_follow: remote_follow:
acct: Inserisci il tuo username@dominio da cui vuoi seguire questo utente acct: Inserisci il tuo username@dominio da cui vuoi seguire questo utente
missing_resource: Impossibile trovare l'URL di reindirizzamento richiesto per il tuo account missing_resource: Impossibile trovare l'URL di reindirizzamento richiesto per il tuo account

View file

@ -594,20 +594,6 @@ ja:
other: その他 other: その他
publishing: 投稿 publishing: 投稿
web: ウェブ web: ウェブ
push_notifications:
favourite:
title: あなたのトゥートが %{name} さんにお気に入り登録されました
follow:
title: "%{name} さんにフォローされました"
group:
title: "%{count} 件の通知"
mention:
action_boost: ブースト
action_expand: もっと見る
action_favourite: お気に入り
title: "%{name} さんから返信がありました"
reblog:
title: あなたのトゥートが %{name} さんにブーストされました
remote_follow: remote_follow:
acct: あなたの ユーザー名@ドメイン を入力してください acct: あなたの ユーザー名@ドメイン を入力してください
missing_resource: リダイレクト先が見つかりませんでした missing_resource: リダイレクト先が見つかりませんでした

View file

@ -596,20 +596,6 @@ ko:
other: 기타 other: 기타
publishing: 퍼블리싱 publishing: 퍼블리싱
web: web:
push_notifications:
favourite:
title: "%{name} 님이 당신의 툿를 즐겨찾기에 등록했습니다"
follow:
title: "%{name} 님이 나를 팔로우 하고 있습니다"
group:
title: "%{count} 건의 알림"
mention:
action_boost: 부스트
action_expand: 더보기
action_favourite: 즐겨찾기
title: "%{name} 님이 답장을 보냈습니다"
reblog:
title: "%{name} 님이 당신의 툿을 부스트 했습니다"
remote_follow: remote_follow:
acct: 아이디@도메인을 입력해 주십시오 acct: 아이디@도메인을 입력해 주십시오
missing_resource: 리디렉션 대상을 찾을 수 없습니다 missing_resource: 리디렉션 대상을 찾을 수 없습니다

View file

@ -594,20 +594,6 @@ nl:
other: Overig other: Overig
publishing: Publiceren publishing: Publiceren
web: Webapp web: Webapp
push_notifications:
favourite:
title: "%{name} markeerde jouw toot als favoriet"
follow:
title: "%{name} volgt jou nu"
group:
title: "%{count} meldingen"
mention:
action_boost: Boost
action_expand: Meer tonen
action_favourite: Favoriet
title: "%{name} vermeldde jou"
reblog:
title: "%{name} boostte jouw toot"
remote_follow: remote_follow:
acct: Geef jouw account@domein.tld op waarvandaan je wilt volgen acct: Geef jouw account@domein.tld op waarvandaan je wilt volgen
missing_resource: Kon vereiste doorverwijzings-URL voor jouw account niet vinden missing_resource: Kon vereiste doorverwijzings-URL voor jouw account niet vinden

View file

@ -531,20 +531,6 @@
other: Annet other: Annet
publishing: Publisering publishing: Publisering
web: Web web: Web
push_notifications:
favourite:
title: "%{name} favoriserte din status"
follow:
title: "%{name} følger deg nå"
group:
title: "%{count} varslinger"
mention:
action_boost: Fremhev
action_expand: Vis mer
action_favourite: Favoritter
title: "%{name} nevnte deg"
reblog:
title: "%{name} fremhevde din status"
remote_follow: remote_follow:
acct: Tast inn brukernavn@domene som du vil følge fra acct: Tast inn brukernavn@domene som du vil følge fra
missing_resource: Kunne ikke finne URLen for din konto missing_resource: Kunne ikke finne URLen for din konto

View file

@ -668,20 +668,6 @@ oc:
other: Autre other: Autre
publishing: Publicar publishing: Publicar
web: Interfàcia Web web: Interfàcia Web
push_notifications:
favourite:
title: "%{name} a mes vòstre estatut en favorit"
follow:
title: "%{name} vos sèc ara"
group:
title: "%{count} notificacions"
mention:
action_boost: Partejar
action_expand: Ne veire mai
action_favourite: Ajustar als favorits
title: "%{name} vos a mencionat"
reblog:
title: "%{name} a partejat vòstre estatut"
remote_follow: remote_follow:
acct: Picatz vòstre utilizaire@instància que cal utilizar per sègre aqueste utilizaire acct: Picatz vòstre utilizaire@instància que cal utilizar per sègre aqueste utilizaire
missing_resource: URL de redireccion pas trobada missing_resource: URL de redireccion pas trobada

View file

@ -603,20 +603,6 @@ pl:
other: Pozostałe other: Pozostałe
publishing: Publikowanie publishing: Publikowanie
web: Sieć web: Sieć
push_notifications:
favourite:
title: "%{name} dodał Twój wpis do ulubionych"
follow:
title: "%{name} zaczął Cię śledzić"
group:
title: "%{count} powiadomień"
mention:
action_boost: Podbij
action_expand: Pokaż więcej
action_favourite: Dodaj do ulubionych
title: "%{name} wspomniał o Tobie"
reblog:
title: "%{name} podbił Twój wpis"
remote_follow: remote_follow:
acct: Podaj swój adres (nazwa@domena), z którego chcesz śledzić acct: Podaj swój adres (nazwa@domena), z którego chcesz śledzić
missing_resource: Nie udało się znaleźć adresu przekierowania z Twojej domeny missing_resource: Nie udało się znaleźć adresu przekierowania z Twojej domeny

View file

@ -593,20 +593,6 @@ pt-BR:
other: Outro other: Outro
publishing: Publicação publishing: Publicação
web: Web web: Web
push_notifications:
favourite:
title: "%{name} favoritou a sua postagem"
follow:
title: "%{name} está te seguindo"
group:
title: "%{count} notificações"
mention:
action_boost: Compartilhar
action_expand: Mostrar mais
action_favourite: Favoritar
title: "%{name} mencionou você"
reblog:
title: "%{name} compartilhou a sua postagem"
remote_follow: remote_follow:
acct: Insira o seu usuário@domínio do qual você quer seguir acct: Insira o seu usuário@domínio do qual você quer seguir
missing_resource: Não foi possível encontrar a URL de direcionamento para a sua conta missing_resource: Não foi possível encontrar a URL de direcionamento para a sua conta

View file

@ -534,20 +534,6 @@ pt:
other: Outro other: Outro
publishing: Publicação publishing: Publicação
web: Web web: Web
push_notifications:
favourite:
title: "%{name} adicionou o teu post aos favoritos"
follow:
title: "%{name} começou a seguir-te"
group:
title: "%{count} notificações"
mention:
action_boost: Partilhar
action_expand: Mostrar mais
action_favourite: Adicionar aos favoritos
title: "%{name} mencionou-te"
reblog:
title: "%{name} partilhou o teu post"
remote_follow: remote_follow:
acct: Entre seu usuário@domínio do qual quer seguir acct: Entre seu usuário@domínio do qual quer seguir
missing_resource: Não foi possível achar a URL de redirecionamento para sua conta missing_resource: Não foi possível achar a URL de redirecionamento para sua conta

View file

@ -606,20 +606,6 @@ ru:
other: Другое other: Другое
publishing: Публикация publishing: Публикация
web: WWW web: WWW
push_notifications:
favourite:
title: Ваш статус понравился %{name}
follow:
title: "%{name} теперь подписан(а) на Вас"
group:
title: "%{count} уведомлений"
mention:
action_boost: Продвинуть
action_expand: Развернуть
action_favourite: Нравится
title: Вас упомянул(а) %{name}
reblog:
title: "%{name} продвинул(а) Ваш статус"
remote_follow: remote_follow:
acct: Введите username@domain, откуда Вы хотите подписаться acct: Введите username@domain, откуда Вы хотите подписаться
missing_resource: Поиск требуемого перенаправления URL для Вашего аккаунта завершился неудачей missing_resource: Поиск требуемого перенаправления URL для Вашего аккаунта завершился неудачей

View file

@ -591,20 +591,6 @@ sk:
other: Ostatné other: Ostatné
publishing: Publikovanie publishing: Publikovanie
web: Web web: Web
push_notifications:
favourite:
title: "%{name} si obľúbil/a tvoj príspevok"
follow:
title: "%{name} ťa teraz následuje"
group:
title: "%{count} notifikácie"
mention:
action_boost: Pozdvihni
action_expand: Ukáž viac
action_favourite: Obľúbené
title: "%{name} ťa spomenul/a"
reblog:
title: "%{name} vyzdvihli tvoj príspevok"
remote_follow: remote_follow:
acct: Napíš svoju prezývku@doménu z ktorej chceš následovať acct: Napíš svoju prezývku@doménu z ktorej chceš následovať
missing_resource: Nemôžeme nájsť potrebnú presmerovaciu adresu k tvojmu účtu missing_resource: Nemôžeme nájsť potrebnú presmerovaciu adresu k tvojmu účtu

View file

@ -525,20 +525,6 @@ sr-Latn:
other: Ostali other: Ostali
publishing: Objavljivanje publishing: Objavljivanje
web: Veb web: Veb
push_notifications:
favourite:
title: "%{name} je stavio Vaš status za omiljeni"
follow:
title: "%{name} Vas je zapratio"
group:
title: "%{count} obaveštenja"
mention:
action_boost: Podrži
action_expand: Prikaži još
action_favourite: Omiljeni
title: "%{name} Vas je pomenuo"
reblog:
title: "%{name} je podržao(la) Vaš status"
remote_follow: remote_follow:
acct: Unesite Vaš korisnik@domen sa koga želite da pratite acct: Unesite Vaš korisnik@domen sa koga želite da pratite
missing_resource: Ne mogu da nađem zahtevanu adresu preusmeravanja za Vaš nalog missing_resource: Ne mogu da nađem zahtevanu adresu preusmeravanja za Vaš nalog

View file

@ -525,20 +525,6 @@ sr:
other: Остали other: Остали
publishing: Објављивање publishing: Објављивање
web: Веб web: Веб
push_notifications:
favourite:
title: "%{name} је ставио Ваш статус за омиљени"
follow:
title: "%{name} Вас је запратио"
group:
title: "%{count} обавештења"
mention:
action_boost: Подржи
action_expand: Прикажи још
action_favourite: Омиљени
title: "%{name} Вас је поменуо"
reblog:
title: "%{name} је подржао(ла) Ваш статус"
remote_follow: remote_follow:
acct: Унесите Ваш корисник@домен са кога желите да пратите acct: Унесите Ваш корисник@домен са кога желите да пратите
missing_resource: Не могу да нађем захтевану адресу преусмеравања за Ваш налог missing_resource: Не могу да нађем захтевану адресу преусмеравања за Ваш налог

View file

@ -592,20 +592,6 @@ sv:
other: Annat other: Annat
publishing: Publicering publishing: Publicering
web: Webb web: Webb
push_notifications:
favourite:
title: "%{name} favoriserade din status"
follow:
title: "%{name} följer nu dig"
group:
title: "%{count} meddelanden"
mention:
action_boost: Knuffa
action_expand: Visa mer
action_favourite: Favoriter
title: "%{name} nämnde dig"
reblog:
title: "%{name} boostade din status"
remote_follow: remote_follow:
acct: Ange ditt användarnamn@domän du vill följa från acct: Ange ditt användarnamn@domän du vill följa från
missing_resource: Det gick inte att hitta den begärda omdirigeringsadressen för ditt konto missing_resource: Det gick inte att hitta den begärda omdirigeringsadressen för ditt konto

View file

@ -523,20 +523,6 @@ zh-CN:
other: 其他 other: 其他
publishing: 发布 publishing: 发布
web: 站内 web: 站内
push_notifications:
favourite:
title: "%{name} 收藏了你的嘟文"
follow:
title: "%{name} 关注了你"
group:
title: "%{count} 条新通知"
mention:
action_boost: 转嘟
action_expand: 显示更多
action_favourite: 收藏
title: "%{name} 提到了你"
reblog:
title: "%{name} 转嘟了你的嘟文"
remote_follow: remote_follow:
acct: 请输入你的“用户名@实例域名” acct: 请输入你的“用户名@实例域名”
missing_resource: 无法确定你的帐户的跳转 URL missing_resource: 无法确定你的帐户的跳转 URL

View file

@ -593,20 +593,6 @@ zh-HK:
other: 其他 other: 其他
publishing: 發佈 publishing: 發佈
web: 站内 web: 站内
push_notifications:
favourite:
title: "%{name} 收藏了你的文章"
follow:
title: "%{name} 關注了你"
group:
title: "%{count} 條新通知"
mention:
action_boost: 轉推
action_expand: 顯示更多
action_favourite: 收藏
title: "%{name} 提到了你"
reblog:
title: "%{name} 轉推了你的文章"
remote_follow: remote_follow:
acct: 請輸入你的︰用戶名稱@服務點域名 acct: 請輸入你的︰用戶名稱@服務點域名
missing_resource: 無法找到你用戶的轉接網址 missing_resource: 無法找到你用戶的轉接網址