Skip to content

Commit 2228d03

Browse files
authored
Merge pull request #30 from headlines-toolkit/refactor_improve_localizations
Refactor improve localizations
2 parents 652990a + a09d30e commit 2228d03

File tree

7 files changed

+482
-46
lines changed

7 files changed

+482
-46
lines changed

lib/app_configuration/view/app_configuration_page.dart

Lines changed: 71 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_bloc/flutter_bloc.dart';
33
import 'package:ht_dashboard/app_configuration/bloc/app_configuration_bloc.dart';
4+
import 'package:ht_dashboard/l10n/app_localizations.dart';
45
import 'package:ht_dashboard/l10n/l10n.dart';
56
import 'package:ht_dashboard/shared/constants/app_spacing.dart';
67
import 'package:ht_dashboard/shared/widgets/widgets.dart';
@@ -766,15 +767,14 @@ class _UserPreferenceLimitsFormState extends State<_UserPreferenceLimitsForm> {
766767
@override
767768
Widget build(BuildContext context) {
768769
final userPreferenceConfig = widget.remoteConfig.userPreferenceConfig;
770+
final l10n = context.l10n;
769771

770772
return Column(
771773
children: [
772774
widget.buildIntField(
773775
context,
774-
label: 'Followed Items Limit',
775-
description:
776-
'Maximum number of countries, news sources, or categories this '
777-
'user role can follow (each type has its own limit).',
776+
label: _getFollowedItemsLimitLabel(l10n),
777+
description: _getFollowedItemsLimitDescription(l10n),
778778
value: _getFollowedItemsLimit(userPreferenceConfig),
779779
onChanged: (value) {
780780
widget.onConfigChanged(
@@ -790,8 +790,8 @@ class _UserPreferenceLimitsFormState extends State<_UserPreferenceLimitsForm> {
790790
),
791791
widget.buildIntField(
792792
context,
793-
label: 'Saved Headlines Limit',
794-
description: 'Maximum number of headlines this user role can save.',
793+
label: _getSavedHeadlinesLimitLabel(l10n),
794+
description: _getSavedHeadlinesLimitDescription(l10n),
795795
value: _getSavedHeadlinesLimit(userPreferenceConfig),
796796
onChanged: (value) {
797797
widget.onConfigChanged(
@@ -809,6 +809,50 @@ class _UserPreferenceLimitsFormState extends State<_UserPreferenceLimitsForm> {
809809
);
810810
}
811811

812+
String _getFollowedItemsLimitLabel(AppLocalizations l10n) {
813+
switch (widget.userRole) {
814+
case AppUserRole.guestUser:
815+
return l10n.guestFollowedItemsLimitLabel;
816+
case AppUserRole.standardUser:
817+
return l10n.standardUserFollowedItemsLimitLabel;
818+
case AppUserRole.premiumUser:
819+
return l10n.premiumFollowedItemsLimitLabel;
820+
}
821+
}
822+
823+
String _getFollowedItemsLimitDescription(AppLocalizations l10n) {
824+
switch (widget.userRole) {
825+
case AppUserRole.guestUser:
826+
return l10n.guestFollowedItemsLimitDescription;
827+
case AppUserRole.standardUser:
828+
return l10n.standardUserFollowedItemsLimitDescription;
829+
case AppUserRole.premiumUser:
830+
return l10n.premiumFollowedItemsLimitDescription;
831+
}
832+
}
833+
834+
String _getSavedHeadlinesLimitLabel(AppLocalizations l10n) {
835+
switch (widget.userRole) {
836+
case AppUserRole.guestUser:
837+
return l10n.guestSavedHeadlinesLimitLabel;
838+
case AppUserRole.standardUser:
839+
return l10n.standardUserSavedHeadlinesLimitLabel;
840+
case AppUserRole.premiumUser:
841+
return l10n.premiumSavedHeadlinesLimitLabel;
842+
}
843+
}
844+
845+
String _getSavedHeadlinesLimitDescription(AppLocalizations l10n) {
846+
switch (widget.userRole) {
847+
case AppUserRole.guestUser:
848+
return l10n.guestSavedHeadlinesLimitDescription;
849+
case AppUserRole.standardUser:
850+
return l10n.standardUserSavedHeadlinesLimitDescription;
851+
case AppUserRole.premiumUser:
852+
return l10n.premiumSavedHeadlinesLimitDescription;
853+
}
854+
}
855+
812856
int _getFollowedItemsLimit(UserPreferenceConfig config) {
813857
switch (widget.userRole) {
814858
case AppUserRole.guestUser:
@@ -990,15 +1034,14 @@ class _AdConfigFormState extends State<_AdConfigForm> {
9901034
@override
9911035
Widget build(BuildContext context) {
9921036
final adConfig = widget.remoteConfig.adConfig;
1037+
final l10n = context.l10n;
9931038

9941039
return Column(
9951040
children: [
9961041
widget.buildIntField(
9971042
context,
998-
label: 'Ad Frequency',
999-
description:
1000-
'How often an ad can appear for this user role (e.g., a value '
1001-
'of 5 means an ad could be placed after every 5 news items).',
1043+
label: l10n.adFrequencyLabel,
1044+
description: l10n.adFrequencyDescription,
10021045
value: _getAdFrequency(adConfig),
10031046
onChanged: (value) {
10041047
widget.onConfigChanged(
@@ -1011,10 +1054,8 @@ class _AdConfigFormState extends State<_AdConfigForm> {
10111054
),
10121055
widget.buildIntField(
10131056
context,
1014-
label: 'Ad Placement Interval',
1015-
description:
1016-
'Minimum number of news items that must be shown before the '
1017-
'very first ad appears for this user role.',
1057+
label: l10n.adPlacementIntervalLabel,
1058+
description: l10n.adPlacementIntervalDescription,
10181059
value: _getAdPlacementInterval(adConfig),
10191060
onChanged: (value) {
10201061
widget.onConfigChanged(
@@ -1027,10 +1068,8 @@ class _AdConfigFormState extends State<_AdConfigForm> {
10271068
),
10281069
widget.buildIntField(
10291070
context,
1030-
label: 'Articles Before Interstitial Ads',
1031-
description:
1032-
'Number of articles this user role needs to read before a '
1033-
'full-screen interstitial ad is shown.',
1071+
label: l10n.articlesBeforeInterstitialAdsLabel,
1072+
description: l10n.articlesBeforeInterstitialAdsDescription,
10341073
value: _getArticlesBeforeInterstitial(adConfig),
10351074
onChanged: (value) {
10361075
widget.onConfigChanged(
@@ -1198,27 +1237,29 @@ class _AccountActionConfigFormState extends State<_AccountActionConfigForm> {
11981237
super.dispose();
11991238
}
12001239

1201-
String _formatLabel(String enumName) {
1202-
// Converts camelCase to Title Case
1203-
final spaced = enumName.replaceAllMapped(
1204-
RegExp('([A-Z])'),
1205-
(match) => ' ${match.group(1)}',
1206-
);
1207-
return '${spaced[0].toUpperCase()}${spaced.substring(1)} Days';
1208-
}
1209-
12101240
@override
12111241
Widget build(BuildContext context) {
12121242
final accountActionConfig = widget.remoteConfig.accountActionConfig;
12131243
final relevantActionTypes = _getDaysMap(accountActionConfig).keys.toList();
1244+
final l10n = context.l10n;
12141245

12151246
return Column(
12161247
children: relevantActionTypes.map((actionType) {
1248+
final localizedActionType = switch (actionType) {
1249+
FeedActionType.linkAccount => l10n.feedActionTypeLinkAccount,
1250+
FeedActionType.rateApp => l10n.feedActionTypeRateApp,
1251+
FeedActionType.followTopics => l10n.feedActionTypeFollowTopics,
1252+
FeedActionType.followSources => l10n.feedActionTypeFollowSources,
1253+
FeedActionType.upgrade => l10n.feedActionTypeUpgrade,
1254+
FeedActionType.enableNotifications =>
1255+
l10n.feedActionTypeEnableNotifications,
1256+
};
12171257
return widget.buildIntField(
12181258
context,
1219-
label: _formatLabel(actionType.name),
1220-
description:
1221-
'Minimum number of days before showing the ${actionType.name} prompt.',
1259+
label: '$localizedActionType ${l10n.daysSuffix}',
1260+
description: l10n.daysBetweenPromptDescription(
1261+
localizedActionType,
1262+
),
12221263
value: _getDaysMap(accountActionConfig)[actionType] ?? 0,
12231264
onChanged: (value) {
12241265
final currentMap = _getDaysMap(accountActionConfig);

lib/l10n/app_localizations.dart

Lines changed: 113 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -716,11 +716,11 @@ abstract class AppLocalizations {
716716
/// **'Android Store URL'**
717717
String get androidStoreUrlLabel;
718718

719-
/// Description for Android Store URL
719+
/// Description for Android Update URL
720720
///
721721
/// In en, this message translates to:
722722
/// **'URL to the app on the Google Play Store.'**
723-
String get androidStoreUrlDescription;
723+
String get androidUpdateUrlDescription;
724724

725725
/// Label for Guest Days Between In-App Prompts
726726
///
@@ -1496,11 +1496,119 @@ abstract class AppLocalizations {
14961496
/// **'Android Update URL'**
14971497
String get androidUpdateUrlLabel;
14981498

1499-
/// Description for Android Update URL
1499+
/// Label for Followed Items Limit
15001500
///
15011501
/// In en, this message translates to:
1502-
/// **'URL for Android app updates.'**
1503-
String get androidUpdateUrlDescription;
1502+
/// **'Followed Items Limit'**
1503+
String get followedItemsLimitLabel;
1504+
1505+
/// Description for Followed Items Limit
1506+
///
1507+
/// In en, this message translates to:
1508+
/// **'Maximum number of countries, news sources, or categories this user role can follow (each type has its own limit).'**
1509+
String get followedItemsLimitDescription;
1510+
1511+
/// Label for Saved Headlines Limit
1512+
///
1513+
/// In en, this message translates to:
1514+
/// **'Saved Headlines Limit'**
1515+
String get savedHeadlinesLimitLabel;
1516+
1517+
/// Description for Saved Headlines Limit
1518+
///
1519+
/// In en, this message translates to:
1520+
/// **'Maximum number of headlines this user role can save.'**
1521+
String get savedHeadlinesLimitDescription;
1522+
1523+
/// Label for Ad Frequency
1524+
///
1525+
/// In en, this message translates to:
1526+
/// **'Ad Frequency'**
1527+
String get adFrequencyLabel;
1528+
1529+
/// Description for Ad Frequency
1530+
///
1531+
/// In en, this message translates to:
1532+
/// **'How often an ad can appear for this user role (e.g., a value of 5 means an ad could be placed after every 5 news items).'**
1533+
String get adFrequencyDescription;
1534+
1535+
/// Label for Ad Placement Interval
1536+
///
1537+
/// In en, this message translates to:
1538+
/// **'Ad Placement Interval'**
1539+
String get adPlacementIntervalLabel;
1540+
1541+
/// Description for Ad Placement Interval
1542+
///
1543+
/// In en, this message translates to:
1544+
/// **'Minimum number of news items that must be shown before the very first ad appears for this user role.'**
1545+
String get adPlacementIntervalDescription;
1546+
1547+
/// Label for Articles Before Interstitial Ads
1548+
///
1549+
/// In en, this message translates to:
1550+
/// **'Articles Before Interstitial Ads'**
1551+
String get articlesBeforeInterstitialAdsLabel;
1552+
1553+
/// Description for Articles Before Interstitial Ads
1554+
///
1555+
/// In en, this message translates to:
1556+
/// **'Number of articles this user role needs to read before a full-screen interstitial ad is shown.'**
1557+
String get articlesBeforeInterstitialAdsDescription;
1558+
1559+
/// Suffix for number of days in prompt descriptions
1560+
///
1561+
/// In en, this message translates to:
1562+
/// **'Days'**
1563+
String get daysSuffix;
1564+
1565+
/// Description for days between in-app prompts
1566+
///
1567+
/// In en, this message translates to:
1568+
/// **'Minimum number of days before showing the {actionType} prompt.'**
1569+
String daysBetweenPromptDescription(String actionType);
1570+
1571+
/// Text for the retry button
1572+
///
1573+
/// In en, this message translates to:
1574+
/// **'Retry'**
1575+
String get retryButtonText;
1576+
1577+
/// Feed action type for linking an account
1578+
///
1579+
/// In en, this message translates to:
1580+
/// **'Link Account'**
1581+
String get feedActionTypeLinkAccount;
1582+
1583+
/// Feed action type for rating the app
1584+
///
1585+
/// In en, this message translates to:
1586+
/// **'Rate App'**
1587+
String get feedActionTypeRateApp;
1588+
1589+
/// Feed action type for following topics
1590+
///
1591+
/// In en, this message translates to:
1592+
/// **'Follow Topics'**
1593+
String get feedActionTypeFollowTopics;
1594+
1595+
/// Feed action type for following sources
1596+
///
1597+
/// In en, this message translates to:
1598+
/// **'Follow Sources'**
1599+
String get feedActionTypeFollowSources;
1600+
1601+
/// Feed action type for upgrading
1602+
///
1603+
/// In en, this message translates to:
1604+
/// **'Upgrade'**
1605+
String get feedActionTypeUpgrade;
1606+
1607+
/// Feed action type for enabling notifications
1608+
///
1609+
/// In en, this message translates to:
1610+
/// **'Enable Notifications'**
1611+
String get feedActionTypeEnableNotifications;
15041612
}
15051613

15061614
class _AppLocalizationsDelegate

lib/l10n/app_localizations_ar.dart

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,7 @@ class AppLocalizationsAr extends AppLocalizations {
371371
String get androidStoreUrlLabel => 'رابط متجر Android';
372372

373373
@override
374-
String get androidStoreUrlDescription =>
375-
'رابط التطبيق على متجر Google Play Store.';
374+
String get androidUpdateUrlDescription => 'رابط تحديثات تطبيق Android.';
376375

377376
@override
378377
String get guestDaysBetweenInAppPromptsLabel =>
@@ -785,5 +784,67 @@ class AppLocalizationsAr extends AppLocalizations {
785784
String get androidUpdateUrlLabel => 'رابط تحديث Android';
786785

787786
@override
788-
String get androidUpdateUrlDescription => 'رابط تحديثات تطبيق Android.';
787+
String get followedItemsLimitLabel => 'حد العناصر المتابعة';
788+
789+
@override
790+
String get followedItemsLimitDescription =>
791+
'الحد الأقصى لعدد البلدان أو مصادر الأخبار أو المواضيع التي يمكن لهذا الدور المستخدم متابعتها (لكل نوع حد خاص به).';
792+
793+
@override
794+
String get savedHeadlinesLimitLabel => 'حد العناوين المحفوظة';
795+
796+
@override
797+
String get savedHeadlinesLimitDescription =>
798+
'الحد الأقصى لعدد العناوين الرئيسية التي يمكن لهذا الدور المستخدم حفظها.';
799+
800+
@override
801+
String get adFrequencyLabel => 'تكرار الإعلان';
802+
803+
@override
804+
String get adFrequencyDescription =>
805+
'عدد مرات ظهور الإعلان لهذا الدور المستخدم (على سبيل المثال، قيمة 5 تعني أنه يمكن وضع إعلان بعد كل 5 عناصر إخبارية).';
806+
807+
@override
808+
String get adPlacementIntervalLabel => 'فترة وضع الإعلان';
809+
810+
@override
811+
String get adPlacementIntervalDescription =>
812+
'الحد الأدنى لعدد عناصر الأخبار التي يجب عرضها قبل ظهور الإعلان الأول لهذا الدور المستخدم.';
813+
814+
@override
815+
String get articlesBeforeInterstitialAdsLabel =>
816+
'مقالات قبل الإعلانات البينية';
817+
818+
@override
819+
String get articlesBeforeInterstitialAdsDescription =>
820+
'عدد المقالات التي يحتاج هذا الدور المستخدم لقراءتها قبل عرض إعلان بيني بملء الشاشة.';
821+
822+
@override
823+
String get daysSuffix => 'أيام';
824+
825+
@override
826+
String daysBetweenPromptDescription(String actionType) {
827+
return 'الحد الأدنى لعدد الأيام قبل عرض تنبيه $actionType.';
828+
}
829+
830+
@override
831+
String get retryButtonText => 'إعادة المحاولة';
832+
833+
@override
834+
String get feedActionTypeLinkAccount => 'ربط الحساب';
835+
836+
@override
837+
String get feedActionTypeRateApp => 'تقييم التطبيق';
838+
839+
@override
840+
String get feedActionTypeFollowTopics => 'متابعة المواضيع';
841+
842+
@override
843+
String get feedActionTypeFollowSources => 'متابعة المصادر';
844+
845+
@override
846+
String get feedActionTypeUpgrade => 'ترقية';
847+
848+
@override
849+
String get feedActionTypeEnableNotifications => 'تفعيل الإشعارات';
789850
}

0 commit comments

Comments
 (0)