     case invalidFormat
 }
 
+enum OverrideError: Error {
+    case invalidKeyPath
+    case invalidOriginalFormat
+    case unspecifiedVariableInOverride(position: Int)
+    case ambiguousVariableTypesInOverride(position: Int, typeA: String, typeB: String)
+}
+
 typealias StringsDB = [BundleURI: [ResourceURI: [LocKey: StringsEntry]]]
 
 @objc final class StringsManager: NSObject {

        db[keyPath.bundleURI]?[keyPath.resourceURI]?[keyPath.locKey] = entry
    }
    
    func addOverride(_ string: String, for keyPath: LocKeyPath) {
        guard var entry = self.entry(for: keyPath) else {
            return
        }
        
        entry.override = .static(string)
        setEntry(entry, for: keyPath)
        
        overriddenKeyPaths.insert(keyPath)
        
        var storedOverrides = userDefaults.dictionary(forKey: storedOverridesKey) ?? [:]
        storedOverrides[keyPath.description] = string
        userDefaults.setValue(storedOverrides, forKey: storedOverridesKey)
    }
    

    
    private func applyOverrides(for bundle: Bundle) {
        let bundleURI = self.bundleURI(for: bundle)
        var storedOverrides: [String: Any] = userDefaults.dictionary(forKey: storedOverridesKey) ?? [:]
        var discardedOverrideKeys: [String] = []
        
        forEachOverride: for storedOverride in storedOverrides {
            guard
                let keyPath = LocKeyPath(string: storedOverride.key),
                keyPath.bundleURI == bundleURI
            else {
                continue
            }
            
            guard var entry = self.entry(for: keyPath) else {
                // ignore override if the key is not found
                discardedOverrideKeys.append(storedOverride.key)
                continue
            }
            
            let override: Translation
            if let overrideText = storedOverride.value as? String {
                override = .static(overrideText)
            }
            else if let config = storedOverride.value as? [String: Any],
                let overrideFormat = try? LocalizedFormat(config: config) {
                override = .dynamic(overrideFormat)
            }
            else {
                // ignore override if it has an invalid format
                discardedOverrideKeys.append(storedOverride.key)
                continue
            }
            
            guard ((try? validateOverride(override, for: entry.translation)) != nil) else {
                discardedOverrideKeys.append(storedOverride.key)
                continue forEachOverride
            }
            
            overriddenKeyPaths.insert(keyPath)
            entry.override = override
            setEntry(entry, for: keyPath)
        }
        
