Make me speak L33T

JavaScript (ES6), 49 bytes

s=>s.replace(/[beis]/gi,c=>parseInt(c+1,31)%9||8)

Try it online!

How?

By using parseInt(), we don't have to worry about the case at all since lowercase and uppercase letters are parsed the same way. The downside of this formula is that we have to explicitly turn \$0\$ into \$8\$. It's still 1 byte shorter than the Node version, though.

 char | +'1' | base 31 -> decimal | mod 9 | || 8
------+------+--------------------+-------+------
  'b' | 'b1' |         342        |   0   |  8
  'e' | 'e1' |         435        |   3   |  3
  'i' | 'i1' |         559        |   1   |  1
  's' | 's1' |         869        |   5   |  5

JavaScript (Node.js),  54  50 bytes

s=>s.replace(/[beis]/gi,c=>17/(Buffer(c)[0]%16)|0)

Try it online!

How?

We look for beis in the input string in a case-insensitive way. For each matching character of ASCII code \$n\$, we apply the following formula:

$$f(n)=\left\lfloor\frac{17}{n\bmod 16}\right\rfloor$$

which gives:

 char | ASCII code | mod 16 -> x | 17 / x | floor
------+------------+-------------+--------+-------
  'B' |      66    |      2      |  8.5   |   8
  'b' |      98    |      2      |  8.5   |   8
  'E' |      69    |      5      |  3.4   |   3
  'e' |     101    |      5      |  3.4   |   3
  'I' |      73    |      9      |  1.889 |   1
  'i' |     105    |      9      |  1.889 |   1
  'S' |      83    |      3      |  5.667 |   5
  's' |     115    |      3      |  5.667 |   5

NB: we could use \$16\$ instead of \$17\$ just as well.


05AB1E, 14 13 12 bytes

„ÛãbÂu«ŽKcº‡

-1 byte thanks to @Grimy by using the dictionary word sie.

Try it online.

12 bytes alternative (from @Grimy):

2F.š„ÛãbŽKc‡

Try it online.

Explanation:

„Ûãb          # Push dictionary string "sieb"
    Â         # Bifurcate it (short for Duplicate & Reverse copy)
     u        # Uppercase the copy
      «       # Merge the strings together: "siebBEIS"
       ŽKc    # Push compressed integer 5138
          º   # Mirror it: 51388315
           ‡  # Transliterate "siebBEIS" to "51388315" in the (implicit) input-string
              # (after which the result is output implicitly)

2F            # Loop 2 times:
  .š          #  Switch the case of the string (lower- to uppercase, and vice-versa)
              #  (which will use the implicit input-string in the first iteration)
    „Ûãb      #  Push dictionary string "sieb"
        ŽKc   #  Push compressed integer 5138
           ‡  #  Transliterate "sieb" to "5138" in the string
              # (after the loop, the result is output implicitly)

See this 05AB1E tip of mine (sections How to use the dictionary? and How to compress large integers?) to understand why „Ûãb is "sieb" and ŽKc is 5138.


QuadR with i flag, 15 bytes

B
E
I
S
8
3
1
5

Try it online!

I don't need to explain this, do I?