volleyballsimtypes 0.0.478 → 0.0.479

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/cjs/src/service/index.d.ts +1 -0
  2. package/dist/cjs/src/service/index.js +1 -0
  3. package/dist/cjs/src/service/notification/catalog/en.json +41 -0
  4. package/dist/cjs/src/service/notification/catalog/es.json +41 -0
  5. package/dist/cjs/src/service/notification/catalog/fr.json +41 -0
  6. package/dist/cjs/src/service/notification/catalog/index.d.ts +3 -0
  7. package/dist/cjs/src/service/notification/catalog/index.js +22 -0
  8. package/dist/cjs/src/service/notification/catalog/it.json +41 -0
  9. package/dist/cjs/src/service/notification/catalog/pl.json +41 -0
  10. package/dist/cjs/src/service/notification/catalog/pt-BR.json +41 -0
  11. package/dist/cjs/src/service/notification/catalog/tr.json +41 -0
  12. package/dist/cjs/src/service/notification/index.d.ts +5 -0
  13. package/dist/cjs/src/service/notification/index.js +23 -0
  14. package/dist/cjs/src/service/notification/notification-type.d.ts +6 -0
  15. package/dist/cjs/src/service/notification/notification-type.js +30 -0
  16. package/dist/cjs/src/service/notification/notification.test.d.ts +1 -0
  17. package/dist/cjs/src/service/notification/notification.test.js +128 -0
  18. package/dist/cjs/src/service/notification/payloads.d.ts +34 -0
  19. package/dist/cjs/src/service/notification/payloads.js +5 -0
  20. package/dist/cjs/src/service/notification/registry.d.ts +13 -0
  21. package/dist/cjs/src/service/notification/registry.js +112 -0
  22. package/dist/cjs/src/service/notification/render.d.ts +10 -0
  23. package/dist/cjs/src/service/notification/render.js +64 -0
  24. package/dist/esm/src/service/index.d.ts +1 -0
  25. package/dist/esm/src/service/index.js +1 -0
  26. package/dist/esm/src/service/notification/catalog/en.json +41 -0
  27. package/dist/esm/src/service/notification/catalog/es.json +41 -0
  28. package/dist/esm/src/service/notification/catalog/fr.json +41 -0
  29. package/dist/esm/src/service/notification/catalog/index.d.ts +3 -0
  30. package/dist/esm/src/service/notification/catalog/index.js +16 -0
  31. package/dist/esm/src/service/notification/catalog/it.json +41 -0
  32. package/dist/esm/src/service/notification/catalog/pl.json +41 -0
  33. package/dist/esm/src/service/notification/catalog/pt-BR.json +41 -0
  34. package/dist/esm/src/service/notification/catalog/tr.json +41 -0
  35. package/dist/esm/src/service/notification/index.d.ts +5 -0
  36. package/dist/esm/src/service/notification/index.js +5 -0
  37. package/dist/esm/src/service/notification/notification-type.d.ts +6 -0
  38. package/dist/esm/src/service/notification/notification-type.js +26 -0
  39. package/dist/esm/src/service/notification/notification.test.d.ts +1 -0
  40. package/dist/esm/src/service/notification/notification.test.js +126 -0
  41. package/dist/esm/src/service/notification/payloads.d.ts +34 -0
  42. package/dist/esm/src/service/notification/payloads.js +4 -0
  43. package/dist/esm/src/service/notification/registry.d.ts +13 -0
  44. package/dist/esm/src/service/notification/registry.js +109 -0
  45. package/dist/esm/src/service/notification/render.d.ts +10 -0
  46. package/dist/esm/src/service/notification/render.js +58 -0
  47. package/package.json +6 -1
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NOTIFICATION_REGISTRY = void 0;
4
+ function readString(value) {
5
+ return typeof value === 'string' && value !== '' ? value : null;
6
+ }
7
+ function teamPath(payload) {
8
+ const teamId = readString(payload.teamId);
9
+ return teamId != null ? `/team/${encodeURIComponent(teamId)}` : '/';
10
+ }
11
+ // MATCH_RESULT copy is recipient-relative: `result` is WIN/LOSS from the recipient's view and `side` marks
12
+ // which team is theirs, so the OTHER team is the opponent. When side/names are missing, do not name a winner.
13
+ function matchOpponent(payload) {
14
+ const homeTeam = typeof payload.homeTeam === 'object' && payload.homeTeam != null ? payload.homeTeam : {};
15
+ const awayTeam = typeof payload.awayTeam === 'object' && payload.awayTeam != null ? payload.awayTeam : {};
16
+ const homeName = readString(homeTeam.name);
17
+ const awayName = readString(awayTeam.name);
18
+ if (payload.side === 'HOME')
19
+ return awayName;
20
+ if (payload.side === 'AWAY')
21
+ return homeName;
22
+ return null;
23
+ }
24
+ function injuredName(payload) {
25
+ // Matches the old Sim injuredPlayerName fallback so a name-less payload never renders a subjectless sentence.
26
+ return readString(payload.playerNickname) ?? readString(payload.playerName) ?? 'A player';
27
+ }
28
+ exports.NOTIFICATION_REGISTRY = {
29
+ MATCH_RESULT: {
30
+ emitsPush: true,
31
+ deepLink: (p) => {
32
+ const matchId = readString(p.matchId);
33
+ return matchId != null ? `/match/${encodeURIComponent(matchId)}` : '/';
34
+ },
35
+ pushTitleKey: 'matchResult.title',
36
+ pushBodyKey: (p) => {
37
+ const outcome = p.result === 'WIN' ? 'won' : 'lost';
38
+ const named = matchOpponent(p) != null ? 'Named' : 'Unnamed';
39
+ return `matchResult.${outcome}${named}`;
40
+ },
41
+ params: (p) => ({ opponent: matchOpponent(p) ?? '' }),
42
+ richRender: 'MATCH_RESULT',
43
+ catalogKeys: ['matchResult.title', 'matchResult.wonNamed', 'matchResult.wonUnnamed', 'matchResult.lostNamed', 'matchResult.lostUnnamed']
44
+ },
45
+ INJURY: {
46
+ emitsPush: true,
47
+ deepLink: () => '/infirmary',
48
+ pushTitleKey: 'injury.title',
49
+ pushBodyKey: 'injury.body',
50
+ inAppMessageKey: 'injury.body',
51
+ params: (p) => ({ name: injuredName(p) }),
52
+ catalogKeys: ['injury.title', 'injury.body']
53
+ },
54
+ INJURY_RECOVERED: {
55
+ emitsPush: true,
56
+ deepLink: teamPath,
57
+ pushTitleKey: 'injuryRecovered.title',
58
+ pushBodyKey: 'injuryRecovered.body',
59
+ inAppMessageKey: 'injuryRecovered.body',
60
+ params: (p) => ({ name: injuredName(p) }),
61
+ catalogKeys: ['injuryRecovered.title', 'injuryRecovered.body']
62
+ },
63
+ SEASON_END: {
64
+ emitsPush: true,
65
+ deepLink: (p) => {
66
+ const leagueId = readString(p.leagueId);
67
+ return leagueId != null ? `/league/${encodeURIComponent(leagueId)}` : '/league';
68
+ },
69
+ pushTitleKey: 'seasonEnd.title',
70
+ pushBodyKey: 'seasonEnd.body',
71
+ inAppMessageKey: 'seasonEnd.body',
72
+ catalogKeys: ['seasonEnd.title', 'seasonEnd.body']
73
+ },
74
+ GRANT_RECEIVED: {
75
+ emitsPush: true,
76
+ deepLink: () => '/recruit',
77
+ pushTitleKey: 'grant.title',
78
+ pushBodyKey: 'grant.body',
79
+ inAppMessageKey: 'grant.body',
80
+ catalogKeys: ['grant.title', 'grant.body']
81
+ },
82
+ PROMOTION: {
83
+ emitsPush: true,
84
+ deepLink: teamPath,
85
+ pushTitleKey: 'promotion.title',
86
+ pushBodyKey: 'promotion.body',
87
+ inAppMessageKey: 'promotion.body',
88
+ catalogKeys: ['promotion.title', 'promotion.body']
89
+ },
90
+ DAILY_LOGIN: {
91
+ emitsPush: true,
92
+ deepLink: () => '/recruit',
93
+ pushTitleKey: 'dailyLogin.title',
94
+ pushBodyKey: 'dailyLogin.body',
95
+ inAppMessageKey: 'dailyLogin.body',
96
+ catalogKeys: ['dailyLogin.title', 'dailyLogin.body']
97
+ },
98
+ WELCOME: {
99
+ emitsPush: true,
100
+ deepLink: () => '/recruit',
101
+ pushTitleKey: 'welcome.title',
102
+ pushBodyKey: 'welcome.body',
103
+ richRender: 'WELCOME',
104
+ catalogKeys: ['welcome.title', 'welcome.body']
105
+ },
106
+ // In-app only (no push); the UI keeps a bespoke renderer (amount formatting) and its own `compensation` label.
107
+ COMPENSATION: {
108
+ emitsPush: false,
109
+ richRender: 'COMPENSATION',
110
+ catalogKeys: []
111
+ }
112
+ };
@@ -0,0 +1,10 @@
1
+ import { type NotificationLocale } from './notification-type';
2
+ export interface RenderedPush {
3
+ title: string;
4
+ body: string;
5
+ data: Record<string, string>;
6
+ }
7
+ export declare function interpolate(template: string, params: Record<string, string>): string;
8
+ export declare function translateNotification(locale: NotificationLocale, key: string, params?: Record<string, string>): string;
9
+ export declare function renderPush(type: string, payload: Record<string, unknown>, locale: NotificationLocale): RenderedPush | undefined;
10
+ export declare function notificationPath(type: string, payload: Record<string, unknown>): string;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.interpolate = interpolate;
4
+ exports.translateNotification = translateNotification;
5
+ exports.renderPush = renderPush;
6
+ exports.notificationPath = notificationPath;
7
+ const notification_type_1 = require("./notification-type");
8
+ const registry_1 = require("./registry");
9
+ const catalog_1 = require("./catalog");
10
+ function readNested(node, dotKey) {
11
+ let current = node;
12
+ for (const part of dotKey.split('.')) {
13
+ if (typeof current !== 'object' || current == null)
14
+ return undefined;
15
+ current = current[part];
16
+ }
17
+ return typeof current === 'string' ? current : undefined;
18
+ }
19
+ function lookupCatalog(locale, dotKey) {
20
+ return readNested(catalog_1.NOTIFICATION_CATALOG[locale], dotKey) ??
21
+ readNested(catalog_1.NOTIFICATION_CATALOG[notification_type_1.DEFAULT_NOTIFICATION_LOCALE], dotKey) ??
22
+ dotKey;
23
+ }
24
+ function resolveKey(resolver, payload) {
25
+ if (resolver == null)
26
+ return undefined;
27
+ return typeof resolver === 'function' ? resolver(payload) : resolver;
28
+ }
29
+ function interpolate(template, params) {
30
+ return template.replace(/\{\{(\w+)\}\}/g, (_match, key) => params[key] ?? '');
31
+ }
32
+ // Resolve one catalog key to a localized, interpolated string. Missing key/locale falls back to English,
33
+ // then to the raw key. Exposed so consumers can render notification copy off the shared catalog too.
34
+ function translateNotification(locale, key, params = {}) {
35
+ return interpolate(lookupCatalog(locale, key), params);
36
+ }
37
+ // Build the localized push payload for a notification. Returns undefined for in-app-only types (emitsPush
38
+ // false, e.g. COMPENSATION). Unknown/future types fall back to the generic copy and the root path, matching
39
+ // the previous hardcoded fallback. Callers pass the recipient's locale (normalizeNotificationLocale first).
40
+ function renderPush(type, payload, locale) {
41
+ const buildData = (path) => ({ type, payload: JSON.stringify(payload), path });
42
+ const descriptor = registry_1.NOTIFICATION_REGISTRY[type];
43
+ if (descriptor == null) {
44
+ return {
45
+ title: translateNotification(locale, 'generic.title'),
46
+ body: translateNotification(locale, 'generic.body'),
47
+ data: buildData('/')
48
+ };
49
+ }
50
+ if (!descriptor.emitsPush)
51
+ return undefined;
52
+ const params = descriptor.params?.(payload) ?? {};
53
+ const titleKey = resolveKey(descriptor.pushTitleKey, payload) ?? 'generic.title';
54
+ const bodyKey = resolveKey(descriptor.pushBodyKey, payload) ?? 'generic.body';
55
+ return {
56
+ title: translateNotification(locale, titleKey, params),
57
+ body: translateNotification(locale, bodyKey, params),
58
+ data: buildData(descriptor.deepLink?.(payload) ?? '/')
59
+ };
60
+ }
61
+ // Deep-link path for a type/payload, used for both the push data.path and the in-app click target.
62
+ function notificationPath(type, payload) {
63
+ return registry_1.NOTIFICATION_REGISTRY[type]?.deepLink?.(payload) ?? '/';
64
+ }
@@ -4,4 +4,5 @@ export * from './team';
4
4
  export * from './event';
