Search / Keyboard layouts

Keyboard layouts

People who write in two alphabets switch keyboard layouts all day, and often type a word with the wrong one on: rhbgnj for крипто, or знерщт for python. Every letter is wrong, so no typo correction finds it. With layouts, Search reads such a word as the same keys type in the other layout, and corrected says what it read, so the page can show "Showing results for крипто".

const courses = store.index<{ name: string }>('courses', { fields: { name: 1 }, layouts: ['ru', 'en'] })
await courses.setMany([
	{ id: 1, value: { name: 'Криптографические методы защиты информации' } },
	{ id: 2, value: { name: 'Python для анализа данных' } },
	{ id: 3, value: { name: 'Линейная алгебра' } },
])
const { hits, corrected } = await courses.search({ text: 'rhbgnj', prefix: true })
hits.map(hit => hit.id) // ['1']
corrected // 'крипто'
courses = store.index("courses", Course, fields={"name": 1}, layouts=["ru", "en"])
await courses.set_many([
    ("1", Course("Криптографические методы защиты информации")),
    ("2", Course("Python для анализа данных")),
    ("3", Course("Линейная алгебра")),
])
result = await courses.search("rhbgnj", prefix=True)
result.corrected  # 'крипто'
courses, err := search.OpenIndex[Course](store, "courses", search.Fields{"name": 1}, search.Layouts("ru", "en"))
result, err := courses.Search(ctx, "rhbgnj", search.Prefix())
result.Corrected // "крипто"
let courses = store.index::<Course>("courses").field("name", 1.0).layouts(["ru", "en"]).open()?;
let found = courses.search("rhbgnj").prefix().run()?;
found.corrected // Some("крипто")

layouts / layouts / Layouts / layouts names the layouts that the index's readers type with. Today these are ru, the Russian ЙЦУКЕН, and en, the US QWERTY. The search reads the text in the other layout of the two.

Which words are read in the other layout

Search splits the text at spaces and looks at each piece on its own:

TypedRead asWhy
rhbgnjкриптоthe QWERTY keys of крипто, which begins a course's word
знерщтpythonthe ЙЦУКЕН keys of python
Python lkzpython дляpython is found as typed, and lkz is read as для
ghbdtnghbdtnfound as typed, in an index that holds ghbdtn
rhbgnjrhbgnjwithout prefix, крипто is a whole word that no name holds
  • A piece is read in the other layout only when none of its words finds anything as typed. A word that finds something is never changed (contract SRCH-12), so a hit as typed ranks as it did.
  • The reading is kept only when every word it gives finds something: a word that the index holds, or, for the last word of a prefix search, the start of one. Otherwise the piece stays as typed.
  • A key keeps its place, letters and marks alike: by; is read as инж, because ж is on the ; key, and [kt, as хлеб.
  • A piece of two scripts, such as pythonдля, or one without a letter, such as 1.5, is never read in another layout.

Several words

Search checks each piece on its own. With prefix, only the last word is read as the start of a word, so kby fku, the QWERTY keys of лин алг, reads as kby алг. The index holds no word лин, so kby stays as typed, and алг begins алгебра. With prefix: 'every', every word is read as the start of a word, so kby fku reads as лин алг.

const found = await courses.search({ text: 'kby fku', prefix: true })
found.corrected // 'kby алг'
result = await courses.search("kby fku", prefix=True)
result.corrected  # 'kby алг'
result, err := courses.Search(ctx, "kby fku", search.Prefix())
result.Corrected // "kby алг"
let found = courses.search("kby fku").prefix().run()?;
found.corrected // Some("kby алг")

Typos and layouts

Search reads the layouts first and corrects typos after. A word read in the other layout finds something, so it is never corrected too. A piece whose reading finds nothing stays as typed and is corrected as any word is, under the rules of typos. corrected shows both: informatoin rhbgnj reads as information крипто.

Layouts work with typoTolerance turned off as well. Opening the index with other layouts, or without them, applies at once: nothing in the index is written again.

Limits and defaults

WhatValue
layoutsnone unless the index says
the layouts knownru (ЙЦУКЕН) and en (QWERTY)
how many an index namestwo, or none
a name that is not knownrefused at open, with an invalid error
a word found as typednever read in another layout

Other pairs, such as Ukrainian or German beside English, are not built yet.

See also

  • Typos: the nearest word, and corrected.
  • As you type: the last word read as the start of others.
  • Search: the engine's overview.

Edit this page on GitHub Updated 1 November 2026

esc
↑↓ navigate ↵ open ⇥ filter 0 results