intelligenthack.MoonBuggy
0.1.3
dotnet add package intelligenthack.MoonBuggy --version 0.1.3
NuGet\Install-Package intelligenthack.MoonBuggy -Version 0.1.3
<PackageReference Include="intelligenthack.MoonBuggy" Version="0.1.3" />
<PackageVersion Include="intelligenthack.MoonBuggy" Version="0.1.3" />
<PackageReference Include="intelligenthack.MoonBuggy" />
paket add intelligenthack.MoonBuggy --version 0.1.3
#r "nuget: intelligenthack.MoonBuggy, 0.1.3"
#:package intelligenthack.MoonBuggy@0.1.3
#addin nuget:?package=intelligenthack.MoonBuggy&version=0.1.3
#tool nuget:?package=intelligenthack.MoonBuggy&version=0.1.3
MoonBuggy
MoonBuggy performs compile-time translation for .NET applications. You write Razor views in English using a lightweight translation syntax, send PO files to translators, and during the build the compiler embeds every translated string directly into the binary. There are no resource files, dictionary lookups, or per-request allocations involved. The application writes the correct language directly to the output stream.
If your stack includes both Razor views and a JavaScript frontend, MoonBuggy can share PO files with Lingui.js. This allows you to maintain a single set of translation files for both server and client.
Quick Start
dotnet add package intelligenthack.MoonBuggy
dotnet add package intelligenthack.MoonBuggy.SourceGenerator
dotnet tool install intelligenthack.MoonBuggy.Cli
Create moonbuggy.config.json, write _t() calls in your views, run moonbuggy extract, translate the PO files, and build. The source generator package handles all compiler configuration automatically. See Getting Started for the full walkthrough.
Razor Pages / MVC: If you use
_t()or_m()in.cshtmlfiles, add<UseRazorSourceGenerator>false</UseRazorSourceGenerator>to your.csproj. This switches to the legacy Razor compilation pipeline, which makes Razor call sites visible to the MoonBuggy source generator.
What it looks like
In Razor views, you wrap translatable text with _t() for plain strings:
// _ViewImports.cshtml
@using static MoonBuggy.Translate
// In any view
<h1>@_t("Welcome to $name$!", new { name = Model.SiteName })</h1>
<p>@_t("You have $#x# new message|#x# new messages$", new { x = Model.MessageCount })</p>
The $name$ token marks a variable placeholder, and the $...|...$ construct expresses plural forms. The pipe character separates the "one" and "other" variants, and #x# represents the count.
For strings that require formatting, _m() allows you to write markdown while keeping translators away from raw HTML:
<p>@_m("Read **this** and click [here]($url$)", new { url = Model.HelpUrl })</p>
The extract / translate / build loop
1. Write views in the source language (English). Use _t() for plain text and _m() for markdown.
2. Extract strings using the CLI.
moonbuggy extract
The extract command scans your source files, transforms the MoonBuggy syntax into standard ICU MessageFormat, and writes PO files.
3. Translators fill in the PO files. PO is a widely supported format with mature tooling (Poedit, Crowdin, Transifex, Weblate).
4. Build the application. During dotnet build, the source generator reads PO files and generates a C# interceptor for every call site. Each interceptor writes strings directly to the output — no lookups, no allocations:
// Conceptual output of the source generator (you never see this)
switch (lcid) {
case 10: // Spanish
writer.Write("Tienes ");
if (x == 1) { writer.Write("1 artículo"); }
else { writer.Write(x); writer.Write(" artículos"); }
writer.Write(" en tu carrito");
break;
default: // English
writer.Write("You have ");
if (x == 1) { writer.Write("1 item"); }
else { writer.Write(x); writer.Write(" items"); }
writer.Write(" in your cart");
break;
}
CLDR plural rules for each language are baked in as inline arithmetic, so no ICU runtime library is needed.
5. Repeat as text changes. Run moonbuggy extract again after modifying strings. The extract step is non-destructive. Use --clean to remove deleted entries. In CI, moonbuggy validate --strict catches untranslated strings before they ship.
Documentation
- Getting Started — step-by-step setup for a new project
- Syntax Reference — variables, plurals, markdown, escaping
- CLI Reference —
extractandvalidatecommands - Configuration — config file, MSBuild properties, Lingui.js co-existence
License
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Markdig (>= 0.38.0)
- Microsoft.AspNetCore.Html.Abstractions (>= 2.3.0)
-
net8.0
- Markdig (>= 0.38.0)
- Microsoft.AspNetCore.Html.Abstractions (>= 2.3.0)
- System.Text.Encodings.Web (>= 9.0.1)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.