In your application, the consistency requirements are pretty weak and easy to meet with a basic client/server architecture with a well defined sync point set on its life-cycle. For example, sync on boot, sync on net-reconnect, etc. Or, you could use a simple P2P protocol so on boot you discover your other connected devices and your apps can shake hand and exchange notes to sync up as they modify their local state: “Hey gang, + “KISS”. “Keep it simple ..”. Use json if you must.
Further simple characteristics of this app is that the state ops on your dictionary are commutative (like a CRDT!). On one device you add word “Foo” and on the other you add “Bar”. You do not care (do you?) that you added them in a certain order, so you don’t even have to bother with what is rather difficult to do in a performant manner: maintain a total ordering over the state of the system. (Think sharded ordered-sets..)
Something fancy like Operational Transforms or CRDT might make your life easier if you find a library that's ergonomic for your use case, but it's definitely not necessary.
Example: last-write-wins register, which is a (v, t) pair, normally has a merge function of "return the pair with the greatest t (with deterministic tie breaking for same t)", and for a super peer just have v's and "the latest value to hit the server wins".
But yeah, you shouldn't use the really complex CRDTs in that case. (And in most cases to be honest.)