Slugify.MultiLang
1.0.1
dotnet add package Slugify.MultiLang --version 1.0.1
NuGet\Install-Package Slugify.MultiLang -Version 1.0.1
<PackageReference Include="Slugify.MultiLang" Version="1.0.1" />
<PackageVersion Include="Slugify.MultiLang" Version="1.0.1" />
<PackageReference Include="Slugify.MultiLang" />
paket add Slugify.MultiLang --version 1.0.1
#r "nuget: Slugify.MultiLang, 1.0.1"
#:package Slugify.MultiLang@1.0.1
#addin nuget:?package=Slugify.MultiLang&version=1.0.1
#tool nuget:?package=Slugify.MultiLang&version=1.0.1
Slugify.MultiLang
A multi-language, dependency-free slug generator for .NET — a faithful C# port of the popular
slugifyJavaScript library, with extended locale support and sensible handling of CJK, Arabic, and other non-Latin scripts.
What it does
Turn any string into a clean, URL-safe slug:
"Director Fu: Your alt account got exposed again!" → "director-fu-your-alt-account-got-exposed-again"
"Café au lait & cròissant" → "cafe-au-lait-and-croissant"
"傅总:你的马甲 又又又掉了!" → "傅总-你的马甲-又又又掉了"
It transliterates accented Latin, Greek, Cyrillic, Armenian, Georgian, Vietnamese and more into ASCII, maps common symbols and currencies to words, applies locale-specific rules, and preserves scripts that have no meaningful romanization (CJK, Arabic, Devanagari, Thai, …) so slugs stay readable in any language.
Features
- No dependencies — a single static helper, targets .NET Standard 2.0 (works on .NET Framework 4.6.1+, .NET Core, .NET 5–8+, Mono, Xamarin, Unity).
- Huge built-in charmap — Latin (incl. Extended), Greek, Cyrillic (incl. Kazakh), Armenian, Georgian, Vietnamese, currencies, punctuation, and math/misc symbols.
- Locale-aware — per-language overrides for
bg,de,es,fr,pt,uk,vi,da,nb,it,nl,sv(e.g. Germanä → ae,& → und). - Script-preserving — CJK / Arabic / Devanagari / Thai letters are kept as-is rather than dropped.
- Configurable — replacement char, lowercasing, strict mode, trimming, and a custom remove-regex.
- Extensible — register your own character mappings at runtime via
Extend.
How It Works
Every string goes through a five-step pipeline:
- NFC normalize — Unicode Normalization Form C is applied so that pre-composed and decomposed forms are treated identically.
- Per-character translation — each character (including surrogate pairs for supplementary-plane code points) is looked up in order:
- Locale override map — if
Localeis set and that locale has an entry for the character. - Global charmap — Latin Extended, Greek, Cyrillic, Armenian, Georgian, Vietnamese, currencies, math symbols, CJK punctuation, …
- Passthrough — characters with no entry are kept as-is.
- Locale override map — if
- Remove pass — the built-in (or custom
Remove) regex strips characters not useful in a URL. - Strict pass (
Strict = trueby default) — the Unicode-aware pattern[^\p{L}\p{N}\s]removes anything that is not a letter, digit, or whitespace. This is how non-Latin scripts are preserved: Arabic, CJK, Hangul, Kana, Thai consonants, and Devanagari consonants all satisfy\p{L}and survive untouched. - Finalize — whitespace runs are collapsed into the replacement char (default
-); optional trim and lower-case are applied.
Script-handling strategies
| Strategy | Scripts / locales | Detail |
|---|---|---|
| Full charmap transliteration | Latin Extended, Greek, Cyrillic (incl. Kazakh), Armenian, Georgian | Non-ASCII letter → ASCII (e.g. é→e, Ж→Zh, Ñ→N) |
| Locale-specific overrides | de, es, fr, pt, it, nl, sv, da, nb, bg, uk, vi |
Language-correct mapping before global charmap (e.g. de: ü→ue, &→und; sv: ö→oe, &→och; da: ø→oe, å→aa) |
| Charmap fallback | pl, tr, ms, id, tl, and any unregistered locale |
Global charmap only; diacritics not in the map pass through then get stripped by strict mode |
| Script-preserving passthrough | Arabic, Chinese, Japanese, Korean, Thai, Devanagari | No charmap entry — letters survive via \p{L}; CJK punctuation (,, 。, !, ?, :, 「」, 【】, —, · …) is mapped to spaces and becomes the separator |
Thai and Devanagari (Hindi) — combining marks stripped
Thai base consonants and Devanagari base consonants are Unicode letters (\p{L}) and survive intact.
Their combining vowel signs and tone marks are Unicode combining marks (\p{M}) — e.g. Thai ้ ู ็ or Devanagari ि ा ी.
With Strict = true (the default) these marks are removed, leaving consonant skeletons in the slug.
Set Strict = false if phonetically complete Thai / Devanagari slugs are needed.
Arabic — letters preserved, diacritics dropped
Arabic letters satisfy \p{L} and are preserved. Harakat (short-vowel diacritics such as َ ِ ُ) are combining marks (\p{M}) and are stripped by strict mode, which is fine for slug purposes since Arabic URLs routinely omit them.
Installation
This repository ships the source directly. Add a project reference to csharp/src/Slugify.MultiLang/Slugify.MultiLang.csproj, or drop SlugifyHelper.cs and SlugifySlugOptions.cs into your project.
<ItemGroup>
<ProjectReference Include="path/to/Slugify.MultiLang/Slugify.MultiLang.csproj" />
</ItemGroup>
Usage
using Slugify.MultiLang;
// Extension-method style (default options)
string slug = "Hello, World!".Slugify();
// → "hello-world"
// Static call with options
string s = SlugifyHelper.Slugify("Müller & Söhne", new SlugifySlugOptions
{
Locale = "de" // German: ü → ue, ö → oe, & → und
});
// → "mueller-und-soehne"
// Custom replacement character
"Some Text".Slugify("_");
// → "some_text"
Options
All options live on SlugifySlugOptions:
| Option | Type | Default | Description |
|---|---|---|---|
Replacement |
string |
"-" |
Character that replaces whitespace and separators. |
Lower |
bool |
true |
Lowercase the result (invariant culture). |
Strict |
bool |
true |
Remove anything that is not a letter, number, or whitespace. |
Trim |
bool |
true |
Trim leading/trailing whitespace before joining. |
Locale |
string? |
null |
Locale code to apply language-specific overrides. |
Remove |
Regex? |
null |
Custom regex of characters to strip (overrides the default remove pattern). |
Extending the charmap
SlugifyHelper.Extend(new Dictionary<char, string>
{
{ '☂', "umbrella" },
{ '♛', "queen" },
});
"☂♛".Slugify(); // → "umbrella-queen"
Demo
A runnable console demo showing 23 languages lives in csharp/demo:
cd csharp
dotnet run --project demo/Slugify.MultiLang.Demo
All examples below use the same source sentence — "傅总:你的马甲 又又又掉了!" ("Director Fu: Your alt account got exposed again and again and again!") — translated into each target language.
With explicit locale mapping
| Language | Locale | Slug output |
|---|---|---|
| Español | es |
director-fu-tu-cuenta-alternativa-ha-quedado-expuesta-otra-vez-y-otra-vez-y-otra-vez |
| Português | pt |
diretor-fu-sua-conta-alternativa-foi-exposta-de-novo-e-de-novo-e-de-novo |
| Français | fr |
directeur-fu-votre-compte-alternatif-a-ete-expose-encore-et-encore-et-encore |
| Deutsch | de |
direktor-fu-dein-alternativkonto-ist-schon-wieder-und-wieder-und-wieder-aufgeflogen |
| Italiano | it |
direttore-fu-il-tuo-account-alternativo-e-stato-smascherato-ancora-e-ancora-e-ancora |
| Svenska | sv |
direktoer-fu-ditt-alternativa-konto-har-avsloejats-igen-och-igen-och-igen |
| Dansk | da |
direktoer-fu-din-alternative-konto-er-blevet-afsloeret-igen-og-igen-og-igen |
| Nederlands | nl |
directeur-fu-uw-alternatieve-account-is-alweer-en-nog-een-keer-ontmaskerd |
| Tiếng Việt | vi |
giam-doc-phu-tai-khoan-phu-cua-ban-da-bi-lo-lai-va-lai-va-lai |
vinote: the locale entry only mapsĐ/đ → D/d; the extensive Vietnamese diacritics (ấ,ề,ộ, …) are handled by the global charmap.
Charmap fallback (no dedicated locale entry)
| Language | Locale | Slug output |
|---|---|---|
| Polski | pl |
dyrektorze-fu-twoje-alternatywne-konto-zostalo-ponownie-i-ponownie-zdemaskowane |
| Norsk | no |
direktor-fu-den-alternative-kontoen-din-har-blitt-avslort-igjen-og-igjen-og-igjen |
| Türkçe | tr |
mudur-fu-sahte-hesabin-yine-yine-yine-desifre-oldu |
| Bahasa Melayu | ms |
pengarah-fu-akaun-tiruan-anda-telah-terdedah-lagi-dan-lagi-dan-lagi |
| Bahasa Indonesia | id |
direktur-fu-akun-samaran-anda-telah-terbongkar-lagi-dan-lagi-dan-lagi |
| Filipino | tl |
direktor-fu-ang-iyong-alternatibong-account-ay-nabunyag-na-naman-at-naman-at-naman |
| English | en |
director-fu-your-alt-account-got-exposed-again-and-again-and-again |
nonote: Norwegian Bokmål (nb) does have a locale entry. The demo passesnowhich falls back to charmap. UseLocale = "nb"for proper Bokmål mapping (ø→oe,å→aa,&→og).
Script-preserving (Unicode passthrough)
Non-Latin scripts with no charmap entries are preserved via \p{L}:
| Language | Locale | Slug output |
|---|---|---|
| العربية | ar |
المدير-فو-لقد-تم-كشف-حسابك-البديل-مرة-أخرى-ومرة-أخرى-ومرة-أخرى |
| 日本語 | ja |
傅総-あなたのサブアカウントがまたまたまたバレちゃった |
| 한국어 | ko |
푸-총재-당신의-부계정이-또-또-또-들통났어요 |
| ภาษาไทย | th † |
ผอำนวยการฝ-บญชอำพรางของคณถกเปดเผยอกและอกและอกครง |
| हिन्दी | hi † |
नदशक-फ-आपक-वकलपक-खत-फर-और-फर-और-फर-उजगर-ह-गय |
| 中文 (简体) | zh |
傅总-你的马甲-又又又掉了 |
| 中文 (繁體) | zh-tw |
傅總-你的馬甲-又又又掉了 |
† Combining vowel marks (\p{M}) are stripped by strict mode — see Thai and Devanagari note in the How It Works section.
Project layout
csharp/
├── Slugify.MultiLang.slnx # solution
├── src/Slugify.MultiLang/ # the library (netstandard2.0)
│ ├── SlugifyHelper.cs # core logic + charmaps + locale maps
│ └── SlugifySlugOptions.cs # options
└── demo/Slugify.MultiLang.Demo/ # multi-language console demo (net8.0)
Credits
Charmap and behavior are derived from simov/slugify (MIT).
License
Released under the MIT License — free for any use, including commercial. Do whatever you like with it.
| Product | Versions 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. |
-
.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.