diff --git a/userfront/lib/features/auth/presentation/reset_password_screen.dart b/userfront/lib/features/auth/presentation/reset_password_screen.dart index f2951e1c..53cbdd65 100644 --- a/userfront/lib/features/auth/presentation/reset_password_screen.dart +++ b/userfront/lib/features/auth/presentation/reset_password_screen.dart @@ -26,6 +26,18 @@ class _ResetPasswordScreenState extends State { Map? _policy; bool _isPolicyLoading = false; + String _renderTranslatedText( + String key, { + String? fallback, + Map values = const {}, + }) { + var text = tr(key, fallback: fallback); + values.forEach((name, value) { + text = text.replaceAll('{{$name}}', value).replaceAll('{$name}', value); + }); + return text; + } + @override void initState() { super.initState(); @@ -123,16 +135,16 @@ class _ResetPasswordScreenState extends State { final requiresSymbol = _policy?['nonAlphanumeric'] ?? true; final parts = [ - tr( + _renderTranslatedText( 'msg.userfront.reset.policy.min_length', - params: {'count': '$minLength'}, + values: {'count': '$minLength'}, ), ]; if (minTypes > 0) { parts.add( - tr( + _renderTranslatedText( 'msg.userfront.reset.policy.min_types', - params: {'count': '$minTypes'}, + values: {'count': '$minTypes'}, ), ); } diff --git a/userfront/lib/features/auth/presentation/signup_screen.dart b/userfront/lib/features/auth/presentation/signup_screen.dart index bde6317f..838e30c6 100644 --- a/userfront/lib/features/auth/presentation/signup_screen.dart +++ b/userfront/lib/features/auth/presentation/signup_screen.dart @@ -76,6 +76,18 @@ class _SignupScreenState extends State { 'baroncs.co.kr': 'BARON', }; + String _renderTranslatedText( + String key, { + String? fallback, + Map values = const {}, + }) { + var text = tr(key, fallback: fallback); + values.forEach((name, value) { + text = text.replaceAll('{{$name}}', value).replaceAll('{$name}', value); + }); + return text; + } + @override void initState() { super.initState(); @@ -1729,16 +1741,16 @@ class _SignupScreenState extends State { final requiresSymbol = _policy?['nonAlphanumeric'] ?? true; final parts = [ - tr( + _renderTranslatedText( 'msg.userfront.signup.policy.min_length', - params: {'count': minLength.toString()}, + values: {'count': minLength.toString()}, ), ]; if (minTypes > 0) { parts.add( - tr( + _renderTranslatedText( 'msg.userfront.signup.policy.min_types', - params: {'count': minTypes.toString()}, + values: {'count': minTypes.toString()}, ), ); } @@ -1755,9 +1767,9 @@ class _SignupScreenState extends State { parts.add(tr('msg.userfront.signup.policy.symbol')); } - return tr( + return _renderTranslatedText( 'msg.userfront.signup.policy.summary', - params: {'rules': parts.join(', ')}, + values: {'rules': parts.join(', ')}, ); } diff --git a/userfront/lib/features/dashboard/presentation/dashboard_screen.dart b/userfront/lib/features/dashboard/presentation/dashboard_screen.dart index cbbbc9fa..fc93c46f 100644 --- a/userfront/lib/features/dashboard/presentation/dashboard_screen.dart +++ b/userfront/lib/features/dashboard/presentation/dashboard_screen.dart @@ -55,6 +55,18 @@ class _DashboardScreenState extends ConsumerState { bool _showAllActivities = false; final Set _revokedClientIds = {}; + String _renderTranslatedText( + String key, { + String? fallback, + Map values = const {}, + }) { + var text = tr(key, fallback: fallback); + values.forEach((name, value) { + text = text.replaceAll('{{$name}}', value).replaceAll('{$name}', value); + }); + return text; + } + @override void initState() { super.initState(); @@ -700,10 +712,10 @@ class _DashboardScreenState extends ConsumerState { final clientId = log.clientId; final tooltip = clientId.isEmpty ? tr('msg.userfront.dashboard.client_id_missing') - : tr( + : _renderTranslatedText( 'msg.userfront.dashboard.client_id', fallback: 'Client ID: {{id}}', - params: {'id': clientId}, + values: {'id': clientId}, ); final baseStyle = style ?? const TextStyle(); final emphasisStyle = clientId.isEmpty @@ -891,7 +903,11 @@ class _DashboardScreenState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - tr('msg.userfront.greeting', params: {'name': userName}), + _renderTranslatedText( + 'msg.userfront.greeting', + fallback: 'Hello, {{name}}.', + values: {'name': userName}, + ), style: const TextStyle( fontSize: 22, fontWeight: FontWeight.bold, @@ -1122,18 +1138,18 @@ class _DashboardScreenState extends ConsumerState { const SizedBox(height: 12), if (browserLabel.isNotEmpty) Text( - tr( + _renderTranslatedText( 'msg.userfront.dashboard.sessions.browser', - params: {'value': browserLabel}, + values: {'value': browserLabel}, ), style: TextStyle(fontSize: 13, color: Colors.grey[700]), ), if (osLabel.isNotEmpty) ...[ const SizedBox(height: 4), Text( - tr( + _renderTranslatedText( 'msg.userfront.dashboard.sessions.os', - params: {'value': osLabel}, + values: {'value': osLabel}, ), style: TextStyle(fontSize: 13, color: Colors.grey[700]), ), @@ -1142,18 +1158,20 @@ class _DashboardScreenState extends ConsumerState { if (session.clientId.trim().isNotEmpty) ...[ const SizedBox(height: 6), Text( - tr( + _renderTranslatedText( 'msg.userfront.dashboard.client_id', - params: {'id': session.clientId}, + fallback: 'Client ID: {{id}}', + values: {'id': session.clientId}, ), style: TextStyle(fontSize: 12, color: Colors.grey[600]), ), ], const SizedBox(height: 8), Text( - tr( + _renderTranslatedText( 'msg.userfront.dashboard.sessions.session_id', - params: {'id': _compactSessionId(session.sessionId)}, + fallback: 'Session ID: {{id}}', + values: {'id': _compactSessionId(session.sessionId)}, ), style: TextStyle(fontSize: 12, color: Colors.grey[600]), ), @@ -1956,10 +1974,10 @@ class _DashboardScreenState extends ConsumerState { ), const SizedBox(height: 6), _selectableText( - tr( + _renderTranslatedText( 'msg.userfront.audit.session_id', fallback: 'Session ID: {{value}}', - params: { + values: { 'value': log.sessionId.isEmpty ? tr('ui.common.hyphen', fallback: '-') : log.sessionId, diff --git a/userfront/lib/features/profile/presentation/pages/profile_page.dart b/userfront/lib/features/profile/presentation/pages/profile_page.dart index 39987e19..9d25748a 100644 --- a/userfront/lib/features/profile/presentation/pages/profile_page.dart +++ b/userfront/lib/features/profile/presentation/pages/profile_page.dart @@ -57,6 +57,18 @@ class _ProfilePageState extends ConsumerState { Map? _passwordPolicy; bool _isPasswordPolicyLoading = false; + String _renderTranslatedText( + String key, { + String? fallback, + Map values = const {}, + }) { + var text = tr(key, fallback: fallback); + values.forEach((name, value) { + text = text.replaceAll('{{$name}}', value).replaceAll('{$name}', value); + }); + return text; + } + @override void initState() { super.initState(); @@ -98,16 +110,16 @@ class _ProfilePageState extends ConsumerState { final requiresSymbol = _passwordPolicy?['nonAlphanumeric'] ?? true; final parts = [ - tr( + _renderTranslatedText( 'msg.userfront.signup.policy.min_length', - params: {'count': '$minLength'}, + values: {'count': '$minLength'}, ), ]; if (minTypes > 0) { parts.add( - tr( + _renderTranslatedText( 'msg.userfront.signup.policy.min_types', - params: {'count': '$minTypes'}, + values: {'count': '$minTypes'}, ), ); } @@ -124,9 +136,9 @@ class _ProfilePageState extends ConsumerState { parts.add(tr('msg.userfront.signup.policy.symbol')); } - return tr( + return _renderTranslatedText( 'msg.userfront.signup.policy.summary', - params: {'rules': parts.join(", ")}, + values: {'rules': parts.join(", ")}, ); } @@ -688,7 +700,11 @@ class _ProfilePageState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - tr('msg.userfront.profile.greeting', params: {'name': name}), + _renderTranslatedText( + 'msg.userfront.profile.greeting', + fallback: 'Hello, {{name}}.', + values: {'name': name}, + ), style: const TextStyle( fontSize: 20, fontWeight: FontWeight.w700,