The translation wiki instructions are probably one of the most confusing sections of the wiki. I think it's because it was written by sheet authors that were figuring it out as they went, and a lot of the more advanced features of the i18n setup just didn't have a lot of use cases in early sheets because we didn't have the tech to make use of them until later on. So, here's my personal outline of translating sheets:
Sheet Dev
Personally, I never put the default text in the content of the element regardless of if its a new sheet or adding translations to an existing sheet. This is because there is no possible display error where the default content gets displayed unless Roll20 completely removes the i18n setup, in which case we probably have bigger issues than some text not displaying.
Translating Attribute Names
There is no way to translate attribute names. Macro calls will always be in whatever the initial language of the sheet is.
Variable Replacement
Of the confusing topic of advanced translation properties, variable replacement is probably one of the least well explained on the wiki. This is likely because there are very few real use cases for it in the context of sheets (especially before we got custom roll parsing; more on that later). The simplest, although not necessarily the most real world, use case I can think of is translating ordinals (e.g. 1st, 2nd, etc). You could just have the translators translate the whole thing, but then you're relying on them to do the format you want it in. For instance, maybe the person translating the sheet into spanish decides to use segundo instead of 2er. This then makes the gender of various items not match in the spanish language version of the sheet whereas 2er wouldn't have cared about gender. Another solution would be to use two separate spans. One for the number and one for the ordinal abbreviation:
<span class="ordinal-container">
<span>1</span>
<span data-i18n="1-ordinal">st</span>
</span>
The problem here is what if a language changes the order of the number and the ordinal, or the spacing between the two, or even adds something before and after the number for an ordinal? I'm not saying these actually exist, but these are the sort of issues that i18n variables help with. They allow us to have untranslated text as well as translated text in the same element. For our ordinal example, this would look like:
<span data-i18n="{{0}}ordinal" data-i18n-vars="1"></span>
Then our (english) translation file for this would look like:
{
"{{0}}ordinal":"{{0}}st"
}
The translation system then sees that {{0}} and uses it as an index to look up the correct untranslated item in the element's data-i18n-vars list. Note that this uses zero-indexing just like javascript arrays, and each individual untranslated item is separated by a bar (|).
Dynamic Key Replacement
This i18n feature is for when we need to translate a value of an attribute so that the displayed value is different from what the actual attribute value is. In the Dragonbane sheet that released recently, we used this for displaying the abbreviations of the selected attribute for each item in the secondary-skills repeating section. This then allowed us to have html like this:
<div class="expanded">
<select name="attr_attribute_translation">
<option data-i18n="strength-abbreviation" value="strength-abbreviation"></option>
<option data-i18n="dexterity-abbreviation" value="dexterity-abbreviation"></option>
</div>
<div class="collapsed">
<span data-i18n-dynamic name="attr_attribute_translation"></span>
</div>
This then lets our expanded mode (or edit mode) use a select so the player can set which ability score to base the secondary skills rolls off of, but when in collapsed (or view) mode, we just show a span that will simply display the translation of the value.
List Ordering
Ironically, I'm going to break the order here to keep the purely html i18n stuff together. List ordering allows us to have a list of things (like say skills) ordered alphabetically (or whatever order we need it in) for each language.
The way this works is to specify the list key on the container. Then add a list-item key to each child of the element (or grandchild depending on how your nesting works). The list-item key will be one of the items in the comma separated list that will be the translation value of the list key on the container. And then finally, we add the list key to the translation.json:
{
"skills-list":"acrobatics,athletics,brawling,lockpicking,flight"
}
Then a translator can reorder those list keys to be in the order that the translated versions are in their language. Of particular note here is that the individual keys in the list are never themselves translated, only the order of them is changed. For instance, the spanish version of this list order would be:
{
"skills-list":"acrobatics,athletics,lockpicking,brawling,flight"
}
Note that the individual words are still in English, but that lockpicking and brawling have changed places (forzar cerraduras and peleando respectively).
getTranslationByKey
This function is actually extremely useful when doing any sort of complex sheet. Before custom roll parsing it was mostly used for dynamically created macro strings. This wasn't ideal as it would then not necessarily be translated into the language of the user that actually sent the roll. With custom roll parsing, we can now dynamically translate roll query prompts as people roll. I use this extensively in the two storypath sheets (Scion 2e and They Came From ...). Which results in roll queries like this:

All the text in that roll query is translated to my language on the fly by the sheet using getTranslationByKey.
With some added code, you can even use this to translate variable strings such that you can translate something like this:

In this example the numbers are untranslated (and dynamically created based on the stats of the sheet and even options the user made in previous roll queries). Academics and Intellect are translated values, but aren't directly in the translation value of the translation key for this string. The rest of the sentence is translated, and then the attribute values injected using regex replacements looking for the various variable indexes in the translation string. Here's what that translation entry looks like in the translation.json:
{
"Roll {{skill}} and {{attribute}} with {{enhancement number}} enhancements and {{addDice}} additional dice?": "Roll {{0}} and {{1}} with {{2}} enhancements and {{3}} additional dice?",
}
Note that the key doesn't use the indexes, it uses descriptions of what that index represents in the string. This is because the replacement, whether done by bespoke javascript using regex replacement or the i18n module's -vars handling, looks at the translated value of the key for the index replacement, not the key itself.
This last example is obviously pretty complex and might not be needed by the majority of sheet authors, but shows how much you can do with CRP and getTranslationByKey.