Slang.Net.Attributes 9.3.0

dotnet add package Slang.Net.Attributes --version 9.3.0
                    
NuGet\Install-Package Slang.Net.Attributes -Version 9.3.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Slang.Net.Attributes" Version="9.3.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Slang.Net.Attributes" Version="9.3.0" />
                    
Directory.Packages.props
<PackageReference Include="Slang.Net.Attributes" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Slang.Net.Attributes --version 9.3.0
                    
#r "nuget: Slang.Net.Attributes, 9.3.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Slang.Net.Attributes@9.3.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Slang.Net.Attributes&version=9.3.0
                    
Install as a Cake Addin
#tool nuget:?package=Slang.Net.Attributes&version=9.3.0
                    
Install as a Cake Tool

Slang.NET

Nuget Nuget License: MIT

Type-safe i18n for .NET

About this library

Slang.NET is a .NET port of the slang from the Dart/Flutter community with new features (like string format).

You can view how the generated files general, en, and de look

Getting Started:

Install the library as a NuGet package:

Install-Package dotnet add package Slang.Net

Add JSON files:

Important file must end with ".i18n.json". This is necessary so that the SourceGenerator does not track changes to other AdditionalFiles.

i18n/strings_en.i18n.json or i18n/strings_en-US.i18n.json or i18n/strings.i18n.json (for base culture)

{
  "screen": {
    "locale1": "Locale 1"
  }
}

i18n/strings_ru.i18n.json or i18n/strings_ru-RU.i18n.json

{
  "screen": {
    "locale1": "Локаль 1"
  }
}

slang.json

{
  "base_culture": "en" // or "en-EN"
}

Recommendation It is recommended to specify the country code, such as "en-US," for proper functionality when formatting strings, especially if you will be retrieving the list of cultures from SupportedCultures.

Include JSON files as AdditionalFiles:


<ItemGroup>
    <AdditionalFiles Include="i18n\*.i18n.json" />
    <AdditionalFiles Include="slang.json" />
</ItemGroup>

Add a partial class:

[Translations(InputFileName = "strings")]
public partial class Strings;

Done!

Strings.SetCulture(new CultureInfo("ru-RU")); 

Console.WriteLine(Strings.Instance.Root.Screen.Locale1); // Локаль 1

Strings.SetCulture(new CultureInfo("en-US"));

Console.WriteLine(Strings.Instance.Root.Screen.Locale1); // Locale 1

or

  <MenuItem  Header="{Binding Root.Screen.Locale1, Source={x:Static localization:Strings.Instance}}" />

Features

String Interpolation

You can specify parameters passed at runtime..

{
  "Hello": "Hello {name}"
}

The generated code will look like this:

/// In en, this message translates to:
/// **"Hello {name}"**
public virtual string Hello(object name) => $"Hello {name}";

Typed Parameters

Parameters are typed as object by default. This is convenient because it offers maximum flexibility.

You can specify the type using two syntax options: 1 - Simple:

{
  "greet": "Hello {name: string}, you are {age: int} years old"
}

2 - Using a placeholders, which allows you to specify a type or format string (see String Format).

{
  "greet2": "Hello {name}, you are {age} years old",
  "@greet2": {
    "placeholders": {
      "name": {
        "type": "string"
      },
      "age": {
        "type": "int"
      }
    }
  }
}

The generated code will look like this:

/// In ru, this message translates to:
/// **"Hello {name}, you are {age} years old"**
public virtual string Greet(string name, int age) => $"Hello {name}, you are {age} years old";

Comments

You can add comments to your translation files.

{
  "@@locale": "en", // fully ignored
  "mainScreen": {
    "button": "Submit",
    // ignored as translation but rendered as a comment
    "@button": "The submit button shown at the bottom",
    // or use 
    "button2": "Submit",
    "@button2": {
      "description": "The submit button shown at the bottom"
    }
  }
}

The generated code will look like this:

/// The submit button shown at the bottom
///
/// In ru, this message translates to:
/// **"Submit"**
public virtual string Button => "Submit";

String Format

This library supports embedding format via ToString(format) for the following types: int, long, double, decimal, float, DateTime, DateOnly, TimeOnly, TimeSpan. For other types, the format string is passed through string.Format(format, locale).

{
  "dateExample": "Date {date}",
  "@dateExample": {
    "placeholders": {
      "date": {
        "type": "DateTime",
        "format": "dd MMMM HH:mm"
      }
    }
  }
}
String s = Strings.Instance.Root.DateExample(DateTime.Now); // Date 17 October 22:25

The generated code will look like this:

/// In ru, this message translates to:
/// **"Date {date}"**
public virtual string DateExample(DateTime date)
{
	string dateString = date.ToString("dd MMMM HH:mm");
	return $"Date {dateString}";
}

Pluralization

This library uses the concept defined here.