5
5
  export * from './player';
6
6
  export * from './competition';
7
+ export * from './notification';
7
8
  export * from './utils';
@@ -4,4 +4,5 @@ export * from './team';
4
4
  export * from './event';
5
5
  export * from './player';
6
6
  export * from './competition';
7
+ export * from './notification';
7
8
  export * from './utils';
@@ -0,0 +1,41 @@
1
+ {
2
+ "matchResult": {
3
+ "title": "Match result",
4
+ "wonNamed": "You won against {{opponent}}",
5
+ "wonUnnamed": "You won your match",
6
+ "lostNamed": "You lost against {{opponent}}",
7
+ "lostUnnamed": "You lost your match"
8
+ },
9
+ "injury": {
10
+ "title": "Player injured",
11
+ "body": "{{name}} has been injured during the last match. Check the infirmary for their recovery time."
12
+ },
13
+ "injuryRecovered": {
14
+ "title": "Player recovered",
15
+ "body": "{{name}} has recovered from their injury and is ready to play!"
16
+ },
17
+ "seasonEnd": {
18
+ "title": "Season complete",
19
+ "body": "Your final league position is ready."
20
+ },
21
+ "grant": {
22
+ "title": "Recruit received",
23
+ "body": "A new recruit reward is available."
24
+ },
25
+ "promotion": {
26
+ "title": "Promotion",
27
+ "body": "Your team has been promoted to a higher division."
28
+ },
29
+ "dailyLogin": {
30
+ "title": "Daily reward claimed",
31
+ "body": "Your daily login reward was added."
32
+ },
33
+ "welcome": {
34
+ "title": "Welcome to World Aces",
35
+ "body": "Your welcome recruit is ready."
36
+ },
37
+ "generic": {
38
+ "title": "World Aces",
39
+ "body": "You have a new notification."
40
+ }
41
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "matchResult": {
3
+ "title": "Resultado del partido",
4
+ "wonNamed": "Ganaste contra {{opponent}}",
5
+ "wonUnnamed": "Ganaste tu partido",
6
+ "lostNamed": "Perdiste contra {{opponent}}",
7
+ "lostUnnamed": "Perdiste tu partido"
8
+ },
9
+ "injury": {
10
+ "title": "Jugador lesionado",
11
+ "body": "{{name}} se ha lesionado durante el último partido. Consulta la enfermería para ver su tiempo de recuperación."
12
+ },
13
+ "injuryRecovered": {
14
+ "title": "Jugador recuperado",
15
+ "body": "¡{{name}} se ha recuperado de su lesión y está listo para jugar!"
16
+ },
17
+ "seasonEnd": {
18
+ "title": "Temporada completada",
19
+ "body": "Tu posición final en la liga está lista."
20
+ },
21
+ "grant": {
22
+ "title": "Reclutamiento recibido",
23
+ "body": "Hay una nueva recompensa de reclutamiento disponible."
24
+ },
25
+ "promotion": {
26
+ "title": "Ascenso",
27
+ "body": "Tu equipo ha ascendido a una división superior."
28
+ },
29
+ "dailyLogin": {
30
+ "title": "Recompensa diaria reclamada",
31
+ "body": "Tu recompensa por inicio de sesión diario se ha añadido."
32
+ },
33
+ "welcome": {
34
+ "title": "Te damos la bienvenida a World Aces",
35
+ "body": "Tu reclutamiento de bienvenida ya está disponible."
36
+ },
37
+ "generic": {
38
+ "title": "World Aces",
39
+ "body": "Tienes una nueva notificación."
40
+ }
41
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "matchResult": {
3
+ "title": "Résultat du match",
4
+ "wonNamed": "Vous avez gagné contre {{opponent}}",
5
+ "wonUnnamed": "Vous avez gagné votre match",
6
+ "lostNamed": "Vous avez perdu contre {{opponent}}",
7
+ "lostUnnamed": "Vous avez perdu votre match"
8
+ },
9
+ "injury": {
10
+ "title": "Joueur blessé",
11
+ "body": "{{name}} s'est blessé lors du dernier match. Consultez l'infirmerie pour connaître son temps de récupération."
12
+ },
13
+ "injuryRecovered": {
14
+ "title": "Joueur rétabli",
15
+ "body": "{{name}} est remis de sa blessure et est prêt à jouer !"
16
+ },
17
+ "seasonEnd": {
18
+ "title": "Saison terminée",
19
+ "body": "Votre classement final dans la ligue est disponible."
20
+ },
21
+ "grant": {
22
+ "title": "Recrutement reçu",
23
+ "body": "Une nouvelle récompense de recrutement est disponible."
24
+ },
25
+ "promotion": {
26
+ "title": "Promotion",
27
+ "body": "Votre équipe a été promue dans une division supérieure."
28
+ },
29
+ "dailyLogin": {
30
+ "title": "Récompense quotidienne récupérée",
31
+ "body": "Votre récompense de connexion quotidienne a été ajoutée."
32
+ },
33
+ "welcome": {
34
+ "title": "Bienvenue sur World Aces",
35
+ "body": "Votre recrutement de bienvenue est prêt."
36
+ },
37
+ "generic": {
38
+ "title": "World Aces",
39
+ "body": "Vous avez une nouvelle notification."
40
+ }
41
+ }
@@ -0,0 +1,3 @@
1
+ import { type NotificationLocale } from '../notification-type';
2
+ export type CatalogNode = Record<string, unknown>;
3
+ export declare const NOTIFICATION_CATALOG: Record<NotificationLocale, CatalogNode>;
@@ -0,0 +1,16 @@
1
+ import en from './en.json';
2
+ import es from './es.json';
3
+ import fr from './fr.json';
4
+ import it from './it.json';
5
+ import pl from './pl.json';
6
+ import ptBR from './pt-BR.json';
7
+ import tr from './tr.json';
8
+ export const NOTIFICATION_CATALOG = {
9
+ en,
10
+ es,
11
+ fr,
12
+ it,
13
+ pl,
14
+ 'pt-BR': ptBR,
15
+ tr
16
+ };
@@ -0,0 +1,41 @@
1
+ {
2
+ "matchResult": {
3
+ "title": "Risultato della partita",
4
+ "wonNamed": "Hai vinto contro {{opponent}}",
5
+ "wonUnnamed": "Hai vinto la partita",
6
+ "lostNamed": "Hai perso contro {{opponent}}",
7
+ "lostUnnamed": "Hai perso la partita"
8
+ },
9
+ "injury": {
10
+ "title": "Giocatore infortunato",
11
+ "body": "{{name}} si è infortunato durante l'ultima partita. Controlla l'infermeria per conoscere i suoi tempi di recupero."
12
+ },
13
+ "injuryRecovered": {
14
+ "title": "Giocatore recuperato",
15
+ "body": "{{name}} si è ripreso dall'infortunio ed è pronto a giocare!"
16
+ },
17
+ "seasonEnd": {
18
+ "title": "Stagione completata",
19
+ "body": "La tua posizione finale in campionato è pronta."
20
+ },
21
+ "grant": {
22
+ "title": "Reclutamento ricevuto",
23
+ "body": "È disponibile una nuova ricompensa di reclutamento."
24
+ },
25
+ "promotion": {
26
+ "title": "Promozione",
27
+ "body": "La tua squadra è stata promossa in una divisione superiore."
28
+ },
29
+ "dailyLogin": {
30
+ "title": "Ricompensa giornaliera riscattata",
31
+ "body": "La tua ricompensa di accesso giornaliero è stata aggiunta."
32
+ },
33
+ "welcome": {
34
+ "title": "Benvenuto in World Aces",
35
+ "body": "La tua recluta di benvenuto è pronta."
36
+ },
37
+ "generic": {
38
+ "title": "World Aces",
39
+ "body": "Hai una nuova notifica."
40
+ }
41
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "matchResult": {
3
+ "title": "Wynik meczu",
4
+ "wonNamed": "Wygrana z {{opponent}}",
5
+ "wonUnnamed": "Wygrana w meczu",
6
+ "lostNamed": "Porażka z {{opponent}}",
7
+ "lostUnnamed": "Porażka w meczu"
8
+ },
9
+ "injury": {
10
+ "title": "Zawodnik kontuzjowany",
11
+ "body": "{{name}} doznał kontuzji w ostatnim meczu. Sprawdź ambulatorium, aby poznać czas powrotu do zdrowia."
12
+ },
13
+ "injuryRecovered": {
14
+ "title": "Zawodnik wyzdrowiał",
15
+ "body": "{{name}} wrócił do zdrowia po kontuzji i jest gotowy do gry!"
16
+ },
17
+ "seasonEnd": {
18
+ "title": "Sezon zakończony",
19
+ "body": "Twoja końcowa pozycja w lidze jest gotowa."
20
+ },
21
+ "grant": {
22
+ "title": "Otrzymano rekrutację",
23
+ "body": "Dostępna jest nowa nagroda rekrutacyjna."
24
+ },
25
+ "promotion": {
26
+ "title": "Awans",
27
+ "body": "Twoja drużyna awansowała do wyższej dywizji."
28
+ },
29
+ "dailyLogin": {
30
+ "title": "Odebrano codzienną nagrodę",
31
+ "body": "Twoja codzienna nagroda za logowanie została dodana."
32
+ },
33
+ "welcome": {
34
+ "title": "Witaj w World Aces",
35
+ "body": "Twoja powitalna rekrutacja jest gotowa."
36
+ },
37
+ "generic": {
38
+ "title": "World Aces",
39
+ "body": "Masz nowe powiadomienie."
40
+ }
41
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "matchResult": {
3
+ "title": "Resultado da partida",
4
+ "wonNamed": "Você venceu {{opponent}}",
5
+ "wonUnnamed": "Você venceu sua partida",
6
+ "lostNamed": "Você perdeu para {{opponent}}",
7
+ "lostUnnamed": "Você perdeu sua partida"
8
+ },
9
+ "injury": {
10
+ "title": "Jogador lesionado",
11
+ "body": "{{name}} se lesionou durante a última partida. Confira a enfermaria para ver o tempo de recuperação."
12
+ },
13
+ "injuryRecovered": {
14
+ "title": "Jogador recuperado",
15
+ "body": "{{name}} se recuperou da lesão e está pronto para jogar!"
16
+ },
17
+ "seasonEnd": {
18
+ "title": "Temporada concluída",
19
+ "body": "Sua colocação final na liga já está disponível."
20
+ },
21
+ "grant": {
22
+ "title": "Recrutamento recebido",
23
+ "body": "Uma nova recompensa de recrutamento está disponível."
24
+ },
25
+ "promotion": {
26
+ "title": "Promoção",
27
+ "body": "Seu time foi promovido para uma divisão superior."
28
+ },
29
+ "dailyLogin": {
30
+ "title": "Recompensa diária coletada",
31
+ "body": "Sua recompensa de login diário foi adicionada."
32
+ },
33
+ "welcome": {
34
+ "title": "Boas-vindas ao World Aces",
35
+ "body": "Seu recrutamento de boas-vindas está pronto."
36
+ },
37
+ "generic": {
38
+ "title": "World Aces",
39
+ "body": "Você tem uma nova notificação."
40
+ }
41
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "matchResult": {
3
+ "title": "Maç sonucu",
4
+ "wonNamed": "{{opponent}} karşısında kazandın",
5
+ "wonUnnamed": "Maçını kazandın",
6
+ "lostNamed": "{{opponent}} karşısında kaybettin",
7
+ "lostUnnamed": "Maçını kaybettin"
8
+ },
9
+ "injury": {
10
+ "title": "Oyuncu sakatlandı",
11
+ "body": "{{name}} son maçta sakatlandı. İyileşme süresini görmek için reviri kontrol edin."
12
+ },
13
+ "injuryRecovered": {
14
+ "title": "Oyuncu iyileşti",
15
+ "body": "{{name}} sakatlığını atlattı ve oynamaya hazır!"
16
+ },
17
+ "seasonEnd": {
18
+ "title": "Sezon tamamlandı",
19
+ "body": "Ligdeki nihai sıralaman hazır."
20
+ },
21
+ "grant": {
22
+ "title": "Transfer alındı",
23
+ "body": "Yeni bir transfer ödülü mevcut."
24
+ },
25
+ "promotion": {
26
+ "title": "Terfi",
27
+ "body": "Takımın bir üst gruba terfi etti."
28
+ },
29
+ "dailyLogin": {
30
+ "title": "Günlük ödül alındı",
31
+ "body": "Günlük giriş ödülün eklendi."
32
+ },
33
+ "welcome": {
34
+ "title": "World Aces'e hoş geldin",
35
+ "body": "Hoş geldin transferin hazır."
36
+ },
37
+ "generic": {
38
+ "title": "World Aces",
39
+ "body": "Yeni bir bildirimin var."
40
+ }
41
+ }
@@ -0,0 +1,5 @@
1
+ export * from './notification-type';
2
+ export * from './payloads';
3
+ export * from './registry';
4
+ export * from './render';
5
+ export { NOTIFICATION_CATALOG, type CatalogNode } from './catalog';
@@ -0,0 +1,5 @@
1
+ export * from './notification-type';
2
+ export * from './payloads';
3
+ export * from './registry';
4
+ export * from './render';
5
+ export { NOTIFICATION_CATALOG } from './catalog';
@@ -0,0 +1,6 @@
1
+ export declare const NOTIFICATION_TYPES: readonly ["MATCH_RESULT", "INJURY", "INJURY_RECOVERED", "SEASON_END", "GRANT_RECEIVED", "PROMOTION", "DAILY_LOGIN", "WELCOME", "COMPENSATION"];
2
+ export type NotificationType = typeof NOTIFICATION_TYPES[number];
3
+ export declare const NOTIFICATION_LOCALES: readonly ["en", "es", "fr", "it", "pl", "pt-BR", "tr"];
4
+ export type NotificationLocale = typeof NOTIFICATION_LOCALES[number];
5
+ export declare const DEFAULT_NOTIFICATION_LOCALE: NotificationLocale;
6
+ export declare function normalizeNotificationLocale(locale: string | null | undefined): NotificationLocale;
@@ -0,0 +1,26 @@
1
+ // Single source of truth for the set of notification types and the locales the catalog ships.
2
+ // Adding a notification type: add it here, add a NOTIFICATION_REGISTRY entry, and add its catalog
3
+ // strings to every locale file. The completeness test (notification.test.ts) fails the build if any
4
+ // of those three is missing. See README.md in this folder.
5
+ export const NOTIFICATION_TYPES = [
6
+ 'MATCH_RESULT',
7
+ 'INJURY',
8
+ 'INJURY_RECOVERED',
9
+ 'SEASON_END',
10
+ 'GRANT_RECEIVED',
11
+ 'PROMOTION',
12
+ 'DAILY_LOGIN',
13
+ 'WELCOME',
14
+ 'COMPENSATION'
15
+ ];
16
+ // The 7 supported locales. Must stay in sync with the API VALID_LOCALES set and the UI src/locales/*.json.
17
+ export const NOTIFICATION_LOCALES = ['en', 'es', 'fr', 'it', 'pl', 'pt-BR', 'tr'];
18
+ export const DEFAULT_NOTIFICATION_LOCALE = 'en';
19
+ // Coalesce an arbitrary/untrusted locale string (e.g. UserSettings.locale, which is nullable) to a
20
+ // supported locale, defaulting to English. Push senders MUST call this before renderPush.
21
+ export function normalizeNotificationLocale(locale) {
22
+ if (locale != null && NOTIFICATION_LOCALES.includes(locale)) {
23
+ return locale;
24
+ }
25
+ return DEFAULT_NOTIFICATION_LOCALE;
26
+ }