C (gcc), 154 152 146 bytes
I wrote nonprintables that won't show up on SE in hex using <kbd>
.
i,p[]=L"muha na zid0x00Priletela ";main(){for(;i<48;p["0x140x120x100x0e0x090x060x030x01"[i%8]]="aeiou"[i++/8])i%8?:printf("%S%S, %2$S, %2$S.\n%1$S%2$S,\n%2$S.\n\n",p+12,p);}
Try it online!
#include <stdio.h>
int main(void)
{
// These are merged together with a raw null byte in the golfed code.
// I set them to wchar_t (L"") solely because of implicit int, cuz screw
// Windows and its UTF-16. :P
char pril[] = "Priletela"; // golfed code has trailing space
char muha[] = "muha na zid";
// The golfed code does a different loop pattern where it does one big
// loop which replaces a char each iteration and prints when i%8==0.
// However, that is difficult to follow.
for (int i = 0; i < 6; i++) {
// Note: golfed code doesn't use positionals on the first two arguments,
// and it uses %S because they are wchar_t strings.
//
// Priletela muha na zid, muha na zid, muha na zid.
// %1$s %2$s , %2$s , %2$s .\n
// Priletela muha na zid,
// %1$s %2$s ,\n
// muha na zid.
// %2$s .\n\n
printf("%1$s %2$s, %2$s, %2$s.\n%1$s %2$s,\n%2$s\n\n", pril, muha);
// Replace the vowels one by one.
// The golfed version loops 8 times since it is one string.
for (int j = 0; j < 4; j++) {
// Nope, never y.
const char vowels[] = "aeiou";
// Vowel indexes. This is encoded in a binary string in the golfed
// code, and it is one array because the strings are merged.
const int pril_lut[] = { 2, 4, 6, 8 };
const int muha_lut[] = { 1, 3, 6, 9 };
pril[pril_lut[j]] = vowels[i];
muha[muha_lut[j]] = vowels[i];
}
}
}
Unless we find a way to kill the printf string, I don't see any other options to make this smaller. I have clearly been proven wrong more than once. :P
-2 bytes thanks to ceilingcat for better variable declaration and looping backwards.
-6 bytes thanks to gastropner for making me eat my words combining the two for loops.