"me-web?" 0.7.0: the name in quotes, copy buttons, and every translation rewritten in plain words
Build / Desktop, server and tools (push) Successful in 1m19s
Release / Every platform, the server, the release (push) Successful in 9m34s

- The name is now always written in quotation marks, each language with its own: “me-web?”, «me-web?», „me-web?“, « me-web? », 「me-web?」. Without them the question mark read as the end of a sentence. In Arabic, Hebrew and the other right-to-left languages the question mark no longer jumps to the wrong side of the name.
- Your addresses, your router, your network, the reverse name, the route and the code of a submission you sent now sit in a small box with a copy button, ready to paste into a message to your provider or anywhere else.
- Every translation except English and Italian was rewritten for people who are not technical: everyday words first, the technical term in brackets, and one word for one thing across the whole app. They are still machine drafts; "Suggest a correction" is welcome in any language.
- A few lines are plainer in English and Italian too: the test servers for calls, and the server in the middle that carries a call when two homes can't connect directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB
This commit is contained in:
thepraandClaude Opus 5.5 committed 2026-10-15 22:49:40 +02:00
1 parent d18caed157
commit 320936c688
260 files changed
+23662 -18072

No files matched your search

+38 -2
View File
@@ -7,13 +7,18 @@ var root = FindRoot();
var folder = Path.Combine(root, "src", "MeWeb.App", "Strings");
var options = new JsonSerializerOptions { WriteIndented = true, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping };
var placeholder = new Regex(@"\{\d+\}");
const string Name = "me-web?";
var quotes = JsonNode.Parse(File.ReadAllText(Path.Combine(root, "data", "languages.json"))).AsArray()
.ToDictionary(n => (string)n["code"], n => ((string)n["quotes"][0], (string)n["quotes"][1]));
var named = new Regex(@"(?:«[\u00A0\u202F ]|[""'“”„‟«»‹›「」『』‘’‚])?me-web\?(?:[\u00A0\u202F ]»|[""'“”„‟«»‹›「」『』‘’‚])?");
if (args.Length >= 1 && args[0] == "check") return Check();
if (args.Length == 3 && args[0] == "set") return Set(args[1], args[2]);
if (args.Length == 2 && args[0] == "merge") return Merge(args[1]);
if (args.Length == 3 && args[0] == "import") return Import(args[1], args[2]);
if (args.Length == 2 && args[0] == "drop") return Drop(args[1]);
Console.Error.WriteLine("usage: dotnet run tools/strings.cs -- check | set <Key> <values.json> | merge <keys.json> | import <code> <strings.json> | drop <Key>");
if (args.Length == 1 && args[0] == "quote") return Quote();
Console.Error.WriteLine("usage: dotnet run tools/strings.cs -- check | set <Key> <values.json> | merge <keys.json> | import <code> <strings.json> | drop <Key> | quote");
Console.Error.WriteLine(" values.json maps a language code to its text; keys.json maps keys to such maps; strings.json maps keys to one language's text");
return 2;
@@ -24,8 +29,15 @@ int Check()
foreach (var file in Directory.GetFiles(folder, "*.json").OrderBy(f => f, StringComparer.Ordinal))
{
var code = Path.GetFileNameWithoutExtension(file);
if (code == "en") continue;
var values = Read(code);
var (open, close) = quotes[code];
var bare = values.Where(p => Bare(p.Value, open, close)).Select(p => p.Key).ToList();
if (bare.Count > 0)
{
problems++;
Console.WriteLine($"{code}: {Name} not between {open.Trim()} and {close.Trim()} in [{string.Join(", ", bare)}]");
}
if (code == "en") continue;
var missing = english.Keys.Where(k => !values.ContainsKey(k)).ToList();
var extra = values.Keys.Where(k => !english.ContainsKey(k)).ToList();
var mismatched = english.Keys.Where(values.ContainsKey)
@@ -105,6 +117,30 @@ int Drop(string key)
return 0;
}
int Quote()
{
var changed = 0;
foreach (var file in Directory.GetFiles(folder, "*.json").OrderBy(f => f, StringComparer.Ordinal))
{
var code = Path.GetFileNameWithoutExtension(file);
var (open, close) = quotes[code];
var strings = Read(code);
var quoted = new SortedDictionary<string, string>(strings.ToDictionary(p => p.Key, p => named.Replace(p.Value, open + Name + close)), StringComparer.Ordinal);
if (quoted.SequenceEqual(strings)) continue;
Write(code, quoted);
changed++;
}
Console.WriteLine($"quote: {changed} language(s) changed");
return 0;
}
static bool Bare(string text, string open, string close)
{
for (var at = text.IndexOf(Name, StringComparison.Ordinal); at >= 0; at = text.IndexOf(Name, at + Name.Length, StringComparison.Ordinal))
if (!text[..at].EndsWith(open, StringComparison.Ordinal) || !text[(at + Name.Length)..].StartsWith(close, StringComparison.Ordinal)) return true;
return false;
}
SortedDictionary<string, string> Read(string code)
{
var path = Path.Combine(folder, $"{code}.json");