native_natural_sort 0.1.4
native_natural_sort: ^0.1.4 copied to clipboard
Locale-aware, numeric-aware natural string sorting for Flutter using each platform's native collation engine.
native_natural_sort #
EN / 中文
Human-friendly string sorting for Flutter — numbers in the right order (
file2beforefile10), locale-aware collation (äwitha), and alphanumeric sorting that works the way people expect. Powered by each platform's native collation engine.
// ❌ Lexicographic (ASCII / dictionary) order:
// file1.txt file10.txt file2.txt ← "10" sorts before "2"
// ✅ Natural (human-friendly) order with native_natural_sort:
// file1.txt file2.txt file10.txt ← numbers treated as numbers
Why not List.sort? #
Dart's default string sort is lexicographic — it compares strings character-by-character by Unicode code point. This produces unintuitive results well beyond just numbers:
| Input | Dart sort() |
native_natural_sort |
|---|---|---|
item2, item10 |
item10, item2 |
item2, item10 |
árbol, amor, azul |
amor, azul, árbol |
amor, árbol, azul |
张, 李, 王 |
张, 李, 王 |
李, 王, 张 (Pinyin) |
Straße, Strasse |
Strasse, Straße |
equal (German: ß = ss) |
v1, v2, v10 |
v1, v10, v2 |
v1, v2, v10 |
native_natural_sort fixes this by delegating to each platform's native
collation engine (ICU on Linux/Windows, android.icu on Android,
localizedStandardCompare on Apple platforms, ECMAScript Intl.Collator on
Web), which understands numeric substrings, locale-specific character
ordering, and linguistic rules out of the box.
Why native, not bundled ICU? #
Some Dart packages ship a copy of the ICU library (~10–30 MB of collation
data) inside your app. native_natural_sort calls the collation APIs
already built into every platform instead:
- Small footprint — zero ICU data in your app bundle.
- OS-consistent results — strings sort the same way they do in Finder, Windows Explorer, or the Android file picker.
- No extra native dependencies — nothing to compile, no FFI bridge to maintain across platforms.
- Free updates — collation data improves with OS updates; no package upgrade needed.
Features #
- 🔢 Numeric-aware — numbers in strings sort by their numeric value, not
digit-by-digit (
"v2.10"after"v2.2", not before). - 🌐 Locale & language aware — respects language-specific collation rules (German ß = ss, Swedish å after z, Chinese by Pinyin or stroke order).
- ⚡ Native performance — zero Dart-level comparison overhead; delegates directly to OS collation APIs.
- 🖥️ All platforms — Android, iOS, macOS, Linux, Windows, Web.
- 🔧 Dual Windows backends — ICU (FFI) or Win32
CompareStringEx(Pigeon).
Getting started #
Add dependency with flutter pub add command #
flutter pub add native_natural_sort
Or add below line to pubspec.yaml #
dependencies:
...
native_natural_sort: any # or specific version
Then run flutter pub get.
Quick Start #
import 'package:native_natural_sort/native_natural_sort.dart';
final sort = NativeSort();
await sort.config(SortOptions());
final sorted = await sort.sort([
SortItem(id: 'a', value: 'file10.txt'),
SortItem(id: 'b', value: 'file2.txt'),
SortItem(id: 'c', value: 'file1.txt'),
]);
// → [c, b, a] (file1.txt < file2.txt < file10.txt)
Sorting plain strings #
If you prefer to work with plain List<String>, wrap it with a small helper:
Future<List<String>> sortStrings(List<String> values) async {
final sort = NativeSort();
await sort.config(SortOptions());
final items = values.asMap().entries
.map((e) => SortItem(id: e.key.toString(), value: e.value))
.toList();
return (await sort.sort(items)).map((e) => e.value).toList();
}
Sort-time overrides #
final sorted = await sort.sort(
items,
locale: Locale('fr'),
direction: SortDirection.descending,
);
Platform-specific options #
await sort.config(SortOptions(
android: SortOptionsAndroid(
locale: Locale('zh'),
direction: SortDirection.descending,
),
windows: SortOptionsWindows(
locale: Locale('en'),
sort: WindowsSort.ffi(), // or WindowsSort.pigeon()
),
));
Windows backend selection #
| Backend | Technology | Notes |
|---|---|---|
WindowsSort.ffi() |
OS-bundled ICU DLL | Default |
WindowsSort.pigeon() |
CompareStringEx (Win32) |
Direct FFI access #
import 'package:native_natural_sort/native_natural_sort.dart';
final loader = MyCollationLibraryLoader(); // see Linux/Windows FFI loaders
await loader.init();
final collator = loader.collator('en');
final sorted = collator.sort(
items: ['file10.txt', 'file2.txt', 'file1.txt'],
idOf: (s) => s,
valueOf: (s) => s,
);
For more examples, see the integration tests.
Architecture #
NativeSortService (unified Dart API)
├── Android → Pigeon → android.icu.text.Collator
├── iOS → Pigeon → localizedStandardCompare
├── macOS → Pigeon → localizedStandardCompare
├── Linux → Dart FFI → system libicui18n
├── Windows → Pigeon (CompareStringEx) or FFI (ICU)
└── Web → Dart → Intl.Collator
Development #
# Regenerate platform channel code
make gen
# Run analysis
make analyze
# Run tests
make test
Donate #
License #
This project is licensed under the Apache License, Version 2.0. See LICENSE for the full license text.
Copyright 2026 Fries_I23
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.