{"id":25642905,"url":"https://github.com/mehalick/xaki","last_synced_at":"2025-04-13T08:20:28.828Z","repository":{"id":71159724,"uuid":"116114974","full_name":"mehalick/Xaki","owner":"mehalick","description":"Simplified multi-language POCO localization for .NET Core","archived":false,"fork":false,"pushed_at":"2025-03-19T12:14:59.000Z","size":262,"stargazers_count":21,"open_issues_count":2,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-03-27T00:10:21.820Z","etag":null,"topics":["c-sharp","dotnet-core","entity-framework-core","localization"],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mehalick.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-03T08:56:52.000Z","updated_at":"2025-03-19T12:15:03.000Z","dependencies_parsed_at":"2025-03-27T00:10:18.277Z","dependency_job_id":"e8bfb4c5-03ba-4418-8234-d6b7898f33d2","html_url":"https://github.com/mehalick/Xaki","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mehalick%2FXaki","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mehalick%2FXaki/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mehalick%2FXaki/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mehalick%2FXaki/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mehalick","download_url":"https://codeload.github.com/mehalick/Xaki/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248681598,"owners_count":21144715,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-sharp","dotnet-core","entity-framework-core","localization"],"created_at":"2025-02-23T06:16:24.221Z","updated_at":"2025-04-13T08:20:28.806Z","avatar_url":"https://github.com/mehalick.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1\u003e\u003cimg src=\"https://cdn.xaki.io/assets/logo-text-636723199289149229.svg\" width=\"512\" height=\"190\" alt=\"Xaki\"\u003e\u003c/h1\u003e\n\n[![appveyor](https://img.shields.io/appveyor/ci/mehalick/xaki/master.svg?label=windows)](https://ci.appveyor.com/project/mehalick/xaki)\n[![azure devops](https://img.shields.io/azure-devops/build/mehalick/ac9e6a14-b763-4434-8b15-a9c0defdf0da/1.svg?label=windows/linux/mac)](https://travis-ci.org/mehalick/Xaki)\n[![tests](https://img.shields.io/appveyor/tests/mehalick/xaki/master.svg)](https://ci.appveyor.com/project/mehalick/xaki/build/tests)\n[![nuget](https://img.shields.io/nuget/v/Xaki.svg)](https://www.nuget.org/packages/Xaki)\n[![myget](https://img.shields.io/myget/xaki/v/Xaki.svg?label=myget)](https://www.myget.org/feed/xaki/package/nuget/Xaki)\n\nXaki is a .NET library for adding multi-language support to POCO classes. It includes a lightweight service for persisting and retrieving data to and from databases using any ORM.\n\nXaki works well with all versions of Entity Framework and includes ASP.NET Core support for automatic localization to language codes provided by routes, querystrings, cookies, and HTTP headers. \n\n## Introduction\n\nSetting up classes to be multi-language starts by implementing `ILocalizable` and adding `LocalizedAttribute` to multi-language properties:\n\n```csharp\npublic class Planet : ILocalizable\n{\n    public int PlanetId { get; set; }\n\n    [Localized]\n    public string Name { get; set; }\n}\n```\n\nInternally multi-language content is stored as serialized JSON:\n\n```js\nplanet.Name = \"{'en':'Earth','ru':'Земля́','ja':'地球'}\";\n```\n\nTo localize a list, say pulled from a database with Entity Framework, you can use the provided `IObjectLocalizer.Localize\u003cT\u003e()` method:\n\n```csharp\n[HttpGet]\npublic async Task\u003cIActionResult\u003e Index()\n{\n    var planets = await _context.Planets.ToListAsync();\n\n    planets = _localizer.Localize\u003cPlanet\u003e(planets).ToList();\n\n    return View(planets);\n}\n```\n\n## Getting Started\n\n### ASP.NET Core\n\n#### 1. Add NuGet Packages\n\nFor ASP.NET Core projects you'll add the **Xaki** and **Xaki.AspNetCore** NuGet packages to your project. While these packages are beta you'll install from MyGet:\n\n##### Package Manager\n\n```powershell\nInstall-Package Xaki.AspNetCore\n```\n\n##### .NET CLI\n\n```powershell\ndotnet add package Xaki.AspNetCore\n```\n\nYou may also want to add the NuGet feed above to your nuget.config file at the root of your solution:\n\n#### 2. Add Xaki to Startup\n\nXaki follows the usual pattern to add and configure services in an ASP.NET Core host, to add Xaki and request localization update `Startup.cs` to include:\n\n```csharp\npublic void ConfigureServices(IServiceCollection services)\n{\n    // ...\n\n    services.AddMvc().AddXaki(new XakiOptions\n    {\n        RequiredLanguages = new[] { \"en\", \"zh\", \"ar\", \"es\", \"hi\" },\n        OptionalLanguages = new[] { \"pt\", \"ru\", \"ja\", \"de\", \"el\" }\n    });\n}\n\npublic void Configure(IApplicationBuilder app, IHostingEnvironment env)\n{\n    // ...\n\n    app.UseXaki(); // must precede UseMvc()\n    app.UseMvc();\n}\n```\n\nFor a sample ASP.NET Core app see [https://github.com/mehalick/Xaki/tree/master/samples/Xaki.Sample]().\n\n#### 3. Create Localized Entity\n\nAny Entity Framework POCO can be localizable by implementing `ILocalizable` with one or more properties decorated with `LocalizedAttribute`:\n\n```csharp\npublic class Planet : ILocalizable\n{\n    public int PlanetId { get; set; }\n\n    [Localized]\n    public string Name { get; set; }\n}\n```\n\n#### 4. Add Localization to Controllers\n\nSimilar to ASP.NET Core's `IStringLocalizer` and `IHtmlLocalizer` you can localize objects and collections with `IObjectLocalizer`, simply add it to any controller:\n\n```csharp\n[Route(\"planets\")]\npublic class PlanetsController : Controller\n{\n    private readonly DataContext _context;\n    private readonly IObjectLocalizer _localizer;\n\n    public PlanetsController(DataContext context, IObjectLocalizer localizer)\n    {\n        _context = context;\n        _localizer = localizer;\n    }\n}\n```\n\nYou can now fetch entities and send the localized versions to your views:\n\n```csharp\n[HttpGet]\npublic async Task\u003cIActionResult\u003e Index()\n{\n    var planets = await _context.Planets.ToListAsync();\n\n    planets = _localizer.Localize\u003cPlanet\u003e(planets).ToList();\n\n    return View(planets);\n}\n```\n\n##### How does IObjectLocalizer resolve the current language?\n\n`IObjectLocalizer` uses ASP.NET Core's `RequestLocalizationMiddleware` to resolve the current language and culture using:\n\n1. Querystrings\n2. Cookies\n3. Accept-Language Header\n\nFor more information see [https://andrewlock.net/adding-localisation-to-an-asp-net-core-application/]().\n\nIf you'd like to customize how `IObjectLocalizer` resolves languages you can create your own resolver by implementing `Xaki.AspNetCore.LanguageResolvers.ILanguageResolver`.\n\n#### 5. Editing Localized Entities\n\nThe **Xaki.AspNetCore** library includes a tag helper and model binder to make edit views and actions extremely simple. \n\n##### Tag Helper\n\nTo convert any input into a rich localization editor simply replace `\u003cinput for=\"Name\" /\u003e` with `\u003cinput localized-for=\"Name\" /\u003e`:\n\n```html\n\u003cform asp-action=\"Edit\"\u003e\n\n    \u003cinput asp-for=\"PlanetId\" type=\"hidden\" /\u003e\n\n    \u003cdiv class=\"form-group\"\u003e\n        \u003clabel\u003eName\u003c/label\u003e\n        \u003cinput localized-for=\"Name\" /\u003e\n    \u003c/div\u003e\n\n    \u003cbutton type=\"submit\" class=\"btn btn-dark\"\u003eSubmit\u003c/button\u003e\n\n\u003c/form\u003e\n```\n\nYou'll automatically get a rich localization editor:\n\n![editor](https://cdn.xaki.io/assets/2018-09-11_10-26-05-636722475947053940.png)\n\nThe editor automatically lists the individual language textboxes in the order they are specified in `Startup.cs` and client-side validation is included:\n\n![validation](https://cdn.xaki.io/assets/2018-09-11_10-28-42-636722477515160922.png)\n\n#### Model Binding\n\nThe **Xaki.AspNetCore** library includes `LocalizableModelBinder` which is automatically registered via `services.AddMvc().AddXaki()`. \n\nThis allows the localization tag helper to correctly model bind to `ILocalized` entities and view models in your actions:\n\n```csharp\n[HttpPost(\"{planetId:int}\")]\npublic async Task\u003cIActionResult\u003e Edit(Planet planet)\n{\n    _context.Entry(planet).State = EntityState.Modified;\n\n    await _context.SaveChangesAsync();\n\n    return RedirectToAction(nameof(Index));\n}\n```\n\nHere your localized properties are automatically bound:\n\n![model binding](https://cdn.xaki.io/assets/2018-09-11_10-34-56-636722481804812672.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmehalick%2Fxaki","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmehalick%2Fxaki","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmehalick%2Fxaki/lists"}