fix(localization): merge duplicate top-level "checks" block in en/de.json
en.json and de.json each defined the checks object twice; JSON silently kept the second block's values, so the first block's friendlier titles/hints (e.g. "Permission Mode" over the raw "--permission-mode auto support" flag) were dead text. Merged into one block per key, keeping the friendlier title and the more actionable hint. Added a Utf8JsonReader-based duplicate-top-level-key test, since JsonDocument accepts duplicates without error and the existing parity test can't see this failure mode either.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace ClaudeDo.Localization.Tests;
|
||||
|
||||
/// <summary>
|
||||
/// JsonDocument/JsonElement silently keep the last value on a duplicate key instead of throwing,
|
||||
/// so a repeated top-level block (e.g. two "checks" objects) is invisible to JSON-validity and
|
||||
/// parity tests alike. This walks the raw token stream instead.
|
||||
/// </summary>
|
||||
public class DuplicateLocaleKeysTests
|
||||
{
|
||||
private static string LocalesDir()
|
||||
{
|
||||
var dir = AppContext.BaseDirectory;
|
||||
while (dir is not null)
|
||||
{
|
||||
var candidate = Path.Combine(dir, "src", "ClaudeDo.Localization", "locales");
|
||||
if (Directory.Exists(candidate)) return candidate;
|
||||
dir = Path.GetDirectoryName(dir);
|
||||
}
|
||||
throw new DirectoryNotFoundException("Could not locate src/ClaudeDo.Localization/locales");
|
||||
}
|
||||
|
||||
private static List<string> FindDuplicateTopLevelKeys(string json)
|
||||
{
|
||||
var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json));
|
||||
var seen = new HashSet<string>(StringComparer.Ordinal);
|
||||
var duplicates = new List<string>();
|
||||
var depth = 0;
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonTokenType.StartObject:
|
||||
case JsonTokenType.StartArray:
|
||||
depth++;
|
||||
break;
|
||||
case JsonTokenType.EndObject:
|
||||
case JsonTokenType.EndArray:
|
||||
depth--;
|
||||
break;
|
||||
case JsonTokenType.PropertyName:
|
||||
if (depth == 1)
|
||||
{
|
||||
var name = reader.GetString()!;
|
||||
if (!seen.Add(name)) duplicates.Add(name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return duplicates;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Detects_duplicate_top_level_key_in_fixture()
|
||||
{
|
||||
const string json = """
|
||||
{
|
||||
"checks": { "a": "1" },
|
||||
"other": { "b": "2" },
|
||||
"checks": { "c": "3" }
|
||||
}
|
||||
""";
|
||||
|
||||
var duplicates = FindDuplicateTopLevelKeys(json);
|
||||
|
||||
Assert.Contains("checks", duplicates);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Locale_files_have_no_duplicate_top_level_keys()
|
||||
{
|
||||
var localesDir = LocalesDir();
|
||||
foreach (var path in Directory.EnumerateFiles(localesDir, "*.json"))
|
||||
{
|
||||
var duplicates = FindDuplicateTopLevelKeys(File.ReadAllText(path));
|
||||
Assert.True(duplicates.Count == 0,
|
||||
$"{Path.GetFileName(path)} has duplicate top-level keys: {string.Join(", ", duplicates)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user