एक फ्लटर पैकेज जो टेक्स्ट इनपुट से बदशगुन शब्दों को फ़िल्टर करने और विभिन्न प्रारूपों में फ़ोन नंबर का पता लगाने के लिए है, जिसमें गुणक शब्द भी शामिल हैं।
सार्वजनिक जानकारी से बना चयन मार्गदर्शन। केवल संदर्भ हेतु।
safe_text एक Flutter पैकेज है जिसका उद्देश्य अनुचित शब्दों को फ़िल्टर करने और विभिन्न प्रारूपों में फ़ोन नंबरों का पता लगाने के माध्यम से टेक्स्ट इनपुट सुरक्षा को बढ़ावा देना है, जिसमें 'दो सौ' जैसे गुणक शब्दों द्वारा व्यक्त किए गए नंबर भी शामिल हैं। यह Android, iOS, Web, macOS, Windows और Linux पर क्रॉस-प्लेटफ़ॉर्म एप्लिकेशन के लिए समर्थन प्रदान करता है। यह पैकेज उपयोगकर्ता-जनित टेक्स्ट में सामग्री अखंडता बनाए रखने में मदद करता है, जिससे चैट ऐप्स, फॉर्म्स और समुदाय प्लेटफ़ॉर्म्स के लिए आदर्श है जहाँ समायोजन आवश्यक है। यह pub.dev के माध्यम से Flutter प्रोजेक्ट्स में आसानी से एकीकृत होता है और विश्वसनीय, वास्तविक समय के टेक्स्ट विश्लेषण प्रदान करता है।
उपयोग
चैट एप्लिकेशन्स
उपयोगकर्ता द्वारा उत्पन्न सामग्री मॉडरेशन
फॉर्म इनपुट साफ करना
समुदाय प्लेटफॉर्म सुरक्षा
पाठ से फ़ोन नंबर निकालें
संदेश ऐप में सामग्री फ़िल्टरिंग
मुख्य विशेषताएँ
बद शब्द फ़िल्टरिंग
बहु-प्रारूप फ़ोन नंबर डिटेक्शन
गुणक-आधारित संख्या व्यक्तिकरण के लिए समर्थन
क्रॉस-प्लेटफॉर्म संगतता
Flutter के साथ आसान एकीकरण
रियल-टाइम टेक्स्ट विश्लेषण
इनके लिए उपयुक्त
सुरक्षित संदेश ऐप बनाने वाले विकासकर्मी
स्वचालित सामग्री मॉडरेशन की आवश्यकता वाली टीमें
उपयोगकर्ता द्वारा प्रस्तुत टेक्स्ट का प्रबंधन करने वाले ऐप्स
फ़ोन नंबर पहचान की आवश्यकता वाले प्रोजेक्ट
टेक्स्ट सुरक्षा पर ध्यान केंद्रित फ्लटर विकासकर्मी
विविध पाठ पैटर्न वाले वैश्विक दर्शकों के लिए लक्षित अनुप्रयोग
विचार योग्य बातें
बुरे शब्द सूची के नियमित अद्यतन की आवश्यकता होती है
क्षेत्र-विशिष्ट अपमानजनक शब्दों के लिए कस्टमाइज़ेशन की आवश्यकता हो सकती है
बड़े टेक्स्ट बैच के साथ प्रदर्शन प्रभाव
पूर्वनिर्धारित निर्देशक नियमों तक सीमित
गहन भावनात्मक विश्लेषण के लिए उपयुक्त नहीं
स्रोत शब्द संग्रह की सटीकता पर निर्भर करता है
मूल README
संबंधित सोर्स रिपॉज़िटरी के मूल README का स्नैपशॉट। नवीनतम सामग्री के लिए रिपॉज़िटरी देखें।
A high-performance pure Dart package for filtering offensive language (profanity) and detecting phone numbers. Powered by the Aho-Corasick algorithm for O(N) single-pass scanning across 80+ languages and 55,000+ curated words.
Scans thousands of bad words in a single pass of the input text.
Catches common character substitutions: @→a, 4→a, 3→e, 0→o, $→s, and more.
Detects phone numbers in digits, words, mixed formats, and multiplier words (e.g., "triple five").
Multiple masking strategies — full (******), partial (f**k), or custom replacement ([censored]).
Customizable — add your own words or exclude specific phrases.
No setup required — lazily auto-initializes with the full Language.english word list (~13k words) on first use; init is optional.
Non-blocking — PhoneNumberChecker runs in a separate isolate via Isolate.run.
Works on Android, iOS, Web, macOS, Linux, and Windows.
Installation
Add safe_text to your project using the Dart CLI:
dart pub add safe_text
Or manually add it to your pubspec.yaml:
dependencies:safe_text:^3.0.0
Then run:
dart pub get
Quick Start
import'package:safe_text/safe_text.dart';
voidmain() async {
// Optional: initialize once at app startup with a specific language.// If you skip this, the filter lazily auto-initializes with the full// Language.english word list (lib/data/en.dart, ~13k words) on first use —// not the small legacy constants/badwords.dart list from v1.x/v2.x.SafeTextFilter.init(language: Language.english);
// Filter profanity (full masking — default)final clean = SafeTextFilter.filterText(text: "What the f@ck!");
print(clean); // "What the ****!"// Partial masking — keeps first & last characters for 4+ letter wordsfinal partial = SafeTextFilter.filterText(
text: "What the f@ck!",
strategy: constMaskStrategy.partial(),
);
print(partial); // "What the f**k!"// Custom replacementfinal custom = SafeTextFilter.filterText(
text: "What the f@ck!",
strategy: constMaskStrategy.custom(replacement: '[censored]'),
);
print(custom); // "What the [censored]!"// Check for bad wordsfinal hasBad = SafeTextFilter.containsBadWord(text: "Some bad input");
print(hasBad); // true or false// Detect phone numbersfinal hasPhone = awaitPhoneNumberChecker.containsPhoneNumber(
text: "Call me at nine 7 eight 3 triple four",
);
print(hasPhone); // true
}
API Reference
SafeTextFilter.init
Optional. Builds the Aho-Corasick trie from the selected word list(s). If you never call it, the filter lazily auto-initializes with Language.english (lib/data/en.dart, ~13k words) on first use of filterText / containsBadWord. Call it explicitly when you want a specific language or combination.
Upgrading from v2.x? In 2.x, an app that never called init fell back to the small legacy list in constants/badwords.dart (~1.7k words). As of 3.0.0, an uninitialized filter now lazily loads the full Language.english list instead — a much larger, different word list. If your app relied on the old, smaller list (e.g. "adult" was previously not flagged), see below for how to opt back into it.
// Single languageSafeTextFilter.init(language: Language.english);
// Custom combinationSafeTextFilter.init(languages: [Language.english, Language.hindi, Language.spanish]);
// All 75+ languagesSafeTextFilter.init(language: Language.all);
Parameter
Type
Default
Description
language
Language?
Language.english
A single language to load. Use Language.all to load every language. Ignored when languages is provided.
languages
List<Language>?
null
A custom list of languages. Takes precedence over language.
Note: If neither parameter is provided, the filter defaults to Language.english.
Check initialization status or reset loaded word lists dynamically (e.g., when switching languages). Because init auto-initializes on first use, you generally don't need to guard calls with isInitialized — but it's available if you want to check, and reset() lets you reload with a different language:
// Reset state to reload with a different languageSafeTextFilter.reset();
SafeTextFilter.init(language: Language.spanish);
SafeTextFilter.filterText
Synchronous. Returns the input text with matched bad words masked according to the chosen MaskStrategy.
// Full masking (default)String result = SafeTextFilter.filterText(
text: "Hello b4dass world!",
extraWords: ["badterm"], // optional: add custom words
excludedWords: ["bass"], // optional: never filter these
useDefaultWords: true, // use the built-in word list
);
// Result: "Hello ****** world!"// Partial maskingString partial = SafeTextFilter.filterText(
text: "Hello b4dass world!",
strategy: constMaskStrategy.partial(),
);
// Result: "Hello b****s world!"// Custom replacementString custom = SafeTextFilter.filterText(
text: "Hello b4dass world!",
strategy: constMaskStrategy.custom(), // defaults to "[censored]"
);
// Result: "Hello [censored] world!"
Parameter
Type
Default
Description
text
String
required
The input string to process.
extraWords
List<String>?
null
Additional words to filter on top of (or instead of) the built-in list.
excludedWords
List<String>?
null
Words that must never be filtered, even if they appear in the list.
useDefaultWords
bool
true
Include the built-in language word list. Set to false to use only extraWords.
Deprecated. Use strategy instead. true maps to MaskStrategy.full(), false maps to MaskStrategy.partial().
obscureSymbol
String
*
Deprecated. Pass obscureSymbol via MaskStrategy.full() or MaskStrategy.partial() instead.
Precedence: When strategy is provided, it takes full precedence over the deprecated fullMode and obscureSymbol parameters. When strategy is omitted, fullMode: true maps to MaskStrategy.full(obscureSymbol: obscureSymbol) and fullMode: false maps to MaskStrategy.partial(obscureSymbol: obscureSymbol).
Masking Strategies
Strategy
Constructor
Output Example
Description
Full
MaskStrategy.full(obscureSymbol: '*')
badass → ******
Replaces every character with the obscure symbol.
Partial
MaskStrategy.partial(obscureSymbol: '*')
damn → d**n, ass → a**
Keeps first character visible. For 4+ letter words, also keeps the last character.
Custom
MaskStrategy.custom(replacement: '[censored]')
badass → [censored]
Replaces the entire word with a fixed string.
Note:obscureSymbol must be exactly one character. This is enforced via assert in debug mode — a multi-character string will trigger an AssertionError during development.
SafeTextFilter.containsBadWord
Asynchronous. Returns true if the text contains at least one filtered word.
If your app depends on the smaller v1.x/v2.x fallback list (constants/badwords.dart, ~1.7k words) instead of the full Language.english list (~13k words) that 3.0.0 lazily auto-initializes with, opt out of the default list and pass the legacy one in explicitly:
import'package:safe_text/constants/badwords.dart';
bool hasBadWord = SafeTextFilter.containsBadWord(
text: text,
useDefaultWords: false,
extraWords: badWords, // the legacy list from constants/badwords.dart
);
PhoneNumberChecker.containsPhoneNumber
Asynchronous. Runs in a separate isolate via Dart's Isolate.run so it never blocks the calling thread.
Detects phone numbers expressed as:
Pure digits: 9783444
Word-based: nine seven eight three four four four
Mixed: 9 seven 8 3444
Multiplier words: nine seven eight three triple four
bool hasPhone = awaitPhoneNumberChecker.containsPhoneNumber(
text: "Call me at nine 7 eight 3 triple four",
minLength: 7, // minimum digit count to be considered a phone number
maxLength: 15, // maximum digit count
);
Parameter
Type
Default
Description
text
String
required
The input string to check.
minLength
int
7
Minimum number of digits for a valid phone number.
maxLength
int
15
Maximum number of digits for a valid phone number.
Supported Languages
Pass any of these Language enum values to SafeTextFilter.init. Use Language.all to load every language simultaneously.
View all 82 supported languages
Enum
Language
Language.afrikaans
Afrikaans
Language.amharic
Amharic
Language.arabic
Arabic
Language.azerbaijani
Azerbaijani
Language.belarusian
Belarusian
Language.bulgarian
Bulgarian
Language.catalan
Catalan
Language.cebuano
Cebuano
Language.czech
Czech
Language.welsh
Welsh
Language.danish
Danish
Language.german
German
Language.dzongkha
Dzongkha
Language.greek
Greek
Language.english
English
Language.esperanto
Esperanto
Language.spanish
Spanish
Language.estonian
Estonian
Language.basque
Basque
Language.persian
Persian
Language.finnish
Finnish
Language.filipino
Filipino
Language.french
French
Language.scottishGaelic
Scottish Gaelic
Language.galician
Galician
Language.hindi
Hindi
Language.croatian
Croatian
Language.hungarian
Hungarian
Language.armenian
Armenian
Language.indonesian
Indonesian
Language.icelandic
Icelandic
Language.italian
Italian
Language.japanese
Japanese
Language.kabyle
Kabyle
Language.kannada
Kannada
Language.khmer
Khmer
Language.korean
Korean
Language.latin
Latin
Language.lithuanian
Lithuanian
Language.latvian
Latvian
Language.maori
Maori
Language.macedonian
Macedonian
Language.malayalam
Malayalam
Language.mongolian
Mongolian
Language.marathi
Marathi
Language.malay
Malay
Language.maltese
Maltese
Language.burmese
Burmese
Language.dutch
Dutch
Language.norwegian
Norwegian
Language.norfuk
Norfuk / Pitcairn
Language.piapoco
Piapoco
Language.polish
Polish
Language.portuguese
Portuguese
Language.romanian
Romanian
Language.kriol
Kriol
Language.russian
Russian
Language.slovak
Slovak
Language.slovenian
Slovenian
Language.samoan
Samoan
Language.albanian
Albanian
Language.serbian
Serbian
Language.swedish
Swedish
Language.tamil
Tamil
Language.telugu
Telugu
Language.tetum
Tetum
Language.thai
Thai
Language.klingon
Klingon
Language.tongan
Tongan
Language.turkish
Turkish
Language.ukrainian
Ukrainian
Language.uzbek
Uzbek
Language.vietnamese
Vietnamese
Language.yiddish
Yiddish
Language.chinese
Chinese
Language.zulu
Zulu
Language.bengali
Bengali
Language.gujarati
Gujarati
Language.punjabi
Punjabi
Language.swahili
Swahili
Language.urdu
Urdu
Language.all
All of the above
How it Works
Legacy approach (v1.x): For each bad word in a list of 10,000+ words, run a separate regex scan over the entire input — O(W × N) where W is the word count.
v2.0.0 approach: The Aho-Corasick algorithm builds a Finite State Automaton (Trie) once from the entire word list. The engine then scans the input exactly once, matching all patterns simultaneously in O(N) time where N is the length of the text — regardless of how many words are in the list.
Input text ──► [Normalizer] ──► [Aho-Corasick FSA] ──► Match ranges ──► [StringBuffer] ──► Filtered text
(leet-speak) (single O(N) pass) (merged) (single-pass)
Migrating from v1.x
The original SafeText class is still available but marked @Deprecated. It internally delegates to the new classes. Migrate when ready:
v1.x
v2.0.0
SafeTextFilter.init(...)
Recommended — call once at startup. If skipped, containsBadWord/filterText fall back to the small legacy constants/badwords.dart list (~1.7k words) instead of the full multilingual dataset.
// v1.x — no init required, but slowbool bad = awaitSafeText.containsBadWord(text: "some input");
After:
// v2.0.0 — init once, then use anywhereSafeTextFilter.init(language: Language.english); // once, e.g. in main()bool bad = SafeTextFilter.containsBadWord(text: "some input");
3.0.0 changed this again:init became fully optional. If you never call it, the filter now lazily auto-initializes with the fullLanguage.english list (~13k words) — not the small legacy list above. See Keeping the legacy word list if you're upgrading from 2.x and relied on the smaller fallback.
Limitations
Skipping init is not behavior-preserving across major versions. An uninitialized filter now lazily loads the full Language.english list (~13k words); in 2.x, an uninitialized filter fell back to the small legacy constants/badwords.dart list (~1.7k words) instead. If you're upgrading from 2.x, see Keeping the legacy word list.
Phone number detection is English-word based. Words like "nine", "triple", etc. are English only — the detector does not parse written numbers in other languages.
False positives on technical terms. Short words in the filter list may match substrings of unrelated technical terms. Use excludedWords to suppress known false positives.
Contributing
Contributions are welcome! Please read CONTRIBUTING.md for the full guidelines. The short version:
Clone the repo and check out the develop branch.
Create a feature branch: git checkout -b feature/your-feature
Add tests for any new behaviour.
Run checks before submitting:
dart analyze
dart test
Open a pull request targeting develop. Ensure CI passes.
For major changes, please open an issue first to discuss the approach.