diff --git a/app/android/app/src/main/kotlin/kr/co/fanuzu/app/MainActivity.kt b/app/android/app/src/main/kotlin/kr/co/fanuzu/app/MainActivity.kt index 80b66a4..ccbc886 100644 --- a/app/android/app/src/main/kotlin/kr/co/fanuzu/app/MainActivity.kt +++ b/app/android/app/src/main/kotlin/kr/co/fanuzu/app/MainActivity.kt @@ -2,6 +2,7 @@ package kr.co.fanuzu.app import android.app.NotificationChannel import android.app.NotificationManager +import android.os.Build import android.os.Bundle import io.flutter.embedding.android.FlutterFragmentActivity import io.flutter.embedding.engine.FlutterEngine @@ -53,5 +54,10 @@ class MainActivity : FlutterFragmentActivity() { .sortedWith(compareBy(collator) { it[1] }) result.success(pairs) } + // API 레벨 — Android 13+ 는 클립보드 복사를 시스템이 알리므로 앱 토스트를 생략한다(Dart `copyToClipboard`). + MethodChannel(flutterEngine.dartExecutor.binaryMessenger, "kr.co.fanuzu.app/device") + .setMethodCallHandler { call, result -> + if (call.method == "sdkInt") result.success(Build.VERSION.SDK_INT) else result.notImplemented() + } } } diff --git a/app/lib/core/data/backend.dart b/app/lib/core/data/backend.dart index 3c1b42a..5907922 100644 --- a/app/lib/core/data/backend.dart +++ b/app/lib/core/data/backend.dart @@ -167,6 +167,12 @@ extension SnapshotReader on Map { return fallback; } + /// 지갑(`users/{uid}/wallet/main`) 총 보유 POP — 일반 + 기여 + 보류(G-05 · 68f9b7a). + /// HOME 헤더(Figma `179:29099` 「보유 포인트 총합」) · 퀘스트 목록 헤더 · POP 내역이 같은 값을 쓴다. + /// 쓸 수 있는 잔액(기여 · 결제 가능액)과는 다르다 — 그쪽은 각 저장소가 따로 계산한다. + int get walletTotal => + intOr('activityBalance') + intOr('supportBalance') + intOr('pendingActivity'); + String strOr(String key, [String fallback = '']) { final value = this[key]; return value is String && value.isNotEmpty ? value : fallback; diff --git a/app/lib/core/ui/clipboard_copy.dart b/app/lib/core/ui/clipboard_copy.dart new file mode 100644 index 0000000..eb0185f --- /dev/null +++ b/app/lib/core/ui/clipboard_copy.dart @@ -0,0 +1,31 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; + +const _deviceChannel = MethodChannel('kr.co.fanuzu.app/device'); + +/// Android API 레벨 — 한 번 읽어 둔다. Android 가 아니거나 채널이 없으면(위젯 테스트) null. +Future? _sdkInt; + +/// 클립보드에 [text] 를 넣고, OS 가 복사를 직접 알리지 않을 때만 [toast] 를 부른다. +/// +/// Android 13(API 33)+ 는 시스템이 「클립보드에 복사했어요」를 띄워 앱 토스트와 겹친다 +/// (10/8 r11 3-8). iOS · Android 12 이하는 앱이 알린다. +Future copyToClipboard(String text, VoidCallback toast) async { + await Clipboard.setData(ClipboardData(text: text)); + if (defaultTargetPlatform == TargetPlatform.android && + ((await (_sdkInt ??= _readSdkInt())) ?? 0) >= 33) { + return; + } + toast(); +} + +Future _readSdkInt() async { + try { + return await _deviceChannel.invokeMethod('sdkInt'); + } on Object { + return null; + } +} + +@visibleForTesting +void resetClipboardSdkCache() => _sdkInt = null; diff --git a/app/lib/features/campaign/campaign_detail_screen.dart b/app/lib/features/campaign/campaign_detail_screen.dart index fa0ed8a..e0df3ea 100644 --- a/app/lib/features/campaign/campaign_detail_screen.dart +++ b/app/lib/features/campaign/campaign_detail_screen.dart @@ -1,7 +1,6 @@ import 'package:flutter/material.dart'; import '../../core/ui/app_dialog.dart'; -import 'package:flutter/services.dart'; import 'package:share_plus/share_plus.dart'; import '../../core/data/backend.dart' show BackendException; @@ -23,6 +22,7 @@ import 'widgets/campaign_rank.dart'; import 'widgets/campaign_share_dialog.dart'; import 'widgets/campaign_style.dart'; import '../../core/ui/fx_intensity.dart'; +import '../../core/ui/clipboard_copy.dart'; /// 캠페인 상세 — 화면 대조 원장 F5 · Figma `272:245738`. /// @@ -448,6 +448,10 @@ class _CampaignDetailScreenState extends State { ), ) : null) + // 모금 중이 아니면(달성 · 미달 환불 · 결과보고 · 취소) 기여할 수 없다 — Figma 는 종료 상태의 + // 버튼을 정하지 않아(`523:18589` 「타인 캠페인에서만 표시」) 숨긴다(10/8 r11). + : card.status != CampaignStatus.funding + ? null : SafeArea( child: Padding( padding: const EdgeInsets.fromLTRB(20, 8, 20, 8), @@ -1070,8 +1074,9 @@ class _CampaignDetailScreenState extends State { } Future _copyText(CampaignCardData card) async { - await Clipboard.setData(ClipboardData(text: _shareBody(card))); - if (mounted) _toast(context.l10n.shareCopied); + await copyToClipboard(_shareBody(card), () { + if (mounted) _toast(context.l10n.shareCopied); + }); } /// 캠페인 신고(`reports/campaign-{캠페인}-{신고자}`) · 개설자 차단. diff --git a/app/lib/features/eclipse/widgets/live_proof.dart b/app/lib/features/eclipse/widgets/live_proof.dart index fa08bbb..e182b42 100644 --- a/app/lib/features/eclipse/widgets/live_proof.dart +++ b/app/lib/features/eclipse/widgets/live_proof.dart @@ -21,6 +21,23 @@ String liveEventMessage(LiveEvent event) => switch (event.kind) { LiveEventKind.notice => '[LIVE] ${event.nickname}', }; +/// 띠·섬광 배너에 올려도 되는 라이브 이벤트. 이클립스 방어 합류는 **그 회차가 진행 중일 때만** 싣는다 — +/// 끝난 회차의 합류 문구가 서버 TTL(1시간)까지 띠에 남던 결함(10/8 r11 2-5). [eclipse] 는 지금 진행 중인 +/// 회차(`watch` 는 마감되면 null 을 낸다)이고, 회차 발생 전의 합류는 지난 회차의 것이다. +List liveEventsFor( + List events, + EclipseState? eclipse, + DateTime now, +) => [ + for (final e in events) + if (e.kind != LiveEventKind.eclipseDefense || + (eclipse != null && + eclipse.result == null && + !eclipse.isExpired(now) && + !(eclipse.startAt?.isAfter(e.at) ?? false))) + e, +]; + /// 홈 라이브 띠(전광판)에 올릴 한 줄. [hero] 면 띠가 HERO TIME 참여 진입이 된다. /// [push] 는 같은 사건을 알리는 Push 의 `kind` — 띠가 떠 있으면 앱 안 Push 를 겹쳐 띄우지 않는다(v1.5 §1.1). typedef TickerLine = ({String text, bool hero, String? push}); @@ -46,7 +63,8 @@ TickerLine? tickerLine({ required DateTime now, String? fallback, }) { - final event = events.isEmpty ? null : events.first; + final live = liveEventsFor(events, eclipse, now); + final event = live.isEmpty ? null : live.first; if (eclipse != null && eclipse.result == null) { final started = eclipse.startAt; if (event == null || started == null || event.at.isBefore(started)) { diff --git a/app/lib/features/galaxy/galaxy_screen.dart b/app/lib/features/galaxy/galaxy_screen.dart index dfccaf1..de0e91c 100644 --- a/app/lib/features/galaxy/galaxy_screen.dart +++ b/app/lib/features/galaxy/galaxy_screen.dart @@ -509,6 +509,7 @@ class _Map extends StatelessWidget { child: _LiveFlash( repository: eclipseRepository, fandomId: eclipse?.fandomId ?? data.mine?.id, + eclipse: eclipse, fallback: data.event, ), ), @@ -1050,12 +1051,16 @@ class _LiveFlash extends StatelessWidget { const _LiveFlash({ required this.repository, required this.fandomId, + required this.eclipse, required this.fallback, }); final EclipseRepository repository; final String? fandomId; + /// 진행 중인 회차. 끝난 회차의 방어 합류는 흘리지 않는다([liveEventsFor]). + final EclipseState? eclipse; + /// 라이브 이벤트가 없을 때 그릴 기존 `galaxyEvents` 한 건. final GalaxyEvent? fallback; @@ -1073,8 +1078,9 @@ class _LiveFlash extends StatelessWidget { return LiveStreamBuilder>( key: ValueKey('flash-$fandomId'), create: () => repository.liveEvents(fandomId: fandomId, limit: 5), - builder: (context, events) { - if (events == null || events.isEmpty) { + builder: (context, all) { + final events = liveEventsFor(all ?? const [], eclipse, DateTime.now()); + if (events.isEmpty) { return fallback == null ? const SizedBox.shrink() : _EventTicker( diff --git a/app/lib/features/galaxy/widgets/zap_feedback.dart b/app/lib/features/galaxy/widgets/zap_feedback.dart index 0733439..df96261 100644 --- a/app/lib/features/galaxy/widgets/zap_feedback.dart +++ b/app/lib/features/galaxy/widgets/zap_feedback.dart @@ -20,8 +20,13 @@ class ZapFeedback extends StatefulWidget { required this.radius, this.fandomName, this.quest = false, + this.messageAboveTarget = false, }); + /// 안내 띠를 [target] 행성 상자 위쪽에 둔다(HOME). 기본 자리(아래 128)는 HOME 에서 행성 이름 · + /// 성장 카드 말풍선을 덮는다(10/8 r11). 행성 상자 반 변 = [radius] / 0.4(HOME 이 넘기는 값). + final bool messageAboveTarget; + /// 퀘스트 보상 확정의 행성 반응인가 — 결과 문구를 퀘스트 반영으로 바꾼다. final bool quest; @@ -101,7 +106,12 @@ class _ZapFeedbackState extends State Positioned( left: 16, right: 16, - bottom: 128, + top: widget.messageAboveTarget && widget.target != Offset.zero + ? math.max(0, widget.target.dy - widget.radius / 0.4 / 2) + : null, + bottom: widget.messageAboveTarget && widget.target != Offset.zero + ? null + : 128, child: Center( child: Semantics( liveRegion: true, diff --git a/app/lib/features/home/home_data.dart b/app/lib/features/home/home_data.dart index 6ed3ffc..90e3a10 100644 --- a/app/lib/features/home/home_data.dart +++ b/app/lib/features/home/home_data.dart @@ -351,8 +351,8 @@ class HomeSnapshot { /// HOME 주간 정보(A-37 · HOME 정보위계 v1.0 §2 · §3). 소속 행성이 없으면 null. final HomeWeekly? weekly; - /// 활동 POP 잔액. 정책 설계서 §P-02 — 활동/지원 원장은 분리되어 있고 - /// 홈 상단에는 활동 POP 을 띄운다. + /// 총 보유 POP(일반 + 기여 + 보류) — Figma `179:29099` 「보유 포인트 총합」. + /// 설정 · POP 내역의 총 보유와 같은 값이다(`walletTotal`). final int popBalance; /// 내 소속 팬덤. 이클립스 경보 배너와 라이브 띠가 **어느 팬덤을 구독할지**를 @@ -499,7 +499,7 @@ abstract interface class HomeRepository { Future load(); Stream watchGrowth(String fandomId); - /// 보유 활동 POP — `users/{uid}/wallet/main.activityBalance` 구독. 퀘스트 목록 헤더 + /// 총 보유 POP — `users/{uid}/wallet/main` 구독(`walletTotal`). 퀘스트 목록 헤더 /// (`QuestRepository.popBalance`)와 같은 문서라, 다른 화면에서 생긴 변동(현상금 예치 · /// 보상)이 HOME 헤더에도 바로 반영된다. Stream watchPopBalance(); diff --git a/app/lib/features/home/home_repository_firestore.dart b/app/lib/features/home/home_repository_firestore.dart index eb998d3..8b1e4fe 100644 --- a/app/lib/features/home/home_repository_firestore.dart +++ b/app/lib/features/home/home_repository_firestore.dart @@ -44,9 +44,7 @@ class FirestoreHomeRepository implements HomeRepository { Stream watchPopBalance() => _backend.db .doc('users/${_backend.requireUid}/wallet/main') .snapshots() - .map( - (s) => (s.data() ?? const {}).intOr('activityBalance'), - ); + .map((s) => (s.data() ?? const {}).walletTotal); @override Future<({String fandomId, bool primaryChanged})> createNebula( @@ -233,7 +231,7 @@ class FirestoreHomeRepository implements HomeRepository { return HomeSnapshot( weekly: weekly, - popBalance: wallet.intOr('activityBalance'), + popBalance: wallet.walletTotal, fandomId: fandomId, liveTicker: fandom.strOr('liveTicker').isEmpty ? null diff --git a/app/lib/features/home/home_screen.dart b/app/lib/features/home/home_screen.dart index 3548252..239a5b5 100644 --- a/app/lib/features/home/home_screen.dart +++ b/app/lib/features/home/home_screen.dart @@ -684,7 +684,8 @@ class _HomeBody extends StatelessWidget { key: ValueKey(('pop', repository)), create: repository.watchPopBalance, builder: (context, wallet) => HomeHeader( - pop: wallet ?? zap?.balance ?? data.popBalance, + // Zap 영수증 잔액(일반 POP)은 섞지 않는다 — 헤더는 총 보유다(`179:29099`). + pop: wallet ?? data.popBalance, notifications: notifications, items: data.items, fandomId: data.fandomId, diff --git a/app/lib/features/home/widgets/briefing_share.dart b/app/lib/features/home/widgets/briefing_share.dart index cc2df62..997e69b 100644 --- a/app/lib/features/home/widgets/briefing_share.dart +++ b/app/lib/features/home/widgets/briefing_share.dart @@ -2,7 +2,6 @@ import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; -import 'package:flutter/services.dart'; import 'package:share_plus/share_plus.dart'; import '../../../core/i18n/app_locale.dart'; @@ -10,6 +9,7 @@ import '../../../core/theme/tokens.dart'; import '../../../core/ui/app_icons.dart'; import '../../campaign/campaign_share.dart' show shareHashtags, shareLink, shareBaseUrl; import '../home_data.dart'; +import '../../../core/ui/clipboard_copy.dart'; /// 브리핑 공유 — 「홈_브리핑 공유」 `266:90445` · 인스타 `272:240423` · 틱톡 `272:240430`. /// @@ -128,13 +128,16 @@ class _BriefingShareDialogState extends State { setState(() => _busy = true); try { if (index == _icons.length - 1) { - await Clipboard.setData(ClipboardData(text: _text)); + var announce = false; + await copyToClipboard(_text, () => announce = true); if (!mounted) return; // 오버레이를 닫고 알린다 — 열린 채로 띄우면 스낵바가 장막 뒤에 가린다. Navigator.of(context).pop(); - toast(widget.link == null - ? l10n.briefingShareTextCopied - : l10n.briefingShareCopied); + if (announce) { + toast(widget.link == null + ? l10n.briefingShareTextCopied + : l10n.briefingShareCopied); + } return; } final file = await _capture(); diff --git a/app/lib/features/home/widgets/home_hero.dart b/app/lib/features/home/widgets/home_hero.dart index 2b8c050..0e624d2 100644 --- a/app/lib/features/home/widgets/home_hero.dart +++ b/app/lib/features/home/widgets/home_hero.dart @@ -183,7 +183,19 @@ class _HomeHeroState extends State { children: [ // 첫 사용자 홈(`343:212939`)은 아바타가 y124, 나머지 상태는 y130. if (!widget.unjoined) const SizedBox(height: 6), - _Contribution(growth: growth, joined: !widget.unjoined), + // 미니맵(오른쪽 위 [HomeHero.miniMapSize])과 같은 높이라 그 폭만큼 비운다 — 긴 언어(ja · + // es)의 제목이 미니맵 아래로 들어가 잘리지 않고 줄바꿈된다(10/8 r11). + Padding( + padding: EdgeInsets.only( + right: widget.miniMap == null + ? 0 + : HomeHero.miniMapSize - AppSpace.s4 + AppSpace.s2, + ), + child: _Contribution( + growth: growth, + joined: !widget.unjoined, + ), + ), const SizedBox(height: AppSpace.s7), // HERO TIME 안내·큰 글자처럼 아래가 길어지면 행성이 먼저 줄어든다. Flexible( @@ -216,19 +228,22 @@ class _HomeHeroState extends State { child: _TapShake( onTap: widget.onTapPlanet, child: LivePlanet25D( - onOpenHistory: widget.onOpenHistory, - key: _planetKey, - fandomId: fandomId, - watch: watchPlanet, - stage: growth.stage, - // 형태 없는 옛 행성은 다른 화면과 같은 그림(10/6 C-5). - image: planetFallbackImage(fandomId), - size: math.min( - planet, - box.maxHeight, + onOpenHistory: + widget.onOpenHistory, + key: _planetKey, + fandomId: fandomId, + watch: watchPlanet, + stage: growth.stage, + // 형태 없는 옛 행성은 다른 화면과 같은 그림(10/6 C-5). + image: planetFallbackImage( + fandomId, + ), + size: math.min( + planet, + box.maxHeight, + ), + glow: AppColors.neonViolet, ), - glow: AppColors.neonViolet, - ), ), ), ], @@ -276,6 +291,7 @@ class _HomeHeroState extends State { child: ZapFeedback( fandomName: widget.growth.fandomName, quest: zap.questReaction, + messageAboveTarget: true, touchSerial: zap.touchSerial, pending: zap.pending > 0 || zap.sending, result: zap.result, @@ -312,96 +328,104 @@ class _Contribution extends StatelessWidget { /// 소속 팬덤이 있는가. 없으면 첫 사용자 문구(`343:212939`)를 쓴다. final bool joined; - @override - Widget build(BuildContext context) => Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // 「{닉네임} 님의」는 로그인 사용자의 인사 줄이다(설명 프레임 `2097:16391`). - if (growth.contributorName.trim().isNotEmpty) ...[ - Row( - children: [ - // 로그인 사용자의 프로필 사진(`2097:16391` 「프로필 - 이미지」). 없으면 이니셜. - Container( - width: 26, - height: 26, - alignment: Alignment.center, - clipBehavior: Clip.antiAlias, - decoration: BoxDecoration( - shape: BoxShape.circle, - // 사본 `Ellipse 3` #9BF8A8(프로필 사진이 없을 때의 바탕). - color: const Color(0xFF9BF8A8), - boxShadow: const [ - BoxShadow(color: Color(0xB3000000), blurRadius: 4), - ], - image: growth.photoUrl == null - ? null - : DecorationImage( - image: NetworkImage(growth.photoUrl!), - fit: BoxFit.cover, - onError: (_, _) {}, - ), - ), - child: growth.photoUrl != null - ? null - : Text( - growth.contributorName.characters.firstOrNull ?? '—', - style: const TextStyle( - fontFamily: AppFonts.body, - fontSize: 12, - fontWeight: FontWeight.w500, - color: Colors.black, - ), - ), - ), - const SizedBox(width: 9), - Text( - growth.contributorName, - style: const TextStyle( - fontFamily: AppFonts.display, - fontSize: 12, - height: 1.3, - letterSpacing: -0.3, - color: AppColors.onCosmic, - ), - ), - const SizedBox(width: 2), - Text( - context.l10n.heroOwnerSuffix, - style: const TextStyle( - fontFamily: AppFonts.body, - fontSize: 12, - fontWeight: FontWeight.w500, - height: 1.3, - letterSpacing: -0.3, - color: AppColors.onCosmicVariant, - ), - ), - ], - ), - const SizedBox(height: 3), - ], - Text( - // 사본 문구의 「팬케이크」는 사용자 노출 브랜드라 「팬우주」로 바꾼다(공통 기준 4항). - !joined - ? context.l10n.heroStartPrompt - : growth.isNebula - ? context.l10n.heroNebulaPrompt - : growth.hasRecentContribution - ? context.l10n.heroRecentContribution( - formatPop(growth.contributedPop), - ) - : context.l10n.heroGrowingTogether, - style: const TextStyle( - fontFamily: AppFonts.body, - fontSize: 20, - fontWeight: FontWeight.w500, - height: 1.4, - letterSpacing: -0.5, - color: AppColors.onCosmic, - ), - ), - ], + static const _ownerAffix = TextStyle( + fontFamily: AppFonts.body, + fontSize: 12, + fontWeight: FontWeight.w500, + height: 1.3, + letterSpacing: -0.3, + color: AppColors.onCosmicVariant, ); + + @override + Widget build(BuildContext context) { + final owner = context.l10n.heroOwner('\u0000').split('\u0000'); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // 「{닉네임} 님의」는 로그인 사용자의 인사 줄이다(설명 프레임 `2097:16391`). + if (growth.contributorName.trim().isNotEmpty) ...[ + Row( + children: [ + // 로그인 사용자의 프로필 사진(`2097:16391` 「프로필 - 이미지」). 없으면 이니셜. + Container( + width: 26, + height: 26, + alignment: Alignment.center, + clipBehavior: Clip.antiAlias, + decoration: BoxDecoration( + shape: BoxShape.circle, + // 사본 `Ellipse 3` #9BF8A8(프로필 사진이 없을 때의 바탕). + color: const Color(0xFF9BF8A8), + boxShadow: const [ + BoxShadow(color: Color(0xB3000000), blurRadius: 4), + ], + image: growth.photoUrl == null + ? null + : DecorationImage( + image: NetworkImage(growth.photoUrl!), + fit: BoxFit.cover, + onError: (_, _) {}, + ), + ), + child: growth.photoUrl != null + ? null + : Text( + growth.contributorName.characters.firstOrNull ?? '—', + style: const TextStyle( + fontFamily: AppFonts.body, + fontSize: 12, + fontWeight: FontWeight.w500, + color: Colors.black, + ), + ), + ), + const SizedBox(width: 9), + // 「님의」는 언어마다 이름 앞(es 「De」) 또는 뒤(ko 「님의」 · ja 「さんの」)에 붙는다 — 문구 + // 하나({name} 자리표시)를 이름 자리에서 갈라 앞뒤를 흐린 색으로 그린다(10/8 r11 es 오역). + if (owner.first.isNotEmpty) Text(owner.first, style: _ownerAffix), + Flexible( + child: Text( + growth.contributorName, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: const TextStyle( + fontFamily: AppFonts.display, + fontSize: 12, + height: 1.3, + letterSpacing: -0.3, + color: AppColors.onCosmic, + ), + ), + ), + if (owner.last.isNotEmpty) Text(owner.last, style: _ownerAffix), + ], + ), + const SizedBox(height: 3), + ], + Text( + // 사본 문구의 「팬케이크」는 사용자 노출 브랜드라 「팬우주」로 바꾼다(공통 기준 4항). + !joined + ? context.l10n.heroStartPrompt + : growth.isNebula + ? context.l10n.heroNebulaPrompt + : growth.hasRecentContribution + ? context.l10n.heroRecentContribution( + formatPop(growth.contributedPop), + ) + : context.l10n.heroGrowingTogether, + style: const TextStyle( + fontFamily: AppFonts.body, + fontSize: 20, + fontWeight: FontWeight.w500, + height: 1.4, + letterSpacing: -0.5, + color: AppColors.onCosmic, + ), + ), + ], + ); + } } /// 성장 카드 — Figma 「홈」 `Frame 1984081073`(343×151 · `#040304` 40% · r12 · 패딩 12/16 · @@ -425,8 +449,21 @@ class _GrowthOverlayCard extends StatelessWidget { color: AppColors.onCosmic, ); - /// 말풍선 가운데의 최소 x — 「행성 성장률 100%」 줄(약 103)과 겹치지 않게 한다. - static const _bubbleMinCenter = 196.0; + /// 말풍선과 성장률 글자 사이 최소 간격. + static const _bubbleGap = 8.0; + + static double _textWidth( + BuildContext context, + String text, + TextStyle style, + ) => + (TextPainter( + text: TextSpan(text: text, style: style), + textDirection: Directionality.of(context), + textScaler: MediaQuery.textScalerOf(context), + maxLines: 1, + )..layout()).width.ceilToDouble() + + 1; String _value(num v) => v == v.roundToDouble() ? formatPop(v.toInt()) : v.toStringAsFixed(1); @@ -464,6 +501,9 @@ class _GrowthOverlayCard extends StatelessWidget { final low = growth.bottleneck; final ratio = low?.ratio; final percent = ratio == null ? '—' : '${(ratio * 100).round()}'; + final rate = growth.isNebula + ? context.l10n.heroNebulaGrowthRate(percent) + : context.l10n.heroGrowthRate(percent); return ClipRRect( borderRadius: BorderRadius.circular(AppRadius.md), child: BackdropFilter( @@ -520,12 +560,7 @@ class _GrowthOverlayCard extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Text( - growth.isNebula - ? context.l10n.heroNebulaGrowthRate(percent) - : context.l10n.heroGrowthRate(percent), - style: _white14, - ), + Text(rate, style: _white14), const SizedBox(height: AppSpace.s3), _Bar(ratio: ratio ?? 0), const SizedBox(height: AppSpace.s3), @@ -541,25 +576,39 @@ class _GrowthOverlayCard extends StatelessWidget { ], ), // 말풍선 — 사본 y566.5(카드 안 31.5) · 꼬리 끝이 바 위에 닿는다. 가운데는 채움 끝 - // (사본 x238 = 채움 206)을 따르되 왼쪽 성장률 글자와 겹치지 않게 민다. + // (사본 x238 = 채움 206)을 따르되 왼쪽 성장률 글자와 겹치지 않게 민다. 두 글자 폭은 + // 언어마다 달라 재서 정한다 — 남는 폭이 모자라면 말풍선 글자를 줄인다(10/8 r11 es). // 성운 카드(`344:213809`)에는 말풍선이 없다. if (!growth.isNebula) - Positioned( - top: 31.5, - left: (box.maxWidth * (ratio ?? 0)).clamp( - math.min(_bubbleMinCenter, box.maxWidth - 84), - box.maxWidth - 84, - ), - child: FractionalTranslation( - translation: const Offset(-0.5, 0), - child: Semantics( - button: true, - child: GestureDetector( - onTap: () => _details(context), - child: _SpeechBubble(text: growth.growthBubble), + Builder( + builder: (context) { + final left = + _textWidth(context, rate, _white14) + _bubbleGap; + final width = math.min( + _textWidth( + context, + growth.growthBubble, + _SpeechBubble.style, + ) + + _SpeechBubble.padding * 2, + math.max(0.0, box.maxWidth - left), + ); + return Positioned( + top: 31.5, + left: (box.maxWidth * (ratio ?? 0) - width / 2).clamp( + math.min(left, box.maxWidth - width), + box.maxWidth - width, ), - ), - ), + width: width, + child: Semantics( + button: true, + child: GestureDetector( + onTap: () => _details(context), + child: _SpeechBubble(text: growth.growthBubble), + ), + ), + ); + }, ), ], ), @@ -606,13 +655,23 @@ class _SpeechBubble extends StatelessWidget { static const _fill = Color(0xCC000000); + static const padding = 10.0; + + static const style = TextStyle( + fontFamily: AppFonts.body, + fontSize: 12, + fontWeight: FontWeight.w500, + height: 1, + color: AppColors.onCosmic, + ); + @override Widget build(BuildContext context) => Column( mainAxisSize: MainAxisSize.min, children: [ Container( height: 30, - padding: const EdgeInsets.symmetric(horizontal: 10), + padding: const EdgeInsets.symmetric(horizontal: padding), alignment: Alignment.center, decoration: BoxDecoration( color: _fill, @@ -620,13 +679,9 @@ class _SpeechBubble extends StatelessWidget { ), child: Text( text, - style: const TextStyle( - fontFamily: AppFonts.body, - fontSize: 12, - fontWeight: FontWeight.w500, - height: 1, - color: AppColors.onCosmic, - ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: style, ), ), CustomPaint( @@ -1049,7 +1104,6 @@ class HomeZap extends StatelessWidget { ); } - /// 행성 터치 반응 — Figma `2024:20758` 「행성 1회 터치시 흔들림 1번」 · UX·FX v1.5 §3 Light Haptic. /// 흔들림이 끝나면 [onTap](커뮤니티 이동)을 부른다. [onTap] 이 없으면 아무 반응도 하지 않는다. class _TapShake extends StatefulWidget { @@ -1062,8 +1116,12 @@ class _TapShake extends StatefulWidget { State<_TapShake> createState() => _TapShakeState(); } -class _TapShakeState extends State<_TapShake> with SingleTickerProviderStateMixin { - late final _shake = AnimationController(vsync: this, duration: const Duration(milliseconds: 320)); +class _TapShakeState extends State<_TapShake> + with SingleTickerProviderStateMixin { + late final _shake = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 320), + ); @override void dispose() { @@ -1087,7 +1145,10 @@ class _TapShakeState extends State<_TapShake> with SingleTickerProviderStateMixi animation: _shake, // 한 번 좌우로 흔들리고 제자리 — 진폭 6 · 감쇠. builder: (context, child) => Transform.translate( - offset: Offset(math.sin(_shake.value * math.pi * 4) * 6 * (1 - _shake.value), 0), + offset: Offset( + math.sin(_shake.value * math.pi * 4) * 6 * (1 - _shake.value), + 0, + ), child: child, ), child: widget.child, diff --git a/app/lib/features/home/widgets/home_weekly.dart b/app/lib/features/home/widgets/home_weekly.dart index f50b205..63872c0 100644 --- a/app/lib/features/home/widgets/home_weekly.dart +++ b/app/lib/features/home/widgets/home_weekly.dart @@ -37,16 +37,22 @@ class HomeWeeklyCard extends StatelessWidget { final l10n = context.l10n; final w = weekly; final change = w.rankChange; + // 라벨 2 : 값 3 으로 나눈다 — 값이 폭을 다 차지하면 긴 언어(es)에서 라벨이 0 폭이 되어 + // 한 글자씩 줄바꿈된다(10/8 r11 「Mis POP」). 넘치면 둘 다 단어 단위로 줄바꿈한다. Widget row(String label, Widget value) => Padding( padding: const EdgeInsets.symmetric(vertical: AppSpace.s2), child: Row( children: [ - Expanded(child: Text(label, style: _label)), - value, + Expanded(flex: 2, child: Text(label, style: _label)), + const SizedBox(width: AppSpace.s2), + Flexible( + flex: 3, + child: Align(alignment: Alignment.centerRight, child: value), + ), ], ), ); - Text text(String s) => Text(s, style: _value); + Text text(String s) => Text(s, style: _value, textAlign: TextAlign.end); return Container( padding: const EdgeInsets.symmetric( diff --git a/app/lib/features/my/my_repository_firestore.dart b/app/lib/features/my/my_repository_firestore.dart index 6ce0a6e..32d796e 100644 --- a/app/lib/features/my/my_repository_firestore.dart +++ b/app/lib/features/my/my_repository_firestore.dart @@ -126,7 +126,7 @@ class FirestoreMyRepository extends SampleMyRepository { userExp: user.intOr('userExp'), userLevel: user.intOr('userLevel').clamp(1, 1 << 31), passportTier: primaryTier, - balancePop: wallet.intOr('activityBalance') + wallet.intOr('supportBalance') + wallet.intOr('pendingActivity'), + balancePop: wallet.walletTotal, reservedPop: wallet.intOr('pendingActivity'), steps: user.intOr('steps'), completedQuests: await completedF, diff --git a/app/lib/features/my/widgets/profile_card.dart b/app/lib/features/my/widgets/profile_card.dart index 51e6635..4ef2539 100644 --- a/app/lib/features/my/widgets/profile_card.dart +++ b/app/lib/features/my/widgets/profile_card.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:share_plus/share_plus.dart'; import '../../../core/format.dart'; @@ -8,6 +7,7 @@ import '../../../core/ui/app_icons.dart'; import '../my_data.dart'; import 'my_cards.dart'; import '../../../core/i18n/app_locale.dart'; +import '../../../core/ui/clipboard_copy.dart'; import '../../campaign/campaign_share.dart' show shareHashtags; /// 프로필 카드 오버레이 — 시안 `374:15738`(명세 `549:22058`). @@ -123,7 +123,8 @@ String profileShareText(MyProfile profile, [AppLocalizations? l10n]) => [ ].join('\n'); /// 프로필 카드 공유. 앱별 전용 SDK 없이 OS 공유 시트로 보내고(사용자가 그 안에서 -/// 인스타 · 틱톡 · X 를 고른다), 마지막 칸은 문구를 복사한다. 복사했으면 true. +/// 인스타 · 틱톡 · X 를 고른다), 마지막 칸은 문구를 복사한다. 복사했고 앱이 알려야 하면 true +/// (Android 13+ 는 시스템이 알린다 — [copyToClipboard]). Future shareProfile( MyProfile profile, String target, { @@ -131,8 +132,9 @@ Future shareProfile( }) async { final text = profileShareText(profile); if (target == ProfileCard.shareTargets.last) { - await Clipboard.setData(ClipboardData(text: text)); - return true; + var announce = false; + await copyToClipboard(text, () => announce = true); + return announce; } await (share ?? SharePlus.instance.share)(ShareParams(text: text)); return false; diff --git a/app/lib/features/notification/notification_data.dart b/app/lib/features/notification/notification_data.dart index 9864cf6..f812db1 100644 --- a/app/lib/features/notification/notification_data.dart +++ b/app/lib/features/notification/notification_data.dart @@ -100,7 +100,10 @@ class AppNotification { /// 없으면 종류 이름([NotificationKind.label])으로 물러난다. final String? source; - String get sourceLabel => source ?? kind.label; + String get sourceLabel => + source ?? + (kind == NotificationKind.campaign ? campaignNotificationLabel(id) : null) ?? + kind.label; /// 눌렀을 때 열 대상 문서 경로(`quests/{id}` · `campaigns/{id}` 등). 서버가 싣는다. /// 명세가 *이동 X* 로 정한 종류(이클립스 · 아이템)는 경로가 있어도 쓰지 않는다. @@ -125,6 +128,17 @@ class AppNotification { ); } +/// 캠페인 알림의 세부 종류 이름. 서버(`campaign/settle.ts` `notifyOnce`)는 `eventType` 을 모두 +/// `campaign` 으로 싣고 문서 ID 앞머리로 가른다 — `campaignSuccess_` · `campaignRefund_`(목표 미달 · +/// 취소 환불) · `campaignCancel_`(개설자 등록비 반환) · `campaignReport_`. 모르는 앞머리는 null +/// (종류 이름 「캠페인 달성」으로 물러난다). +String? campaignNotificationLabel(String id) => switch (id.split('_').first) { + 'campaignRefund' => appL10n.notifKindCampaignRefund, + 'campaignCancel' => appL10n.notifKindCampaignCancel, + 'campaignReport' => appL10n.notifKindCampaignReport, + _ => null, +}; + /// 날짜 머리글. 명세 — *오늘 및 어제를 제외한 과거는 yyyy.mm.dd 로 표시*. String notificationDayLabel(DateTime at, {DateTime? now}) { final today = _dateOnly(now ?? DateTime.now()); diff --git a/app/lib/features/quest/quest_data.dart b/app/lib/features/quest/quest_data.dart index 2709ddd..aeebab2 100644 --- a/app/lib/features/quest/quest_data.dart +++ b/app/lib/features/quest/quest_data.dart @@ -740,7 +740,7 @@ abstract interface class QuestRepository { Future create(QuestDraft draft); - /// 보유 일반 POP(`wallet/main.activityBalance`) — 생성 · 보상 뒤 목록 헤더를 다시 맞춘다. + /// 총 보유 POP(`wallet/main` 일반 + 기여 + 보류, HOME 헤더와 같은 값) — 생성 · 보상 뒤 목록 헤더를 다시 맞춘다. /// 모르면 null(헤더는 받은 값을 유지한다). Future popBalance(); diff --git a/app/lib/features/quest/quest_repository_firestore.dart b/app/lib/features/quest/quest_repository_firestore.dart index 5c671b6..3383e8b 100644 --- a/app/lib/features/quest/quest_repository_firestore.dart +++ b/app/lib/features/quest/quest_repository_firestore.dart @@ -649,7 +649,7 @@ class FirestoreQuestRepository implements QuestRepository { @override Future popBalance() async { final wallet = await _backend.db.doc('users/${_backend.requireUid}/wallet/main').get(); - return wallet.data()?.intOr('activityBalance'); + return wallet.data()?.walletTotal; } @override diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index 38e88b6..5eb1f6e 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -272,7 +272,7 @@ "campaignView": "View campaign", "growthFinalReached": "You've reached the final stage", "zapRetrySame": "Recheck same contribution", - "heroOwnerSuffix": "'s", + "heroOwner": "{name}'s", "heroStartPrompt": "Create or join a planet\nand start your FANUZU journey!", "heroNebulaPrompt": "Use the POP you earn from activities\nto contribute to the nebula!", "heroRecentContribution": "Growing steadily with\n{pop} POP contributed.", @@ -450,6 +450,9 @@ "notifKindCampaign": "Campaign goal", "notifKindQuest": "Quest complete", "notifKindEvolution": "Planet evolution", + "notifKindCampaignRefund": "Campaign refund", + "notifKindCampaignCancel": "Campaign cancelled", + "notifKindCampaignReport": "Result report", "notifTargetPost": "post", "notifTargetCampaign": "campaign", "notifTargetQuest": "quest details", @@ -827,7 +830,7 @@ "heroNebulaGrowthRate": "Nebula growth {percent}%", "homeIncubator": "Fandom Planet Incubator", "homeGrowTogether": "Grow together", - "homeArtistNews": "Artist News", + "homeArtistNews": "AI Daily Briefing", "growthConditionsTitle": "Growth conditions", "eclipseButtonSoon": "Eclipse in {time}!\nShake your phone to stop it!", "eclipseButtonActive": "The eclipse has started!\nShake your phone within {seconds}s to stop it!", diff --git a/app/lib/l10n/app_es.arb b/app/lib/l10n/app_es.arb index b997918..db12467 100644 --- a/app/lib/l10n/app_es.arb +++ b/app/lib/l10n/app_es.arb @@ -241,7 +241,7 @@ "growthNebulaGoalPassed": "El plazo objetivo ha pasado · Cumple las condiciones y nacerá el planeta", "growthFinalStage": "Etapa final", "growthPromotionPending": "Ascenso pendiente", - "growthCheckConditions": "Ver condiciones de crecimiento", + "growthCheckConditions": "Ver condiciones", "growthConditionChecking": "Comprobando condición de {name}", "growthConditionMet": "Condición de {name} cumplida", "growthConditionUnmet": "Condición de {name} no cumplida", @@ -272,7 +272,7 @@ "campaignView": "Ver campaña", "growthFinalReached": "Has llegado a la etapa final", "zapRetrySame": "Volver a comprobar la contribución", - "heroOwnerSuffix": "aporta:", + "heroOwner": "De {name}", "heroStartPrompt": "¡Crea o únete a un planeta\ny empieza en FANUZU!", "heroNebulaPrompt": "¡Usa el POP que ganas con actividades\npara contribuir a la nebulosa!", "heroRecentContribution": "Creciendo sin parar con\n{pop} POP aportados.", @@ -450,6 +450,9 @@ "notifKindCampaign": "Meta de campaña", "notifKindQuest": "Misión completada", "notifKindEvolution": "Evolución del planeta", + "notifKindCampaignRefund": "Reembolso de campaña", + "notifKindCampaignCancel": "Campaña cancelada", + "notifKindCampaignReport": "Informe de resultados", "notifTargetPost": "la publicación", "notifTargetCampaign": "la campaña", "notifTargetQuest": "el detalle de la misión", @@ -827,7 +830,7 @@ "heroNebulaGrowthRate": "Crecimiento de la nebulosa {percent}%", "homeIncubator": "Incubadora de planetas fandom", "homeGrowTogether": "Crecer juntos", - "homeArtistNews": "Noticias del artista", + "homeArtistNews": "AI Daily Briefing", "growthConditionsTitle": "Condiciones de crecimiento", "eclipseButtonSoon": "¡Eclipse en {time}!\n¡Agita tu móvil para detenerlo!", "eclipseButtonActive": "¡El eclipse ha comenzado!\n¡Agita el teléfono en {seconds} s para detenerlo!", diff --git a/app/lib/l10n/app_ja.arb b/app/lib/l10n/app_ja.arb index d4ddd36..2600198 100644 --- a/app/lib/l10n/app_ja.arb +++ b/app/lib/l10n/app_ja.arb @@ -272,7 +272,7 @@ "campaignView": "キャンペーンを見る", "growthFinalReached": "最終ステージに到達しました", "zapRetrySame": "同じ貢献を再確認", - "heroOwnerSuffix": "さんの", + "heroOwner": "{name} さんの", "heroStartPrompt": "惑星を作成または参加して\nファン宇宙を始めよう!", "heroNebulaPrompt": "活動で獲得したPOPで\n星雲に貢献しよう!", "heroRecentContribution": "{pop} POPの貢献で\n着実に成長しています。", @@ -450,6 +450,9 @@ "notifKindCampaign": "キャンペーン達成", "notifKindQuest": "クエスト完了", "notifKindEvolution": "惑星の進化", + "notifKindCampaignRefund": "キャンペーン返金", + "notifKindCampaignCancel": "キャンペーン中止", + "notifKindCampaignReport": "結果報告", "notifTargetPost": "投稿", "notifTargetCampaign": "キャンペーン", "notifTargetQuest": "クエスト詳細", @@ -827,7 +830,7 @@ "heroNebulaGrowthRate": "星雲成長率 {percent}%", "homeIncubator": "ファンダム惑星インキュベーター", "homeGrowTogether": "一緒に成長する", - "homeArtistNews": "アーティストニュース", + "homeArtistNews": "AI Daily Briefing", "growthConditionsTitle": "成長条件", "eclipseButtonSoon": "{time}後にイクリプスが発生します!\nスマホを振ってイクリプスを防ぎましょう!", "eclipseButtonActive": "イクリプスが発生しました!\n{seconds}秒以内にスマホを振って防ぎましょう!", diff --git a/app/lib/l10n/app_ko.arb b/app/lib/l10n/app_ko.arb index 725dd37..16bc916 100644 --- a/app/lib/l10n/app_ko.arb +++ b/app/lib/l10n/app_ko.arb @@ -633,7 +633,14 @@ "campaignView": "캠페인 보기", "growthFinalReached": "최종 Stage에 도달했어요", "zapRetrySame": "같은 기여 다시 확인", - "heroOwnerSuffix": "님의", + "heroOwner": "{name} 님의", + "@heroOwner": { + "placeholders": { + "name": { + "type": "String" + } + } + }, "heroStartPrompt": "행성을 생성 또는 가입하고\n팬우주를 시작해 보세요!", "heroNebulaPrompt": "활동을 통해 얻은 POP을 통해\n성운에 기여해 보세요!", "heroRecentContribution": "{pop} POP 기여로\n꾸준하게 성장하고 있어요.", @@ -898,6 +905,9 @@ "notifKindCampaign": "캠페인 달성", "notifKindQuest": "퀘스트 완료", "notifKindEvolution": "행성 진화", + "notifKindCampaignRefund": "캠페인 환불", + "notifKindCampaignCancel": "캠페인 취소", + "notifKindCampaignReport": "결과 보고", "notifTargetPost": "게시물", "notifTargetCampaign": "캠페인", "notifTargetQuest": "퀘스트 상세", @@ -1698,7 +1708,7 @@ }, "homeIncubator": "팬덤행성 인큐베이터", "homeGrowTogether": "함께 성장하기", - "homeArtistNews": "아티스트 소식", + "homeArtistNews": "AI Daily Briefing", "growthConditionsTitle": "성장 조건", "eclipseButtonSoon": "{time} 후 이클립스가 발생해요!\n휴대폰을 흔들어 이클립스를 막으세요!", "@eclipseButtonSoon": { diff --git a/app/lib/l10n/app_localizations.dart b/app/lib/l10n/app_localizations.dart index fb2ec8d..e980b65 100644 --- a/app/lib/l10n/app_localizations.dart +++ b/app/lib/l10n/app_localizations.dart @@ -65,7 +65,8 @@ import 'app_localizations_zh.dart'; /// be consistent with the languages listed in the AppLocalizations.supportedLocales /// property. abstract class AppLocalizations { - AppLocalizations(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString()); + AppLocalizations(String locale) + : localeName = intl.Intl.canonicalizedLocale(locale.toString()); final String localeName; @@ -73,7 +74,8 @@ abstract class AppLocalizations { return Localizations.of(context, AppLocalizations); } - static const LocalizationsDelegate delegate = _AppLocalizationsDelegate(); + static const LocalizationsDelegate delegate = + _AppLocalizationsDelegate(); /// A list of this localizations delegate along with the default localizations /// delegates. @@ -85,12 +87,13 @@ abstract class AppLocalizations { /// Additional delegates can be added by appending to this list in /// MaterialApp. This list does not have to be used at all if a custom list /// of delegates is preferred or required. - static const List> localizationsDelegates = >[ - delegate, - GlobalMaterialLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ]; + static const List> localizationsDelegates = + >[ + delegate, + GlobalMaterialLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ]; /// A list of this localizations delegate's supported locales. static const List supportedLocales = [ @@ -98,7 +101,7 @@ abstract class AppLocalizations { Locale('es'), Locale('ja'), Locale('ko'), - Locale('zh') + Locale('zh'), ]; /// No description provided for @commonConfirm. @@ -1733,11 +1736,11 @@ abstract class AppLocalizations { /// **'같은 기여 다시 확인'** String get zapRetrySame; - /// No description provided for @heroOwnerSuffix. + /// No description provided for @heroOwner. /// /// In ko, this message translates to: - /// **'님의'** - String get heroOwnerSuffix; + /// **'{name} 님의'** + String heroOwner(String name); /// No description provided for @heroStartPrompt. /// @@ -2801,6 +2804,24 @@ abstract class AppLocalizations { /// **'행성 진화'** String get notifKindEvolution; + /// No description provided for @notifKindCampaignRefund. + /// + /// In ko, this message translates to: + /// **'캠페인 환불'** + String get notifKindCampaignRefund; + + /// No description provided for @notifKindCampaignCancel. + /// + /// In ko, this message translates to: + /// **'캠페인 취소'** + String get notifKindCampaignCancel; + + /// No description provided for @notifKindCampaignReport. + /// + /// In ko, this message translates to: + /// **'결과 보고'** + String get notifKindCampaignReport; + /// No description provided for @notifTargetPost. /// /// In ko, this message translates to: @@ -4353,7 +4374,12 @@ abstract class AppLocalizations { /// /// In ko, this message translates to: /// **'{startMonth}월 {startDay}일 ~ {endMonth}월 {endDay}일'** - String campaignPeriodRange(String startMonth, String startDay, String endMonth, String endDay); + String campaignPeriodRange( + String startMonth, + String startDay, + String endMonth, + String endDay, + ); /// No description provided for @campaignPeriodSelect. /// @@ -4815,7 +4841,14 @@ abstract class AppLocalizations { /// /// In ko, this message translates to: /// **'{title}\n보상 {reward} POP × {count}명 = {pool} POP\n수수료 {fee} POP (공개 시 소멸)\n총 {total} POP 이 차감됩니다.'** - String questCreateCost(String title, String reward, String count, String pool, String fee, String total); + String questCreateCost( + String title, + String reward, + String count, + String pool, + String fee, + String total, + ); /// No description provided for @questNoReward. /// @@ -5066,7 +5099,7 @@ abstract class AppLocalizations { /// No description provided for @homeArtistNews. /// /// In ko, this message translates to: - /// **'아티스트 소식'** + /// **'AI Daily Briefing'** String get homeArtistNews; /// No description provided for @growthConditionsTitle. @@ -5538,7 +5571,8 @@ abstract class AppLocalizations { String questReflected(String fandom); } -class _AppLocalizationsDelegate extends LocalizationsDelegate { +class _AppLocalizationsDelegate + extends LocalizationsDelegate { const _AppLocalizationsDelegate(); @override @@ -5547,28 +5581,32 @@ class _AppLocalizationsDelegate extends LocalizationsDelegate } @override - bool isSupported(Locale locale) => ['en', 'es', 'ja', 'ko', 'zh'].contains(locale.languageCode); + bool isSupported(Locale locale) => + ['en', 'es', 'ja', 'ko', 'zh'].contains(locale.languageCode); @override bool shouldReload(_AppLocalizationsDelegate old) => false; } AppLocalizations lookupAppLocalizations(Locale locale) { - - // Lookup logic when only language code is specified. switch (locale.languageCode) { - case 'en': return AppLocalizationsEn(); - case 'es': return AppLocalizationsEs(); - case 'ja': return AppLocalizationsJa(); - case 'ko': return AppLocalizationsKo(); - case 'zh': return AppLocalizationsZh(); + case 'en': + return AppLocalizationsEn(); + case 'es': + return AppLocalizationsEs(); + case 'ja': + return AppLocalizationsJa(); + case 'ko': + return AppLocalizationsKo(); + case 'zh': + return AppLocalizationsZh(); } throw FlutterError( 'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely ' 'an issue with the localizations generation tool. Please file an issue ' 'on GitHub with a reproducible sample app and the gen-l10n configuration ' - 'that was used.' + 'that was used.', ); } diff --git a/app/lib/l10n/app_localizations_en.dart b/app/lib/l10n/app_localizations_en.dart index e8b081c..54f35a5 100644 --- a/app/lib/l10n/app_localizations_en.dart +++ b/app/lib/l10n/app_localizations_en.dart @@ -63,31 +63,25 @@ class AppLocalizationsEn extends AppLocalizations { @override String authProviderLogin(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'apple': 'Log in with Apple', - 'google': 'Log in with Google', - 'kakao': 'Log in with Kakao', - 'line': 'Log in with LINE', - 'other': 'Log in with email', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'apple': 'Log in with Apple', + 'google': 'Log in with Google', + 'kakao': 'Log in with Kakao', + 'line': 'Log in with LINE', + 'other': 'Log in with email', + }); return '$_temp0'; } @override String authProviderSignup(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'apple': 'Sign up with Apple', - 'google': 'Sign up with Google', - 'kakao': 'Sign up with Kakao', - 'line': 'Sign up with LINE', - 'other': 'Sign up with email', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'apple': 'Sign up with Apple', + 'google': 'Sign up with Google', + 'kakao': 'Sign up with Kakao', + 'line': 'Sign up with LINE', + 'other': 'Sign up with email', + }); return '$_temp0'; } @@ -107,7 +101,8 @@ class AppLocalizationsEn extends AppLocalizations { } @override - String get authResetNeedEmail => 'Enter the email address for the reset link first.'; + String get authResetNeedEmail => + 'Enter the email address for the reset link first.'; @override String get authResetSent => 'We sent reset instructions to that address.'; @@ -128,13 +123,15 @@ class AppLocalizationsEn extends AppLocalizations { String get termsAge => 'I am 14 or older. (required)'; @override - String get termsMarketing => 'Receive marketing and event notifications (optional)'; + String get termsMarketing => + 'Receive marketing and event notifications (optional)'; @override String get signupDoneTitle => 'You\'re all signed up'; @override - String get signupDoneBody => 'You can start your fandom activities.\nGrow your fandom planet through all kinds of activities.'; + String get signupDoneBody => + 'You can start your fandom activities.\nGrow your fandom planet through all kinds of activities.'; @override String get homeItemsTooltip => 'Items'; @@ -258,7 +255,8 @@ class AppLocalizationsEn extends AppLocalizations { String get settingsWithdrawConfirm => 'Do you want to delete your account?'; @override - String get settingsWithdrawBody => 'Your POP will be lost and this cannot be undone.'; + String get settingsWithdrawBody => + 'Your POP will be lost and this cannot be undone.'; @override String get settingsWithdrawLater => 'Account deletion is coming soon.'; @@ -267,13 +265,15 @@ class AppLocalizationsEn extends AppLocalizations { String get settingsUnlinkConfirm => 'Unlink this account?'; @override - String get settingsUnlinkBody => 'Only this social login method is removed. Your account data is not deleted.'; + String get settingsUnlinkBody => + 'Only this social login method is removed. Your account data is not deleted.'; @override String get settingsUnlink => 'Unlink'; @override - String get settingsSameEmailOnly => 'Only social accounts with the same\nemail as your account can be linked.'; + String get settingsSameEmailOnly => + 'Only social accounts with the same\nemail as your account can be linked.'; @override String settingsLinkNotReady(String name) { @@ -290,10 +290,12 @@ class AppLocalizationsEn extends AppLocalizations { String get settingsEmailProvider => 'Email'; @override - String get pushDeviceOff => 'Push notifications are turned off on this device.'; + String get pushDeviceOff => + 'Push notifications are turned off on this device.'; @override - String get pushDeviceOffHint => 'Allow notifications in system settings to receive them.'; + String get pushDeviceOffHint => + 'Allow notifications in system settings to receive them.'; @override String get pushRequesting => 'Requesting…'; @@ -305,7 +307,8 @@ class AppLocalizationsEn extends AppLocalizations { String get pushOpeningDeviceSettings => 'Opening device settings.'; @override - String get pushEnableInDevice => 'Turn on FANUZU notifications in device settings to receive them.'; + String get pushEnableInDevice => + 'Turn on FANUZU notifications in device settings to receive them.'; @override String get pushDeviceSection => 'Device notifications'; @@ -343,7 +346,8 @@ class AppLocalizationsEn extends AppLocalizations { String get linkLinked => 'Linked'; @override - String get linkSameEmailOnly => 'Only social accounts with the same email as your account can be linked.'; + String get linkSameEmailOnly => + 'Only social accounts with the same email as your account can be linked.'; @override String get linkUnlink => 'Unlink'; @@ -384,10 +388,12 @@ class AppLocalizationsEn extends AppLocalizations { String get translationInvalid => 'Invalid'; @override - String get translationSelfMarkBlocked => 'You can\'t mark your own translation.'; + String get translationSelfMarkBlocked => + 'You can\'t mark your own translation.'; @override - String get translationSubmitted => 'Translation posted. If it passes review, POP is paid after 24 hours.'; + String get translationSubmitted => + 'Translation posted. If it passes review, POP is paid after 24 hours.'; @override String get translationMarked => 'Marked.'; @@ -396,13 +402,16 @@ class AppLocalizationsEn extends AppLocalizations { String get translationAlreadyMarked => 'You already marked this translation.'; @override - String get translationDuplicate => 'You already posted a translation in this language.'; + String get translationDuplicate => + 'You already posted a translation in this language.'; @override - String get translationFailed => 'Something went wrong. Please try again shortly.'; + String get translationFailed => + 'Something went wrong. Please try again shortly.'; @override - String get translationNotEligible => 'Only members of this fandom whose account is at least 24 hours old can mark.'; + String get translationNotEligible => + 'Only members of this fandom whose account is at least 24 hours old can mark.'; @override String get translationDailyCap => 'You can\'t post more translations today.'; @@ -417,13 +426,15 @@ class AppLocalizationsEn extends AppLocalizations { String get commonFan => 'Fan'; @override - String get adLoadFailed => 'Couldn\'t load the ad. You\'ll get the basic reward only.'; + String get adLoadFailed => + 'Couldn\'t load the ad. You\'ll get the basic reward only.'; @override String get storeNotReady => 'Store items coming soon'; @override - String get storePending => 'Waiting for payment approval. It will apply automatically once approved.'; + String get storePending => + 'Waiting for payment approval. It will apply automatically once approved.'; @override String get storeFailed => 'Couldn\'t complete the payment.'; @@ -455,7 +466,8 @@ class AppLocalizationsEn extends AppLocalizations { } @override - String get stageNames => 'Nebula,Start,Growth,Together,Journey,Light,Eternity'; + String get stageNames => + 'Nebula,Start,Growth,Together,Journey,Light,Eternity'; @override String get planetStageUnknown => 'Planet · No stage info'; @@ -500,7 +512,8 @@ class AppLocalizationsEn extends AppLocalizations { String get playHeadline => 'Let\'s go meet your fandom!'; @override - String get playBody => 'Create a planet, connect with fandoms, and enjoy fan activities...'; + String get playBody => + 'Create a planet, connect with fandoms, and enjoy fan activities...'; @override String get timeJustNow => 'Just now'; @@ -525,31 +538,25 @@ class AppLocalizationsEn extends AppLocalizations { @override String authProviderStart(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'email': 'Continue with email', - 'kakao': 'Continue with Kakao', - 'line': 'Continue with LINE', - 'apple': 'Continue with Apple', - 'other': 'Continue with Google', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'email': 'Continue with email', + 'kakao': 'Continue with Kakao', + 'line': 'Continue with LINE', + 'apple': 'Continue with Apple', + 'other': 'Continue with Google', + }); return '$_temp0'; } @override String authProviderName(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'email': 'Email', - 'kakao': 'Kakao', - 'line': 'LINE', - 'apple': 'Apple', - 'other': 'Google', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'email': 'Email', + 'kakao': 'Kakao', + 'line': 'LINE', + 'apple': 'Apple', + 'other': 'Google', + }); return '$_temp0'; } @@ -560,7 +567,8 @@ class AppLocalizationsEn extends AppLocalizations { String get authLoginRequired => 'Please sign in.'; @override - String get authDifferentEmail => 'This account doesn\'t match your sign-up email.'; + String get authDifferentEmail => + 'This account doesn\'t match your sign-up email.'; @override String get authLinkFailed => 'Couldn\'t link the account.'; @@ -578,13 +586,15 @@ class AppLocalizationsEn extends AppLocalizations { String get authSocialFailed => 'Social sign-in failed.'; @override - String get authAppleUnavailable => 'Sign in with Apple isn\'t available on this device.'; + String get authAppleUnavailable => + 'Sign in with Apple isn\'t available on this device.'; @override String get authEmailInUse => 'This email is already registered.'; @override - String get authWeakPassword => 'Password is too short. Use at least 8 characters.'; + String get authWeakPassword => + 'Password is too short. Use at least 8 characters.'; @override String get authInvalidEmail => 'Invalid email format.'; @@ -593,13 +603,15 @@ class AppLocalizationsEn extends AppLocalizations { String get commonTryLater => 'Please try again later.'; @override - String get authCredentialInUse => 'This social account is already linked to another FANUZU account.'; + String get authCredentialInUse => + 'This social account is already linked to another FANUZU account.'; @override String get authAlreadyLinked => 'This account is already linked.'; @override - String get authMethodUnavailable => 'This sign-in method isn\'t available yet.'; + String get authMethodUnavailable => + 'This sign-in method isn\'t available yet.'; @override String get authRecentLogin => 'For security, please sign in again and retry.'; @@ -613,10 +625,12 @@ class AppLocalizationsEn extends AppLocalizations { String get authThisAccount => 'This'; @override - String get eclipseCapped => 'You reached the participation cap, so some shakes weren\'t counted.'; + String get eclipseCapped => + 'You reached the participation cap, so some shakes weren\'t counted.'; @override - String get eclipseResultUnknown => 'Couldn\'t confirm your participation. Please check again with the same request.'; + String get eclipseResultUnknown => + 'Couldn\'t confirm your participation. Please check again with the same request.'; @override String get eclipseChecking => 'Checking participation'; @@ -625,10 +639,12 @@ class AppLocalizationsEn extends AppLocalizations { String get eclipseRetrySame => 'Recheck same participation'; @override - String get eclipseEnded => 'The eclipse has already ended or was successfully defended.'; + String get eclipseEnded => + 'The eclipse has already ended or was successfully defended.'; @override - String get eclipseTooFast => 'You\'re participating too fast. Please try again shortly.'; + String get eclipseTooFast => + 'You\'re participating too fast. Please try again shortly.'; @override String get eclipseNone => 'No eclipse in progress'; @@ -649,13 +665,15 @@ class AppLocalizationsEn extends AppLocalizations { String get eclipseCancelTitle => 'Eclipse cancelled'; @override - String get eclipseCancelBody => 'Cancelled due to a tally error. No FPI was deducted.'; + String get eclipseCancelBody => + 'Cancelled due to a tally error. No FPI was deducted.'; @override String get eclipsePendingTitle => 'Checking defense result'; @override - String get eclipsePendingBody => 'Participation time is over. Waiting for the server\'s decision.'; + String get eclipsePendingBody => + 'Participation time is over. Waiting for the server\'s decision.'; @override String get eclipseShakeTimed => 's — shake your phone\nto stop the eclipse!'; @@ -738,7 +756,8 @@ class AppLocalizationsEn extends AppLocalizations { } @override - String get galaxySetPrimaryConfirm => 'Set the selected planet as your main planet?'; + String get galaxySetPrimaryConfirm => + 'Set the selected planet as your main planet?'; @override String get galaxyLoadFailed => 'Couldn\'t load the galaxy'; @@ -821,10 +840,12 @@ class AppLocalizationsEn extends AppLocalizations { String get zapFailNoPop => 'Not enough POP to contribute.'; @override - String get zapFailLedger => 'Contribution stopped: balance and earnings history don\'t match.'; + String get zapFailLedger => + 'Contribution stopped: balance and earnings history don\'t match.'; @override - String get zapFailRetry => 'Check your connection and recheck the same contribution.'; + String get zapFailRetry => + 'Check your connection and recheck the same contribution.'; @override String get zapDone => 'Contributed'; @@ -843,7 +864,8 @@ class AppLocalizationsEn extends AppLocalizations { } @override - String get growthNebulaGoalPassed => 'The goal period has passed · Meet the conditions and the planet will be born'; + String get growthNebulaGoalPassed => + 'The goal period has passed · Meet the conditions and the planet will be born'; @override String get growthFinalStage => 'Final stage'; @@ -881,7 +903,8 @@ class AppLocalizationsEn extends AppLocalizations { String get nebulaNameTaken => 'This name is already taken.'; @override - String get nebulaNameInvalid => 'Use 2–20 letters, numbers or spaces (no symbols, emoji, or double/leading/trailing spaces).'; + String get nebulaNameInvalid => + 'Use 2–20 letters, numbers or spaces (no symbols, emoji, or double/leading/trailing spaces).'; @override String get nebulaNameHint => 'Fandom name'; @@ -921,7 +944,8 @@ class AppLocalizationsEn extends AppLocalizations { String get commonNext => 'Next'; @override - String get planetCreateFailed => 'Couldn\'t create the planet. Please try again later.'; + String get planetCreateFailed => + 'Couldn\'t create the planet. Please try again later.'; @override String get planetCreateConfirm => 'Create a planet\nwith these options?'; @@ -959,13 +983,17 @@ class AppLocalizationsEn extends AppLocalizations { String get zapRetrySame => 'Recheck same contribution'; @override - String get heroOwnerSuffix => '\'s'; + String heroOwner(String name) { + return '$name\'s'; + } @override - String get heroStartPrompt => 'Create or join a planet\nand start your FANUZU journey!'; + String get heroStartPrompt => + 'Create or join a planet\nand start your FANUZU journey!'; @override - String get heroNebulaPrompt => 'Use the POP you earn from activities\nto contribute to the nebula!'; + String get heroNebulaPrompt => + 'Use the POP you earn from activities\nto contribute to the nebula!'; @override String heroRecentContribution(String pop) { @@ -1195,19 +1223,24 @@ class AppLocalizationsEn extends AppLocalizations { String get payStateRefundRejected => 'Refund rejected'; @override - String get pushTopicEssentialDesc => 'Account, payment, and maintenance notices. These can\'t be turned off.'; + String get pushTopicEssentialDesc => + 'Account, payment, and maintenance notices. These can\'t be turned off.'; @override - String get pushTopicFandomEventDesc => 'Eclipse, campaign, quest, and Artist Hot Time news.'; + String get pushTopicFandomEventDesc => + 'Eclipse, campaign, quest, and Artist Hot Time news.'; @override - String get pushTopicBriefingDesc => 'Daily briefing cards summarizing your planet\'s day.'; + String get pushTopicBriefingDesc => + 'Daily briefing cards summarizing your planet\'s day.'; @override - String get pushTopicCommunityDesc => 'Comments, likes, and answers on your posts.'; + String get pushTopicCommunityDesc => + 'Comments, likes, and answers on your posts.'; @override - String get pushTopicMarketingDesc => 'Get event and benefit info. Only on if you agree.'; + String get pushTopicMarketingDesc => + 'Get event and benefit info. Only on if you agree.'; @override String get inquiryPending => 'Received'; @@ -1219,13 +1252,16 @@ class AppLocalizationsEn extends AppLocalizations { String get inquiryAnswered => 'Answered'; @override - String get photoBadType => 'Only JPG, PNG, WEBP, or GIF images can be uploaded.'; + String get photoBadType => + 'Only JPG, PNG, WEBP, or GIF images can be uploaded.'; @override - String get photoTooBig => 'The photo is over 10MB. Please choose a smaller one.'; + String get photoTooBig => + 'The photo is over 10MB. Please choose a smaller one.'; @override - String get photoUnreadable => 'Couldn\'t read the photo. Please choose again.'; + String get photoUnreadable => + 'Couldn\'t read the photo. Please choose again.'; @override String get myListInside => 'My INSIDE'; @@ -1270,10 +1306,12 @@ class AppLocalizationsEn extends AppLocalizations { String get inquiryFallback => 'Inquiry'; @override - String get photoRejectedServer => 'Couldn\'t upload the photo. Check its format and size.'; + String get photoRejectedServer => + 'Couldn\'t upload the photo. Check its format and size.'; @override - String get photoUploadFailed => 'Photo upload failed. Please try again later.'; + String get photoUploadFailed => + 'Photo upload failed. Please try again later.'; @override String focusClaimed(String pop) { @@ -1295,7 +1333,8 @@ class AppLocalizationsEn extends AppLocalizations { String get focusClaimToday => 'Claim today\'s reward'; @override - String get storeConnectFailed => 'Couldn\'t connect to the store. Please try again later.'; + String get storeConnectFailed => + 'Couldn\'t connect to the store. Please try again later.'; @override String get payRestore => 'Restore purchases'; @@ -1304,7 +1343,8 @@ class AppLocalizationsEn extends AppLocalizations { String get payEmpty => 'No payment history.'; @override - String get payRefundGuide => 'Consumables: refundable within 7 days of purchase if unused. Items that have been partly used are not refundable.\nSubscriptions: refundable within 24 hours of payment if no benefits (e.g., bonus rewards) were used.\nRefunds are completed within 7–14 days after approval.'; + String get payRefundGuide => + 'Consumables: refundable within 7 days of purchase if unused. Items that have been partly used are not refundable.\nSubscriptions: refundable within 24 hours of payment if no benefits (e.g., bonus rewards) were used.\nRefunds are completed within 7–14 days after approval.'; @override String get payDetailTitle => 'Payment details'; @@ -1376,7 +1416,8 @@ class AppLocalizationsEn extends AppLocalizations { String get nicknameEdit => 'Edit nickname'; @override - String get nicknameReserved => 'You can\'t use a name that could be mistaken for staff.'; + String get nicknameReserved => + 'You can\'t use a name that could be mistaken for staff.'; @override String get nicknameTaken => 'This nickname is already in use.'; @@ -1448,7 +1489,8 @@ class AppLocalizationsEn extends AppLocalizations { String get inquiryBodyHint => 'Describe your inquiry.'; @override - String get inquiryBodyHelper => 'Writing 10+ characters helps us assist you faster.'; + String get inquiryBodyHelper => + 'Writing 10+ characters helps us assist you faster.'; @override String inquirySubmitFailed(String reason) { @@ -1490,7 +1532,8 @@ class AppLocalizationsEn extends AppLocalizations { String get tierPromptSuffix => '\nby contributing to planets and nebulae'; @override - String get tierPassportNote => 'Passport Tier is a card appearance grade separate from your level, and it never goes down.'; + String get tierPassportNote => + 'Passport Tier is a card appearance grade separate from your level, and it never goes down.'; @override String get tierTotalContribution => 'Total contribution'; @@ -1516,6 +1559,15 @@ class AppLocalizationsEn extends AppLocalizations { @override String get notifKindEvolution => 'Planet evolution'; + @override + String get notifKindCampaignRefund => 'Campaign refund'; + + @override + String get notifKindCampaignCancel => 'Campaign cancelled'; + + @override + String get notifKindCampaignReport => 'Result report'; + @override String get notifTargetPost => 'post'; @@ -1561,13 +1613,15 @@ class AppLocalizationsEn extends AppLocalizations { String get stationSuggest => 'Suggest a shop'; @override - String get stationEmpty => 'No links yet.\nJoin a planet to see curated links.'; + String get stationEmpty => + 'No links yet.\nJoin a planet to see curated links.'; @override String get stationCategoryEmpty => 'No links in this category yet.'; @override - String get stationSuggestLater => 'Suggestions open once the server is connected.'; + String get stationSuggestLater => + 'Suggestions open once the server is connected.'; @override String get commonSubmit => 'Submit'; @@ -1594,25 +1648,30 @@ class AppLocalizationsEn extends AppLocalizations { String get stationReason => 'Why you recommend it (optional)'; @override - String get stationSuggestNote => 'Suggested links are added after review. We\'ll notify you of the result.'; + String get stationSuggestNote => + 'Suggested links are added after review. We\'ll notify you of the result.'; @override String get heroGiftUnavailable => 'This gift can\'t be claimed right now.'; @override - String get heroGiftAlready => 'You\'ve already joined this gift. Check your POP history.'; + String get heroGiftAlready => + 'You\'ve already joined this gift. Check your POP history.'; @override String get heroGiftRelogin => 'Please sign in again to join.'; @override - String get heroGiftNoPermission => 'You don\'t have permission to join this gift.'; + String get heroGiftNoPermission => + 'You don\'t have permission to join this gift.'; @override - String get heroGiftHowTo => 'Shake your phone or tap the button below to join the light energy gift.'; + String get heroGiftHowTo => + 'Shake your phone or tap the button below to join the light energy gift.'; @override - String get heroGiftPopNote => 'POP you can receive depends on the remaining gift and the per-person cap.'; + String get heroGiftPopNote => + 'POP you can receive depends on the remaining gift and the per-person cap.'; @override String heroGiftReceived(String total) { @@ -1620,7 +1679,8 @@ class AppLocalizationsEn extends AppLocalizations { } @override - String get heroGiftUnknown => 'Couldn\'t confirm the payout. Please check again.'; + String get heroGiftUnknown => + 'Couldn\'t confirm the payout. Please check again.'; @override String get heroGiftNone => 'No gifts to join right now.'; @@ -1707,13 +1767,15 @@ class AppLocalizationsEn extends AppLocalizations { String get reportReasonLabel => 'Reason'; @override - String get reportConfirm => 'Report this post?\nThis can\'t be undone once submitted.'; + String get reportConfirm => + 'Report this post?\nThis can\'t be undone once submitted.'; @override String get blockMemberConfirm => 'Block all posts from this member?'; @override - String get loungeMembersOnly => 'Only members of this planet\'s fandom can post, comment, or like.'; + String get loungeMembersOnly => + 'Only members of this planet\'s fandom can post, comment, or like.'; @override String get loungeFailed => 'Couldn\'t complete that. Please try again later.'; @@ -1843,34 +1905,31 @@ class AppLocalizationsEn extends AppLocalizations { @override String countryName(String code) { - String _temp0 = intl.Intl.selectLogic( - code, - { - 'KR': 'South Korea', - 'JP': 'Japan', - 'US': 'United States', - 'CN': 'China', - 'TW': 'Taiwan', - 'HK': 'Hong Kong', - 'TH': 'Thailand', - 'VN': 'Vietnam', - 'ID': 'Indonesia', - 'PH': 'Philippines', - 'MY': 'Malaysia', - 'SG': 'Singapore', - 'IN': 'India', - 'GB': 'United Kingdom', - 'FR': 'France', - 'DE': 'Germany', - 'ES': 'Spain', - 'BR': 'Brazil', - 'MX': 'Mexico', - 'CA': 'Canada', - 'AU': 'Australia', - 'ZZ': 'Unspecified', - 'other': '-', - }, - ); + String _temp0 = intl.Intl.selectLogic(code, { + 'KR': 'South Korea', + 'JP': 'Japan', + 'US': 'United States', + 'CN': 'China', + 'TW': 'Taiwan', + 'HK': 'Hong Kong', + 'TH': 'Thailand', + 'VN': 'Vietnam', + 'ID': 'Indonesia', + 'PH': 'Philippines', + 'MY': 'Malaysia', + 'SG': 'Singapore', + 'IN': 'India', + 'GB': 'United Kingdom', + 'FR': 'France', + 'DE': 'Germany', + 'ES': 'Spain', + 'BR': 'Brazil', + 'MX': 'Mexico', + 'CA': 'Canada', + 'AU': 'Australia', + 'ZZ': 'Unspecified', + 'other': '-', + }); return '$_temp0'; } @@ -2001,7 +2060,8 @@ class AppLocalizationsEn extends AppLocalizations { String get questResume => 'Resume'; @override - String get questShakeRestart => 'The quest settings changed, so you will start from the beginning.'; + String get questShakeRestart => + 'The quest settings changed, so you will start from the beginning.'; @override String get questPaused => 'Paused'; @@ -2019,7 +2079,8 @@ class AppLocalizationsEn extends AppLocalizations { String get questTypeStreaming => 'Streaming'; @override - String get questTypeUnverifiable => 'This quest isn\'t open for participation yet.'; + String get questTypeUnverifiable => + 'This quest isn\'t open for participation yet.'; @override String get questTabMine => 'My quests'; @@ -2066,10 +2127,12 @@ class AppLocalizationsEn extends AppLocalizations { } @override - String get adWarpBefore => 'Warping... Finding the right ad so you can contribute more to your fandom and artist.'; + String get adWarpBefore => + 'Warping... Finding the right ad so you can contribute more to your fandom and artist.'; @override - String get adWarpAfter => 'Warping... Preparing the reward for your contribution.'; + String get adWarpAfter => + 'Warping... Preparing the reward for your contribution.'; @override String get adSkip => 'Skip'; @@ -2133,10 +2196,12 @@ class AppLocalizationsEn extends AppLocalizations { String get questTabEmpty => 'No quests in this tab yet.'; @override - String get questCreateNotReady => 'Quest creation opens together with reward funding. Coming soon.'; + String get questCreateNotReady => + 'Quest creation opens together with reward funding. Coming soon.'; @override - String get questNoBaseReward => 'Couldn\'t find the basic reward record, so the ad bonus isn\'t available.'; + String get questNoBaseReward => + 'Couldn\'t find the basic reward record, so the ad bonus isn\'t available.'; @override String get questNoSteps => 'No steps recorded yet. Walk a bit and try again.'; @@ -2171,28 +2236,35 @@ class AppLocalizationsEn extends AppLocalizations { String get questStop => 'Stop'; @override - String get adNotFinished => 'You didn\'t finish the ad, so there\'s no bonus. You still get the basic reward.'; + String get adNotFinished => + 'You didn\'t finish the ad, so there\'s no bonus. You still get the basic reward.'; @override - String get adNotVerified => 'We couldn\'t confirm the ad view, so there\'s no bonus. You still get the basic reward.'; + String get adNotVerified => + 'We couldn\'t confirm the ad view, so there\'s no bonus. You still get the basic reward.'; @override String get openSettings => 'Open settings'; @override - String get permStepsDenied => 'Step permission is off. Allow \"Physical activity\" in Settings.'; + String get permStepsDenied => + 'Step permission is off. Allow \"Physical activity\" in Settings.'; @override - String get permStepsNeeded => 'Physical activity permission is needed to count steps.'; + String get permStepsNeeded => + 'Physical activity permission is needed to count steps.'; @override - String get permLocationOff => 'Location services are off. Turn them on and try again.'; + String get permLocationOff => + 'Location services are off. Turn them on and try again.'; @override - String get permLocationNeeded => 'Location permission is needed to verify your visit.'; + String get permLocationNeeded => + 'Location permission is needed to verify your visit.'; @override - String get permLocationDenied => 'Location permission is off. Allow location access in Settings.'; + String get permLocationDenied => + 'Location permission is off. Allow location access in Settings.'; @override String get questRewardReceived => ' received!'; @@ -2213,13 +2285,15 @@ class AppLocalizationsEn extends AppLocalizations { } @override - String get nebulaCreateFailed => 'Couldn\'t create the nebula. Please try again later.'; + String get nebulaCreateFailed => + 'Couldn\'t create the nebula. Please try again later.'; @override String get nebulaAlreadyToday => 'You\'ve already created a nebula today.'; @override - String get nebulaCreatedKeepPrimary => 'Nebula created. Your main planet stays the same because it can only be changed 30 days after the last change.'; + String get nebulaCreatedKeepPrimary => + 'Nebula created. Your main planet stays the same because it can only be changed 30 days after the last change.'; @override String get planetLeave => 'Leave'; @@ -2228,7 +2302,8 @@ class AppLocalizationsEn extends AppLocalizations { String get planetLeaveConfirmTitle => 'Leave this planet?'; @override - String get planetLeaveConfirmBody => 'Contributed POP and activity\ncannot be undone.'; + String get planetLeaveConfirmBody => + 'Contributed POP and activity\ncannot be undone.'; @override String get sortPopular => 'Popular'; @@ -2240,13 +2315,16 @@ class AppLocalizationsEn extends AppLocalizations { String get campaignStatusReview => 'This campaign is under review.'; @override - String get campaignStatusRejected => 'This campaign was rejected in review. Your registration fee has been returned.'; + String get campaignStatusRejected => + 'This campaign was rejected in review. Your registration fee has been returned.'; @override - String get campaignStatusWithdrawn => 'This campaign was withdrawn by its creator.'; + String get campaignStatusWithdrawn => + 'This campaign was withdrawn by its creator.'; @override - String get campaignStatusCancelled => 'This campaign was cancelled for operational reasons. The registration fee and supported POP have been returned.'; + String get campaignStatusCancelled => + 'This campaign was cancelled for operational reasons. The registration fee and supported POP have been returned.'; @override String get rankWindowDaily => 'Daily'; @@ -2329,7 +2407,8 @@ class AppLocalizationsEn extends AppLocalizations { String get campaignContributePop => 'Set POP to contribute'; @override - String get campaignEmptyContributing => 'You haven\'t contributed to any campaigns yet.'; + String get campaignEmptyContributing => + 'You haven\'t contributed to any campaigns yet.'; @override String get campaignEmpty => 'No campaigns yet.'; @@ -2385,7 +2464,12 @@ class AppLocalizationsEn extends AppLocalizations { String get campaignWeekdays => 'S,M,T,W,T,F,S'; @override - String campaignPeriodRange(String startMonth, String startDay, String endMonth, String endDay) { + String campaignPeriodRange( + String startMonth, + String startDay, + String endMonth, + String endDay, + ) { return '$startMonth/$startDay ~ $endMonth/$endDay'; } @@ -2411,7 +2495,8 @@ class AppLocalizationsEn extends AppLocalizations { String get campaignBodyHint => 'Describe your campaign.'; @override - String get campaignReviewNote => 'Once submitted, funding opens after review.'; + String get campaignReviewNote => + 'Once submitted, funding opens after review.'; @override String get campaignSupportType => 'Choose support type'; @@ -2429,7 +2514,12 @@ class AppLocalizationsEn extends AppLocalizations { String get campaignSubmitTitle => 'Submit this campaign?'; @override - String campaignSubmitBody(String title, String goal, String days, String fee) { + String campaignSubmitBody( + String title, + String goal, + String days, + String fee, + ) { return '$title · Goal $goal POP · $days days\nThe $fee POP registration fee will be deducted, and funding opens after review.'; } @@ -2448,16 +2538,20 @@ class AppLocalizationsEn extends AppLocalizations { String get campaignPendingTitle => 'Awaiting review'; @override - String get campaignPendingBody => 'Once review is complete, funding opens and the campaign appears in the list.'; + String get campaignPendingBody => + 'Once review is complete, funding opens and the campaign appears in the list.'; @override - String get insideRefundPending => 'The acceptance deadline has passed. The bounty will be refunded.'; + String get insideRefundPending => + 'The acceptance deadline has passed. The bounty will be refunded.'; @override - String get insideRefundDone => 'The acceptance deadline has passed. The bounty has been refunded.'; + String get insideRefundDone => + 'The acceptance deadline has passed. The bounty has been refunded.'; @override - String get insideRefundChecking => 'The acceptance deadline has passed. We are checking the bounty refund.'; + String get insideRefundChecking => + 'The acceptance deadline has passed. We are checking the bounty refund.'; @override String get insideErrPopShort => 'Not enough POP to set the bounty.'; @@ -2466,10 +2560,12 @@ class AppLocalizationsEn extends AppLocalizations { String get insideErrSelfAccept => 'You can\'t accept your own answer.'; @override - String get insideErrAlreadyAccepted => 'An answer has already been accepted and cannot be changed.'; + String get insideErrAlreadyAccepted => + 'An answer has already been accepted and cannot be changed.'; @override - String get insideErrNotOwner => 'Only the person who asked can accept an answer.'; + String get insideErrNotOwner => + 'Only the person who asked can accept an answer.'; @override String get commonCheckConnection => 'Check your connection and try again.'; @@ -2530,7 +2626,8 @@ class AppLocalizationsEn extends AppLocalizations { } @override - String get insideAttachLater => 'Image attachments open once the server is connected.'; + String get insideAttachLater => + 'Image attachments open once the server is connected.'; @override String get insideBountyRequired => 'Please enter a bounty.'; @@ -2599,7 +2696,8 @@ class AppLocalizationsEn extends AppLocalizations { String get questActivity => 'Activity'; @override - String get questNoCreatable => 'No quest activities are open for creation right now.'; + String get questNoCreatable => + 'No quest activities are open for creation right now.'; @override String get questDescriptionOptional => 'Description (optional)'; @@ -2611,10 +2709,12 @@ class AppLocalizationsEn extends AppLocalizations { String get questLinkCheck => 'Check link'; @override - String get questLinkInvalid => 'This link isn\'t valid. Please check the address.'; + String get questLinkInvalid => + 'This link isn\'t valid. Please check the address.'; @override - String get questLinkPreviewFailed => 'Couldn\'t load the link info. Please enter a title.'; + String get questLinkPreviewFailed => + 'Couldn\'t load the link info. Please enter a title.'; @override String get questLinkTitle => 'Link title'; @@ -2636,7 +2736,14 @@ class AppLocalizationsEn extends AppLocalizations { } @override - String questCreateCost(String title, String reward, String count, String pool, String fee, String total) { + String questCreateCost( + String title, + String reward, + String count, + String pool, + String fee, + String total, + ) { return '$title\nReward $reward POP × $count = $pool POP\nFee $fee POP (burned on publishing)\n$total POP in total will be deducted.'; } @@ -2644,10 +2751,12 @@ class AppLocalizationsEn extends AppLocalizations { String get questNoReward => 'This quest has no reward.'; @override - String get questStreamJoined => 'Your participation is recorded. This quest has no POP reward.'; + String get questStreamJoined => + 'Your participation is recorded. This quest has no POP reward.'; @override - String get questNoShake => 'No shakes recorded. Tap Start and shake to the beat.'; + String get questNoShake => + 'No shakes recorded. Tap Start and shake to the beat.'; @override String get questDeadline => 'Deadline'; @@ -2687,10 +2796,12 @@ class AppLocalizationsEn extends AppLocalizations { String get questSubmitted => 'Submitted. The reward is paid after review.'; @override - String get questReviewPending => 'Under review. The reward is paid once approved.'; + String get questReviewPending => + 'Under review. The reward is paid once approved.'; @override - String get questReviewDelayed => 'Review is taking longer than usual. Our team is checking.'; + String get questReviewDelayed => + 'Review is taking longer than usual. Our team is checking.'; @override String get questApprovedPaying => 'Approved. Paying your reward.'; @@ -2733,7 +2844,8 @@ class AppLocalizationsEn extends AppLocalizations { String get questEdit => 'Edit title and description'; @override - String get questEditNotice => 'After publishing, only the title and description can be edited, and edits are logged.'; + String get questEditNotice => + 'After publishing, only the title and description can be edited, and edits are logged.'; @override String get popReasonQuestUgc => 'Quest reward'; @@ -2778,7 +2890,7 @@ class AppLocalizationsEn extends AppLocalizations { String get homeGrowTogether => 'Grow together'; @override - String get homeArtistNews => 'Artist News'; + String get homeArtistNews => 'AI Daily Briefing'; @override String get growthConditionsTitle => 'Growth conditions'; @@ -2842,13 +2954,16 @@ class AppLocalizationsEn extends AppLocalizations { String get questCancel => 'Cancel quest'; @override - String get questCancelInReview => 'Cancelling while under review returns the deposited reward POP and the fee in full.'; + String get questCancelInReview => + 'Cancelling while under review returns the deposited reward POP and the fee in full.'; @override - String get questCancelPublished => 'Cancelling a published quest closes it now and returns the unused reward POP. The fee is not refunded.'; + String get questCancelPublished => + 'Cancelling a published quest closes it now and returns the unused reward POP. The fee is not refunded.'; @override - String get questUnderReview => 'Under review. It will be published once approved.'; + String get questUnderReview => + 'Under review. It will be published once approved.'; @override String questModerationRejected(String reason) { @@ -2856,7 +2971,8 @@ class AppLocalizationsEn extends AppLocalizations { } @override - String get questSubmittedForReview => 'Submitted. It will be published after review.'; + String get questSubmittedForReview => + 'Submitted. It will be published after review.'; @override String get popReasonQuestFeeRefund => 'Quest fee refund'; @@ -2868,7 +2984,8 @@ class AppLocalizationsEn extends AppLocalizations { String get eclipseTapToJoin => 'Can\'t shake? Tap to join'; @override - String get termsPrivacy => 'Privacy Policy and Personal Data Collection (required)'; + String get termsPrivacy => + 'Privacy Policy and Personal Data Collection (required)'; @override String get onbSkip => 'Skip'; @@ -2877,19 +2994,22 @@ class AppLocalizationsEn extends AppLocalizations { String get onbIntro1Title => 'Grow your fandom\'s planet'; @override - String get onbIntro1Body => 'Collect POP and send it with ZAP\nto grow your fandom planet together.'; + String get onbIntro1Body => + 'Collect POP and send it with ZAP\nto grow your fandom planet together.'; @override String get onbIntro2Title => 'Cheer with quests'; @override - String get onbIntro2Body => 'Complete walking, attendance and streaming quests\nand earn POP rewards.'; + String get onbIntro2Body => + 'Complete walking, attendance and streaming quests\nand earn POP rewards.'; @override String get onbIntro3Title => 'Protect it with fellow fans'; @override - String get onbIntro3Body => 'Stop the Eclipse together and support\nyour artist through campaigns.'; + String get onbIntro3Body => + 'Stop the Eclipse together and support\nyour artist through campaigns.'; @override String get onbProfileTitle => 'Set up your profile'; @@ -2916,7 +3036,8 @@ class AppLocalizationsEn extends AppLocalizations { String get onbArtistTitle => 'Choose the artists you follow'; @override - String get onbArtistBody => 'The first artist you pick becomes your main planet. You can join several fandoms.'; + String get onbArtistBody => + 'The first artist you pick becomes your main planet. You can join several fandoms.'; @override String get onbArtistSearch => 'Search artist name'; @@ -2948,7 +3069,8 @@ class AppLocalizationsEn extends AppLocalizations { String get onbPermTitle => 'App permissions'; @override - String get onbPermBody => 'These permissions are needed only for the related features. You can use the app without them.'; + String get onbPermBody => + 'These permissions are needed only for the related features. You can use the app without them.'; @override String get onbPermPush => 'Notifications'; @@ -2960,13 +3082,15 @@ class AppLocalizationsEn extends AppLocalizations { String get onbPermHealth => 'Health data (steps)'; @override - String get onbPermHealthDesc => 'Counts steps for walking quests. Requested when you first start one.'; + String get onbPermHealthDesc => + 'Counts steps for walking quests. Requested when you first start one.'; @override String get onbPermLocation => 'Location'; @override - String get onbPermLocationDesc => 'Checks arrival for location quests. Requested when you first start one.'; + String get onbPermLocationDesc => + 'Checks arrival for location quests. Requested when you first start one.'; @override String get onbPermContinue => 'Continue'; @@ -2978,7 +3102,8 @@ class AppLocalizationsEn extends AppLocalizations { String get coachMy => 'Your records are here'; @override - String get settingsWithdrawLinked => 'Please unlink your connected accounts before deleting your account.'; + String get settingsWithdrawLinked => + 'Please unlink your connected accounts before deleting your account.'; @override String get homeWeeklyTitle => 'Our planet this week'; @@ -3019,7 +3144,8 @@ class AppLocalizationsEn extends AppLocalizations { String get questScanQr => 'Scan the on-site QR'; @override - String get questScanQrDenied => 'Can\'t open the camera. Allow camera access in Settings.'; + String get questScanQrDenied => + 'Can\'t open the camera. Allow camera access in Settings.'; @override String get questQrForPlace => 'Verification QR to post on site'; diff --git a/app/lib/l10n/app_localizations_es.dart b/app/lib/l10n/app_localizations_es.dart index 0a9d896..b4fa909 100644 --- a/app/lib/l10n/app_localizations_es.dart +++ b/app/lib/l10n/app_localizations_es.dart @@ -56,38 +56,33 @@ class AppLocalizationsEs extends AppLocalizations { String get authAlreadyMember => '¿Ya tienes una cuenta?'; @override - String get authLoginHeadline => '¡Inicia sesión en FANUZU\nde la forma más fácil!'; + String get authLoginHeadline => + '¡Inicia sesión en FANUZU\nde la forma más fácil!'; @override String get authSignupHeadline => '¡Únete a FANUZU\nde la forma más fácil!'; @override String authProviderLogin(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'apple': 'Iniciar sesión con Apple', - 'google': 'Iniciar sesión con Google', - 'kakao': 'Iniciar sesión con Kakao', - 'line': 'Iniciar sesión con LINE', - 'other': 'Iniciar sesión con correo', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'apple': 'Iniciar sesión con Apple', + 'google': 'Iniciar sesión con Google', + 'kakao': 'Iniciar sesión con Kakao', + 'line': 'Iniciar sesión con LINE', + 'other': 'Iniciar sesión con correo', + }); return '$_temp0'; } @override String authProviderSignup(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'apple': 'Registrarse con Apple', - 'google': 'Registrarse con Google', - 'kakao': 'Registrarse con Kakao', - 'line': 'Registrarse con LINE', - 'other': 'Registrarse con correo', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'apple': 'Registrarse con Apple', + 'google': 'Registrarse con Google', + 'kakao': 'Registrarse con Kakao', + 'line': 'Registrarse con LINE', + 'other': 'Registrarse con correo', + }); return '$_temp0'; } @@ -107,7 +102,8 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get authResetNeedEmail => 'Primero introduce el correo para recibir el enlace.'; + String get authResetNeedEmail => + 'Primero introduce el correo para recibir el enlace.'; @override String get authResetSent => 'Enviamos las instrucciones a esa dirección.'; @@ -122,19 +118,22 @@ class AppLocalizationsEs extends AppLocalizations { String get termsService => 'Términos del servicio (obligatorio)'; @override - String get termsLocation => 'Términos de servicios de ubicación (obligatorio)'; + String get termsLocation => + 'Términos de servicios de ubicación (obligatorio)'; @override String get termsAge => 'Tengo 14 años o más. (obligatorio)'; @override - String get termsMarketing => 'Recibir información de marketing y eventos (opcional)'; + String get termsMarketing => + 'Recibir información de marketing y eventos (opcional)'; @override String get signupDoneTitle => 'Registro completado'; @override - String get signupDoneBody => 'Ya puedes empezar tus actividades de fandom.\nHaz crecer tu planeta con muchas actividades.'; + String get signupDoneBody => + 'Ya puedes empezar tus actividades de fandom.\nHaz crecer tu planeta con muchas actividades.'; @override String get homeItemsTooltip => 'Objetos'; @@ -261,19 +260,22 @@ class AppLocalizationsEs extends AppLocalizations { String get settingsWithdrawBody => 'Perderás tus POP y no se puede deshacer.'; @override - String get settingsWithdrawLater => 'La eliminación de cuenta llegará pronto.'; + String get settingsWithdrawLater => + 'La eliminación de cuenta llegará pronto.'; @override String get settingsUnlinkConfirm => '¿Desvincular esta cuenta?'; @override - String get settingsUnlinkBody => 'Solo se quita este método de inicio social; los datos de tu cuenta no se eliminan.'; + String get settingsUnlinkBody => + 'Solo se quita este método de inicio social; los datos de tu cuenta no se eliminan.'; @override String get settingsUnlink => 'Desvincular'; @override - String get settingsSameEmailOnly => 'Solo se pueden vincular cuentas sociales\ncon el mismo correo.'; + String get settingsSameEmailOnly => + 'Solo se pueden vincular cuentas sociales\ncon el mismo correo.'; @override String settingsLinkNotReady(String name) { @@ -290,10 +292,12 @@ class AppLocalizationsEs extends AppLocalizations { String get settingsEmailProvider => 'Correo'; @override - String get pushDeviceOff => 'Las notificaciones push están desactivadas en este dispositivo.'; + String get pushDeviceOff => + 'Las notificaciones push están desactivadas en este dispositivo.'; @override - String get pushDeviceOffHint => 'Permite las notificaciones en los ajustes del sistema.'; + String get pushDeviceOffHint => + 'Permite las notificaciones en los ajustes del sistema.'; @override String get pushRequesting => 'Solicitando…'; @@ -302,10 +306,12 @@ class AppLocalizationsEs extends AppLocalizations { String get pushGoToSettings => 'Ir a ajustes'; @override - String get pushOpeningDeviceSettings => 'Abriendo los ajustes del dispositivo.'; + String get pushOpeningDeviceSettings => + 'Abriendo los ajustes del dispositivo.'; @override - String get pushEnableInDevice => 'Activa las notificaciones de FANUZU en los ajustes del dispositivo.'; + String get pushEnableInDevice => + 'Activa las notificaciones de FANUZU en los ajustes del dispositivo.'; @override String get pushDeviceSection => 'Notificaciones del dispositivo'; @@ -343,7 +349,8 @@ class AppLocalizationsEs extends AppLocalizations { String get linkLinked => 'Vinculada'; @override - String get linkSameEmailOnly => 'Solo se pueden vincular cuentas sociales con el mismo correo.'; + String get linkSameEmailOnly => + 'Solo se pueden vincular cuentas sociales con el mismo correo.'; @override String get linkUnlink => 'Desvincular'; @@ -384,10 +391,12 @@ class AppLocalizationsEs extends AppLocalizations { String get translationInvalid => 'No válida'; @override - String get translationSelfMarkBlocked => 'No puedes marcar tu propia traducción.'; + String get translationSelfMarkBlocked => + 'No puedes marcar tu propia traducción.'; @override - String get translationSubmitted => 'Traducción publicada. Si se valida, recibirás POP en 24 horas.'; + String get translationSubmitted => + 'Traducción publicada. Si se valida, recibirás POP en 24 horas.'; @override String get translationMarked => 'Marcada.'; @@ -396,16 +405,20 @@ class AppLocalizationsEs extends AppLocalizations { String get translationAlreadyMarked => 'Ya marcaste esta traducción.'; @override - String get translationDuplicate => 'Ya publicaste una traducción en este idioma.'; + String get translationDuplicate => + 'Ya publicaste una traducción en este idioma.'; @override - String get translationFailed => 'No se pudo procesar. Inténtalo de nuevo en un momento.'; + String get translationFailed => + 'No se pudo procesar. Inténtalo de nuevo en un momento.'; @override - String get translationNotEligible => 'Solo los miembros de este fandom con más de 24 horas de antigüedad pueden marcar.'; + String get translationNotEligible => + 'Solo los miembros de este fandom con más de 24 horas de antigüedad pueden marcar.'; @override - String get translationDailyCap => 'Hoy ya no puedes publicar más traducciones.'; + String get translationDailyCap => + 'Hoy ya no puedes publicar más traducciones.'; @override String get translationInvalidTarget => 'Este contenido no se puede traducir.'; @@ -417,13 +430,15 @@ class AppLocalizationsEs extends AppLocalizations { String get commonFan => 'Fan'; @override - String get adLoadFailed => 'No se pudo cargar el anuncio. Solo recibirás la recompensa básica.'; + String get adLoadFailed => + 'No se pudo cargar el anuncio. Solo recibirás la recompensa básica.'; @override String get storeNotReady => 'Productos de la tienda en preparación'; @override - String get storePending => 'Esperando la aprobación del pago. Se aplicará automáticamente al aprobarse.'; + String get storePending => + 'Esperando la aprobación del pago. Se aplicará automáticamente al aprobarse.'; @override String get storeFailed => 'No se pudo completar el pago.'; @@ -455,7 +470,8 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get stageNames => 'Nebulosa,Inicio,Crecimiento,Juntos,Compañía,Luz,Eternidad'; + String get stageNames => + 'Nebulosa,Inicio,Crecimiento,Juntos,Compañía,Luz,Eternidad'; @override String get planetStageUnknown => 'Planeta · Sin información de etapa'; @@ -500,7 +516,8 @@ class AppLocalizationsEs extends AppLocalizations { String get playHeadline => '¡Vamos a conocer a tu fandom!'; @override - String get playBody => 'Crea un planeta, conecta con fandoms y disfruta de la actividad fan...'; + String get playBody => + 'Crea un planeta, conecta con fandoms y disfruta de la actividad fan...'; @override String get timeJustNow => 'Ahora'; @@ -525,42 +542,38 @@ class AppLocalizationsEs extends AppLocalizations { @override String authProviderStart(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'email': 'Continuar con correo', - 'kakao': 'Continuar con Kakao', - 'line': 'Continuar con LINE', - 'apple': 'Continuar con Apple', - 'other': 'Continuar con Google', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'email': 'Continuar con correo', + 'kakao': 'Continuar con Kakao', + 'line': 'Continuar con LINE', + 'apple': 'Continuar con Apple', + 'other': 'Continuar con Google', + }); return '$_temp0'; } @override String authProviderName(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'email': 'Correo', - 'kakao': 'Kakao', - 'line': 'LINE', - 'apple': 'Apple', - 'other': 'Google', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'email': 'Correo', + 'kakao': 'Kakao', + 'line': 'LINE', + 'apple': 'Apple', + 'other': 'Google', + }); return '$_temp0'; } @override - String get authLastProvider => 'No puedes desvincular tu último método de inicio de sesión.'; + String get authLastProvider => + 'No puedes desvincular tu último método de inicio de sesión.'; @override String get authLoginRequired => 'Debes iniciar sesión.'; @override - String get authDifferentEmail => 'Esta cuenta no coincide con tu correo de registro.'; + String get authDifferentEmail => + 'Esta cuenta no coincide con tu correo de registro.'; @override String get authLinkFailed => 'No se pudo vincular la cuenta.'; @@ -569,7 +582,8 @@ class AppLocalizationsEs extends AppLocalizations { String get authNotLinked => 'Esta cuenta no está vinculada.'; @override - String get authEmailUnavailable => 'El inicio de sesión con correo no está disponible.'; + String get authEmailUnavailable => + 'El inicio de sesión con correo no está disponible.'; @override String get authCheckCredentials => 'Revisa tu correo o contraseña.'; @@ -578,13 +592,15 @@ class AppLocalizationsEs extends AppLocalizations { String get authSocialFailed => 'Error al iniciar sesión con la red social.'; @override - String get authAppleUnavailable => 'Iniciar sesión con Apple no está disponible en este dispositivo.'; + String get authAppleUnavailable => + 'Iniciar sesión con Apple no está disponible en este dispositivo.'; @override String get authEmailInUse => 'Este correo ya está registrado.'; @override - String get authWeakPassword => 'La contraseña es muy corta. Usa al menos 8 caracteres.'; + String get authWeakPassword => + 'La contraseña es muy corta. Usa al menos 8 caracteres.'; @override String get authInvalidEmail => 'El formato del correo no es válido.'; @@ -593,16 +609,19 @@ class AppLocalizationsEs extends AppLocalizations { String get commonTryLater => 'Inténtalo de nuevo más tarde.'; @override - String get authCredentialInUse => 'Esta cuenta social ya está vinculada a otra cuenta de FANUZU.'; + String get authCredentialInUse => + 'Esta cuenta social ya está vinculada a otra cuenta de FANUZU.'; @override String get authAlreadyLinked => 'Esta cuenta ya está vinculada.'; @override - String get authMethodUnavailable => 'Este método de inicio de sesión aún no está disponible.'; + String get authMethodUnavailable => + 'Este método de inicio de sesión aún no está disponible.'; @override - String get authRecentLogin => 'Por seguridad, vuelve a iniciar sesión e inténtalo de nuevo.'; + String get authRecentLogin => + 'Por seguridad, vuelve a iniciar sesión e inténtalo de nuevo.'; @override String authOtherProviderGuide(String email) { @@ -613,10 +632,12 @@ class AppLocalizationsEs extends AppLocalizations { String get authThisAccount => 'Esta'; @override - String get eclipseCapped => 'Alcanzaste el límite de participación; algunas no se contaron.'; + String get eclipseCapped => + 'Alcanzaste el límite de participación; algunas no se contaron.'; @override - String get eclipseResultUnknown => 'No se pudo confirmar tu participación. Vuelve a comprobarlo con la misma solicitud.'; + String get eclipseResultUnknown => + 'No se pudo confirmar tu participación. Vuelve a comprobarlo con la misma solicitud.'; @override String get eclipseChecking => 'Comprobando participación'; @@ -628,7 +649,8 @@ class AppLocalizationsEs extends AppLocalizations { String get eclipseEnded => 'El eclipse ya terminó o se defendió con éxito.'; @override - String get eclipseTooFast => 'Estás participando demasiado rápido. Inténtalo en un momento.'; + String get eclipseTooFast => + 'Estás participando demasiado rápido. Inténtalo en un momento.'; @override String get eclipseNone => 'No hay ningún eclipse en curso'; @@ -640,25 +662,30 @@ class AppLocalizationsEs extends AppLocalizations { String get eclipseQualified => 'Participación confirmada'; @override - String get eclipseFailTitle => 'Lamentablemente,\nla defensa del planeta falló'; + String get eclipseFailTitle => + 'Lamentablemente,\nla defensa del planeta falló'; @override - String get eclipseFailBody => 'No se alcanzó el objetivo de defensa de esta ronda.'; + String get eclipseFailBody => + 'No se alcanzó el objetivo de defensa de esta ronda.'; @override String get eclipseCancelTitle => 'Eclipse cancelado'; @override - String get eclipseCancelBody => 'Se canceló por un error de recuento. No se descontó FPI.'; + String get eclipseCancelBody => + 'Se canceló por un error de recuento. No se descontó FPI.'; @override String get eclipsePendingTitle => 'Comprobando resultado de la defensa'; @override - String get eclipsePendingBody => 'El tiempo de participación terminó. Esperando la decisión del servidor.'; + String get eclipsePendingBody => + 'El tiempo de participación terminó. Esperando la decisión del servidor.'; @override - String get eclipseShakeTimed => 's: ¡agita tu móvil\npara detener el eclipse!'; + String get eclipseShakeTimed => + 's: ¡agita tu móvil\npara detener el eclipse!'; @override String get eclipseShake => '¡Agita tu móvil\npara detener el eclipse!'; @@ -682,7 +709,8 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get eclipseNoSensor => 'Este dispositivo no admite la defensa con agitación'; + String get eclipseNoSensor => + 'Este dispositivo no admite la defensa con agitación'; @override String get eclipseTimeLeft => 'Tiempo restante del eclipse:'; @@ -738,7 +766,8 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get galaxySetPrimaryConfirm => '¿Establecer el planeta seleccionado como principal?'; + String get galaxySetPrimaryConfirm => + '¿Establecer el planeta seleccionado como principal?'; @override String get galaxyLoadFailed => 'No se pudo cargar la galaxia'; @@ -821,10 +850,12 @@ class AppLocalizationsEs extends AppLocalizations { String get zapFailNoPop => 'No tienes POP suficiente para contribuir.'; @override - String get zapFailLedger => 'Se detuvo la contribución: el saldo no coincide con el historial.'; + String get zapFailLedger => + 'Se detuvo la contribución: el saldo no coincide con el historial.'; @override - String get zapFailRetry => 'Revisa tu conexión y vuelve a comprobar la contribución.'; + String get zapFailRetry => + 'Revisa tu conexión y vuelve a comprobar la contribución.'; @override String get zapDone => 'Contribución completada'; @@ -843,7 +874,8 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get growthNebulaGoalPassed => 'El plazo objetivo ha pasado · Cumple las condiciones y nacerá el planeta'; + String get growthNebulaGoalPassed => + 'El plazo objetivo ha pasado · Cumple las condiciones y nacerá el planeta'; @override String get growthFinalStage => 'Etapa final'; @@ -852,7 +884,7 @@ class AppLocalizationsEs extends AppLocalizations { String get growthPromotionPending => 'Ascenso pendiente'; @override - String get growthCheckConditions => 'Ver condiciones de crecimiento'; + String get growthCheckConditions => 'Ver condiciones'; @override String growthConditionChecking(String name) { @@ -881,7 +913,8 @@ class AppLocalizationsEs extends AppLocalizations { String get nebulaNameTaken => 'Este nombre ya está en uso.'; @override - String get nebulaNameInvalid => 'Usa de 2 a 20 letras, números o espacios (sin símbolos, emojis ni espacios dobles o al inicio/final).'; + String get nebulaNameInvalid => + 'Usa de 2 a 20 letras, números o espacios (sin símbolos, emojis ni espacios dobles o al inicio/final).'; @override String get nebulaNameHint => 'Nombre del fandom'; @@ -921,7 +954,8 @@ class AppLocalizationsEs extends AppLocalizations { String get commonNext => 'Siguiente'; @override - String get planetCreateFailed => 'No se pudo crear el planeta. Inténtalo más tarde.'; + String get planetCreateFailed => + 'No se pudo crear el planeta. Inténtalo más tarde.'; @override String get planetCreateConfirm => '¿Crear el planeta\ncon estas opciones?'; @@ -959,13 +993,17 @@ class AppLocalizationsEs extends AppLocalizations { String get zapRetrySame => 'Volver a comprobar la contribución'; @override - String get heroOwnerSuffix => 'aporta:'; + String heroOwner(String name) { + return 'De $name'; + } @override - String get heroStartPrompt => '¡Crea o únete a un planeta\ny empieza en FANUZU!'; + String get heroStartPrompt => + '¡Crea o únete a un planeta\ny empieza en FANUZU!'; @override - String get heroNebulaPrompt => '¡Usa el POP que ganas con actividades\npara contribuir a la nebulosa!'; + String get heroNebulaPrompt => + '¡Usa el POP que ganas con actividades\npara contribuir a la nebulosa!'; @override String heroRecentContribution(String pop) { @@ -999,7 +1037,8 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get itemJoinFirst => 'Únete a un planeta para enviar un Regalo del Héroe.'; + String get itemJoinFirst => + 'Únete a un planeta para enviar un Regalo del Héroe.'; @override String get itemBuyNotReady => 'La compra de objetos llegará pronto.'; @@ -1195,19 +1234,24 @@ class AppLocalizationsEs extends AppLocalizations { String get payStateRefundRejected => 'Reembolso rechazado'; @override - String get pushTopicEssentialDesc => 'Avisos de cuenta, pagos y mantenimiento. No se pueden desactivar.'; + String get pushTopicEssentialDesc => + 'Avisos de cuenta, pagos y mantenimiento. No se pueden desactivar.'; @override - String get pushTopicFandomEventDesc => 'Novedades de eclipses, campañas, misiones y Artist Hot Time.'; + String get pushTopicFandomEventDesc => + 'Novedades de eclipses, campañas, misiones y Artist Hot Time.'; @override - String get pushTopicBriefingDesc => 'Tarjetas de resumen diario de tu planeta.'; + String get pushTopicBriefingDesc => + 'Tarjetas de resumen diario de tu planeta.'; @override - String get pushTopicCommunityDesc => 'Comentarios, me gusta y respuestas en tus publicaciones.'; + String get pushTopicCommunityDesc => + 'Comentarios, me gusta y respuestas en tus publicaciones.'; @override - String get pushTopicMarketingDesc => 'Recibe eventos y beneficios. Solo se activa si aceptas.'; + String get pushTopicMarketingDesc => + 'Recibe eventos y beneficios. Solo se activa si aceptas.'; @override String get inquiryPending => 'Recibida'; @@ -1270,10 +1314,12 @@ class AppLocalizationsEs extends AppLocalizations { String get inquiryFallback => 'Consulta'; @override - String get photoRejectedServer => 'No se pudo subir la foto. Revisa el formato y el tamaño.'; + String get photoRejectedServer => + 'No se pudo subir la foto. Revisa el formato y el tamaño.'; @override - String get photoUploadFailed => 'Error al subir la foto. Inténtalo más tarde.'; + String get photoUploadFailed => + 'Error al subir la foto. Inténtalo más tarde.'; @override String focusClaimed(String pop) { @@ -1295,7 +1341,8 @@ class AppLocalizationsEs extends AppLocalizations { String get focusClaimToday => 'Reclamar hoy'; @override - String get storeConnectFailed => 'No se pudo conectar con la tienda. Inténtalo más tarde.'; + String get storeConnectFailed => + 'No se pudo conectar con la tienda. Inténtalo más tarde.'; @override String get payRestore => 'Restaurar compras'; @@ -1304,7 +1351,8 @@ class AppLocalizationsEs extends AppLocalizations { String get payEmpty => 'No hay historial de pagos.'; @override - String get payRefundGuide => 'Consumibles: reembolsables en 7 días desde la compra si no se usaron. Los artículos usados parcialmente no son reembolsables.\nSuscripciones: reembolsables en 24 horas desde el pago si no se usaron beneficios (p. ej., recompensas extra).\nEl reembolso se completa en 7–14 días tras la aprobación.'; + String get payRefundGuide => + 'Consumibles: reembolsables en 7 días desde la compra si no se usaron. Los artículos usados parcialmente no son reembolsables.\nSuscripciones: reembolsables en 24 horas desde el pago si no se usaron beneficios (p. ej., recompensas extra).\nEl reembolso se completa en 7–14 días tras la aprobación.'; @override String get payDetailTitle => 'Detalle del pago'; @@ -1376,7 +1424,8 @@ class AppLocalizationsEs extends AppLocalizations { String get nicknameEdit => 'Editar apodo'; @override - String get nicknameReserved => 'No puedes usar un nombre que parezca del equipo.'; + String get nicknameReserved => + 'No puedes usar un nombre que parezca del equipo.'; @override String get nicknameTaken => 'Este apodo ya está en uso.'; @@ -1448,7 +1497,8 @@ class AppLocalizationsEs extends AppLocalizations { String get inquiryBodyHint => 'Describe tu consulta.'; @override - String get inquiryBodyHelper => 'Con 10 caracteres o más podremos ayudarte antes.'; + String get inquiryBodyHelper => + 'Con 10 caracteres o más podremos ayudarte antes.'; @override String inquirySubmitFailed(String reason) { @@ -1490,7 +1540,8 @@ class AppLocalizationsEs extends AppLocalizations { String get tierPromptSuffix => '\ncontribuyendo a planetas y nebulosas'; @override - String get tierPassportNote => 'Passport Tier es un grado de apariencia de tarjeta, independiente del nivel, y nunca baja.'; + String get tierPassportNote => + 'Passport Tier es un grado de apariencia de tarjeta, independiente del nivel, y nunca baja.'; @override String get tierTotalContribution => 'Contribución total'; @@ -1516,6 +1567,15 @@ class AppLocalizationsEs extends AppLocalizations { @override String get notifKindEvolution => 'Evolución del planeta'; + @override + String get notifKindCampaignRefund => 'Reembolso de campaña'; + + @override + String get notifKindCampaignCancel => 'Campaña cancelada'; + + @override + String get notifKindCampaignReport => 'Informe de resultados'; + @override String get notifTargetPost => 'la publicación'; @@ -1561,13 +1621,15 @@ class AppLocalizationsEs extends AppLocalizations { String get stationSuggest => 'Sugerir tienda'; @override - String get stationEmpty => 'Aún no hay enlaces.\nÚnete a un planeta para ver la selección.'; + String get stationEmpty => + 'Aún no hay enlaces.\nÚnete a un planeta para ver la selección.'; @override String get stationCategoryEmpty => 'Aún no hay enlaces en esta categoría.'; @override - String get stationSuggestLater => 'Las sugerencias se abrirán al conectar el servidor.'; + String get stationSuggestLater => + 'Las sugerencias se abrirán al conectar el servidor.'; @override String get commonSubmit => 'Enviar'; @@ -1594,25 +1656,30 @@ class AppLocalizationsEs extends AppLocalizations { String get stationReason => 'Por qué lo recomiendas (opcional)'; @override - String get stationSuggestNote => 'Los enlaces sugeridos se añaden tras una revisión. Te avisaremos del resultado.'; + String get stationSuggestNote => + 'Los enlaces sugeridos se añaden tras una revisión. Te avisaremos del resultado.'; @override String get heroGiftUnavailable => 'Este regalo no se puede recibir ahora.'; @override - String get heroGiftAlready => 'Ya participaste en este regalo. Revisa tu historial de POP.'; + String get heroGiftAlready => + 'Ya participaste en este regalo. Revisa tu historial de POP.'; @override String get heroGiftRelogin => 'Vuelve a iniciar sesión para participar.'; @override - String get heroGiftNoPermission => 'No tienes permiso para participar en este regalo.'; + String get heroGiftNoPermission => + 'No tienes permiso para participar en este regalo.'; @override - String get heroGiftHowTo => 'Agita el móvil o toca el botón para unirte al regalo de energía de luz.'; + String get heroGiftHowTo => + 'Agita el móvil o toca el botón para unirte al regalo de energía de luz.'; @override - String get heroGiftPopNote => 'El POP que recibes depende del regalo restante y del límite por persona.'; + String get heroGiftPopNote => + 'El POP que recibes depende del regalo restante y del límite por persona.'; @override String heroGiftReceived(String total) { @@ -1620,7 +1687,8 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get heroGiftUnknown => 'No se pudo confirmar el pago. Vuelve a comprobarlo.'; + String get heroGiftUnknown => + 'No se pudo confirmar el pago. Vuelve a comprobarlo.'; @override String get heroGiftNone => 'No hay regalos disponibles ahora.'; @@ -1707,13 +1775,16 @@ class AppLocalizationsEs extends AppLocalizations { String get reportReasonLabel => 'Motivo'; @override - String get reportConfirm => '¿Denunciar esta publicación?\nNo se puede deshacer.'; + String get reportConfirm => + '¿Denunciar esta publicación?\nNo se puede deshacer.'; @override - String get blockMemberConfirm => '¿Bloquear todas las publicaciones de este miembro?'; + String get blockMemberConfirm => + '¿Bloquear todas las publicaciones de este miembro?'; @override - String get loungeMembersOnly => 'Solo los miembros del fandom de este planeta pueden publicar, comentar o dar me gusta.'; + String get loungeMembersOnly => + 'Solo los miembros del fandom de este planeta pueden publicar, comentar o dar me gusta.'; @override String get loungeFailed => 'No se pudo completar. Inténtalo más tarde.'; @@ -1810,13 +1881,15 @@ class AppLocalizationsEs extends AppLocalizations { String get historyFunding => 'Contribución a Campaign'; @override - String get historyEclipseSuccess => 'Participaste en una defensa exitosa del eclipse'; + String get historyEclipseSuccess => + 'Participaste en una defensa exitosa del eclipse'; @override String get historyEmblemEvolution => 'Emblema de evolución'; @override - String get historyFounderBadge => 'Insignia conmemorativa de los primeros 100'; + String get historyFounderBadge => + 'Insignia conmemorativa de los primeros 100'; @override String get historyHistoric => 'Momento histórico'; @@ -1843,34 +1916,31 @@ class AppLocalizationsEs extends AppLocalizations { @override String countryName(String code) { - String _temp0 = intl.Intl.selectLogic( - code, - { - 'KR': 'Corea del Sur', - 'JP': 'Japón', - 'US': 'Estados Unidos', - 'CN': 'China', - 'TW': 'Taiwán', - 'HK': 'Hong Kong', - 'TH': 'Tailandia', - 'VN': 'Vietnam', - 'ID': 'Indonesia', - 'PH': 'Filipinas', - 'MY': 'Malasia', - 'SG': 'Singapur', - 'IN': 'India', - 'GB': 'Reino Unido', - 'FR': 'Francia', - 'DE': 'Alemania', - 'ES': 'España', - 'BR': 'Brasil', - 'MX': 'México', - 'CA': 'Canadá', - 'AU': 'Australia', - 'ZZ': 'Sin especificar', - 'other': '-', - }, - ); + String _temp0 = intl.Intl.selectLogic(code, { + 'KR': 'Corea del Sur', + 'JP': 'Japón', + 'US': 'Estados Unidos', + 'CN': 'China', + 'TW': 'Taiwán', + 'HK': 'Hong Kong', + 'TH': 'Tailandia', + 'VN': 'Vietnam', + 'ID': 'Indonesia', + 'PH': 'Filipinas', + 'MY': 'Malasia', + 'SG': 'Singapur', + 'IN': 'India', + 'GB': 'Reino Unido', + 'FR': 'Francia', + 'DE': 'Alemania', + 'ES': 'España', + 'BR': 'Brasil', + 'MX': 'México', + 'CA': 'Canadá', + 'AU': 'Australia', + 'ZZ': 'Sin especificar', + 'other': '-', + }); return '$_temp0'; } @@ -1939,7 +2009,8 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get planetHideMember => 'Ocultar todas las publicaciones de este miembro'; + String get planetHideMember => + 'Ocultar todas las publicaciones de este miembro'; @override String get reportReasonUnknown => 'No se pudo verificar el motivo.'; @@ -2001,7 +2072,8 @@ class AppLocalizationsEs extends AppLocalizations { String get questResume => 'Reanudar'; @override - String get questShakeRestart => 'La configuración de la misión cambió, así que empiezas desde el principio.'; + String get questShakeRestart => + 'La configuración de la misión cambió, así que empiezas desde el principio.'; @override String get questPaused => 'En pausa'; @@ -2019,7 +2091,8 @@ class AppLocalizationsEs extends AppLocalizations { String get questTypeStreaming => 'Streaming'; @override - String get questTypeUnverifiable => 'Aún no puedes participar en esta misión.'; + String get questTypeUnverifiable => + 'Aún no puedes participar en esta misión.'; @override String get questTabMine => 'Mis misiones'; @@ -2040,7 +2113,8 @@ class AppLocalizationsEs extends AppLocalizations { String get adMoreChance => 'Consigue más oportunidades de contribuir.'; @override - String get adWatchPrompt => '¡Mira un anuncio para\nconseguir una recompensa extra!'; + String get adWatchPrompt => + '¡Mira un anuncio para\nconseguir una recompensa extra!'; @override String get adBonusPlaceholder => '+ POP de contribución'; @@ -2066,10 +2140,12 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get adWarpBefore => 'Warping... Buscando el anuncio ideal para que aportes más a tu fandom y artista.'; + String get adWarpBefore => + 'Warping... Buscando el anuncio ideal para que aportes más a tu fandom y artista.'; @override - String get adWarpAfter => 'Warping... Preparando la recompensa por tu contribución.'; + String get adWarpAfter => + 'Warping... Preparando la recompensa por tu contribución.'; @override String get adSkip => 'Omitir'; @@ -2133,13 +2209,16 @@ class AppLocalizationsEs extends AppLocalizations { String get questTabEmpty => 'Aún no hay misiones en esta pestaña.'; @override - String get questCreateNotReady => 'La creación de misiones se abrirá junto con los fondos de recompensa. Próximamente.'; + String get questCreateNotReady => + 'La creación de misiones se abrirá junto con los fondos de recompensa. Próximamente.'; @override - String get questNoBaseReward => 'No se encontró la recompensa básica, así que no hay extra por anuncio.'; + String get questNoBaseReward => + 'No se encontró la recompensa básica, así que no hay extra por anuncio.'; @override - String get questNoSteps => 'Aún no hay pasos registrados. Camina un poco y vuelve a intentarlo.'; + String get questNoSteps => + 'Aún no hay pasos registrados. Camina un poco y vuelve a intentarlo.'; @override String get questNoPlace => 'Esta misión no tiene una ubicación registrada.'; @@ -2171,28 +2250,35 @@ class AppLocalizationsEs extends AppLocalizations { String get questStop => 'Detener'; @override - String get adNotFinished => 'No terminaste el anuncio, así que no hay extra. Recibes la recompensa básica.'; + String get adNotFinished => + 'No terminaste el anuncio, así que no hay extra. Recibes la recompensa básica.'; @override - String get adNotVerified => 'No pudimos confirmar el anuncio, así que no hay extra. Recibes la recompensa básica.'; + String get adNotVerified => + 'No pudimos confirmar el anuncio, así que no hay extra. Recibes la recompensa básica.'; @override String get openSettings => 'Abrir ajustes'; @override - String get permStepsDenied => 'El permiso de pasos está desactivado. Permite \"Actividad física\" en Ajustes.'; + String get permStepsDenied => + 'El permiso de pasos está desactivado. Permite \"Actividad física\" en Ajustes.'; @override - String get permStepsNeeded => 'Se necesita el permiso de actividad física para contar pasos.'; + String get permStepsNeeded => + 'Se necesita el permiso de actividad física para contar pasos.'; @override - String get permLocationOff => 'La ubicación del dispositivo está desactivada. Actívala e inténtalo de nuevo.'; + String get permLocationOff => + 'La ubicación del dispositivo está desactivada. Actívala e inténtalo de nuevo.'; @override - String get permLocationNeeded => 'Se necesita el permiso de ubicación para verificar tu visita.'; + String get permLocationNeeded => + 'Se necesita el permiso de ubicación para verificar tu visita.'; @override - String get permLocationDenied => 'El permiso de ubicación está desactivado. Permite el acceso en Ajustes.'; + String get permLocationDenied => + 'El permiso de ubicación está desactivado. Permite el acceso en Ajustes.'; @override String get questRewardReceived => ' ¡recibidos!'; @@ -2213,13 +2299,15 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get nebulaCreateFailed => 'No se pudo crear la nebulosa. Inténtalo más tarde.'; + String get nebulaCreateFailed => + 'No se pudo crear la nebulosa. Inténtalo más tarde.'; @override String get nebulaAlreadyToday => 'Ya creaste una nebulosa hoy.'; @override - String get nebulaCreatedKeepPrimary => 'Nebulosa creada. Tu planeta principal no cambia: solo puede cambiarse 30 días después del último cambio.'; + String get nebulaCreatedKeepPrimary => + 'Nebulosa creada. Tu planeta principal no cambia: solo puede cambiarse 30 días después del último cambio.'; @override String get planetLeave => 'Salir'; @@ -2228,7 +2316,8 @@ class AppLocalizationsEs extends AppLocalizations { String get planetLeaveConfirmTitle => '¿Salir de este planeta?'; @override - String get planetLeaveConfirmBody => 'El POP aportado y la actividad\nno se pueden deshacer.'; + String get planetLeaveConfirmBody => + 'El POP aportado y la actividad\nno se pueden deshacer.'; @override String get sortPopular => 'Populares'; @@ -2240,13 +2329,15 @@ class AppLocalizationsEs extends AppLocalizations { String get campaignStatusReview => 'Esta campaña está en revisión.'; @override - String get campaignStatusRejected => 'Esta campaña fue rechazada en la revisión. Te hemos devuelto la tarifa de registro.'; + String get campaignStatusRejected => + 'Esta campaña fue rechazada en la revisión. Te hemos devuelto la tarifa de registro.'; @override String get campaignStatusWithdrawn => 'El creador retiró esta campaña.'; @override - String get campaignStatusCancelled => 'Se canceló por motivos operativos. Te hemos devuelto la tarifa de registro y los POP aportados.'; + String get campaignStatusCancelled => + 'Se canceló por motivos operativos. Te hemos devuelto la tarifa de registro y los POP aportados.'; @override String get rankWindowDaily => 'Diario'; @@ -2329,7 +2420,8 @@ class AppLocalizationsEs extends AppLocalizations { String get campaignContributePop => 'Elige los POP a aportar'; @override - String get campaignEmptyContributing => 'Aún no has contribuido a ninguna campaña.'; + String get campaignEmptyContributing => + 'Aún no has contribuido a ninguna campaña.'; @override String get campaignEmpty => 'No hay campañas.'; @@ -2385,7 +2477,12 @@ class AppLocalizationsEs extends AppLocalizations { String get campaignWeekdays => 'D,L,M,X,J,V,S'; @override - String campaignPeriodRange(String startMonth, String startDay, String endMonth, String endDay) { + String campaignPeriodRange( + String startMonth, + String startDay, + String endMonth, + String endDay, + ) { return '$startDay/$startMonth ~ $endDay/$endMonth'; } @@ -2411,7 +2508,8 @@ class AppLocalizationsEs extends AppLocalizations { String get campaignBodyHint => 'Describe tu campaña.'; @override - String get campaignReviewNote => 'Tras enviarla, la financiación se abre después de la revisión.'; + String get campaignReviewNote => + 'Tras enviarla, la financiación se abre después de la revisión.'; @override String get campaignSupportType => 'Elige el tipo de apoyo'; @@ -2429,7 +2527,12 @@ class AppLocalizationsEs extends AppLocalizations { String get campaignSubmitTitle => '¿Enviar esta campaña?'; @override - String campaignSubmitBody(String title, String goal, String days, String fee) { + String campaignSubmitBody( + String title, + String goal, + String days, + String fee, + ) { return '$title · Objetivo $goal POP · $days días\nSe descontará la tarifa de registro de $fee POP y la financiación se abrirá tras la revisión.'; } @@ -2448,34 +2551,43 @@ class AppLocalizationsEs extends AppLocalizations { String get campaignPendingTitle => 'Pendiente de revisión'; @override - String get campaignPendingBody => 'Cuando termine la revisión, se abrirá la financiación y aparecerá en la lista.'; + String get campaignPendingBody => + 'Cuando termine la revisión, se abrirá la financiación y aparecerá en la lista.'; @override - String get insideRefundPending => 'El plazo de aceptación venció. Se reembolsará la recompensa.'; + String get insideRefundPending => + 'El plazo de aceptación venció. Se reembolsará la recompensa.'; @override - String get insideRefundDone => 'El plazo de aceptación venció. Se reembolsó la recompensa.'; + String get insideRefundDone => + 'El plazo de aceptación venció. Se reembolsó la recompensa.'; @override - String get insideRefundChecking => 'El plazo de aceptación venció. Estamos revisando el reembolso de la recompensa.'; + String get insideRefundChecking => + 'El plazo de aceptación venció. Estamos revisando el reembolso de la recompensa.'; @override - String get insideErrPopShort => 'No tienes POP suficientes para la recompensa.'; + String get insideErrPopShort => + 'No tienes POP suficientes para la recompensa.'; @override String get insideErrSelfAccept => 'No puedes aceptar tu propia respuesta.'; @override - String get insideErrAlreadyAccepted => 'Ya se aceptó una respuesta y no se puede cambiar.'; + String get insideErrAlreadyAccepted => + 'Ya se aceptó una respuesta y no se puede cambiar.'; @override - String get insideErrNotOwner => 'Solo quien preguntó puede aceptar una respuesta.'; + String get insideErrNotOwner => + 'Solo quien preguntó puede aceptar una respuesta.'; @override - String get commonCheckConnection => 'Revisa tu conexión e inténtalo de nuevo.'; + String get commonCheckConnection => + 'Revisa tu conexión e inténtalo de nuevo.'; @override - String get insideAnswerLater => 'Los comentarios se abrirán cuando se conecte el servidor.'; + String get insideAnswerLater => + 'Los comentarios se abrirán cuando se conecte el servidor.'; @override String insideAcceptConfirm(String pop) { @@ -2530,7 +2642,8 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get insideAttachLater => 'Los adjuntos de imagen se abrirán cuando se conecte el servidor.'; + String get insideAttachLater => + 'Los adjuntos de imagen se abrirán cuando se conecte el servidor.'; @override String get insideBountyRequired => 'Indica una recompensa.'; @@ -2599,7 +2712,8 @@ class AppLocalizationsEs extends AppLocalizations { String get questActivity => 'Actividad'; @override - String get questNoCreatable => 'Ahora no hay actividades disponibles para crear.'; + String get questNoCreatable => + 'Ahora no hay actividades disponibles para crear.'; @override String get questDescriptionOptional => 'Descripción (opcional)'; @@ -2614,7 +2728,8 @@ class AppLocalizationsEs extends AppLocalizations { String get questLinkInvalid => 'El enlace no es válido. Revisa la dirección.'; @override - String get questLinkPreviewFailed => 'No se pudo cargar el enlace. Escribe un título.'; + String get questLinkPreviewFailed => + 'No se pudo cargar el enlace. Escribe un título.'; @override String get questLinkTitle => 'Título del enlace'; @@ -2636,7 +2751,14 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String questCreateCost(String title, String reward, String count, String pool, String fee, String total) { + String questCreateCost( + String title, + String reward, + String count, + String pool, + String fee, + String total, + ) { return '$title\nRecompensa $reward POP × $count = $pool POP\nComisión $fee POP (se quema al publicar)\nSe descontarán $total POP en total.'; } @@ -2644,10 +2766,12 @@ class AppLocalizationsEs extends AppLocalizations { String get questNoReward => 'Esta misión no tiene recompensa.'; @override - String get questStreamJoined => 'Tu participación quedó registrada. Esta misión no otorga POP.'; + String get questStreamJoined => + 'Tu participación quedó registrada. Esta misión no otorga POP.'; @override - String get questNoShake => 'No se registraron sacudidas. Pulsa Empezar y agita al ritmo.'; + String get questNoShake => + 'No se registraron sacudidas. Pulsa Empezar y agita al ritmo.'; @override String get questDeadline => 'Fecha límite'; @@ -2684,13 +2808,16 @@ class AppLocalizationsEs extends AppLocalizations { String get questEvidenceText => 'Detalles de la prueba'; @override - String get questSubmitted => 'Enviado. La recompensa se paga tras la revisión.'; + String get questSubmitted => + 'Enviado. La recompensa se paga tras la revisión.'; @override - String get questReviewPending => 'En revisión. La recompensa se paga al aprobarse.'; + String get questReviewPending => + 'En revisión. La recompensa se paga al aprobarse.'; @override - String get questReviewDelayed => 'La revisión se está retrasando. Nuestro equipo lo está revisando.'; + String get questReviewDelayed => + 'La revisión se está retrasando. Nuestro equipo lo está revisando.'; @override String get questApprovedPaying => 'Aprobado. Pagando tu recompensa.'; @@ -2733,7 +2860,8 @@ class AppLocalizationsEs extends AppLocalizations { String get questEdit => 'Editar título y descripción'; @override - String get questEditNotice => 'Tras publicar solo puedes editar el título y la descripción, y se guarda el historial.'; + String get questEditNotice => + 'Tras publicar solo puedes editar el título y la descripción, y se guarda el historial.'; @override String get popReasonQuestUgc => 'Recompensa de misión'; @@ -2778,7 +2906,7 @@ class AppLocalizationsEs extends AppLocalizations { String get homeGrowTogether => 'Crecer juntos'; @override - String get homeArtistNews => 'Noticias del artista'; + String get homeArtistNews => 'AI Daily Briefing'; @override String get growthConditionsTitle => 'Condiciones de crecimiento'; @@ -2842,10 +2970,12 @@ class AppLocalizationsEs extends AppLocalizations { String get questCancel => 'Cancelar misión'; @override - String get questCancelInReview => 'Si cancelas durante la revisión, te devolvemos todo el POP depositado y la comisión.'; + String get questCancelInReview => + 'Si cancelas durante la revisión, te devolvemos todo el POP depositado y la comisión.'; @override - String get questCancelPublished => 'Si cancelas una misión publicada, se cierra al momento y te devolvemos el POP no usado. La comisión no se reembolsa.'; + String get questCancelPublished => + 'Si cancelas una misión publicada, se cierra al momento y te devolvemos el POP no usado. La comisión no se reembolsa.'; @override String get questUnderReview => 'En revisión. Se publicará cuando se apruebe.'; @@ -2856,7 +2986,8 @@ class AppLocalizationsEs extends AppLocalizations { } @override - String get questSubmittedForReview => 'Enviada. Se publicará tras la revisión.'; + String get questSubmittedForReview => + 'Enviada. Se publicará tras la revisión.'; @override String get popReasonQuestFeeRefund => 'Reembolso de comisión de misión'; @@ -2868,7 +2999,8 @@ class AppLocalizationsEs extends AppLocalizations { String get eclipseTapToJoin => '¿No puedes agitar? Toca para participar'; @override - String get termsPrivacy => 'Política de privacidad y recopilación de datos personales (obligatorio)'; + String get termsPrivacy => + 'Política de privacidad y recopilación de datos personales (obligatorio)'; @override String get onbSkip => 'Omitir'; @@ -2877,19 +3009,22 @@ class AppLocalizationsEs extends AppLocalizations { String get onbIntro1Title => 'Haz crecer el planeta de tu fandom'; @override - String get onbIntro1Body => 'Reúne POP y envíalo con ZAP\npara que el planeta de tu fandom crezca.'; + String get onbIntro1Body => + 'Reúne POP y envíalo con ZAP\npara que el planeta de tu fandom crezca.'; @override String get onbIntro2Title => 'Apoya con misiones'; @override - String get onbIntro2Body => 'Completa misiones de caminar, asistencia y streaming\ny gana POP.'; + String get onbIntro2Body => + 'Completa misiones de caminar, asistencia y streaming\ny gana POP.'; @override String get onbIntro3Title => 'Protégelo junto a otros fans'; @override - String get onbIntro3Body => 'Detengan juntos el Eclipse y apoyen\na su artista con campañas.'; + String get onbIntro3Body => + 'Detengan juntos el Eclipse y apoyen\na su artista con campañas.'; @override String get onbProfileTitle => 'Configura tu perfil'; @@ -2916,7 +3051,8 @@ class AppLocalizationsEs extends AppLocalizations { String get onbArtistTitle => 'Elige a los artistas que sigues'; @override - String get onbArtistBody => 'El primer artista que elijas será tu planeta principal. Puedes unirte a varios fandoms.'; + String get onbArtistBody => + 'El primer artista que elijas será tu planeta principal. Puedes unirte a varios fandoms.'; @override String get onbArtistSearch => 'Buscar nombre del artista'; @@ -2948,25 +3084,29 @@ class AppLocalizationsEs extends AppLocalizations { String get onbPermTitle => 'Permisos de la app'; @override - String get onbPermBody => 'Estos permisos solo se necesitan para las funciones relacionadas. Puedes usar la app sin ellos.'; + String get onbPermBody => + 'Estos permisos solo se necesitan para las funciones relacionadas. Puedes usar la app sin ellos.'; @override String get onbPermPush => 'Notificaciones'; @override - String get onbPermPushDesc => 'Recibe avisos de Eclipse, HERO TIME y misiones.'; + String get onbPermPushDesc => + 'Recibe avisos de Eclipse, HERO TIME y misiones.'; @override String get onbPermHealth => 'Datos de salud (pasos)'; @override - String get onbPermHealthDesc => 'Cuenta pasos para misiones de caminar. Se solicita al empezar la primera.'; + String get onbPermHealthDesc => + 'Cuenta pasos para misiones de caminar. Se solicita al empezar la primera.'; @override String get onbPermLocation => 'Ubicación'; @override - String get onbPermLocationDesc => 'Comprueba la llegada en misiones de ubicación. Se solicita al empezar la primera.'; + String get onbPermLocationDesc => + 'Comprueba la llegada en misiones de ubicación. Se solicita al empezar la primera.'; @override String get onbPermContinue => 'Continuar'; @@ -2978,7 +3118,8 @@ class AppLocalizationsEs extends AppLocalizations { String get coachMy => 'Aquí puedes ver tus registros'; @override - String get settingsWithdrawLinked => 'Desvincula tus cuentas conectadas antes de eliminar tu cuenta.'; + String get settingsWithdrawLinked => + 'Desvincula tus cuentas conectadas antes de eliminar tu cuenta.'; @override String get homeWeeklyTitle => 'Nuestro planeta esta semana'; @@ -3019,7 +3160,8 @@ class AppLocalizationsEs extends AppLocalizations { String get questScanQr => 'Escanea el QR del lugar'; @override - String get questScanQrDenied => 'No se puede abrir la cámara. Permite el acceso en Ajustes.'; + String get questScanQrDenied => + 'No se puede abrir la cámara. Permite el acceso en Ajustes.'; @override String get questQrForPlace => 'QR de verificación para colocar en el lugar'; diff --git a/app/lib/l10n/app_localizations_ja.dart b/app/lib/l10n/app_localizations_ja.dart index 32b4e99..6a9d7e0 100644 --- a/app/lib/l10n/app_localizations_ja.dart +++ b/app/lib/l10n/app_localizations_ja.dart @@ -63,31 +63,25 @@ class AppLocalizationsJa extends AppLocalizations { @override String authProviderLogin(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'apple': 'Appleでログイン', - 'google': 'Googleでログイン', - 'kakao': 'Kakaoでログイン', - 'line': 'LINEでログイン', - 'other': 'メールでログイン', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'apple': 'Appleでログイン', + 'google': 'Googleでログイン', + 'kakao': 'Kakaoでログイン', + 'line': 'LINEでログイン', + 'other': 'メールでログイン', + }); return '$_temp0'; } @override String authProviderSignup(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'apple': 'Appleで登録', - 'google': 'Googleで登録', - 'kakao': 'Kakaoで登録', - 'line': 'LINEで登録', - 'other': 'メールで登録', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'apple': 'Appleで登録', + 'google': 'Googleで登録', + 'kakao': 'Kakaoで登録', + 'line': 'LINEで登録', + 'other': 'メールで登録', + }); return '$_temp0'; } @@ -525,31 +519,25 @@ class AppLocalizationsJa extends AppLocalizations { @override String authProviderStart(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'email': 'メールではじめる', - 'kakao': 'Kakaoではじめる', - 'line': 'LINEではじめる', - 'apple': 'Appleではじめる', - 'other': 'Googleではじめる', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'email': 'メールではじめる', + 'kakao': 'Kakaoではじめる', + 'line': 'LINEではじめる', + 'apple': 'Appleではじめる', + 'other': 'Googleではじめる', + }); return '$_temp0'; } @override String authProviderName(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'email': 'メール', - 'kakao': 'Kakao', - 'line': 'LINE', - 'apple': 'Apple', - 'other': 'Google', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'email': 'メール', + 'kakao': 'Kakao', + 'line': 'LINE', + 'apple': 'Apple', + 'other': 'Google', + }); return '$_temp0'; } @@ -881,7 +869,8 @@ class AppLocalizationsJa extends AppLocalizations { String get nebulaNameTaken => 'すでに使用されている名前です。'; @override - String get nebulaNameInvalid => '2〜20文字のハングル・英字・数字で入力してください(記号・絵文字・連続/前後の空白は不可)。'; + String get nebulaNameInvalid => + '2〜20文字のハングル・英字・数字で入力してください(記号・絵文字・連続/前後の空白は不可)。'; @override String get nebulaNameHint => 'ファンダム名'; @@ -959,7 +948,9 @@ class AppLocalizationsJa extends AppLocalizations { String get zapRetrySame => '同じ貢献を再確認'; @override - String get heroOwnerSuffix => 'さんの'; + String heroOwner(String name) { + return '$name さんの'; + } @override String get heroStartPrompt => '惑星を作成または参加して\nファン宇宙を始めよう!'; @@ -1198,7 +1189,8 @@ class AppLocalizationsJa extends AppLocalizations { String get pushTopicEssentialDesc => 'アカウント・決済・メンテナンスのお知らせです。オフにできません。'; @override - String get pushTopicFandomEventDesc => 'イクリプス・キャンペーン・クエスト・アーティストホットタイムのお知らせです。'; + String get pushTopicFandomEventDesc => + 'イクリプス・キャンペーン・クエスト・アーティストホットタイムのお知らせです。'; @override String get pushTopicBriefingDesc => '惑星の一日をまとめたブリーフィングカードをお届けします。'; @@ -1304,7 +1296,8 @@ class AppLocalizationsJa extends AppLocalizations { String get payEmpty => '決済履歴はありません。'; @override - String get payRefundGuide => '消費型商品:購入後7日以内かつ未使用の商品は返金できます。一部でも使用した商品は返金対象外です。\nサブスク商品:決済後24時間以内に特典(追加報酬など)を未使用の場合、返金できます。\n返金承認後7〜14日以内に返金が完了します。'; + String get payRefundGuide => + '消費型商品:購入後7日以内かつ未使用の商品は返金できます。一部でも使用した商品は返金対象外です。\nサブスク商品:決済後24時間以内に特典(追加報酬など)を未使用の場合、返金できます。\n返金承認後7〜14日以内に返金が完了します。'; @override String get payDetailTitle => '決済履歴の詳細'; @@ -1516,6 +1509,15 @@ class AppLocalizationsJa extends AppLocalizations { @override String get notifKindEvolution => '惑星の進化'; + @override + String get notifKindCampaignRefund => 'キャンペーン返金'; + + @override + String get notifKindCampaignCancel => 'キャンペーン中止'; + + @override + String get notifKindCampaignReport => '結果報告'; + @override String get notifTargetPost => '投稿'; @@ -1843,34 +1845,31 @@ class AppLocalizationsJa extends AppLocalizations { @override String countryName(String code) { - String _temp0 = intl.Intl.selectLogic( - code, - { - 'KR': '韓国', - 'JP': '日本', - 'US': 'アメリカ', - 'CN': '中国', - 'TW': '台湾', - 'HK': '香港', - 'TH': 'タイ', - 'VN': 'ベトナム', - 'ID': 'インドネシア', - 'PH': 'フィリピン', - 'MY': 'マレーシア', - 'SG': 'シンガポール', - 'IN': 'インド', - 'GB': 'イギリス', - 'FR': 'フランス', - 'DE': 'ドイツ', - 'ES': 'スペイン', - 'BR': 'ブラジル', - 'MX': 'メキシコ', - 'CA': 'カナダ', - 'AU': 'オーストラリア', - 'ZZ': '未指定', - 'other': '-', - }, - ); + String _temp0 = intl.Intl.selectLogic(code, { + 'KR': '韓国', + 'JP': '日本', + 'US': 'アメリカ', + 'CN': '中国', + 'TW': '台湾', + 'HK': '香港', + 'TH': 'タイ', + 'VN': 'ベトナム', + 'ID': 'インドネシア', + 'PH': 'フィリピン', + 'MY': 'マレーシア', + 'SG': 'シンガポール', + 'IN': 'インド', + 'GB': 'イギリス', + 'FR': 'フランス', + 'DE': 'ドイツ', + 'ES': 'スペイン', + 'BR': 'ブラジル', + 'MX': 'メキシコ', + 'CA': 'カナダ', + 'AU': 'オーストラリア', + 'ZZ': '未指定', + 'other': '-', + }); return '$_temp0'; } @@ -2066,7 +2065,8 @@ class AppLocalizationsJa extends AppLocalizations { } @override - String get adWarpBefore => 'Warping...ファンダムとアーティストにもっと貢献できるよう、ぴったりの広告を探しています。'; + String get adWarpBefore => + 'Warping...ファンダムとアーティストにもっと貢献できるよう、ぴったりの広告を探しています。'; @override String get adWarpAfter => 'Warping...あなたの貢献への報酬を準備しています。'; @@ -2219,7 +2219,8 @@ class AppLocalizationsJa extends AppLocalizations { String get nebulaAlreadyToday => '今日はすでに星雲を作成しました。'; @override - String get nebulaCreatedKeepPrimary => '星雲を作成しました。メイン惑星は前回の変更から30日経過後に変更できるため、そのままです。'; + String get nebulaCreatedKeepPrimary => + '星雲を作成しました。メイン惑星は前回の変更から30日経過後に変更できるため、そのままです。'; @override String get planetLeave => '脱退する'; @@ -2385,7 +2386,12 @@ class AppLocalizationsJa extends AppLocalizations { String get campaignWeekdays => '日,月,火,水,木,金,土'; @override - String campaignPeriodRange(String startMonth, String startDay, String endMonth, String endDay) { + String campaignPeriodRange( + String startMonth, + String startDay, + String endMonth, + String endDay, + ) { return '$startMonth月$startDay日 ~ $endMonth月$endDay日'; } @@ -2429,7 +2435,12 @@ class AppLocalizationsJa extends AppLocalizations { String get campaignSubmitTitle => 'この内容で投稿しますか?'; @override - String campaignSubmitBody(String title, String goal, String days, String fee) { + String campaignSubmitBody( + String title, + String goal, + String days, + String fee, + ) { return '$title · 目標 $goal POP · $days日\n登録料 $fee POP が差し引かれ、運営の審査後に支援が始まります。'; } @@ -2636,7 +2647,14 @@ class AppLocalizationsJa extends AppLocalizations { } @override - String questCreateCost(String title, String reward, String count, String pool, String fee, String total) { + String questCreateCost( + String title, + String reward, + String count, + String pool, + String fee, + String total, + ) { return '$title\n報酬 $reward POP × $count人 = $pool POP\n手数料 $fee POP(公開時に消滅)\n合計 $total POP が差し引かれます。'; } @@ -2778,7 +2796,7 @@ class AppLocalizationsJa extends AppLocalizations { String get homeGrowTogether => '一緒に成長する'; @override - String get homeArtistNews => 'アーティストニュース'; + String get homeArtistNews => 'AI Daily Briefing'; @override String get growthConditionsTitle => '成長条件'; @@ -2845,7 +2863,8 @@ class AppLocalizationsJa extends AppLocalizations { String get questCancelInReview => '審査中に取り消すと、預けた報酬POPと手数料はすべて返還されます。'; @override - String get questCancelPublished => '公開中のクエストを取り消すと参加はすぐ締め切られ、残りの報酬POPは返還されます。手数料は返還されません。'; + String get questCancelPublished => + '公開中のクエストを取り消すと参加はすぐ締め切られ、残りの報酬POPは返還されます。手数料は返還されません。'; @override String get questUnderReview => '運営の審査中です。承認されると公開されます。'; diff --git a/app/lib/l10n/app_localizations_ko.dart b/app/lib/l10n/app_localizations_ko.dart index 83881b7..e626b49 100644 --- a/app/lib/l10n/app_localizations_ko.dart +++ b/app/lib/l10n/app_localizations_ko.dart @@ -63,31 +63,25 @@ class AppLocalizationsKo extends AppLocalizations { @override String authProviderLogin(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'apple': 'Apple로 로그인', - 'google': 'Google로 로그인', - 'kakao': 'Kakao로 로그인', - 'line': 'LINE으로 로그인', - 'other': '이메일로 로그인', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'apple': 'Apple로 로그인', + 'google': 'Google로 로그인', + 'kakao': 'Kakao로 로그인', + 'line': 'LINE으로 로그인', + 'other': '이메일로 로그인', + }); return '$_temp0'; } @override String authProviderSignup(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'apple': 'Apple로 가입하기', - 'google': 'Google로 가입하기', - 'kakao': 'Kakao로 가입하기', - 'line': 'LINE으로 가입하기', - 'other': '이메일로 가입하기', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'apple': 'Apple로 가입하기', + 'google': 'Google로 가입하기', + 'kakao': 'Kakao로 가입하기', + 'line': 'LINE으로 가입하기', + 'other': '이메일로 가입하기', + }); return '$_temp0'; } @@ -525,31 +519,25 @@ class AppLocalizationsKo extends AppLocalizations { @override String authProviderStart(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'email': '이메일로 시작하기', - 'kakao': '카카오로 시작하기', - 'line': 'LINE으로 시작하기', - 'apple': 'Apple로 시작하기', - 'other': 'Google로 시작하기', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'email': '이메일로 시작하기', + 'kakao': '카카오로 시작하기', + 'line': 'LINE으로 시작하기', + 'apple': 'Apple로 시작하기', + 'other': 'Google로 시작하기', + }); return '$_temp0'; } @override String authProviderName(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'email': '이메일', - 'kakao': '카카오', - 'line': 'LINE', - 'apple': 'Apple', - 'other': 'Google', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'email': '이메일', + 'kakao': '카카오', + 'line': 'LINE', + 'apple': 'Apple', + 'other': 'Google', + }); return '$_temp0'; } @@ -881,7 +869,8 @@ class AppLocalizationsKo extends AppLocalizations { String get nebulaNameTaken => '이미 사용중인 이름입니다.'; @override - String get nebulaNameInvalid => '2~20자 한글·영문·숫자로 입력해 주세요(특수문자·이모지·연속/앞뒤 공백 불가).'; + String get nebulaNameInvalid => + '2~20자 한글·영문·숫자로 입력해 주세요(특수문자·이모지·연속/앞뒤 공백 불가).'; @override String get nebulaNameHint => '팬덤 이름'; @@ -959,7 +948,9 @@ class AppLocalizationsKo extends AppLocalizations { String get zapRetrySame => '같은 기여 다시 확인'; @override - String get heroOwnerSuffix => '님의'; + String heroOwner(String name) { + return '$name 님의'; + } @override String get heroStartPrompt => '행성을 생성 또는 가입하고\n팬우주를 시작해 보세요!'; @@ -1304,7 +1295,8 @@ class AppLocalizationsKo extends AppLocalizations { String get payEmpty => '결제 내역이 없습니다.'; @override - String get payRefundGuide => '소비형 상품 : 구매 후 7일 이내이며 사용하지 않은 상품은 환불 가능합니다. 일부라도 사용된 상품은 환불 대상에서 제외됩니다.\n구독형 상품 : 결제 후 24시간 이내 혜택 미사용(추가 보상 등) 시 환불 가능합니다.\n환불 승인 후 7-14 이내 환불 완료 처리가 됩니다.'; + String get payRefundGuide => + '소비형 상품 : 구매 후 7일 이내이며 사용하지 않은 상품은 환불 가능합니다. 일부라도 사용된 상품은 환불 대상에서 제외됩니다.\n구독형 상품 : 결제 후 24시간 이내 혜택 미사용(추가 보상 등) 시 환불 가능합니다.\n환불 승인 후 7-14 이내 환불 완료 처리가 됩니다.'; @override String get payDetailTitle => '결제 내역 상세'; @@ -1490,7 +1482,8 @@ class AppLocalizationsKo extends AppLocalizations { String get tierPromptSuffix => '를 올려보세요'; @override - String get tierPassportNote => 'Passport Tier 는 레벨과 별개인 카드 외형 등급이며 내려가지 않습니다.'; + String get tierPassportNote => + 'Passport Tier 는 레벨과 별개인 카드 외형 등급이며 내려가지 않습니다.'; @override String get tierTotalContribution => '누적 기여'; @@ -1516,6 +1509,15 @@ class AppLocalizationsKo extends AppLocalizations { @override String get notifKindEvolution => '행성 진화'; + @override + String get notifKindCampaignRefund => '캠페인 환불'; + + @override + String get notifKindCampaignCancel => '캠페인 취소'; + + @override + String get notifKindCampaignReport => '결과 보고'; + @override String get notifTargetPost => '게시물'; @@ -1594,7 +1596,8 @@ class AppLocalizationsKo extends AppLocalizations { String get stationReason => '추천 이유 (선택)'; @override - String get stationSuggestNote => '제안하신 링크는 운영 검토를 거쳐 등록됩니다. 검토 결과는 알림으로 알려 드립니다.'; + String get stationSuggestNote => + '제안하신 링크는 운영 검토를 거쳐 등록됩니다. 검토 결과는 알림으로 알려 드립니다.'; @override String get heroGiftUnavailable => '이 선물은 현재 수령할 수 없습니다.'; @@ -1843,34 +1846,31 @@ class AppLocalizationsKo extends AppLocalizations { @override String countryName(String code) { - String _temp0 = intl.Intl.selectLogic( - code, - { - 'KR': '대한민국', - 'JP': '일본', - 'US': '미국', - 'CN': '중국', - 'TW': '대만', - 'HK': '홍콩', - 'TH': '태국', - 'VN': '베트남', - 'ID': '인도네시아', - 'PH': '필리핀', - 'MY': '말레이시아', - 'SG': '싱가포르', - 'IN': '인도', - 'GB': '영국', - 'FR': '프랑스', - 'DE': '독일', - 'ES': '스페인', - 'BR': '브라질', - 'MX': '멕시코', - 'CA': '캐나다', - 'AU': '호주', - 'ZZ': '미지정', - 'other': '-', - }, - ); + String _temp0 = intl.Intl.selectLogic(code, { + 'KR': '대한민국', + 'JP': '일본', + 'US': '미국', + 'CN': '중국', + 'TW': '대만', + 'HK': '홍콩', + 'TH': '태국', + 'VN': '베트남', + 'ID': '인도네시아', + 'PH': '필리핀', + 'MY': '말레이시아', + 'SG': '싱가포르', + 'IN': '인도', + 'GB': '영국', + 'FR': '프랑스', + 'DE': '독일', + 'ES': '스페인', + 'BR': '브라질', + 'MX': '멕시코', + 'CA': '캐나다', + 'AU': '호주', + 'ZZ': '미지정', + 'other': '-', + }); return '$_temp0'; } @@ -2066,7 +2066,8 @@ class AppLocalizationsKo extends AppLocalizations { } @override - String get adWarpBefore => 'Warping...우리 팬덤과 아티스트에 더 많은 기여를 위해 적합한 광고를 열심히 찾고 있어요.'; + String get adWarpBefore => + 'Warping...우리 팬덤과 아티스트에 더 많은 기여를 위해 적합한 광고를 열심히 찾고 있어요.'; @override String get adWarpAfter => 'Warping...당신의 기여에 대한 보상을 준비하고 있어요.'; @@ -2219,7 +2220,8 @@ class AppLocalizationsKo extends AppLocalizations { String get nebulaAlreadyToday => '이미 오늘 성운을 생성하셨습니다.'; @override - String get nebulaCreatedKeepPrimary => '성운을 만들었습니다. 기본 행성은 최근 변경 후 30일이 지나야 바꿀 수 있어 그대로 유지됩니다.'; + String get nebulaCreatedKeepPrimary => + '성운을 만들었습니다. 기본 행성은 최근 변경 후 30일이 지나야 바꿀 수 있어 그대로 유지됩니다.'; @override String get planetLeave => '탈퇴하기'; @@ -2246,7 +2248,8 @@ class AppLocalizationsKo extends AppLocalizations { String get campaignStatusWithdrawn => '개설자가 철회한 캠페인입니다.'; @override - String get campaignStatusCancelled => '운영 사유로 취소되었습니다. 등록비와 후원 POP 을 돌려드렸습니다.'; + String get campaignStatusCancelled => + '운영 사유로 취소되었습니다. 등록비와 후원 POP 을 돌려드렸습니다.'; @override String get rankWindowDaily => '일간'; @@ -2385,7 +2388,12 @@ class AppLocalizationsKo extends AppLocalizations { String get campaignWeekdays => '일,월,화,수,목,금,토'; @override - String campaignPeriodRange(String startMonth, String startDay, String endMonth, String endDay) { + String campaignPeriodRange( + String startMonth, + String startDay, + String endMonth, + String endDay, + ) { return '$startMonth월 $startDay일 ~ $endMonth월 $endDay일'; } @@ -2429,7 +2437,12 @@ class AppLocalizationsKo extends AppLocalizations { String get campaignSubmitTitle => '이 내용으로 올릴까요?'; @override - String campaignSubmitBody(String title, String goal, String days, String fee) { + String campaignSubmitBody( + String title, + String goal, + String days, + String fee, + ) { return '$title · 목표 $goal POP · $days일\n등록비 $fee POP 이 빠지고 운영 검수 뒤 모금이 열립니다.'; } @@ -2636,7 +2649,14 @@ class AppLocalizationsKo extends AppLocalizations { } @override - String questCreateCost(String title, String reward, String count, String pool, String fee, String total) { + String questCreateCost( + String title, + String reward, + String count, + String pool, + String fee, + String total, + ) { return '$title\n보상 $reward POP × $count명 = $pool POP\n수수료 $fee POP (공개 시 소멸)\n총 $total POP 이 차감됩니다.'; } @@ -2778,7 +2798,7 @@ class AppLocalizationsKo extends AppLocalizations { String get homeGrowTogether => '함께 성장하기'; @override - String get homeArtistNews => '아티스트 소식'; + String get homeArtistNews => 'AI Daily Briefing'; @override String get growthConditionsTitle => '성장 조건'; @@ -2842,10 +2862,12 @@ class AppLocalizationsKo extends AppLocalizations { String get questCancel => '퀘스트 취소'; @override - String get questCancelInReview => '검수 중인 퀘스트를 취소하면 예치한 보상 POP 과 수수료를 모두 돌려드려요.'; + String get questCancelInReview => + '검수 중인 퀘스트를 취소하면 예치한 보상 POP 과 수수료를 모두 돌려드려요.'; @override - String get questCancelPublished => '공개된 퀘스트를 취소하면 참여가 바로 마감되고 남은 보상 POP 은 돌려드려요. 수수료는 돌려드리지 않아요.'; + String get questCancelPublished => + '공개된 퀘스트를 취소하면 참여가 바로 마감되고 남은 보상 POP 은 돌려드려요. 수수료는 돌려드리지 않아요.'; @override String get questUnderReview => '운영 검수 중이에요. 승인되면 공개됩니다.'; @@ -2966,7 +2988,8 @@ class AppLocalizationsKo extends AppLocalizations { String get onbPermLocation => '위치'; @override - String get onbPermLocationDesc => '위치 퀘스트의 장소 도착을 확인합니다. 위치 퀘스트를 처음 시작할 때 요청해요.'; + String get onbPermLocationDesc => + '위치 퀘스트의 장소 도착을 확인합니다. 위치 퀘스트를 처음 시작할 때 요청해요.'; @override String get onbPermContinue => '계속'; diff --git a/app/lib/l10n/app_localizations_zh.dart b/app/lib/l10n/app_localizations_zh.dart index 9a6caba..0996370 100644 --- a/app/lib/l10n/app_localizations_zh.dart +++ b/app/lib/l10n/app_localizations_zh.dart @@ -63,31 +63,25 @@ class AppLocalizationsZh extends AppLocalizations { @override String authProviderLogin(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'apple': '通过Apple登录', - 'google': '通过Google登录', - 'kakao': '通过Kakao登录', - 'line': '通过LINE登录', - 'other': '通过邮箱登录', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'apple': '通过Apple登录', + 'google': '通过Google登录', + 'kakao': '通过Kakao登录', + 'line': '通过LINE登录', + 'other': '通过邮箱登录', + }); return '$_temp0'; } @override String authProviderSignup(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'apple': '通过Apple注册', - 'google': '通过Google注册', - 'kakao': '通过Kakao注册', - 'line': '通过LINE注册', - 'other': '通过邮箱注册', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'apple': '通过Apple注册', + 'google': '通过Google注册', + 'kakao': '通过Kakao注册', + 'line': '通过LINE注册', + 'other': '通过邮箱注册', + }); return '$_temp0'; } @@ -525,31 +519,25 @@ class AppLocalizationsZh extends AppLocalizations { @override String authProviderStart(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'email': '使用邮箱开始', - 'kakao': '使用 Kakao 开始', - 'line': '使用 LINE 开始', - 'apple': '使用 Apple 开始', - 'other': '使用 Google 开始', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'email': '使用邮箱开始', + 'kakao': '使用 Kakao 开始', + 'line': '使用 LINE 开始', + 'apple': '使用 Apple 开始', + 'other': '使用 Google 开始', + }); return '$_temp0'; } @override String authProviderName(String provider) { - String _temp0 = intl.Intl.selectLogic( - provider, - { - 'email': '邮箱', - 'kakao': 'Kakao', - 'line': 'LINE', - 'apple': 'Apple', - 'other': 'Google', - }, - ); + String _temp0 = intl.Intl.selectLogic(provider, { + 'email': '邮箱', + 'kakao': 'Kakao', + 'line': 'LINE', + 'apple': 'Apple', + 'other': 'Google', + }); return '$_temp0'; } @@ -959,7 +947,9 @@ class AppLocalizationsZh extends AppLocalizations { String get zapRetrySame => '重新确认本次贡献'; @override - String get heroOwnerSuffix => '的'; + String heroOwner(String name) { + return '$name 的'; + } @override String get heroStartPrompt => '创建或加入星球,\n开启粉丝宇宙吧!'; @@ -1304,7 +1294,8 @@ class AppLocalizationsZh extends AppLocalizations { String get payEmpty => '暂无支付记录。'; @override - String get payRefundGuide => '消耗型商品:购买后 7 天内且未使用可退款,已部分使用的商品不予退款。\n订阅型商品:支付后 24 小时内未使用权益(如额外奖励)可退款。\n退款批准后 7–14 天内完成退款。'; + String get payRefundGuide => + '消耗型商品:购买后 7 天内且未使用可退款,已部分使用的商品不予退款。\n订阅型商品:支付后 24 小时内未使用权益(如额外奖励)可退款。\n退款批准后 7–14 天内完成退款。'; @override String get payDetailTitle => '支付详情'; @@ -1516,6 +1507,15 @@ class AppLocalizationsZh extends AppLocalizations { @override String get notifKindEvolution => '星球进化'; + @override + String get notifKindCampaignRefund => '活动退款'; + + @override + String get notifKindCampaignCancel => '活动取消'; + + @override + String get notifKindCampaignReport => '结果报告'; + @override String get notifTargetPost => '帖子'; @@ -1843,34 +1843,31 @@ class AppLocalizationsZh extends AppLocalizations { @override String countryName(String code) { - String _temp0 = intl.Intl.selectLogic( - code, - { - 'KR': '韩国', - 'JP': '日本', - 'US': '美国', - 'CN': '中国', - 'TW': '台湾', - 'HK': '香港', - 'TH': '泰国', - 'VN': '越南', - 'ID': '印度尼西亚', - 'PH': '菲律宾', - 'MY': '马来西亚', - 'SG': '新加坡', - 'IN': '印度', - 'GB': '英国', - 'FR': '法国', - 'DE': '德国', - 'ES': '西班牙', - 'BR': '巴西', - 'MX': '墨西哥', - 'CA': '加拿大', - 'AU': '澳大利亚', - 'ZZ': '未指定', - 'other': '-', - }, - ); + String _temp0 = intl.Intl.selectLogic(code, { + 'KR': '韩国', + 'JP': '日本', + 'US': '美国', + 'CN': '中国', + 'TW': '台湾', + 'HK': '香港', + 'TH': '泰国', + 'VN': '越南', + 'ID': '印度尼西亚', + 'PH': '菲律宾', + 'MY': '马来西亚', + 'SG': '新加坡', + 'IN': '印度', + 'GB': '英国', + 'FR': '法国', + 'DE': '德国', + 'ES': '西班牙', + 'BR': '巴西', + 'MX': '墨西哥', + 'CA': '加拿大', + 'AU': '澳大利亚', + 'ZZ': '未指定', + 'other': '-', + }); return '$_temp0'; } @@ -2385,7 +2382,12 @@ class AppLocalizationsZh extends AppLocalizations { String get campaignWeekdays => '日,一,二,三,四,五,六'; @override - String campaignPeriodRange(String startMonth, String startDay, String endMonth, String endDay) { + String campaignPeriodRange( + String startMonth, + String startDay, + String endMonth, + String endDay, + ) { return '$startMonth月$startDay日 ~ $endMonth月$endDay日'; } @@ -2429,7 +2431,12 @@ class AppLocalizationsZh extends AppLocalizations { String get campaignSubmitTitle => '按此内容提交吗?'; @override - String campaignSubmitBody(String title, String goal, String days, String fee) { + String campaignSubmitBody( + String title, + String goal, + String days, + String fee, + ) { return '$title · 目标 $goal POP · $days天\n将扣除 $fee POP 登记费,运营审核后开放筹集。'; } @@ -2636,7 +2643,14 @@ class AppLocalizationsZh extends AppLocalizations { } @override - String questCreateCost(String title, String reward, String count, String pool, String fee, String total) { + String questCreateCost( + String title, + String reward, + String count, + String pool, + String fee, + String total, + ) { return '$title\n奖励 $reward POP × $count人 = $pool POP\n手续费 $fee POP(发布时销毁)\n共扣除 $total POP。'; } @@ -2778,7 +2792,7 @@ class AppLocalizationsZh extends AppLocalizations { String get homeGrowTogether => '一起成长'; @override - String get homeArtistNews => '艺人动态'; + String get homeArtistNews => 'AI Daily Briefing'; @override String get growthConditionsTitle => '成长条件'; diff --git a/app/lib/l10n/app_zh.arb b/app/lib/l10n/app_zh.arb index 0328cd2..e3d0562 100644 --- a/app/lib/l10n/app_zh.arb +++ b/app/lib/l10n/app_zh.arb @@ -272,7 +272,7 @@ "campaignView": "查看活动", "growthFinalReached": "已到达最终阶段", "zapRetrySame": "重新确认本次贡献", - "heroOwnerSuffix": "的", + "heroOwner": "{name} 的", "heroStartPrompt": "创建或加入星球,\n开启粉丝宇宙吧!", "heroNebulaPrompt": "用活动获得的 POP\n为星云做贡献吧!", "heroRecentContribution": "凭借 {pop} POP 的贡献\n正在稳步成长。", @@ -450,6 +450,9 @@ "notifKindCampaign": "活动达成", "notifKindQuest": "任务完成", "notifKindEvolution": "星球进化", + "notifKindCampaignRefund": "活动退款", + "notifKindCampaignCancel": "活动取消", + "notifKindCampaignReport": "结果报告", "notifTargetPost": "帖子", "notifTargetCampaign": "活动", "notifTargetQuest": "任务详情", @@ -827,7 +830,7 @@ "heroNebulaGrowthRate": "星云成长率 {percent}%", "homeIncubator": "粉丝星球孵化器", "homeGrowTogether": "一起成长", - "homeArtistNews": "艺人动态", + "homeArtistNews": "AI Daily Briefing", "growthConditionsTitle": "成长条件", "eclipseButtonSoon": "{time}后将发生日食!\n摇动手机来阻止日食!", "eclipseButtonActive": "日食已发生!\n请在{seconds}秒内摇动手机来阻止!", diff --git a/app/lib/l10n/remote_app_localizations.dart b/app/lib/l10n/remote_app_localizations.dart index f24882a..7fc0ec4 100644 --- a/app/lib/l10n/remote_app_localizations.dart +++ b/app/lib/l10n/remote_app_localizations.dart @@ -887,7 +887,7 @@ class RemoteAppLocalizations extends AppLocalizations { String get heroNextEvolution => _remote['heroNextEvolution'] ?? _base.heroNextEvolution; @override - String get heroOwnerSuffix => _remote['heroOwnerSuffix'] ?? _base.heroOwnerSuffix; + String heroOwner(String name) => _fill('heroOwner', {'name': name}) ?? _base.heroOwner(name); @override String get heroParticipate => _remote['heroParticipate'] ?? _base.heroParticipate; @@ -1357,6 +1357,15 @@ class RemoteAppLocalizations extends AppLocalizations { @override String get notifKindCampaign => _remote['notifKindCampaign'] ?? _base.notifKindCampaign; + @override + String get notifKindCampaignCancel => _remote['notifKindCampaignCancel'] ?? _base.notifKindCampaignCancel; + + @override + String get notifKindCampaignRefund => _remote['notifKindCampaignRefund'] ?? _base.notifKindCampaignRefund; + + @override + String get notifKindCampaignReport => _remote['notifKindCampaignReport'] ?? _base.notifKindCampaignReport; + @override String get notifKindComment => _remote['notifKindComment'] ?? _base.notifKindComment; diff --git a/app/test/backend_repository_test.dart b/app/test/backend_repository_test.dart index 24b39dc..c27b9d4 100644 --- a/app/test/backend_repository_test.dart +++ b/app/test/backend_repository_test.dart @@ -196,7 +196,7 @@ void main() { final db = await _seed(); final snapshot = await FirestoreHomeRepository(_backend(db)).load(); - expect(snapshot.popBalance, 12540); + expect(snapshot.popBalance, 12840, reason: '총 보유 = 일반 12,540 + 기여 300'); expect(snapshot.liveTicker, contains('버프')); expect(snapshot.growth.fandomName, 'BTS'); // 설명 프레임 `2097:16391` — 인사 줄은 로그인 사용자 기준. 팬덤의 직전 기여자가 아니다. @@ -734,6 +734,21 @@ void main() { expect(again.first.title, '글 0'); }); + test('HOME 헤더 POP 은 총 보유(일반 + 기여 + 보류) — POP 내역 · 퀘스트 목록과 같은 값(179:29099 · 10/8 r11)', () async { + final db = await _seed(); + await db.doc('users/$_uid/wallet/main').set({ + 'activityBalance': 12130, + 'supportBalance': 330, + 'pendingActivity': 20, + }); + final backend = _backend(db); + final home = FirestoreHomeRepository(backend); + expect((await home.load()).popBalance, 12480); + expect(await home.watchPopBalance().first, 12480); + expect(await FirestoreQuestRepository(backend).popBalance(), 12480); + expect((await FirestoreMyRepository(backend).profile()).balancePop, 12480); + }); + test('다른 팬덤 글은 섞이지 않는다', () async { final db = await seedPlanet(); await db.collection('posts').add({ diff --git a/app/test/clipboard_copy_test.dart b/app/test/clipboard_copy_test.dart new file mode 100644 index 0000000..680d0b8 --- /dev/null +++ b/app/test/clipboard_copy_test.dart @@ -0,0 +1,25 @@ +import 'package:fancake/core/ui/clipboard_copy.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +/// 링크 복사 — Android 13+ 는 시스템이 「클립보드에 복사했어요」를 띄우므로 앱 토스트를 생략한다(10/8 r11 3-8). +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + const channel = MethodChannel('kr.co.fanuzu.app/device'); + final messenger = + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger; + + tearDown(() { + messenger.setMockMethodCallHandler(channel, null); + resetClipboardSdkCache(); + }); + + for (final (sdk, toasts) in [(33, 0), (34, 0), (32, 1), (null, 1)]) { + test('Android API $sdk → 앱 토스트 $toasts 회', () async { + messenger.setMockMethodCallHandler(channel, (_) async => sdk); + var count = 0; + await copyToClipboard('https://fanuzu.app/c/1', () => count++); + expect(count, toasts); + }); + } +} diff --git a/app/test/eclipse_live_test.dart b/app/test/eclipse_live_test.dart index dbc28cc..d1919ba 100644 --- a/app/test/eclipse_live_test.dart +++ b/app/test/eclipse_live_test.dart @@ -275,7 +275,10 @@ void main() { }); testWidgets('홈 라이브 띠가 라이브 이벤트를 그린다', (tester) async { - final repo = FakeEclipseRepository(); + // 방어 합류는 진행 중인 회차에서만 띠에 오른다(r11 2-5). + final repo = FakeEclipseRepository( + state: eclipseFixture(startAt: DateTime(2026, 9, 13), defense: 1), + ); addTearDown(repo.dispose); tester.view.physicalSize = const Size(1080, 2400); tester.view.devicePixelRatio = 2; @@ -293,16 +296,16 @@ void main() { ); await tester.pumpAndSettle(); - // 이벤트가 없으면 스냅샷의 폴백 문구를 그린다. - expect(find.textContaining('아이템 사용으로 버프가 발동'), findsOneWidget); + // 합류 이벤트가 아직 없으면 발생 소식을 그린다. + expect(find.text('BTS 행성에 이클립스가 발생했어요!'), findsOneWidget); repo.pushEvents([ LiveEvent(id: 'e1', nickname: '무민', defense: 20, at: DateTime(2026, 9, 14)), ]); await tester.pumpAndSettle(); - // 이벤트가 오면 그 문구가 폴백을 대체한다. - expect(find.textContaining('아이템 사용으로 버프가 발동'), findsNothing); + // 이벤트가 오면 그 문구가 발생 소식을 대체한다. + expect(find.text('BTS 행성에 이클립스가 발생했어요!'), findsNothing); expect( find.text('[LIVE] 무민님이 이클립스 방어에 합류했습니다!'), findsOneWidget, diff --git a/app/test/f0_screens_test.dart b/app/test/f0_screens_test.dart index 86f9273..29e0716 100644 --- a/app/test/f0_screens_test.dart +++ b/app/test/f0_screens_test.dart @@ -83,6 +83,20 @@ void main() { }); }); + test('캠페인 알림은 문서 ID 앞머리로 달성 · 환불 · 취소 · 결과보고를 가른다(10/8 r11)', () { + String label(String id) => AppNotification( + id: id, + kind: NotificationKind.campaign, + title: 't', + at: DateTime(2026, 10, 8), + ).sourceLabel; + expect(label('campaignSuccess_c1'), '캠페인 달성'); + expect(label('campaignRefund_tx1'), '캠페인 환불'); + expect(label('campaignCancel_c1'), '캠페인 취소'); + expect(label('campaignReport_c1_r1'), '결과 보고'); + expect(label('n1'), '캠페인 달성', reason: '모르는 앞머리는 종류 이름'); + }); + group('알림 화면 (F0 · 229:11265)', () { testWidgets('날짜 머리글과 항목을 함께 보여 준다', (tester) async { // 표본은 DateTime.now() 기준이라 자정 전후로 「오늘/어제」가 갈린다. diff --git a/app/test/f5_screens_test.dart b/app/test/f5_screens_test.dart index 49a8dbf..15a1424 100644 --- a/app/test/f5_screens_test.dart +++ b/app/test/f5_screens_test.dart @@ -267,6 +267,28 @@ void main() { expect(find.widgetWithText(FilledButton, '기여하기'), findsNothing); }); + testWidgets('모금 중이 아닌 타인 캠페인(달성 · 미달 환불 · 결과보고 · 취소)에는 기여하기 버튼이 없다(10/8 r11)', (tester) async { + for (final (status, shown) in [ + (CampaignStatus.funding, findsOneWidget), + (CampaignStatus.success, findsNothing), + (CampaignStatus.failed, findsNothing), + (CampaignStatus.reported, findsNothing), + (CampaignStatus.cancelled, findsNothing), + ]) { + await pumpWide( + tester, + CampaignDetailScreen( + key: ValueKey(status), + campaignId: 'c1', + repository: _Mine(status, supporters: 1, owned: false), + myPop: 0, + ), + ); + await tester.pumpAndSettle(); + expect(find.widgetWithText(FilledButton, '기여하기'), shown, reason: status.name); + } + }); + testWidgets('타인 캠페인에는 기여하기 버튼이 있다', (tester) async { await pumpWide(tester, CampaignDetailScreen(campaignId: 'c1')); await tester.pumpAndSettle(); @@ -529,10 +551,11 @@ void main() { /// 내 캠페인 상세 — 상태 · 후원 수를 바꿔 철회 버튼을 본다(B-58). class _Mine extends SampleCampaignRepository { - _Mine(this.status, {this.supporters = 0}); + _Mine(this.status, {this.supporters = 0, this.owned = true}); final CampaignStatus status; final int supporters; + final bool owned; final withdrawn = []; @override @@ -545,7 +568,7 @@ class _Mine extends SampleCampaignRepository { createdAt: c.createdAt, status: withdrawn.isEmpty ? status : CampaignStatus.withdrawn, goalPop: c.goalPop, raisedPop: supporters == 0 ? 0 : 10, - supporters: supporters, mine: true, + supporters: supporters, mine: owned, likes: 0, comments: 0, views: 0, shares: 0, ), mediaLabels: base.mediaLabels, diff --git a/app/test/f6_screens_test.dart b/app/test/f6_screens_test.dart index a3b4177..bd1b8f9 100644 --- a/app/test/f6_screens_test.dart +++ b/app/test/f6_screens_test.dart @@ -1,3 +1,4 @@ +import 'package:fancake/core/ui/clipboard_copy.dart'; import 'dart:async'; import 'dart:convert'; @@ -240,8 +241,18 @@ void main() { null, ), ); - expect(await shareProfile(profile, '문구 복사'), isTrue); - expect(clip, profileShareText(profile)); + // Android 12 이하는 앱이 알리고(true), 13+ 는 시스템이 알려 앱 토스트를 생략한다(false). + const device = MethodChannel('kr.co.fanuzu.app/device'); + addTearDown(() { + tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(device, null); + resetClipboardSdkCache(); + }); + for (final (sdk, announce) in [(32, true), (33, false)]) { + resetClipboardSdkCache(); + tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(device, (_) async => sdk); + expect(await shareProfile(profile, '문구 복사'), announce); + expect(clip, profileShareText(profile)); + } }); testWidgets('티어 카드를 누르면 행성별 티어로 넘어간다', (tester) async { diff --git a/app/test/home_i18n_layout_test.dart b/app/test/home_i18n_layout_test.dart new file mode 100644 index 0000000..6676c42 --- /dev/null +++ b/app/test/home_i18n_layout_test.dart @@ -0,0 +1,86 @@ +import 'package:fancake/core/i18n/app_locale.dart'; +import 'package:fancake/core/theme/app_theme.dart'; +import 'package:fancake/features/home/home_data.dart'; +import 'package:fancake/features/home/widgets/home_hero.dart'; +import 'package:fancake/features/home/widgets/home_weekly.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:flutter_test/flutter_test.dart'; + +/// 긴 언어(es · ja)에서 HOME 이 깨지지 않는다 — 10/8 r11 실기기(Flip3) 관찰. +void main() { + tearDown(() => appL10n = koL10n); + + Future pump(WidgetTester tester, Locale locale, Widget child, + {double width = 360}) async { + tester.view.physicalSize = Size(width * 3, 2400); + tester.view.devicePixelRatio = 3; + addTearDown(tester.view.reset); + await tester.pumpWidget(MaterialApp( + theme: buildAppTheme(), + locale: locale, + supportedLocales: appLocales, + localizationsDelegates: const [ + RemoteL10nDelegate({}), + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + home: Scaffold(body: child), + )); + await tester.pumpAndSettle(); + } + + const growth = PlanetGrowth( + fandomName: '오로라', + contributorName: 'Kinos', + stage: 2, + contributedPop: 0, + growthPercent: 1, + currentPop: 189, + requiredPop: 16575, + ); + + testWidgets('es 주간 카드 「Mis POP」 라벨이 한 글자씩 줄바꿈되지 않는다', (tester) async { + final weekly = HomeWeekly.from( + fandomId: 'f', + snapshots: const [], + fandom: const {}, + myWeekPop: 250, + wallet: const {'activityBalance': 12130, 'supportBalance': 330}, + ); + await pump(tester, const Locale('es'), HomeWeeklyCard(weekly: weekly)); + expect(tester.takeException(), isNull); + // 한 줄 = 글자 13 × 행간 18/13. + expect(tester.getSize(find.text('Mis POP')).height, 18); + }); + + testWidgets('es 인사 줄은 「De Kinos」 — 「aporta:」 오역이 아니다', (tester) async { + await pump(tester, const Locale('es'), const HomeHero(growth: growth)); + expect(find.text('De '), findsOneWidget); + expect(find.text('Kinos'), findsOneWidget); + expect(find.textContaining('aporta'), findsNothing); + }); + + testWidgets('es 성장 말풍선이 성장률 글자를 가리지 않는다', (tester) async { + await pump(tester, const Locale('es'), const HomeHero(growth: growth), + width: 540); + final rate = tester.getRect(find.text('Crecimiento del planeta 1%')); + final bubble = tester.getRect(find.text('Ver condiciones')); + expect(bubble.left, greaterThanOrEqualTo(rate.right)); + }); + + testWidgets('ja 제목이 미니맵 아래로 들어가지 않는다', (tester) async { + await pump( + tester, + const Locale('ja'), + const HomeHero( + growth: growth, + miniMap: SizedBox(width: HomeHero.miniMapSize, height: 90), + ), + ); + expect(tester.takeException(), isNull); + final title = tester.getRect(find.text('みんなで育てるファンダム惑星')); + expect(title.right, lessThanOrEqualTo(360 - HomeHero.miniMapSize)); + }); +} diff --git a/app/test/home_screen_test.dart b/app/test/home_screen_test.dart index 9ff2715..304ba4c 100644 --- a/app/test/home_screen_test.dart +++ b/app/test/home_screen_test.dart @@ -166,7 +166,7 @@ void main() { for (final title in [ 'TODAY’S QUEST', '팬덤행성 인큐베이터', - '아티스트 소식', + 'AI Daily Briefing', 'HOT ARCHIVE', '인기 K-INSIDE', ]) { @@ -296,7 +296,7 @@ void main() { /// *문구도 노출하지 않음)*. 서버가 당일 게시분을 0 건으로 주는 상황이다. testWidgets('브리핑이 0 건이면 구획 제목까지 숨긴다', (tester) async { await _pump(tester, repo: const _BriefingRepo([])); - expect(find.text('아티스트 소식'), findsNothing); + expect(find.text('AI Daily Briefing'), findsNothing); // 빈 상태 문구도 두지 않는다 — 아래 구획은 그대로 있어야 한다. await tester.scrollUntilVisible( find.text('HOT ARCHIVE'), @@ -309,7 +309,7 @@ void main() { testWidgets('브리핑 헤더의 「공유」는 브리핑 공유 카드를 연다(F8 · 별첨 1 ③-5)', (tester) async { await _pump(tester, repo: _BriefingRepo([_brief('공유할 한 줄')])); final header = find.byWidgetPredicate( - (w) => w is HomeSectionHeader && w.title == '아티스트 소식', + (w) => w is HomeSectionHeader && w.title == 'AI Daily Briefing', ); await tester.scrollUntilVisible(find.text('공유할 한 줄'), 220, scrollable: find.byType(Scrollable).first); @@ -328,7 +328,7 @@ void main() { 220, scrollable: find.byType(Scrollable).first, ); - expect(find.text('아티스트 소식'), findsOneWidget); + expect(find.text('AI Daily Briefing'), findsOneWidget); expect(find.text('오늘 게시된 한 줄'), findsOneWidget); }); diff --git a/app/test/quest_react_push_test.dart b/app/test/quest_react_push_test.dart index 4ac590a..45d16c0 100644 --- a/app/test/quest_react_push_test.dart +++ b/app/test/quest_react_push_test.dart @@ -298,5 +298,43 @@ void main() { expect(zap.balance, 100); await tester.pump(const Duration(seconds: 2)); }); + + testWidgets('HOME 반영 문구는 행성 상자 위쪽 — 아래 성장 카드(행성 이름 · 말풍선)를 덮지 않는다(10/8 r11)', (tester) async { + final zap = ZapController(SampleGalaxyRepository(), onFailure: (_) {}); + addTearDown(zap.dispose); + await tester.pumpWidget( + MaterialApp( + home: Scaffold( + body: ListenableBuilder( + listenable: zap, + builder: (_, _) => ZapFeedback( + fandomName: 'BTS', + quest: zap.questReaction, + touchSerial: zap.touchSerial, + pending: zap.pending > 0 || zap.sending, + result: zap.result, + source: Offset.zero, + target: const Offset(200, 400), + radius: 80, + messageAboveTarget: true, + ), + ), + ), + ), + ); + final reacting = zap.react(); + await tester.pump(const Duration(milliseconds: 400)); + await reacting; + await tester.pump(); + final text = find.text('퀘스트 완료가 BTS 성장에 반영되었습니다'); + expect(text, findsOneWidget); + // 행성 상자(반 변 80 / 0.4 / 2 = 100) 윗변 y300 에서 시작해 행성 중심(y400) 위에서 끝난다. + final box = tester.getRect( + find.ancestor(of: text, matching: find.byType(DecoratedBox)).first, + ); + expect(box.top, 300); + expect(box.bottom, lessThan(400)); + await tester.pump(const Duration(seconds: 2)); + }); }); } diff --git a/app/test/uxfx_round2_test.dart b/app/test/uxfx_round2_test.dart index 8c01400..458699e 100644 --- a/app/test/uxfx_round2_test.dart +++ b/app/test/uxfx_round2_test.dart @@ -134,6 +134,35 @@ void main() { final l = line(eclipse: eclipseFixture(startAt: start), hero: true)!; expect(l.hero, isFalse); }); + test('끝난 회차의 방어 합류는 띠에 남지 않는다 (r11 2-5)', () { + expect(line(events: [join])!.text, 'fallback', reason: '진행 중 회차 없음'); + expect( + line( + eclipse: eclipseFixture( + startAt: start, + defense: 1, + result: EclipseResult.failure, + ), + events: [join], + )!.text, + 'fallback', + reason: '판정 끝난 회차', + ); + expect( + line( + eclipse: eclipseFixture(startAt: DateTime.now(), defense: 1), + events: [ + LiveEvent( + id: 'old', + nickname: '팬', + at: DateTime.now().subtract(const Duration(minutes: 40)), + ), + ], + )!.text, + 'BTS 행성에 이클립스가 발생했어요!', + reason: '지난 회차의 합류', + ); + }); test('아무것도 없으면 폴백', () { expect(line()!.text, 'fallback'); });