I'm trying to wrap my head around how this string substitution actually works. In a command block I have this command:
tellraw @a {"rawtext":[{"translate":"test.one","with":["1","2","3"]}]}, with strings in numerical order.
Now I change the translation key with the structure test.one=Hello A, B, and C and also D. These are the outputs when I edit A, B, C, & D:
%0 %1 %s %s = 2 3 1 2
%1 %2 %s %s = 3 _ 1 2
%2 %3 %s %s = _ _ 1 2
%s %1 %s %s = 1 _ 2 3
%s %s %1 $s = 1 2 _ 3
%s %s %s %1 = 1 2 3 _ This is when you want to add new variables
%1 %2 %3 %s = 2 3 _ 1
%0 %1 %2 %s = 1 2 3 1 This is when you want to loop back to the beginning.
%0 %1 %2 %3 = _ 1 2 3 But alas, %0 doesn't work if the highest number ≥ array length.
%1 %2 %3 %4 = 1 2 3 _ This makes a little more sense, I guess. The pattern continues with higher numbers; 4-7 would leave everything blank.
%s %s %s %s = 1 2 3 _ Same result as above.
%s %s %s %0 = 1 2 3 3 Huh? It's not null & it doesn't loop back, but it does repeat the last element? What's going on?
So what I can gather is that %# and %s don't play nicely together. When they do, it's only when using numbers 0-(n-1) & using %s for looping back. Using %s for unaccounted variables does not work when you already used numbers. Using %s & then using numbers to add more works fine so long as you don't use 0.
If you know how many variables to expect & order matters, I'd recommend only using numbers. If you just need to plug in things in a list, I'd recommend only using %s. In my limited testing, $s did absolutely nothing.