Some languages have support out of the box. See here.

Plurals are detected by the following keywords: zero, one, two, few, many, other.

{
  "someKey": {
    "apple": {
      "one": "I have {n} apple.",
      "other": "I have {n} apples."
    }
  }
}
String a = Strings.Instance.Root.SomeKey.Apple(n: 1); // I have 1 apple.
String b = Strings.Instance.Root.SomeKey.Apple(n: 2); // I have 2 apples.    

The generated code will look like this:

public virtual string Apple(int n) => PluralResolvers.Cardinal("en")(n,
					one: $"I have {n} apple.",
					other: $"I have {n} apples.");

The detected plurals are cardinals by default.

To specify ordinals, you need to add the (ordinal) modifier.

{
  "someKey": {
    "apple(cardinal)": {
      "one": "I have {n} apple.",
      "other": "I have {n} apples."
    },
    "place(ordinal)": {
      "one": "{n}st place.",
      "two": "{n}nd place.",
      "few": "{n}rd place.",
      "other": "{n}th place."
    }
  }
}

By default, the parameter name is n. You can change that by adding a modifier.

{
  "someKey": {
    "apple(param=appleCount)": {
      "one": "I have one apple.",
      "other": "I have multiple apples."
    }
  }
}
String a = Strings.Instance.Root.SomeKey.Apple(appleCount: 1); // notice 'appleCount' instead of 'n'

You can set the default parameter globally using PluralParameter.

[Translations(
    InputFileName = "strings",
    PluralParameter = "count")]
internal partial class Strings;

Linked Translations

You can link one translation to another. Add the prefix @: followed by the absolute path to the desired translation.

{
  "fields": {
    "name": "my name is {firstName}",
    "age": "I am {age} years old"
  },
  "introduce": "Hello, @:fields.name and @:fields.age"
}
String s = Strings.Instance.Root.Introduce(firstName: "Tom", age: 27); // Hello, my name is Tom and I am 27 years old.

The generated code will look like this:

/// In ru, this message translates to:
/// **"Hello, {_root.Fields.Name(firstName: firstName)} and {_root.Fields.Age(age: age)}"**
public virtual string Introduce(object firstName, object age) => $"Hello, {_root.Fields.Name(firstName: firstName)} and {_root.Fields.Age(age: age)}";

Optionally, you can escape linked translations by surrounding the path with {}:

{
  "fields": {
    "name": "my name is {firstName}"
  },
  "introduce": "Hello, @:{fields.name}inator"
}

Lists

You can also place lists inside lists!

{
  "niceList": [
    "hello",
    "nice",
    [
      "first item in nested list",
      "second item in nested list"
    ],
    {
      "wow": "WOW!",
      "ok": "OK!"
    },
    {
      "aMapEntry": "access via key",
      "anotherEntry": "access via second key"
    }
  ]
}
String a = Strings.Instance.Root.NiceList[1]; // "nice"
String b = Strings.Instance.Root.NiceList[2][0]; // "first item in nested list"
String c = Strings.Instance.Root.NiceList[3].Ok; // "OK!"
String d = Strings.Instance.Root.NiceList[4].AMapEntry; // "access via key"

The generated code will look like this:

public virtual List<dynamic> NiceList => [
				"hello",
				"nice",
				new[]{
					"first item in nested list",
					"second item in nested list",
		    },
				new Feature1NiceList0i3Ru(_root),
				new Feature1NiceList0i4Ru(_root),
	];

Maps

You can access each translation using string keys.

Add the (map) modifier.

{
  "a(map)": {
    "helloWorld": "hello"
  },
  "b": {
    "b0": "hey",
    "b1(map)": {
      "hiThere": "hi"
    }
  }
}

Now you can access translations using keys:

String a = Strings.Instance.Root.A["helloWorld"]; // "hello"
String b = Strings.Instance.Root.B.B0; // "hey"
String c = Strings.Instance.Root.B.B1["hiThere"]; // "hi"

The generated code will look like this:

/// In ru, this message translates to:
/// **"hey"**
public virtual string B0 => "hey";
public virtual IReadOnlyDictionary<string, string> B1 => new Dictionary<string, string> {
					{"hiThere", "hi"},
};

Slang CLI

Translate with GPT

Take advantage of GPT to internationalize your app with context-aware translations.

Install Slang CLI:

dotnet tool install --global Slang.CLI

Then add the following configuration in your slang.json:

{
  "base_culture": "en",
  "gpt": {
    "base_culture": "ru",
    "model": "gpt-4o-mini",
    "description": "Showcase for Slang.Net.Gpt"
  }
}

Then use slang-gpt:

slang gpt --target=en --api-key=<api-key>

See more: Documentation

Additional Materials

Articles

Videos

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  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 was computed.  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. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
9.3.0 99 7/12/2025