From 3bc79ad8e22d6ae3cfd5063f223e89c75c1cd5ba Mon Sep 17 00:00:00 2001 From: Vicky <10212746+haifeng-jiang@user.noreply.gitee.com> Date: Sat, 31 Oct 2026 00:02:53 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix(i18n):=20=E5=8E=BB=E6=8E=89=E5=8D=B0?= =?UTF-8?q?=E5=B0=BC=E8=AF=AD=E5=86=85=E5=AE=B9=E5=AE=8C=E6=95=B4=E6=80=A7?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=EF=BC=8C=E7=BC=BA=E5=A4=B1=E6=97=B6=E5=9B=9E?= =?UTF-8?q?=E9=80=80=E4=B8=AD=E6=96=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/core/data/models/drama.dart | 4 +-- lib/core/data/models/locale_text.dart | 13 ------- lib/core/formatting/content_locale_guard.dart | 21 ------------ .../widgets/discover_search_results.dart | 13 ++----- .../home/widgets/home_category_dramas.dart | 6 +--- lib/pages/home/widgets/home_feed_grid.dart | 16 ++------- .../recommend/recommend_discover_page.dart | 6 +--- lib/pages/recommend/recommend_page.dart | 6 +--- .../widgets/all_dramas_filter_grid.dart | 6 +--- .../widgets/playlist_detail_page.dart | 6 +--- .../widgets/recommend_sections_view.dart | 9 ++--- test/formatting/localized_content_test.dart | 34 ++----------------- 12 files changed, 17 insertions(+), 123 deletions(-) delete mode 100644 lib/core/formatting/content_locale_guard.dart diff --git a/lib/core/data/models/drama.dart b/lib/core/data/models/drama.dart index 23e30dd..6611f72 100644 --- a/lib/core/data/models/drama.dart +++ b/lib/core/data/models/drama.dart @@ -241,11 +241,11 @@ class Drama { } String localizedTitle(String languageCode) { - return localizedRequiredText(languageCode, title, titleLocales); + return localizedText(languageCode, title, titleLocales); } String localizedSynopsis(String languageCode) { - return localizedRequiredText(languageCode, synopsis, synopsisLocales); + return localizedText(languageCode, synopsis, synopsisLocales); } String localizedTag(String languageCode) { diff --git a/lib/core/data/models/locale_text.dart b/lib/core/data/models/locale_text.dart index 058004d..f397393 100644 --- a/lib/core/data/models/locale_text.dart +++ b/lib/core/data/models/locale_text.dart @@ -18,16 +18,3 @@ String localizedText( if (chinese.isNotEmpty) return chinese; return fallback; } - -/// 按当前语言取必须本地化的文案;印尼语缺失时不回退中文。 -String localizedRequiredText( - String languageCode, - String fallback, - Map locales, -) { - final primaryCode = languageCode.split(RegExp(r'[_-]')).first; - final selected = locales[languageCode] ?? locales[primaryCode] ?? ''; - if (selected.trim().isNotEmpty) return selected; - if (primaryCode == 'id') return ''; - return localizedText(primaryCode, fallback, locales); -} diff --git a/lib/core/formatting/content_locale_guard.dart b/lib/core/formatting/content_locale_guard.dart deleted file mode 100644 index 8735d83..0000000 --- a/lib/core/formatting/content_locale_guard.dart +++ /dev/null @@ -1,21 +0,0 @@ -// Author: fruit.com.cn - -import '../data/models/drama.dart'; - -const String _indonesianLanguageCode = 'id'; - -/// 判断短剧是否满足当前界面语言的基础文案完整度。 -bool isDramaCompleteForLocale(Drama drama, String languageCode) { - final primaryCode = languageCode.split(RegExp(r'[_-]')).first; - if (primaryCode != _indonesianLanguageCode) return true; - return drama.localizedTitle(primaryCode).trim().isNotEmpty && - drama.localizedSynopsis(primaryCode).trim().isNotEmpty; -} - -/// 过滤不满足首发语言文案完整度的短剧,保持原顺序。 -List visibleDramasForLocale( - Iterable dramas, - String languageCode, -) => dramas - .where((drama) => isDramaCompleteForLocale(drama, languageCode)) - .toList(growable: false); diff --git a/lib/pages/discover/widgets/discover_search_results.dart b/lib/pages/discover/widgets/discover_search_results.dart index dd46451..076c427 100644 --- a/lib/pages/discover/widgets/discover_search_results.dart +++ b/lib/pages/discover/widgets/discover_search_results.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import '../../../core/data/models/drama.dart'; import '../../../core/formatting/error_text.dart'; -import '../../../core/formatting/content_locale_guard.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/widgets/empty_state.dart'; import '../../../l10n/app_localizations.dart'; @@ -34,18 +33,10 @@ class DiscoverSearchResults extends StatelessWidget { @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; - final visibleResults = visibleDramasForLocale( - results, - Localizations.localeOf(context).languageCode, - ); - if (!loading && error == null && visibleResults.isNotEmpty) { + if (!loading && error == null && results.isNotEmpty) { return SliverPadding( padding: _topPadding, - sliver: SliverDramaGrid( - l10n: l10n, - dramas: visibleResults, - onOpen: onOpen, - ), + sliver: SliverDramaGrid(l10n: l10n, dramas: results, onOpen: onOpen), ); } return SliverPadding( diff --git a/lib/pages/home/widgets/home_category_dramas.dart b/lib/pages/home/widgets/home_category_dramas.dart index 9e0bafc..f74df38 100644 --- a/lib/pages/home/widgets/home_category_dramas.dart +++ b/lib/pages/home/widgets/home_category_dramas.dart @@ -7,7 +7,6 @@ import 'package:provider/provider.dart'; import '../../../core/data/models/drama.dart'; import '../../../core/data/services/category_controller.dart'; -import '../../../core/formatting/content_locale_guard.dart'; import '../../../core/theme/app_dimens.dart'; import '../../../core/widgets/app_pull_to_refresh.dart'; import '../../../core/widgets/drama_grid_skeleton.dart'; @@ -78,10 +77,7 @@ class _HomeCategoryDramasState extends State { final controller = context.watch(); final categoryId = widget.lockedCategoryId ?? ''; final slot = categoryId.isEmpty ? null : controller.slotOf(categoryId); - final dramas = visibleDramasForLocale( - slot?.dramas ?? const [], - Localizations.localeOf(context).languageCode, - ); + final dramas = slot?.dramas ?? const []; return Column( children: [ Expanded( diff --git a/lib/pages/home/widgets/home_feed_grid.dart b/lib/pages/home/widgets/home_feed_grid.dart index a07b7d8..3afbc7f 100644 --- a/lib/pages/home/widgets/home_feed_grid.dart +++ b/lib/pages/home/widgets/home_feed_grid.dart @@ -12,7 +12,6 @@ import '../../../core/data/services/catalog_controller.dart'; import '../../../core/data/services/category_controller.dart'; import '../../../core/data/services/home_feed_controller.dart'; import '../../../core/data/services/wallet_controller.dart'; -import '../../../core/formatting/content_locale_guard.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_dimens.dart'; import '../../../core/widgets/app_pull_to_refresh.dart'; @@ -195,10 +194,7 @@ class _HomeFeedGridState extends State { mainAxisSpacing: AppDimens.homeGridRowGap, ); } - final dramas = _dramasFor( - category, - Localizations.localeOf(context).languageCode, - ); + final dramas = _dramasFor(category); if (widget.feedController.loadingFirstPage && dramas.isEmpty) { return const DramaGridSkeleton( key: Key('home-grid-skeleton'), @@ -328,14 +324,8 @@ class _HomeFeedGridState extends State { ]; } - List _dramasFor( - HomeGridCategoryShortcut category, - String languageCode, - ) { - final dramas = visibleDramasForLocale( - widget.feedController.dramas, - languageCode, - ); + List _dramasFor(HomeGridCategoryShortcut category) { + final dramas = widget.feedController.dramas; final categoryName = category.categoryName.toLowerCase(); if (categoryName.isEmpty) return dramas; final matched = dramas diff --git a/lib/pages/recommend/recommend_discover_page.dart b/lib/pages/recommend/recommend_discover_page.dart index 8178700..ce9a17f 100644 --- a/lib/pages/recommend/recommend_discover_page.dart +++ b/lib/pages/recommend/recommend_discover_page.dart @@ -9,7 +9,6 @@ import '../../core/data/models/drama.dart'; import '../../core/data/models/home_feed.dart'; import '../../core/data/remote/catalog_api.dart'; import '../../core/data/services/category_controller.dart'; -import '../../core/formatting/content_locale_guard.dart'; import '../../core/theme/app_colors.dart'; import '../../core/widgets/app_pull_to_refresh.dart'; import '../../core/widgets/empty_state.dart'; @@ -285,10 +284,7 @@ class _ChannelFeedState extends State<_ChannelFeed> super.build(context); final categories = context.watch(); final slot = categories.slotOf(widget.categoryId); - final dramas = visibleDramasForLocale( - slot.dramas, - Localizations.localeOf(context).languageCode, - ); + final dramas = slot.dramas; final showCarousel = widget.isFeatured && widget.banners.isNotEmpty; final bottomInset = MediaQuery.of(context).padding.bottom; diff --git a/lib/pages/recommend/recommend_page.dart b/lib/pages/recommend/recommend_page.dart index 3087aa4..e7f136e 100644 --- a/lib/pages/recommend/recommend_page.dart +++ b/lib/pages/recommend/recommend_page.dart @@ -13,7 +13,6 @@ import '../../core/data/services/download_controller.dart'; import '../../core/data/services/home_feed_controller.dart'; import '../../core/data/services/playlist_controller.dart'; import '../../core/data/services/wallet_controller.dart'; -import '../../core/formatting/content_locale_guard.dart'; import '../../core/theme/app_colors.dart'; import '../../core/widgets/empty_state.dart'; import '../../l10n/app_localizations.dart'; @@ -299,10 +298,7 @@ class _RecommendPageState extends State Widget _recommendFeed(BuildContext context) { final feed = widget.feedController; - final dramas = visibleDramasForLocale( - widget.feedController.dramas, - Localizations.localeOf(context).languageCode, - ); + final dramas = widget.feedController.dramas; if (dramas.isNotEmpty) { return PlayerPage( key: const Key('recommend-feed-player'), diff --git a/lib/pages/recommend/widgets/all_dramas_filter_grid.dart b/lib/pages/recommend/widgets/all_dramas_filter_grid.dart index 623bb22..75d28ab 100644 --- a/lib/pages/recommend/widgets/all_dramas_filter_grid.dart +++ b/lib/pages/recommend/widgets/all_dramas_filter_grid.dart @@ -10,7 +10,6 @@ import '../../../core/data/models/drama.dart'; import '../../../core/data/remote/catalog_api.dart'; import '../../../core/data/services/all_dramas_controller.dart'; import '../../../core/data/services/home_feed_controller.dart'; -import '../../../core/formatting/content_locale_guard.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_dimens.dart'; import '../../../core/widgets/app_pull_to_refresh.dart'; @@ -108,10 +107,7 @@ class _AllDramasFilterGridState extends State { } Widget _dramaList(AppLocalizations l10n, double itemExtent) { - final dramas = visibleDramasForLocale( - _dramas, - Localizations.localeOf(context).languageCode, - ); + final dramas = _dramas; return NotificationListener( onNotification: _onScroll, child: AppPullToRefresh( diff --git a/lib/pages/recommend/widgets/playlist_detail_page.dart b/lib/pages/recommend/widgets/playlist_detail_page.dart index 4b9933b..d847754 100644 --- a/lib/pages/recommend/widgets/playlist_detail_page.dart +++ b/lib/pages/recommend/widgets/playlist_detail_page.dart @@ -4,7 +4,6 @@ import 'package:flutter/material.dart'; import '../../../core/data/models/drama.dart'; import '../../../core/data/models/playlist_detail.dart'; -import '../../../core/formatting/content_locale_guard.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_dimens.dart'; import '../../../core/widgets/app_pull_to_refresh.dart'; @@ -158,10 +157,7 @@ class _PlaylistDetailPageState extends State { } Widget _body(double itemExtent) { - final visibleDramas = visibleDramasForLocale( - _dramas, - Localizations.localeOf(context).languageCode, - ); + final visibleDramas = _dramas; return CustomScrollView( key: const Key('playlist-detail-scroll'), physics: AppPullToRefresh.physics, diff --git a/lib/pages/recommend/widgets/recommend_sections_view.dart b/lib/pages/recommend/widgets/recommend_sections_view.dart index 87be83b..7979962 100644 --- a/lib/pages/recommend/widgets/recommend_sections_view.dart +++ b/lib/pages/recommend/widgets/recommend_sections_view.dart @@ -8,7 +8,6 @@ import '../../../core/data/models/playlist_detail.dart'; import '../../../core/data/services/category_controller.dart'; import '../../../core/data/services/home_feed_controller.dart'; import '../../../core/data/services/playlist_controller.dart'; -import '../../../core/formatting/content_locale_guard.dart'; import '../../../core/theme/app_colors.dart'; import '../../../core/theme/app_dimens.dart'; import '../../../core/widgets/app_pull_to_refresh.dart'; @@ -44,8 +43,7 @@ class RecommendSectionsView extends StatelessWidget { @override Widget build(BuildContext context) { final l10n = AppLocalizations.of(context)!; - final languageCode = Localizations.localeOf(context).languageCode; - final source = visibleDramasForLocale(feedController.dramas, languageCode); + final source = feedController.dramas; final remote = playlists; return AppPullToRefresh( key: const Key('recommend-sections-refresh'), @@ -165,10 +163,7 @@ class RecommendSectionsView extends StatelessWidget { subtitle: playlist.localizedDescription( Localizations.localeOf(context).languageCode, ), - dramas: visibleDramasForLocale( - playlist.dramas, - Localizations.localeOf(context).languageCode, - ).take(_sectionPreviewCount).toList(), + dramas: playlist.dramas.take(_sectionPreviewCount).toList(), onMore: () => onOpenPlaylist?.call(playlist), ), ); diff --git a/test/formatting/localized_content_test.dart b/test/formatting/localized_content_test.dart index 9e1e834..8f5935b 100644 --- a/test/formatting/localized_content_test.dart +++ b/test/formatting/localized_content_test.dart @@ -1,7 +1,6 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:fruitshorts/core/data/models/drama.dart'; import 'package:fruitshorts/core/formatting/localized_content.dart'; -import 'package:fruitshorts/core/formatting/content_locale_guard.dart'; import 'package:fruitshorts/l10n/app_localizations_en.dart'; import 'package:fruitshorts/l10n/app_localizations_id.dart'; import 'package:fruitshorts/l10n/app_localizations_zh.dart'; @@ -77,7 +76,7 @@ void main() { expect(localizedDramaSynopsis(zh, custom), 'Custom synopsis'); }); - test('should_not_fall_back_to_chinese_when_indonesian_copy_is_missing', () { + test('should_fall_back_to_chinese_when_indonesian_copy_is_missing', () { const drama = Drama( id: 'missing-id-copy', title: '古城', @@ -87,35 +86,8 @@ void main() { posterUrl: '/files/poster.png', ); - expect(drama.localizedTitle('id'), isEmpty); - expect(drama.localizedSynopsis('id'), isEmpty); - }); - - test('should_filter_incomplete_indonesian_content_from_visible_list', () { - const complete = Drama( - id: 'complete-id-copy', - title: 'Kota Lama', - synopsis: 'Kisah dari kota lama.', - titleLocales: {'id': 'Kota Lama'}, - synopsisLocales: {'id': 'Kisah dari kota lama.'}, - posterUrl: '/files/complete.png', - ); - const incomplete = Drama( - id: 'incomplete-id-copy', - title: '古城', - synopsis: '中文简介', - titleLocales: {'zh': '古城'}, - synopsisLocales: {'zh': '中文简介'}, - posterUrl: '/files/incomplete.png', - ); - - expect(isDramaCompleteForLocale(complete, 'id'), isTrue); - expect(isDramaCompleteForLocale(incomplete, 'id'), isFalse); - expect(visibleDramasForLocale([complete, incomplete], 'id'), [complete]); - expect(visibleDramasForLocale([complete, incomplete], 'en'), [ - complete, - incomplete, - ]); + expect(drama.localizedTitle('id'), '古城'); + expect(drama.localizedSynopsis('id'), '中文简介'); }); test('should_ignore_raw_catalog_text_when_drama_is_seeded', () { From 2ddf9ee1c625b892edec408c1306d3732baf65a7 Mon Sep 17 00:00:00 2001 From: Vicky <10212746+haifeng-jiang@user.noreply.gitee.com> Date: Sat, 31 Oct 2026 00:02:53 +0800 Subject: [PATCH 2/2] =?UTF-8?q?test(config):=20=E6=9C=8D=E5=8A=A1=E5=9C=B0?= =?UTF-8?q?=E5=9D=80=E6=96=AD=E8=A8=80=E8=B7=9F=E9=9A=8F=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E5=BC=80=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/config/server_endpoint_test.dart | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/test/config/server_endpoint_test.dart b/test/config/server_endpoint_test.dart index 3226838..4db8a3c 100644 --- a/test/config/server_endpoint_test.dart +++ b/test/config/server_endpoint_test.dart @@ -62,10 +62,12 @@ void main() { }); test('should_pick_address_by_environment_switch', () { - // 仓库里的开关默认指向开发环境。 - expect(AppConfig.useDevConfig, isTrue); - expect(AppConfig.baseUrl, DevConfig.baseUrl); - expect(AppConfig.apiBaseUrl, DevConfig.baseUrl); + // 跟随开关:开发分支为 true(开发地址),发版分支为 false(生产地址)。 + final expected = AppConfig.useDevConfig + ? DevConfig.baseUrl + : ProdConfig.baseUrl; + expect(AppConfig.baseUrl, expected); + expect(AppConfig.apiBaseUrl, expected); expect(Uri.parse(AppConfig.baseUrl).port, 8081); }); @@ -87,7 +89,10 @@ void main() { AppConfig.applyRuntimeBaseUrl('http://runtime.test:8081'); expect(AppConfig.apiBaseUrl, 'http://runtime.test:8081'); - expect(AppConfig.baseUrl, DevConfig.baseUrl); + expect( + AppConfig.baseUrl, + AppConfig.useDevConfig ? DevConfig.baseUrl : ProdConfig.baseUrl, + ); }); test('should_append_host_to_relative_media_paths', () {