Все ключи в файле .resx одноуровневые , однако ничто не мешает вам использовать свой собственный формат XML, если вы напишите код для его чтения и все инструменты, необходимые для поддержки это.
Для вывода переменных сеанса я бы использовал String.Format ()
Обычно вы пишете
String.Format(“"Your Card #{0} has been reserved for you.",
HttpContext.Current.Session["ReservedCardNum"])
Так что вместо этого просто используйте
String.Format(stringLookedFromResouceFile,
HttpContext.Current.Session["ReservedCardNum"])
И поместите «{0}» в переведенную строку, чтобы переводчики могли изменить порядок слов при необходимости.
Подумайте, как вы будете сообщать переводчикам, какие заполнители. Если переводчики используют редактор ресурсов, отображающий поле комментария, вы можете добавить комментарии, например «{0} = имя пользователя»
Вам также нужно будет как-то проверить, чтобы переводчики не запутали заполнители, я видел, как переводчики меняли «{0}» на «(0)», поскольку они «думают, что скобки другого типа выглядят лучше» так далее! или удалите один из скобок, чтобы формат строки больше не действовал.
см. Как проверить строку формата