1
0
forked from baron/baron-sso

Merge pull request 'userfront i18n placeholder 치환과 번역 렌더링 오류 수정' (#523) from feature/i18n-enhancement into dev

Reviewed-on: baron/baron-sso#523
This commit is contained in:
2026-04-06 17:53:21 +09:00
4 changed files with 88 additions and 30 deletions

View File

@@ -26,6 +26,18 @@ class _ResetPasswordScreenState extends State<ResetPasswordScreen> {
Map<String, dynamic>? _policy;
bool _isPolicyLoading = false;
String _renderTranslatedText(
String key, {
String? fallback,
Map<String, String> 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<ResetPasswordScreen> {
final requiresSymbol = _policy?['nonAlphanumeric'] ?? true;
final parts = <String>[
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'},
),
);
}

View File

@@ -76,6 +76,18 @@ class _SignupScreenState extends State<SignupScreen> {
'baroncs.co.kr': 'BARON',
};
String _renderTranslatedText(
String key, {
String? fallback,
Map<String, String> 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<SignupScreen> {
final requiresSymbol = _policy?['nonAlphanumeric'] ?? true;
final parts = <String>[
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<SignupScreen> {
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(', ')},
);
}

View File

@@ -55,6 +55,18 @@ class _DashboardScreenState extends ConsumerState<DashboardScreen> {
bool _showAllActivities = false;
final Set<String> _revokedClientIds = {};
String _renderTranslatedText(
String key, {
String? fallback,
Map<String, String> 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<DashboardScreen> {
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<DashboardScreen> {
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<DashboardScreen> {
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<DashboardScreen> {
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<DashboardScreen> {
),
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,

View File

@@ -57,6 +57,18 @@ class _ProfilePageState extends ConsumerState<ProfilePage> {
Map<String, dynamic>? _passwordPolicy;
bool _isPasswordPolicyLoading = false;
String _renderTranslatedText(
String key, {
String? fallback,
Map<String, String> 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<ProfilePage> {
final requiresSymbol = _passwordPolicy?['nonAlphanumeric'] ?? true;
final parts = <String>[
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<ProfilePage> {
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<ProfilePage> {
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,