Update JSON Localization File
Safely update a JSON localization file by adding, updating, or removing keys while preserving proper formatting.
Inputs
- •file_path: Path to the JSON file to update
- •additions: Dictionary of
{key: value}pairs to add or update - •deletions: List of keys to remove
- •preserve_formatting: Boolean (default:
true) - maintain existing key order vs. sort alphabetically
Output
Return a summary object:
{
"file_path": "src/assets/i18n/es-ES.json",
"keys_added": 5,
"keys_updated": 3,
"keys_deleted": 2,
"total_keys": 450
}
Process
Step 1: Read Current File
Read the existing file content. If the file doesn't exist, start with an empty object {}.
file_path: src/assets/i18n/es-ES.json
Handle errors gracefully:
- •File not found → Create new file
- •Permission denied → Report error
- •Invalid JSON → Report error with line number if possible
Step 2: Parse JSON
Parse the JSON content while preserving structure:
- •Maintain nested object hierarchy
- •Track existing keys for add vs. update distinction
Step 3: Apply Deletions
For each key in the deletions list:
- •Support dot notation for nested keys:
"about.title"→ deletejson.about.title - •If key doesn't exist, skip silently (idempotent)
- •If deleting a key leaves an empty parent object, keep the empty object
deletions: ["obsolete.key1", "deprecated.feature"]
Deletion logic for nested keys:
Key: "about.opensource.paragraph3"
Before:
{
"about": {
"opensource": {
"paragraph1": "...",
"paragraph2": "...",
"paragraph3": "..."
}
}
}
After:
{
"about": {
"opensource": {
"paragraph1": "...",
"paragraph2": "..."
}
}
}
Step 4: Apply Additions
For each key-value pair in additions:
- •Support dot notation:
"about.newKey"→json.about.newKey = value - •If key exists: update value, count as "updated"
- •If key is new: add it, count as "added"
- •Create intermediate objects as needed for nested keys
additions: {
"about.title": "Acerca de TMI",
"newSection.newKey": "New Value"
}
Addition logic for nested keys:
Key: "newSection.subSection.key"
Value: "Hello"
Before:
{
"existingKey": "..."
}
After:
{
"existingKey": "...",
"newSection": {
"subSection": {
"key": "Hello"
}
}
}
Step 5: Sort Keys (Optional)
If preserve_formatting is false, sort all keys alphabetically at each level of nesting.
Sorting rules:
- •Case-sensitive alphabetical sort
- •Sort recursively at every nesting level
- •Numbers sort before letters in ASCII order
If preserve_formatting is true:
- •Keep existing keys in their original order
- •Add new keys at the end of their respective objects (or in sorted position among new keys)
Step 6: Write File
Write the updated JSON back to the file with proper formatting.
Formatting requirements:
- •2-space indentation
- •UTF-8 encoding
- •Final newline at end of file
- •No trailing whitespace on lines
- •Unix line endings (
\n)
Safe write process:
- •Create backup:
{file_path}.bak - •Write to temporary file:
{file_path}.tmp - •Rename temporary file to target (atomic operation)
- •Preserve original file permissions
# Conceptual process cp file.json file.json.bak write_json > file.json.tmp mv file.json.tmp file.json
Error Handling
File Errors
| Error | Behavior |
|---|---|
| File not found | Create new file with additions only |
| Permission denied | Return error, do not modify |
| Disk full | Return error, backup preserved |
| Invalid JSON | Return error with details |
Key Errors
| Error | Behavior |
|---|---|
| Delete non-existent key | Skip silently (idempotent) |
| Invalid key format | Return error |
| Key collision (add + delete same) | Delete wins, then add |
Examples
Add New Translations
Input:
file_path: "src/assets/i18n/es-ES.json"
additions: {
"common.save": "Guardar",
"common.cancel": "Cancelar",
"errors.network": "Error de red"
}
deletions: []
Output:
{
"file_path": "src/assets/i18n/es-ES.json",
"keys_added": 3,
"keys_updated": 0,
"keys_deleted": 0,
"total_keys": 453
}
Update Existing Translation
Input:
file_path: "src/assets/i18n/fr-FR.json"
additions: {
"common.save": "Sauvegarder"
}
deletions: []
Output:
{
"file_path": "src/assets/i18n/fr-FR.json",
"keys_added": 0,
"keys_updated": 1,
"keys_deleted": 0,
"total_keys": 450
}
Remove Obsolete Keys
Input:
file_path: "src/assets/i18n/de-DE.json"
additions: {}
deletions: ["deprecated.oldFeature", "legacy.button"]
Output:
{
"file_path": "src/assets/i18n/de-DE.json",
"keys_added": 0,
"keys_updated": 0,
"keys_deleted": 2,
"total_keys": 448
}
Mixed Operations
Input:
file_path: "src/assets/i18n/ja-JP.json"
additions: {
"new.feature.title": "新機能",
"common.ok": "はい"
}
deletions: ["old.feature.title"]
Output:
{
"file_path": "src/assets/i18n/ja-JP.json",
"keys_added": 1,
"keys_updated": 1,
"keys_deleted": 1,
"total_keys": 450
}
Create New File
Input:
file_path: "src/assets/i18n/new-LANG.json"
additions: {
"app.title": "Application Title",
"app.description": "Description"
}
deletions: []
Output:
{
"file_path": "src/assets/i18n/new-LANG.json",
"keys_added": 2,
"keys_updated": 0,
"keys_deleted": 0,
"total_keys": 2
}
Implementation Notes
- •
Atomic writes: Always use temp file + rename to prevent corruption on failure.
- •
Backup retention: Keep only the most recent
.bakfile. Consider timestamped backups for critical operations. - •
Key counting: For nested structures, count leaf keys only (keys with string values, not object parents).
- •
Dot notation edge cases:
- •Key contains literal dot: Not supported (use nested structure)
- •Empty key segment: Invalid (
"a..b") - •Leading/trailing dots: Invalid (
".key","key.")
- •
Concurrent access: This operation is not atomic across multiple callers. Use external locking if needed.
- •
Large files: For files over 1MB, consider streaming JSON parser. Standard i18n files are typically under 100KB.
- •
Validation: After writing, optionally re-read and parse the file to verify it's valid JSON.