there are many ways to do this, but frankly, this is not a wordpress question it’s a php question. here is your code doing what you asked for
$imageAttr = [
"class" => "alignnone size-medium",
"alt" => get_the_title(get_the_ID()),
"title" => __('hi', 'theme-textdomain') . ' ' . wp_trim_words(get_the_title(get_the_ID()), 2),
];
$variable = [] is just a shorthand for Array()
get_the_ID() is the same as $post->ID but without the use of global variable $post. well it is called inside that function, but you don’t have to define it first. because calling $post without the prior global $post;
might cause issues elsewhere. simply use the build in wordpress functions and you should be fine. reference
__('hi', 'theme-textdomain')
is a function, that let’s you translate your theme. ‘hi’ is simply the string, that is returned from that function, ‘theme-textdomain’ is the domain of the set, thr string is saved in. this quite old article is still a good read on how to do it properly.
last bit i added is the . ' ' .
that is the space between your custom string and the title of the post, .
is simply the php glue of multiple strings. you could have added that space to your custom string in the previous function, but when it comes to the translation part, this can easily be forgotten, so i added it separately.
and as a bonus, here is another method:
"title" => sprintf('%1$d %2$d', __('hi', 'theme-textdomain'), wp_trim_words(get_the_title(get_the_ID()), 2))
it’s combining the 2 strings via php sprintf function. same same.. but different..
"title" => sprintf(__('hi %d', 'theme-textdomain'), wp_trim_words(get_the_title(get_the_ID()), 2))
yet another one. sprintf() documentation here