It looks like \alph (or rather, \@alph) is redefined to use the macro \@hebrew@numeral, which produces these numbers.
I'm redefining it to first look up if a number is bad and print something different if this is the case. The output will be unchanged otherwise.
Bad numbers are declared using \newbadnum{<number>}{<good representation>}, which I also define below.
Note: Like the original, this is a XeLaTeX document.
\documentclass{book}
\usepackage{polyglossia}
\setdefaultlanguage{hebrew}
\setotherlanguage{english}
\usepackage{fontspec}
\newfontfamily\hebrewfont{Times New Roman}[Script=Hebrew]
\makeatletter %% <- make @ usable in command names
\let\@hebrew@numeral@bad\@hebrew@numeral %% <- store old definition
\newcommand*\@hebrew@numeral@good[1]{% %% <- new definition
\ifcsdef{badnum@\number#1} %% <- if this number is bad
{\csuse{badnum@\number#1}} %% <- replace it
{\@hebrew@numeral@bad{#1}}% %% <- otherwise use old definition
}
\let\@hebrew@numeral\@hebrew@numeral@good %% <- replace old definition
\makeatother %% <- revert @
%% Declare bad numbers:
\newcommand*\newbadnum[2]{\csdef{badnum@#1}{#2}}
\newbadnum{270}{ער} %% <- literally bad
\newbadnum{271}{אאאא} %% <- for demonstration purposes
\newbadnum{272}{בבבב} %% <- for demonstration purposes
\newbadnum{274}{:-)} %% <- I wonder if this will smile in reverse
\pagenumbering{alph}
\begin{document}
\setcounter{page}{270}
\textenglish{The page number is now correct: $\uparrow\uparrow$}
\begin{enumerate}
\item \textenglish{Also second level enumerations use these:}
\begin{enumerate}\setcounter{enumii}{268}
\item \textenglish{This is item \#\arabic{enumii}}
\item \textenglish{This is item \#\arabic{enumii}}
\item \textenglish{This is item \#\arabic{enumii}}
\item \textenglish{This is item \#\arabic{enumii}}
\item \textenglish{This is item \#\arabic{enumii}}
\item \textenglish{This is item \#\arabic{enumii}} %% <- Still smiling :-)
\end{enumerate}
\end{enumerate}
\end{document}

This also changes the behaviour of \hebrewnumeral, \Hebrewnumeral and \Hebrewnumeralfinal, which may not be desirable. (See the addendum below for how to avoid this.)
Here's a brief explanation of what a couple of the above lines do:
\newbadnum{270}{ער} calls \csdef{badnum@270}{ער}, which defines the macro \badnum@270 to expand to ער.
You can't call \badnum@270 directly because it contains an @ and digits. However, \csuse{badnum@270} does expand to ער if it was defined as above.
If you were to call \@hebrew@numeral@good{\somectr} and \somectr is a TeX counter (not a LaTeX counter) with value 270, it will effectively run \ifcsdef{badnum@270}{<true branch>}{<false branch>}.
This tests if \badnum@270 is defined and chooses the appropriate branch.
The true branch is simply \csuse{badnum@\number#1}, so it'd expand to ער as described above.
The false branch just calls the original \@hebrew@numeral with the same argument.
The commands \csuse, \ifcsdef and \csdef are all from the etoolbox package, which was already loaded by polyglossia.
If there are a lot of bad numbers, you can replace the "Declare bad numbers" block by something like
%% Declare bad numbers:
\makeatletter %% <- make @ usable in command names
\newcommand*\newbadnum[2]{\csdef{badnum@#1}{#2}}
\newcommand*\newbadnums[1]{\forcsvlist\newbadnum@{#1}}
\def\newbadnum@#1{\newbadnum@@#1\newbadnum@@}
\def\newbadnum@@#1=#2\newbadnum@@{\newbadnum{#1}{#2}}
\makeatother %% <- revert @
\newbadnums{{270}={ער},{271}={אאאא},{272}={בבבב},
{274}={:-)}}
Edit: Interesting, the last line above looks fine in my editor, but it appears rather messed up here.
It'll work if you copy-paste it, but I can't guarantee that it'll be human-readable. (The combination of left-to-right and right-to-left text in a single document is supremely confusing.)
Note that the =s are not allowed to be surrounded by spaces and that the ,s are not allowed to be preceded by spaces, but are allowed to be followed by spaces and/or a single newline. The braces ({…}) are entirely optional, but without them the combination of left-to-right and right-to-left text just confuses the hell out of both my text editor and this website (and me):
\newbadnums{270=ער,271=אאאא,272=בבבב,274=:-)}
(That's the same as the last two lines above, just without the {…} and the line break.)
Addendum
Here's a version that lets you specify separately what the \Hebrewnumeral numbers (used by \Alph) and the \Hebrewnumeralfinal numbers (not used?) look like. The syntax is
\newbadnum{<number>}{<hebrew>}{<Hebrew>}[<Hebrewfinal>]
where <number> is a number in arabic numerals and the other three arguments are the three relevant representations.
The same value is used for <Hebrew> and <Hebrewfinal> if the optional argument is left out because it appears that these two representations usually coincide.
I must say that attempting post code fragments that contain Hebrew here is nightmare. The bottom four lines below appear rather mangled in my browser, but they're fine when I copy them to a text editor.
%% Declare bad numbers:
\makeatletter %% <- make @ usable in command names
\newcommand*\newbadnum[3]{\@testopt{\newbadnumopt{#1}{#2}{#3}}{#3}}
\def\newbadnumopt#1#2#3[#4]{%
\csdef{badnum@#1}{%
\if@gim@apost
\if@gim@final #4\else #3\fi
\else
#2%
\fi
}%
}
\makeatother %% <- revert @
%% The following looks fine in my editor, but not here.
\newbadnum{270}{ער}{ר״ע} %% <- leave \Hebrew unchanged
\newbadnum{271}{אאאא}{אאאא}[רע״א] %% <- leave only \Hebrewfinal version unchanged
\newbadnum{274}{:-)}{:-D}[:-P] %% <- In a good mood
\newbadnum{50}{נ}{נ׳}[ן׳] %% <- The default
If you use numbers greater than (or equal to) 1000 some further modification may (or may not?) be required because \@hebrew@numeral is actually recursive for those. I don't know if these replacements should also be applied to parts of numbers.
\Hebrewnumeralor\Hebrewnumeralfinal? – egreg Jan 14 '19 at 18:02