Skip to content

Add configurable character equivalence folding for search:#6636

Open
com-master wants to merge 3 commits into
space-wizards:masterfrom
com-master:search-char-equivalences
Open

Add configurable character equivalence folding for search:#6636
com-master wants to merge 3 commits into
space-wizards:masterfrom
com-master:search-char-equivalences

Conversation

@com-master

Copy link
Copy Markdown

Summary

Some languages have letters that players commonly type interchangeably, but which are technically distinct Unicode code points. The most common example is Russian ё and е: native speakers almost universally write е in informal text, but entity names in YAML may use ё, causing searches to miss results. The same problem exists in other languages (German umlauts typed without diacritics, etc.).

This PR adds a lightweight, language-agnostic mechanism to fold such characters before comparing search strings.

What changed

Robust.Shared/Utility/SearchHelpers.cs — new public static class with:

  • string.ContainsSearch(search) — drop-in replacement for string.Contains() in search filters; applies character folding transparently
  • SearchHelpers.NormalizeForSearch(value) — normalizes a string according to the current equivalence table, for use cases that need the normalized value directly
  • Self-initializing via IoC on first call — no setup required; works from engine code and game-content UI alike

Robust.Shared/CVars.cs — new CVar interface.search_char_equivalences:

  • Comma-separated list of two-character pairs; first character is folded to second before comparing
  • Both case variants registered automatically (ёе also covers ЁЕ)
  • Ships with defaults for Russian, German, Scandinavian, Spanish, French, and Turkish
  • CLIENTONLY | ARCHIVE — players can extend or clear the list in their client config

EntitySpawningUIController, TileSpawningUIController — search filters switched to ContainsSearch

Why config-driven

Hardcoding equivalences would require a code change for every new language. A CVar lets server owners, localization teams, or individual players add pairs for their language without touching the engine. The default list covers the most common cases; anything beyond that is one config line away.

Usage from game content

// No setup needed — works anywhere IoC is available
if (entityName.ContainsSearch(searchString))
...

Future work

This PR lays the groundwork in the engine. A follow-up change on the content side (Space Station 14) is planned to roll out ContainsSearch across all in-game search interfaces — crafting machines, research consoles, cargo order menus, and any other UI that filters lists by player input. Since SearchHelpers is self-initializing and requires no wiring, the content-side change is purely a find-and-replace of .Contains( with .ContainsSearch( in the relevant UI systems.

@com-master com-master requested a review from PJB3005 as a code owner June 15, 2026 00:51

@PJB3005 PJB3005 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't there standard Unicode systems for this? Have you investigated thoes?

@Illiux

Illiux commented Jun 15, 2026

Copy link
Copy Markdown

Yup. There's casefolding obviously. But there's also per-locale collation equality which would probably be appropriate here, likely at primary strength. But this is something you really don't want to handroll.

@com-master

com-master commented Jun 15, 2026

Copy link
Copy Markdown
Author

Done, switched to CompareInfo.IndexOf with CompareOptions.IgnoreNonSpace | CompareOptions.IgnoreCase. The custom CVar and character table are gone — Unicode NFD decomposition handles everything automatically. The implementation is now a single static method with no dependencies, no configuration, and no setup required.

Example of this feature on russian fork.
image

Both spellings of the word черный and чёрный are acceptable in Russian, and the two forms are now treated as equivalent when compared by the program.

Comment thread Robust.Shared/CVars.cs
Comment thread Robust.Shared/Utility/SearchHelpers.cs Outdated
Comment thread Robust.Shared/Utility/SearchHelpers.cs Outdated
@com-master

Copy link
Copy Markdown
Author

Added IgnoreWidth and IgnoreKanaType. Also switched to CurrentCulture — agreed it's more correct for player-facing search since the text being searched is already rendered in the player's locale.

@com-master

Copy link
Copy Markdown
Author

I checked failed test and i think its bug not in my code (it fails on Vulpakin profile which i didnt edit) rerun test pls if it necessary

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants