[Question]
  [
*This challenge is based on, and contains test cases from, [a programming course](http://mooc.aalto.fi/ohjelmointi/scala_2017.html) I took at Aalto University. The material is used with permission.*
Two and a half years ago there was a challenge about [spoonerisms in English](https://codegolf.stackexchange.com/questions/69385/spoonerise-words). However, in Finnish spoonerisms are much more complicated.
## Spoonerisms in Finnish
In Finnish, the vowels are `aeiouyäö` and the consonants are `bcdfghjklmnpqrstvwxz`. (`å` is technically part of Finnish, but is not considered here.)
The most basic spoonerisms only take the first vowel of each word, and any consonants preceding them, and exchange the parts:
```
**he**nri **ko**ntinen -> **ko**nri **he**ntinen
**ta**rja **ha**lonen -> **ha**rja **ta**lonen
**fra**kki **ko**ntti -> **ko**kki **fra**ntti
**o**vi **ke**llo -> **ke**vi **o**llo
```
### Long vowels
Some words contain two of the same consecutive vowel. In those cases, the vowel pair must be swapped with the other word's first vowel, shortening or lengthening vowels to keep the length same.
```
**haa**mu **ko**ntti -> **koo**mu **ha**ntti
**ki**sko **kaa**ppi -> **ka**sko **kii**ppi
```
In the case of two *different* consecutive vowels this does not apply:
```
**ha**uva **ko**ntti -> **ko**uva **ha**ntti
**pu**oskari **ko**ntti -> **ko**oskari **pu**ntti
```
Three or more of the same consecutive letter will **not** appear in the input.
### Vowel harmony
Finnish has this lovely thing called [vowel harmony](https://en.wikipedia.org/wiki/Vowel_harmony#Finnish). Basically, it means that the *back vowels* `aou` and *front vowels* `äöy` should not appear in the same word.
When swapping front or back vowels into a word, all vowels of the other kind in the rest of the word should be changed to match the new beginning of the word (`a <-> ä`, `o <-> ö`, `u <-> y`):
```
**kö***y*h*ä* **ko**ntti -> **ko***u*h*a* **kö**ntti
**ha***u*v*a* **lää**h*ä*tt*ää* -> **lä***y*v*ä* **haa**h*a*tt*aa*
```
`e` and `i` are neutral and may appear with all other letters; swapping them into a word *must not* cause changes to the rest of the word.
### Special cases
Vowel harmony does not apply to some words, including many loan words and compound words. These cases are not required to be handled "correctly".
## Challenge
Given two words, output the words spoonerised.
The input words will only contain the characters `a-z` and `äö`. You may choose to use uppercase or lowercase, but your choice must be consistent between both words and input/output.
I/O may be done [in any convenient format](http://meta.codegolf.stackexchange.com/q/2447/42963). (Words should be considered strings or arrays of characters.)
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest solution in bytes wins.
## Test cases
```
henri kontinen -> konri hentinen
tarja halonen -> harja talonen
frakki kontti -> kokki frantti
ovi kello -> kevi ollo
haamu kontti -> koomu hantti
hauva kontti -> kouva hantti
puoskari kontti -> kooskari puntti
köyhä kontti -> kouha köntti
hauva läähättää -> läyvä haahattaa
frakki stressi -> strekki frassi
äyskäri kontti -> kouskari äntti
hattu sfääri -> sfätty haari
ovi silmä -> sivi olma
haamu prätkä -> präämy hatka
puoskari sfääri -> sfäöskäri puuri
puoskari äyskäri -> äöskäri puuskari
uimapuku hajoa -> haimapuku ujoa
ihme baletti -> bahme iletti
uhka lima -> lihka uma
osuma makkara -> masuma okkara
makkara fakta -> fakkara makta
lapsi laiva -> lapsi laiva
firma hajoa -> harma fijoa
dimensio bitti -> bimensio ditti
flamingo joustava -> jomingo flaustava
globaali latomo -> labaali glotomo
trilogia fakta -> falogia trikta
printti maksa -> mantti priksa
riisi bitti -> biisi ritti
sini riisi -> rini siisi
aarre nyrkki -> nyyrre arkki
laavu laki -> laavu laki
kliininen parveke -> paaninen klirveke
priimus kahvi -> kaamus prihvi
spriinen lasta -> laanen sprista
kliimaksi mammona -> maamaksi klimmona
hylky hupsu -> hulku hypsy
kehys fiksu -> fihys keksu
levy huhu -> huvu lehu
tiheys guru -> guheus tiru
nyrkki heiluri -> herkki nyilyri
latomo hajoa -> hatomo lajoa
prisma lehti -> lesma prihti
viina baletti -> baana viletti
```
  
[Answer]
# JavaScript (ES6), ~~196~~ 175 bytes
Takes the words as two strings in currying syntax `(a)(b)`. Returns an array of two arrays of characters.
```
a=>b=>[(e=/(.*?)([eiäaöoyu])(\2?)(.*)/,g=(a,[,c,v])=>[...c+v+(a[3]&&v)+a[4]].map(c=>(j=e.search(v),i=e.search(c))>9&j>9?e[i&~1|j&1]:c))(a=e.exec(a),b=e.exec(b),e+=e),g(b,a)]
```
[Try it online!](https://tio.run/##bVRLjuM2EN3PKQq9sMVptQeTZDMDyI1sAgQJkAM4XpTdtEmLEg1@NBEQ5DQ@Q19AB@sUP5LVdq9UfPVYqnpVxRN2aPdGnt1Tq1/426F6w2q9q9abgldfitXnZ1ZsuBwuOLzq3m9Z8fdPBK0@sy/lsSqw3JT7stsyurBarfaP3WOBm5@3i0XHHnHzy3a7avBc7Kt1car4ynI0e1F0rJTX056x9bfFaf3tmW/k4r@v/54WX7ffCS2QSPwfvi@QlbvR3rGSP1aclcdiVyLbvjluHVRAucCuBMMtg2oNe91arfhK6WP2LJ@e1ssSLHEPFJECxdx@BPaP1UnLtlguGcsWLFnkViEiPMOy@OsPtoTvZPz26@9/siX79Cn8uXgQvDXyoYSHWrdOtrzNtpFAroSwzHVoThj8ApXOVBEwcBkYmQeDdT2FddkiCMgTgZGpu@TkSulkdBJ0OIwMgdj421C68SDeRxLoO7zlEXTLO3ttazR32SUUzv4dux5eezFc7uIKBHJ9nIAaLsOFLjkXjIz03XChVFCgc4gfKGUd9cpOZhYrICOXgth6uNyn7lPqw@UmH@eicPYQ8kjXgu1cHzIxd12wUjUpYStjGxq8b8PZUIQ60YI9XJoQztX4ocS3Px9eUw0ktDcfd@Vdne9vJM54yUvaAV/7NIgnnYczo@ADMnKlaHhw71DxLNwOCQOZzlNMUacmUpT0JQD8TAltfXI11Do02Qwg6ASMzBnhgLUbjYBBE4GRqfCcWq9Q5iEKCKTjNCzSNHhTLCFwkPNKX2TDWyvjOu3kWGsG4UXOqz0obGR7jNwTzZHD9PeTjjCQP4PjjaPSO0SVk3W60cmKIJA3QtOTYSS9YfJWgogBOecanI0cR5rEsVnXAAG5AjAyjZRW3pRHCJh3tVnZRt/EpvgSbDyNHNoCE8ei7U3ew7bvCQOM52t/sPOp0DqXTgDE0/RUKEk/yO/iGU3Ha55MjDAQIYGzimXjbVxiFPklDHtmQ8UBmGoJ1BxaoXV5RDCEDT470zHkEQTMSjaNbrOWGOGQRwKn3e5V3cdx8mebtskrWiDRn21/jctFH3M9UDN8MgiBmofjpBTvciiRIwWduLgynBQ8BTp649NXcKrZSXNlXRsiuFTeZDOA0PZS9WbenXEOZ4sRIGrQfDOCUHmruUiDozghUe3Z5HSkNd49FtgidONr8fY/ "JavaScript (Node.js) – Try It Online")
### How?
Each input word is passed through the regular expression **e**, which has 4 capturing groups:
```
e = /(.*?)([eiäaöoyu])(\2?)(.*)/    1: leading consonants (or empty)
     [ 1 ][     2    ][ 3 ][ 4]     2: first vowel
                                    3: doubled first vowel (or empty)
                                    4: all remaining characters
```
The helper function **g()** takes all capturing groups of the word to be updated as **a[ ]** and the first and second capturing groups of the other word as **c** and **v**.
We apply basic spoonerism and take care of long vowels with:
```
c + v + (a[3] && v) + a[4]
```
To apply vowel harmony, we first coerce the regular expression **e** to a string by adding it to itself, which gives:
```
e = "/(.*?)([eiäaöoyu])(\2?)(.*)//(.*?)([eiäaöoyu])(\2?)(.*)/"
     ^^^^^^^^^^^^^^^^
     0123456789ABCDEF (position as hexa)
```
Vowels that need to be harmonized have a position greater than 9 in the resulting string. Furthermore, the expression was arranged in such a way that front vowels ***äöy*** are located at even positions, while back vowels ***aou*** are located at odd positions, next to their counterparts.
Hence the following translation formula which is applied to each character **c** of the output word:
```
(j = e.search(v), i = e.search(c)) > 9 & j > 9 ? e[i & ~1 | j & 1] : c
```
[Answer]
# [Python 3](https://docs.python.org/3/), ~~235~~ ~~231~~ ~~225~~ ~~221~~ ~~217~~ 215 bytes
```
import re
S=F,B='äöy','aou'
def f(a,b,C=1):
 e,r,Q,W=re.findall(fr' ?(.*?([ei{B+F}]))(\2)?(\w*)'*2,a+' '+b)[0][2:6]
 for c in zip(*S*(W in B)+(B,F)*(W in F)):r=r.replace(*c)
 return[Q+W*len(e)+r]+(C and f(b,a,[]))
```
[Try it online!](https://tio.run/##XVNLbuM4EN3zFNxJsjXBdAaYRQB3gDSQfXcvskiCQTmmzIooUuBH3erB3MZnyAV8sEwVKSN2b2y@91jFVx@Nc9TO/vX@jsPofJReie@b@/ZuUx0Px7e5aitwqRI71cmuhnbbftl8am6EVK1vv7YPG6@uOrQ7MKbufCVv66vVbf2o8N@79f1/z01TP103t/XTj1VTra5bWFeyWm@bxz@fH69v/n4WsnNevki08heO9er7qn5gcNes67v2vlngfdPc@I2/8mo08KLq1UsjyGlM3j5@XT@sjLK1atb@eV1/kWB3ZHXbQvtI77//0GiU/ESW2f0/7Tdov203aMcU6@YqjAbpX8if7bzJBdJ59GhjLWvims2mzhFNWz3FqmXqXSvrUfbORrTKyj8@85kY4jMjIvhXkBqMW3SdiVgI0Xno@5IgYglnTDQTwk2kKWNclhQhR0BogCFdBDnCusRoSBNciIwXcUwu9OAvX1yoMeUrPc1aHw@XGTRlPL6d5Te0Ewe6FiMf@BYx80RHMqchRoBTcSF6FULOxMelPmIERYT@ePjNTip2jofluRiTDB0/40uSjp@d@SFfWhTQDMVEwNyjAZYejZ7u9kXj8/EwcGDs4aMVv@c@vi2mxpT8Wcs@3NLFy2v5gkg4wJh6nsSrgzLsE5WIEagHJbdg1FLrFpjAjEXSPbWV7udmIqNEdbhAv3KgToLP0gCZcZkQJ6GDPma5W4iBCWFgpM4bwKmk/YCiQz/AuVWGHbLPHQ7KBnRyiyenJ2bHjOgMDGj3Tr7StCKU5K@ucCQWUuyN2wIYfjG6wRUHhSGJKRE9GrfHiwIKQQpXkL9AMkH1hKX@jIknQnhEqujMJ0OfTQa0fMSyep5RYCRob7ySdva8iiTZeWYCGFPHYEpks0gfSPQGKQV/xSP4SfUq7xRA4UjNJPvFIQXZg57KQvMiBvZLhAisc4CBEJeZAGMWiMnPcK1c8TA4u9QMhSM1k0LPpqdNTmNIeXrJ8N7NY5hFr/QcaJJ9kTpk2CuCwqiJg/QSw6UpnURErejOPvks7JNW5DiiT2LpklZoUtl8rTJjZzSz537l0Z7tUcaGMTcj0FbRI2U8RjHkVtB8JmoEXH4OQMRUvof/AQ "Python 3 – Try It Online")
---
Saved 
* -2 bytes, thanks to Lynn
* -4 bytes, thanks to Zacharý
[Answer]
# Pyth, 84 bytes
```
.b++hY*W@N2JhtY2XW}JeA@DJc2"aouäöy"eNGH_Bmth:d:"^([^A*)([A)(\\2)*(.+)"\A"aeiouyäö]"4
```
[Try it online.](http://pyth.herokuapp.com/?code=.b%2B%2BhY%2aW%40N2JhtY2XW%7DJeA%40DJc2%22aou%C3%A4%C3%B6y%22eNGH_Bmth%3Ad%3A%22%5E%28%5B%5EA%2a%29%28%5BA%29%28%5C%5C2%29%2a%28.%2B%29%22%5CA%22aeiouy%C3%A4%C3%B6%5D%224&input=%5B%22hauva%22%2C%22l%C3%A4%C3%A4h%C3%A4tt%C3%A4%C3%A4%22%5D&test_suite_input=%5B%22henri%22%2C+%22kontinen%22%5D%0A%5B%22tarja%22%2C+%22halonen%22%5D%0A%5B%22frakki%22%2C+%22kontti%22%5D%0A%5B%22ovi%22%2C+%22kello%22%5D%0A%5B%22haamu%22%2C+%22kontti%22%5D%0A%5B%22hauva%22%2C+%22kontti%22%5D%0A%5B%22puoskari%22%2C+%22kontti%22%5D%0A%5B%22k%C3%B6yh%C3%A4%22%2C+%22kontti%22%5D%0A%5B%22hauva%22%2C+%22l%C3%A4%C3%A4h%C3%A4tt%C3%A4%C3%A4%22%5D%0A%5B%22frakki%22%2C+%22stressi%22%5D%0A%5B%22%C3%A4ysk%C3%A4ri%22%2C+%22kontti%22%5D%0A%5B%22hattu%22%2C+%22sf%C3%A4%C3%A4ri%22%5D%0A%5B%22ovi%22%2C+%22silm%C3%A4%22%5D%0A%5B%22haamu%22%2C+%22pr%C3%A4tk%C3%A4%22%5D%0A%5B%22puoskari%22%2C+%22sf%C3%A4%C3%A4ri%22%5D%0A%5B%22puoskari%22%2C+%22%C3%A4ysk%C3%A4ri%22%5D%0A%5B%22uimapuku%22%2C+%22hajoa%22%5D%0A%5B%22ihme%22%2C+%22baletti%22%5D%0A%5B%22uhka%22%2C+%22lima%22%5D%0A%5B%22osuma%22%2C+%22makkara%22%5D%0A%5B%22makkara%22%2C+%22fakta%22%5D%0A%5B%22lapsi%22%2C+%22laiva%22%5D%0A%5B%22firma%22%2C+%22hajoa%22%5D%0A%5B%22dimensio%22%2C+%22bitti%22%5D%0A%5B%22flamingo%22%2C+%22joustava%22%5D%0A%5B%22globaali%22%2C+%22latomo%22%5D%0A%5B%22trilogia%22%2C+%22fakta%22%5D%0A%5B%22printti%22%2C+%22maksa%22%5D%0A%5B%22riisi%22%2C+%22bitti%22%5D%0A%5B%22sini%22%2C+%22riisi%22%5D%0A%5B%22aarre%22%2C+%22nyrkki%22%5D%0A%5B%22laavu%22%2C+%22laki%22%5D%0A%5B%22kliininen%22%2C+%22parveke%22%5D%0A%5B%22priimus%22%2C+%22kahvi%22%5D%0A%5B%22spriinen%22%2C+%22lasta%22%5D%0A%5B%22kliimaksi%22%2C+%22mammona%22%5D%0A%5B%22hylky%22%2C+%22hupsu%22%5D%0A%5B%22kehys%22%2C+%22fiksu%22%5D%0A%5B%22levy%22%2C+%22huhu%22%5D%0A%5B%22tiheys%22%2C+%22guru%22%5D%0A%5B%22nyrkki%22%2C+%22heiluri%22%5D%0A%5B%22latomo%22%2C+%22hajoa%22%5D%0A%5B%22prisma%22%2C+%22lehti%22%5D%0A%5B%22viina%22%2C+%22baletti%22%5D&debug=1) [Test suite.](http://pyth.herokuapp.com/?code=.b%2B%2BhY%2aW%40N2JhtY2XW%7DJeA%40DJc2%22aou%C3%A4%C3%B6y%22eNGH_Bmth%3Ad%3A%22%5E%28%5B%5EA%2a%29%28%5BA%29%28%5C%5C2%29%2a%28.%2B%29%22%5CA%22aeiouy%C3%A4%C3%B6%5D%224&input=%5B%22hauva%22%2C%22l%C3%A4%C3%A4h%C3%A4tt%C3%A4%C3%A4%22%5D&test_suite=1&test_suite_input=%5B%22henri%22%2C+%22kontinen%22%5D%0A%5B%22tarja%22%2C+%22halonen%22%5D%0A%5B%22frakki%22%2C+%22kontti%22%5D%0A%5B%22ovi%22%2C+%22kello%22%5D%0A%5B%22haamu%22%2C+%22kontti%22%5D%0A%5B%22hauva%22%2C+%22kontti%22%5D%0A%5B%22puoskari%22%2C+%22kontti%22%5D%0A%5B%22k%C3%B6yh%C3%A4%22%2C+%22kontti%22%5D%0A%5B%22hauva%22%2C+%22l%C3%A4%C3%A4h%C3%A4tt%C3%A4%C3%A4%22%5D%0A%5B%22frakki%22%2C+%22stressi%22%5D%0A%5B%22%C3%A4ysk%C3%A4ri%22%2C+%22kontti%22%5D%0A%5B%22hattu%22%2C+%22sf%C3%A4%C3%A4ri%22%5D%0A%5B%22ovi%22%2C+%22silm%C3%A4%22%5D%0A%5B%22haamu%22%2C+%22pr%C3%A4tk%C3%A4%22%5D%0A%5B%22puoskari%22%2C+%22sf%C3%A4%C3%A4ri%22%5D%0A%5B%22puoskari%22%2C+%22%C3%A4ysk%C3%A4ri%22%5D%0A%5B%22uimapuku%22%2C+%22hajoa%22%5D%0A%5B%22ihme%22%2C+%22baletti%22%5D%0A%5B%22uhka%22%2C+%22lima%22%5D%0A%5B%22osuma%22%2C+%22makkara%22%5D%0A%5B%22makkara%22%2C+%22fakta%22%5D%0A%5B%22lapsi%22%2C+%22laiva%22%5D%0A%5B%22firma%22%2C+%22hajoa%22%5D%0A%5B%22dimensio%22%2C+%22bitti%22%5D%0A%5B%22flamingo%22%2C+%22joustava%22%5D%0A%5B%22globaali%22%2C+%22latomo%22%5D%0A%5B%22trilogia%22%2C+%22fakta%22%5D%0A%5B%22printti%22%2C+%22maksa%22%5D%0A%5B%22riisi%22%2C+%22bitti%22%5D%0A%5B%22sini%22%2C+%22riisi%22%5D%0A%5B%22aarre%22%2C+%22nyrkki%22%5D%0A%5B%22laavu%22%2C+%22laki%22%5D%0A%5B%22kliininen%22%2C+%22parveke%22%5D%0A%5B%22priimus%22%2C+%22kahvi%22%5D%0A%5B%22spriinen%22%2C+%22lasta%22%5D%0A%5B%22kliimaksi%22%2C+%22mammona%22%5D%0A%5B%22hylky%22%2C+%22hupsu%22%5D%0A%5B%22kehys%22%2C+%22fiksu%22%5D%0A%5B%22levy%22%2C+%22huhu%22%5D%0A%5B%22tiheys%22%2C+%22guru%22%5D%0A%5B%22nyrkki%22%2C+%22heiluri%22%5D%0A%5B%22latomo%22%2C+%22hajoa%22%5D%0A%5B%22prisma%22%2C+%22lehti%22%5D%0A%5B%22viina%22%2C+%22baletti%22%5D&debug=1)
Proving that it's not *that* hard in golf languages. A stack-based language might do even better.
Pyth uses ISO-8859-1 by default, so `äö` are one byte each.
### Explanation
* `Q`, containing the input pair of words, is appended implicitly.
* `m`: map each word `d` in the input to:
	+ `:"^([^A*)([A)(\\2)*(.+)"\A"aeiouyäö]"`: replace `A` with `aeiouyäö]` in the string to get the regex `^([^aeiouyäö]*)([aeiouyäö])(\2)*(.+)`.
	+ `:d`: find all matches and return their capturing groups.
	+ `h`: take the first (and only) match.
	+ `t`: drop the first group containing the entire match.
* `_B`: pair with reverse to get `[[first, second], [second, first]]`.
* `.b`: map each pair of words `N, Y` in that to:
	+ `hY`: take the beginning consonants of the second word.
	+ `@N2`: take the long first vowel of the first word, or `None`.
	+ `htY`: take the first vowel of the second word.
	+ `J`: save that in `J`.
	+ `*W`…`2`: if there was a long vowel, duplicate the second word's vowel.
	+ `+`: append that to the consonants.
	+ `c2"aouäöy"`: split `aouäöy` in two to get `["aou", "äöy"]`.
	+ `@DJ`: sort the pair by intersection with the first vowel of the second word. This gets the half with the second word's first vowel in the end of the pair.
	+ `A`: save the pair to `G, H`.
	+ `e`: take the second half.
	+ `}J`: see if the first vowel of the second word is in the second half.
	+ `XW`…`eNGH`: if it was, map `G` to `H` in the suffix of the first word, otherwise keep the suffix as-is.
	+ `+`: append the suffix.
]