Skip to content

Commit c64b343

Browse files
committed
Update documentation with OTA sample references
1 parent 4cc143c commit c64b343

4 files changed

Lines changed: 339 additions & 0 deletions

File tree

LocalizationManager.JsonLocalization/README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,52 @@ app.MapGet("/items/{count}", (int count, JsonLocalizer localizer) =>
155155
});
156156
```
157157

158+
### 4. OTA (Over-The-Air) Localization with LRM Cloud
159+
160+
Update translations in real-time without redeploying your application. The FIRST OTA localization solution for .NET!
161+
162+
```csharp
163+
// Program.cs
164+
var builder = WebApplication.CreateBuilder(args);
165+
166+
// Add JSON localization with OTA support
167+
builder.Services.AddJsonLocalizationWithOta(options =>
168+
{
169+
options.UseOta(
170+
endpoint: "https://lrm-cloud.com",
171+
apiKey: "lrm_your_read_only_api_key",
172+
project: "@username/my-project" // or "org/project" for organizations
173+
);
174+
175+
// Optional: Configure refresh interval (default: 5 minutes)
176+
options.Ota!.RefreshInterval = TimeSpan.FromMinutes(5);
177+
178+
// Optional: Fall back to local resources when offline
179+
options.FallbackToLocal = true;
180+
options.ResourcesPath = "Resources"; // Local fallback path
181+
});
182+
```
183+
184+
**How it works:**
185+
1. App starts → Uses embedded/local resources immediately
186+
2. Background service fetches translations from LRM Cloud
187+
3. Translations sync automatically every 5 minutes (configurable)
188+
4. Changes in LRM Cloud are reflected in your app without redeployment
189+
190+
**Requirements:**
191+
- Create a read-only API key in your LRM Cloud project settings
192+
- API key must have `read` scope
193+
194+
**Benefits:**
195+
- Fix typos instantly in production
196+
- Add new languages without code changes
197+
- A/B test translations
198+
- Works with all .NET platforms (ASP.NET Core, Blazor, MAUI, WPF, etc.)
199+
200+
**Note:** When using with the [Generator package](https://www.nuget.org/packages/LocalizationManager.JsonLocalization.Generator), generated classes work for compile-time keys. For new keys added via OTA, use dynamic access: `Strings.Localizer["NewKey"]`.
201+
202+
**Try it locally:** The [ConsoleApp.OtaDemo](https://github.com/nickprotop/LocalizationManager/tree/main/samples/ConsoleApp.OtaDemo) sample demonstrates OTA features using a mock HTTP handler - no real server required.
203+
158204
## Configuration Options
159205

160206
| Option | Type | Default | Description |
@@ -385,6 +431,7 @@ Complete working examples are available in the GitHub repository:
385431
| [ConsoleApp.Standalone](https://github.com/nickprotop/LocalizationManager/tree/main/samples/ConsoleApp.Standalone) | File system resources, standalone API |
386432
| [ConsoleApp.Embedded](https://github.com/nickprotop/LocalizationManager/tree/main/samples/ConsoleApp.Embedded) | Embedded resources in assembly |
387433
| [ConsoleApp.SourceGenerator](https://github.com/nickprotop/LocalizationManager/tree/main/samples/ConsoleApp.SourceGenerator) | Compile-time strongly-typed access |
434+
| [ConsoleApp.OtaDemo](https://github.com/nickprotop/LocalizationManager/tree/main/samples/ConsoleApp.OtaDemo) | OTA localization with mock server (no real server needed) |
388435
| [WebApp.AspNetCore](https://github.com/nickprotop/LocalizationManager/tree/main/samples/WebApp.AspNetCore) | ASP.NET Core with DI integration |
389436

390437
## API Reference

cloud/src/www/docs/cloud.html

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@
550550
<a href="#translation-memory" class="sidebar-link">Translation Memory</a>
551551
<a href="#glossary" class="sidebar-link">Glossary</a>
552552
<a href="#cli-sync" class="sidebar-link">CLI Sync</a>
553+
<a href="#ota" class="sidebar-link">OTA Localization</a>
553554
<a href="#teams" class="sidebar-link">Teams & Organizations</a>
554555
<a href="#billing" class="sidebar-link">Billing & Plans</a>
555556
</div>
@@ -945,6 +946,78 @@ <h3>Snapshots</h3>
945946
<p>See the <a href="https://github.com/nickprotop/LocalizationManager/blob/main/docs/CLOUD_SYNC.md" target="_blank">Cloud Sync Guide</a> for complete CLI documentation.</p>
946947
</div>
947948

949+
<h2 id="ota">OTA (Over-The-Air) Localization</h2>
950+
<p>Update translations in your .NET applications in real-time without redeploying. LRM is the <strong>first and only OTA localization solution for .NET!</strong></p>
951+
952+
<h3>What is OTA?</h3>
953+
<p>OTA localization allows your .NET application to fetch translations directly from LRM Cloud at runtime. When you update translations in the web editor, your app automatically receives the changes without any code deployment.</p>
954+
955+
<h3>OTA vs CLI Sync</h3>
956+
<table>
957+
<tr>
958+
<th>Aspect</th>
959+
<th>CLI Sync</th>
960+
<th>OTA</th>
961+
</tr>
962+
<tr>
963+
<td><strong>Update Method</strong></td>
964+
<td>Pull to local files, rebuild & deploy</td>
965+
<td>Automatic at runtime</td>
966+
</tr>
967+
<tr>
968+
<td><strong>Deployment</strong></td>
969+
<td>Required for changes</td>
970+
<td>Not required</td>
971+
</tr>
972+
<tr>
973+
<td><strong>Offline Support</strong></td>
974+
<td>Full (embedded resources)</td>
975+
<td>Fallback to local</td>
976+
</tr>
977+
<tr>
978+
<td><strong>Best For</strong></td>
979+
<td>CI/CD workflows, version control</td>
980+
<td>Quick fixes, live updates</td>
981+
</tr>
982+
</table>
983+
984+
<h3>Quick Setup (.NET)</h3>
985+
<pre><code>// Install the NuGet package
986+
// dotnet add package LocalizationManager.JsonLocalization
987+
988+
// Program.cs
989+
builder.Services.AddJsonLocalizationWithOta(options =>
990+
{
991+
options.UseOta(
992+
endpoint: "https://lrm-cloud.com",
993+
apiKey: "lrm_your_read_only_api_key",
994+
project: "@username/my-project" // or "org/project"
995+
);
996+
});</code></pre>
997+
998+
<h3>Creating an API Key</h3>
999+
<ol>
1000+
<li>Go to <strong>Project Settings</strong> &rarr; <strong>API Keys</strong></li>
1001+
<li>Click <strong>"Create API Key"</strong></li>
1002+
<li>Select <strong>"Read"</strong> scope (minimum required for OTA)</li>
1003+
<li>Copy the key (format: <code>lrm_xxxxxxxx</code>)</li>
1004+
</ol>
1005+
1006+
<h3>Supported Platforms</h3>
1007+
<p>OTA works with the entire .NET ecosystem:</p>
1008+
<ul>
1009+
<li>ASP.NET Core (Web APIs, MVC, Razor Pages, Blazor)</li>
1010+
<li>.NET MAUI (iOS, Android, Windows, macOS)</li>
1011+
<li>Avalonia, WPF, WinForms</li>
1012+
<li>Console apps, Worker Services</li>
1013+
<li>Azure Functions, AWS Lambda</li>
1014+
</ul>
1015+
1016+
<div class="info-box">
1017+
<div class="info-box-title">.NET Documentation</div>
1018+
<p>For complete OTA setup instructions, configuration options, and code examples, see the <a href="dotnet.html#ota">.NET Libraries OTA documentation</a>.</p>
1019+
</div>
1020+
9481021
<h2 id="teams">Teams & Organizations</h2>
9491022
<p>Organizations allow team collaboration on localization projects (Team and Enterprise plans).</p>
9501023

cloud/src/www/docs/dotnet.html

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,7 @@
547547
<a href="#installation" class="sidebar-link">Installation</a>
548548
<a href="#standalone" class="sidebar-link">Standalone Usage</a>
549549
<a href="#aspnetcore" class="sidebar-link">ASP.NET Core</a>
550+
<a href="#ota" class="sidebar-link">OTA Localization</a>
550551
<a href="#pluralization" class="sidebar-link">Pluralization</a>
551552
<a href="#source-generator" class="sidebar-link">Source Generator</a>
552553
<a href="#samples" class="sidebar-link">Sample Projects</a>
@@ -727,6 +728,131 @@ <h3>Configuration Options</h3>
727728
options.ResourceAssembly = typeof(Program).Assembly;
728729
});</code></pre>
729730

731+
<h2 id="ota">OTA (Over-The-Air) Localization</h2>
732+
<p>Update translations in real-time without redeploying your application. LRM is the <strong>first and only OTA localization solution for .NET!</strong></p>
733+
734+
<div class="info-box">
735+
<div class="info-box-title">What is OTA?</div>
736+
<p>OTA localization allows your .NET application to fetch translations from LRM Cloud at runtime, automatically syncing updates without code changes or redeployment.</p>
737+
</div>
738+
739+
<h3>How It Works</h3>
740+
<ol>
741+
<li>Your app starts and uses embedded/local resources immediately</li>
742+
<li>A background service fetches translations from LRM Cloud</li>
743+
<li>Translations sync automatically (default: every 5 minutes)</li>
744+
<li>Changes in LRM Cloud reflect in your app without redeployment</li>
745+
</ol>
746+
747+
<h3>Quick Setup</h3>
748+
<pre><code>// Program.cs
749+
builder.Services.AddJsonLocalizationWithOta(options =>
750+
{
751+
options.UseOta(
752+
endpoint: "https://lrm-cloud.com",
753+
apiKey: "lrm_your_read_only_api_key",
754+
project: "@username/my-project" // or "org/project"
755+
);
756+
757+
// Optional: Configure refresh interval (default: 5 minutes)
758+
options.Ota!.RefreshInterval = TimeSpan.FromMinutes(5);
759+
760+
// Optional: Fall back to local resources when offline
761+
options.FallbackToLocal = true;
762+
options.ResourcesPath = "Resources"; // Local fallback path
763+
});</code></pre>
764+
765+
<h3>Creating an API Key</h3>
766+
<ol>
767+
<li>Go to <strong>Project Settings</strong> &rarr; <strong>API Keys</strong> in LRM Cloud</li>
768+
<li>Click <strong>"Create API Key"</strong></li>
769+
<li>Select <strong>"Read"</strong> scope (sufficient for OTA)</li>
770+
<li>Copy the key (starts with <code>lrm_</code>)</li>
771+
</ol>
772+
773+
<h3>Configuration Options</h3>
774+
<table>
775+
<tr>
776+
<th>Option</th>
777+
<th>Default</th>
778+
<th>Description</th>
779+
</tr>
780+
<tr>
781+
<td><code>Endpoint</code></td>
782+
<td><code>https://lrm-cloud.com</code></td>
783+
<td>LRM Cloud API endpoint</td>
784+
</tr>
785+
<tr>
786+
<td><code>ApiKey</code></td>
787+
<td>-</td>
788+
<td>API key with read scope (required)</td>
789+
</tr>
790+
<tr>
791+
<td><code>Project</code></td>
792+
<td>-</td>
793+
<td>Project path: <code>@user/project</code> or <code>org/project</code></td>
794+
</tr>
795+
<tr>
796+
<td><code>RefreshInterval</code></td>
797+
<td>5 minutes</td>
798+
<td>How often to check for updates</td>
799+
</tr>
800+
<tr>
801+
<td><code>FallbackToLocal</code></td>
802+
<td><code>true</code></td>
803+
<td>Use local resources when offline</td>
804+
</tr>
805+
<tr>
806+
<td><code>Timeout</code></td>
807+
<td>10 seconds</td>
808+
<td>HTTP request timeout</td>
809+
</tr>
810+
<tr>
811+
<td><code>MaxRetries</code></td>
812+
<td>3</td>
813+
<td>Retry attempts for failed requests</td>
814+
</tr>
815+
</table>
816+
817+
<h3>Supported Platforms</h3>
818+
<p>OTA works with the entire .NET ecosystem:</p>
819+
<ul>
820+
<li>ASP.NET Core (Web APIs, MVC, Razor Pages)</li>
821+
<li>Blazor (Server + WebAssembly)</li>
822+
<li>.NET MAUI (iOS, Android, Windows, macOS)</li>
823+
<li>Avalonia (Cross-platform desktop)</li>
824+
<li>WPF and WinForms</li>
825+
<li>Console applications</li>
826+
<li>Azure Functions / AWS Lambda</li>
827+
<li>Worker Services</li>
828+
</ul>
829+
830+
<h3>Network Resilience</h3>
831+
<p>The OTA client includes built-in resilience features:</p>
832+
<ul>
833+
<li><strong>Retry with exponential backoff</strong> - Automatically retries failed requests</li>
834+
<li><strong>Circuit breaker</strong> - Stops requests after repeated failures, auto-recovers</li>
835+
<li><strong>ETag caching</strong> - Efficient bandwidth usage, only fetches when changed</li>
836+
<li><strong>Graceful fallback</strong> - Uses local resources when cloud is unavailable</li>
837+
</ul>
838+
839+
<h3>Generator Package Compatibility</h3>
840+
<p>When using OTA with the source generator package:</p>
841+
<ul>
842+
<li>Generated classes work for compile-time keys</li>
843+
<li>New OTA keys use dynamic access: <code>Strings.Localizer["NewKey"]</code></li>
844+
</ul>
845+
846+
<div class="info-box">
847+
<div class="info-box-title">Use Cases</div>
848+
<ul style="margin-bottom: 0;">
849+
<li><strong>Fix typos instantly</strong> - No redeployment needed</li>
850+
<li><strong>Add new languages</strong> - Without code changes</li>
851+
<li><strong>A/B test translations</strong> - Update specific strings</li>
852+
<li><strong>Emergency updates</strong> - Correct mistakes immediately</li>
853+
</ul>
854+
</div>
855+
730856
<h2 id="pluralization">Pluralization</h2>
731857
<p>The library supports CLDR plural rules for 30+ languages with the following categories:</p>
732858

docs/CLOUD.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,99 @@ Organizations enable team collaboration on localization projects.
439439
3. **Import Resources** - Upload ZIP or push via CLI
440440
4. **Start Translating** - Use the web editor or CLI
441441

442+
## OTA (Over-The-Air) Localization
443+
444+
Update translations in real-time without redeploying your .NET application. LRM is the **first and only OTA localization solution for .NET**!
445+
446+
### How OTA Works
447+
448+
1. Your .NET app starts and loads local/embedded resources
449+
2. Background service fetches translations from LRM Cloud
450+
3. Translations sync automatically (default: every 5 minutes)
451+
4. Changes in LRM Cloud reflect in your app without redeployment
452+
453+
### Quick Setup
454+
455+
```csharp
456+
// Program.cs
457+
builder.Services.AddJsonLocalizationWithOta(options =>
458+
{
459+
options.UseOta(
460+
endpoint: "https://lrm-cloud.com",
461+
apiKey: "lrm_your_read_only_api_key",
462+
project: "@username/my-project" // or "org/project"
463+
);
464+
});
465+
```
466+
467+
### Creating an API Key
468+
469+
1. Go to **Project Settings** > **API Keys**
470+
2. Click **"Create API Key"**
471+
3. Select **"Read"** scope (sufficient for OTA)
472+
4. Copy the key (`lrm_...`)
473+
474+
### OTA Configuration Options
475+
476+
| Option | Default | Description |
477+
|--------|---------|-------------|
478+
| `Endpoint` | `https://lrm-cloud.com` | LRM Cloud API endpoint |
479+
| `ApiKey` | - | API key with read scope (required) |
480+
| `Project` | - | Project path: `@user/project` or `org/project` |
481+
| `RefreshInterval` | 5 minutes | How often to check for updates |
482+
| `FallbackToLocal` | true | Use local resources when offline |
483+
| `Timeout` | 10 seconds | HTTP request timeout |
484+
| `MaxRetries` | 3 | Retry attempts for failed requests |
485+
486+
### Supported Platforms
487+
488+
OTA works with the entire .NET ecosystem:
489+
490+
- ASP.NET Core (Web APIs, MVC, Razor Pages)
491+
- Blazor (Server + WebAssembly)
492+
- .NET MAUI (iOS, Android, Windows, macOS)
493+
- Avalonia (Cross-platform desktop)
494+
- WPF and WinForms
495+
- Console applications
496+
- Azure Functions / AWS Lambda
497+
- Worker Services
498+
499+
### Network Resilience
500+
501+
The OTA client includes:
502+
503+
- **Retry with exponential backoff** - Automatically retries failed requests
504+
- **Circuit breaker** - Stops requests after repeated failures, auto-recovers
505+
- **ETag caching** - Efficient bandwidth usage, only fetches when changed
506+
- **Graceful fallback** - Uses local resources when cloud is unavailable
507+
508+
### Generator Package Compatibility
509+
510+
When using OTA with `LocalizationManager.JsonLocalization.Generator`:
511+
512+
- Generated classes work for compile-time keys
513+
- New OTA keys use dynamic access: `Strings.Localizer["NewKey"]`
514+
515+
### Sample Project
516+
517+
The [ConsoleApp.OtaDemo](https://github.com/nickprotop/LocalizationManager/tree/main/samples/ConsoleApp.OtaDemo) sample demonstrates all OTA features using a mock HTTP handler - **no real LRM Cloud server required**:
518+
519+
- Initial bundle fetch
520+
- ETag caching (304 Not Modified)
521+
- Multi-language support
522+
- CLDR pluralization
523+
- Live translation updates
524+
- Fallback to embedded resources
525+
526+
Run it directly to see OTA in action:
527+
528+
```bash
529+
cd samples/ConsoleApp.OtaDemo
530+
dotnet run
531+
```
532+
533+
See the [NuGet package documentation](https://www.nuget.org/packages/LocalizationManager.JsonLocalization) for full OTA API details.
534+
442535
## See Also
443536

444537
- [Cloud Sync Guide](CLOUD_SYNC.md) - Complete CLI sync documentation

0 commit comments

Comments
 (0)