{"id":29148693,"url":"https://github.com/ygg01/linguini","last_synced_at":"2025-06-30T22:06:29.168Z","repository":{"id":39884476,"uuid":"344444516","full_name":"Ygg01/Linguini","owner":"Ygg01","description":"C# Port of fluent.rs zero-copy parser","archived":false,"fork":false,"pushed_at":"2025-04-05T23:29:27.000Z","size":714,"stargazers_count":34,"open_issues_count":4,"forks_count":10,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-30T22:06:24.765Z","etag":null,"topics":["c-sharp","dotnet","i18n","localization","zero-copy"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Ygg01.png","metadata":{"files":{"readme":"README.md","changelog":"changelog.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE-APACHE","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},"funding":{"github":["Ygg01"]}},"created_at":"2021-03-04T11:03:18.000Z","updated_at":"2025-05-23T10:57:21.000Z","dependencies_parsed_at":"2023-02-19T16:35:40.321Z","dependency_job_id":"ef2284d1-e4d4-478b-b462-ca83d17e480a","html_url":"https://github.com/Ygg01/Linguini","commit_stats":null,"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/Ygg01/Linguini","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ygg01%2FLinguini","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ygg01%2FLinguini/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ygg01%2FLinguini/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ygg01%2FLinguini/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Ygg01","download_url":"https://codeload.github.com/Ygg01/Linguini/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Ygg01%2FLinguini/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262857289,"owners_count":23375492,"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","i18n","localization","zero-copy"],"created_at":"2025-06-30T22:06:25.383Z","updated_at":"2025-06-30T22:06:29.130Z","avatar_url":"https://github.com/Ygg01.png","language":"C#","funding_links":["https://github.com/sponsors/Ygg01"],"categories":[],"sub_categories":[],"readme":"[![.NET](https://github.com/Ygg01/Linguini/actions/workflows/dotnet.yml/badge.svg?branch=master)](https://github.com/Ygg01/Linguini/actions/workflows/dotnet.yml)\n![Nuget](https://img.shields.io/nuget/v/Linguini.Bundle?label=Linguini.Bundle)\n![Nuget](https://img.shields.io/nuget/v/Linguini.Shared?label=Linguini.Shared)\n![Nuget](https://img.shields.io/nuget/v/Linguini.Syntax?label=Linguini.Syntax)\n![Nuget](https://img.shields.io/nuget/v/PluralRules.Generator?label=%20PluralRules.Generator)\n\n# Linguini\nLinguini is a C# implementation of Project Fluent, a localization system for natural-sounding translations with features like:\n\n## Asymmetric Localization\nNatural-sounding translations with genders and grammatical cases only when necessary. Expressiveness is not limited by the grammar of the source language.\n\n## Progressive Enhancement\nTranslations are isolated; locale-specific logic doesn't leak to other locales. Authors can iteratively improve translations without impact on other languages.\n\n## Modular\nLinguini is highly modular. You only can use the parts you need.\nNeed just parsing? Get Linguni.Syntax.\nNeed only Plural Rules data? Get PluralRules.Generator and connect to XML CLDR Plural rules data.\n\n## Performant\nLinguini uses a zero-copy parser to parse the resources. While at the moment, there are no benchmarks,\nit is used by [RobustToolbox](https://github.com/space-wizards/RobustToolbox) as a localization framework.\n\n# How to get it?\n\nTo install the [Fluent Bundle](https://www.nuget.org/packages/Linguini.Bundle/) type in your console:\n\n```dotnet add package Linguini.Bundle```\n\nYou can also follow other NuGet installation instructions. E.g. :\n\n```paket add Linguini.Bundle```\n\nOr copy this code to your [PackageReference](https://learn.microsoft.com/en-gb/nuget/consume-packages/package-references-in-project-files)\n\n```xml\n\u003cPackageReference Include=\"Linguini.Bundle\" Version=\"0.8.2\" /\u003e\n```\n\n# How to use it?\n\nFor a 2-minute tour of Linguini, add this to your C# code:\n```csharp\nvar bundler = LinguiniBuilder.Builder()\n    .CultureInfo(new CultureInfo(\"en\"))\n    .AddResource(\"hello-user =  Hello, { $username }!\")\n    .UncheckedBuild();\n\nvar message = bundler.GetAttrMessage(\"hello-user\",  (\"username\", (FluentString)\"Test\"));\nAssert.AreEqual(\"Hello, Test!\", message);\n```\n\n## The 10 min tour - What do the lines mean?\n\nLet's go line by line and see how `LinguiniBuilder` works.\n\n1. Init - This creates a `LinguiniBuilder` using a type-safe builder pattern.\n    ```csharp\n    var bundler = LinguiniBuilder.Builder()\n    ```\n\n2. Set the language - a translation bundle **must** have a language to translate to. In this case, we choose the English language.\n    ```csharp\n    .CultureInfo(new CultureInfo(\"en\"))\n    ```\n\n3. Add a resource - a translation bundle without resources is pointless. We choose inline string for ease of the example. \n    ```csharp\n        .AddResource(\"hello-user =  Hello, { $username }!\")\n    ```\n    \n   If you need an example of passing files, here is a oneliner example assuming you defined `using var streamReader = new StreamReader(path_to_file);` somewhere (Hint: no need to use `StreamReader`, any [`TextReader`](https://learn.microsoft.com/en-us/dotnet/api/system.io.textreader?view=net-7.0) will do).\n   ```csharp\n        .AddResource(streamReader)\n   ```\n\n4. Complete the `ResourceBundle` - We call `UncheckedBuild()` to convert a builder to a bundle. The bundle will parse its resources and report\n   errors. Since we don't care about errors, we are fine with `ResourceBundle` throwing errors.\n   ```\n       .UncheckedBuild();\n   ```\n   \n5. Get `hello-user` term where `username` is `Test`.\n   ```csharp\n   bundler.GetAttrMessage(\"hello-user\",  (\"username\", (FluentString)\"Test\"));\n   ```\n\n# How to develop for it?\n\nTo develop you need to install [Git](https://git-scm.com/) and [.NET SDK](https://dotnet.microsoft.com/en-us/download) first.\n\nInstallation of these tools is out of the scope of the document\n\n```shell\ngit clone https://github.com/Ygg01/Linguini.git\ncd Linguini\ndotnet test\n```\n\n## Build documentation\n\nTo build API documentation for `Linguini`.\n\n1. Install [`docfx`](https://github.com/dotnet/docfx)\n```shell\ndotnet tool install -g docfx\n```\n2. Build documentation\n```shell\ndocfx build .\\docfx_project\\docfx.json --serve\n```\n3. Open http://localhost:8080/api\n\n\n# Quick questions and answers\n\n## Why FluentBundle isn't thread-safe?\n\nMaking it concurrent could add a performance penalty; otherwise, a concurrent bundle would be the default. To make it thread-safe, add `UseConcurrent()`\nin builder:\n```csharp\n    var bundler = LinguiniBuilder.Builder()\n       .CultureInfo(new CultureInfo(\"en\"))\n       .AddResource(\"hello-user =  Hello, { $username }!\")\n       .UseConcurrent()\n       .UncheckedBuild();\n```\nOr set `UseConcurrent = true` in `FluentBundleOption` passed to the factory method:\n```csharp\n    var x = new FluentBundleOption()\n    {\n        UseConcurrent = true,\n    };\n    var bundle = FluentBundle.MakeUnchecked(defaultBundleOpt);\n```\n## Isn't `.ftl` FreeMarker Template language?\n\nNo, it can also be Fluent, a localization system by Mozilla.\n\n## What syntax does Fluent Localization use?\nFor more details, see [Fluent syntax guide](https://projectfluent.org/fluent/guide/).\n\n# Licenses\n\nLinguini Bundle and associated projects are licensed under Apache and MIT licenses. Consult the LICENSE-MIT and LICENSE-APACHE for more detail.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fygg01%2Flinguini","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fygg01%2Flinguini","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fygg01%2Flinguini/lists"}