We have implemented #3 using a small content item with key and value fields. Created a service to return these items and we inject that into a Tag Helper
[HtmlTargetElement("resource-string")]
public class ResourceStringTagHelper : TagHelper
{
    [HtmlAttributeName("baseKey")]
    public string BaseKey { get; set; }
    [HtmlAttributeName("key")]
    public string Key { get; set; }
    private readonly IApplicationLocalizationService _applicationLocalizationService;
    private readonly IWebsiteChannelContext _websiteChannelContext;
    public ResourceStringTagHelper(IApplicationLocalizationService applicationLocalizationService, 
        IWebsiteChannelContext websiteChannelContext)
    {
        _applicationLocalizationService = applicationLocalizationService;
        _websiteChannelContext = websiteChannelContext;
    }
    public async override Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.TagName = string.Empty;
        var rs = await _applicationLocalizationService.GetLocalizedString($"{BaseKey}{Key}", _websiteChannelContext.WebsiteChannelName, echoBack:false);
        output.Content.SetHtmlContent(rs);
    }
}
You can then drop the tags into your views e.g.
<resource-string key="Default.SiteUI.Shipping.BackToCart" />
We also ensured that the keys are unique by checking the keys everytime an item of the reusable content item type was either created or updated