addKey method
Implementation
Future<CatalogRow> addKey({
required String keyPath,
required Map<String, dynamic> valuesByLocale,
String? note,
bool markGreenIfComplete = true,
}) async {
if (!isValidCatalogKeyPath(keyPath)) {
throw CatalogOperationException(
'Invalid key path "$keyPath". Use dot-separated segments with letters, numbers, and underscores.',
);
}
if (config.hideCatalogUiKeys) {
final reserved = await _uiKeyResolver.resolve();
if (reserved.contains(keyPath)) {
throw CatalogOperationException('Key "$keyPath" is reserved by the catalog UI.');
}
}
final dataset = await _repository.load();
final locales = dataset.locales;
if (locales.isEmpty) {
throw CatalogOperationException(
'No locale files found in ${config.resolveLangDirectory(projectRootPath)}.',
);
}
for (final locale in locales) {
if (catalogHasPath(dataset.translationsByLocale[locale] ?? const <String, dynamic>{}, keyPath)) {
throw CatalogOperationException('Key "$keyPath" already exists in locale "$locale".');
}
}
for (final locale in locales) {
final localeMap = dataset.translationsByLocale.putIfAbsent(locale, () => <String, dynamic>{});
final value = valuesByLocale.containsKey(locale) ? valuesByLocale[locale] : '';
catalogSetValueByPath(localeMap, keyPath, value ?? '');
}
final state = await _stateStore.load(
config: config,
projectRootPath: projectRootPath,
);
final now = DateTime.now().toUtc();
final sourceValue = valuesByLocale[config.effectiveSourceLocale] ?? '';
final sourceHash = _statusEngine.hashSourceValue(sourceValue);
state.keys[keyPath] = _statusEngine.newKeyState(
locales: locales,
sourceLocale: config.effectiveSourceLocale,
sourceHash: sourceHash,
valuesByLocale: valuesByLocale,
markGreenIfComplete: markGreenIfComplete,
now: now,
)..note = _normalizeCatalogNote(note);
_appendActivityEvent(
keyState: state.keys[keyPath]!,
event: CatalogActivityEvent(
kind: CatalogActivityKinds.keyCreated,
timestamp: now,
),
);
_mergeDataTypesIntoDataset(dataset, state, locales);
await _repository.save(dataset);
await _stateStore.save(
config: config,
projectRootPath: projectRootPath,
state: state,
);
_triggerDictionaryGeneration();
return _buildRowForKey(
keyPath: keyPath,
locales: locales,
translationsByLocale: dataset.translationsByLocale,
state: state,
now: now,
);
}