Skip to main content
MoonBuggy

Compile-time i18n for .NET

Zero-allocation translations via source generators. ICU MessageFormat with CLDR plural rules. Industry-standard PO files.

Zero Allocations

The source generator emits direct TextWriter.Write chains. No dictionary lookups, no string formatting, no per-request allocations.

ICU MessageFormat

Full CLDR plural rules for all Unicode locales, baked into the binary as inline arithmetic. No ICU runtime library needed.

PO File Format

Industry-standard format supported by Crowdin, Weblate, Poedit, and every major translation management system.

Compile-Time Safety

Diagnostics MB0001–MB0009 catch missing variables, malformed syntax, and type errors directly in your IDE.

Lingui.js Compatible

Share PO files between .NET and JavaScript. Both extractors use ICU MessageFormat as the msgid key.

Markdown Support

_m() converts markdown to HTML with reorderable numbered placeholders. Translators never touch raw HTML.

How it works

You write Razor views

@* _ViewImports.cshtml *@
@using static MoonBuggy.Translate

@* In any view *@
<h1>@_t("Welcome to $name$!", new { name = Model.SiteName })</h1>
<p>@_t("You have $#x# item|#x# items$", new { x = Model.Count })</p>
<p>@_m("Click **[here]($url$)** to continue", new { url })</p>

The compiler generates direct writes

// Emitted by the source generator (conceptual)
switch (lcid) {
case 10: // Spanish
writer.Write("Tienes ");
if (x == 1) { writer.Write("1 artículo"); }
else { writer.Write(x); writer.Write(" artículos"); }
break;
default: // English (source locale)
writer.Write("You have ");
if (x == 1) { writer.Write("1 item"); }
else { writer.Write(x); writer.Write(" items"); }
break;
}

Quick install

dotnet add package intelligenthack.MoonBuggy
dotnet add package intelligenthack.MoonBuggy.SourceGenerator
dotnet tool install intelligenthack.MoonBuggy.Cli