forked from baron/baron-sso
116 lines
3.1 KiB
Dart
116 lines
3.1 KiB
Dart
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter/services.dart';
|
|
|
|
const _translationAssetPrefix = 'assets/translations/';
|
|
const _templateFileName = 'template.toml';
|
|
const _safeFallbackLocaleCode = 'en';
|
|
|
|
List<String> extractSupportedLocaleCodesFromAssets(Iterable<String> assets) {
|
|
final localeCodes = <String>{};
|
|
for (final asset in assets) {
|
|
if (!asset.startsWith(_translationAssetPrefix) ||
|
|
!asset.endsWith('.toml')) {
|
|
continue;
|
|
}
|
|
final fileName = asset.substring(_translationAssetPrefix.length);
|
|
if (fileName.contains('/') || fileName == _templateFileName) {
|
|
continue;
|
|
}
|
|
final rawCode = fileName.substring(0, fileName.length - '.toml'.length);
|
|
final normalized = rawCode.toLowerCase().replaceAll('_', '-');
|
|
if (_isValidLocaleCode(normalized)) {
|
|
localeCodes.add(normalized);
|
|
}
|
|
}
|
|
|
|
final sorted = localeCodes.toList()..sort();
|
|
return sorted;
|
|
}
|
|
|
|
class LocaleRegistry {
|
|
static final Set<String> _localeCodes = <String>{};
|
|
static bool _initialized = false;
|
|
|
|
static void primeWithDefaults({
|
|
Iterable<String> localeCodes = const ['en', 'ko'],
|
|
}) {
|
|
if (_localeCodes.isNotEmpty) {
|
|
return;
|
|
}
|
|
_localeCodes.addAll(
|
|
localeCodes
|
|
.map((code) => code.toLowerCase().replaceAll('_', '-'))
|
|
.where(_isValidLocaleCode),
|
|
);
|
|
if (_localeCodes.isEmpty) {
|
|
_localeCodes.add(_safeFallbackLocaleCode);
|
|
}
|
|
}
|
|
|
|
static Future<void> initialize({AssetBundle? assetBundle}) async {
|
|
if (_initialized) {
|
|
return;
|
|
}
|
|
final bundle = assetBundle ?? rootBundle;
|
|
try {
|
|
final manifest = await AssetManifest.loadFromAssetBundle(bundle);
|
|
final extracted = extractSupportedLocaleCodesFromAssets(
|
|
manifest.listAssets(),
|
|
);
|
|
_localeCodes.addAll(extracted);
|
|
} catch (_) {
|
|
// manifest 로딩 실패 시 안전 fallback으로 계속 진행합니다.
|
|
}
|
|
|
|
if (_localeCodes.isEmpty) {
|
|
_localeCodes.add(_safeFallbackLocaleCode);
|
|
}
|
|
_initialized = true;
|
|
}
|
|
|
|
static List<String> get supportedLocaleCodes {
|
|
final sorted = _localeCodes.toList()..sort();
|
|
return List.unmodifiable(sorted);
|
|
}
|
|
|
|
static String get fallbackLocaleCode {
|
|
final supported = supportedLocaleCodes;
|
|
if (supported.isEmpty) {
|
|
return _safeFallbackLocaleCode;
|
|
}
|
|
if (supported.contains('en')) {
|
|
return 'en';
|
|
}
|
|
return supported.first;
|
|
}
|
|
|
|
static bool contains(String code) {
|
|
return _localeCodes.contains(code.toLowerCase());
|
|
}
|
|
|
|
@visibleForTesting
|
|
static void setSupportedLocaleCodesForTest(Iterable<String> localeCodes) {
|
|
_localeCodes
|
|
..clear()
|
|
..addAll(
|
|
localeCodes
|
|
.map((code) => code.toLowerCase().replaceAll('_', '-'))
|
|
.where(_isValidLocaleCode),
|
|
);
|
|
if (_localeCodes.isEmpty) {
|
|
_localeCodes.add(_safeFallbackLocaleCode);
|
|
}
|
|
_initialized = true;
|
|
}
|
|
|
|
@visibleForTesting
|
|
static void resetForTest() {
|
|
_localeCodes.clear();
|
|
_initialized = false;
|
|
}
|
|
}
|
|
|
|
bool _isValidLocaleCode(String value) {
|
|
return RegExp(r'^[a-z]{2,3}$').hasMatch(value);
|
|
}
|