Skip to content

Load and tokenize a localized text template

This operation loads a text template — from a configured filesystem directory or from an assembly's embedded manifest resources — for a requested culture, then hands the loaded text to the shared base class to record the original text and parse {token}-style placeholders for later replacement. Both concrete loaders (clsFileResourceManager and clsAssemblyResourceManager) implement the same culture fallback chain independently, each against its own storage medium.

Field Value
Operation ID OP-RES-01
Trigger Caller instantiates clsFileResourceManager (with a resource directory) or clsAssemblyResourceManager (with an Assembly) and calls LoadResource(inResourceName, inTemplateExtension, inCultureCode) (or the single-argument overload, which defaults the culture code to the current UI culture)
Inputs Resource name, template file extension (defaults to html on the base overload), culture code, and — for the file-based loader — the configured resource directory, or — for the assembly-based loader — the target Assembly and an optional namespace override
Outputs Populated Text and ReplacedText on the loader instance, and a parsed Tokens list; no content is loaded and prior state is left unchanged if no matching file/resource is ever found
Primary components clsFileResourceManager.LoadResource, clsAssemblyResourceManager.LoadResource, clsResourceManager.Initialize, clsResourceManager.LoadTokens
Entry point Resources\SAIF.Resources\clsFileResourceManager.vb, Resources\SAIF.Resources\clsAssemblyResourceManager.vb, Resources\SAIF.Resources\clsResourceManager.vb

Steps

  1. Select a loader. The caller instantiates either clsFileResourceManager (constructed with a resource directory, trimmed of a trailing backslash) or clsAssemblyResourceManager (constructed with an Assembly, defaulting to the executing assembly).
  2. Build the exact-culture resource identifier.
  3. File loader: builds the path {ResourceDirectory}\{inResourceName}_{inCultureCode}.{inTemplateExtension} (omitting the culture segment entirely when the culture code is empty).
  4. Assembly loader: resolves the namespace (the supplied inNamespace, or the assembly's own name when none is supplied) and builds the manifest resource name {namespace}.{inResourceName}_{inCultureCode}.{inTemplateExtension} (again omitting the culture segment when empty).
  5. Attempt to load the exact-culture resource.
  6. File loader: checks IO.File.Exists for the built path.
  7. Assembly loader: calls Dll.GetManifestResourceStream for the built resource name.
  8. Fall back to a two-letter culture if the exact match is not found. If the requested culture code is longer than two characters, the loader retries steps 2–3 using only the first two characters of the culture code (for example, en-US retries as en).
  9. Fall back to no culture suffix if the two-letter match is also not found. If the (possibly already-shortened) culture code is still non-empty, the loader retries steps 2–3 with an empty culture code, which resolves to the unsuffixed default resource name.
  10. If no exact, two-letter, or unsuffixed resource exists, the loader returns without loading any content — Text, ReplacedText, and Tokens remain at their prior (or initial empty) state.
  11. Read the found content.
  12. File loader: opens an IO.StreamReader on the resolved path and reads the full text with ReadToEnd.
  13. Assembly loader: opens the manifest resource stream and reads the full text with ReadToEnd through an IO.StreamReader.
  14. Initialize the shared state. The loader calls clsResourceManager.Initialize(text), which stores the raw text in Text, copies it into ReplacedText, and calls LoadTokens().
  15. Parse simple tokens. LoadTokens matches the pattern {token-start}(?<token>[a-zA-Z0-9_]*){token-end} (delimiters default to { and }) against the loaded text and adds a Token entry (name, pattern, raw value) for every match.
  16. Parse content-bearing tokens. LoadTokens then matches the pattern {token-start}(?<token>[a-zA-Z0-9_]*):(?<content>.*){token-end} for colon-delimited tokens and adds a Token entry that also records the captured content, using a token-specific pattern for later replacement.
  17. Return the token list. LoadTokens returns the populated Tokens list, now available on the loader instance for use by Replace a token in loaded text.

Process flow

The following diagram visualizes the culture fallback and tokenization flow shared by both concrete resource loaders.

flowchart TD
    Start([Caller calls LoadResource]) --> BuildExact[Build exact-culture path<br>or manifest resource name]
    BuildExact --> FoundExact{Resource found?}
    FoundExact -->|Yes| Read[Read full template text]
    FoundExact -->|No| TwoLetter{Culture code<br>longer than 2 chars?}
    TwoLetter -->|Yes| BuildTwo[Retry with first<br>two characters]
    BuildTwo --> FoundTwo{Resource found?}
    FoundTwo -->|Yes| Read
    FoundTwo -->|No| NoSuffix{Culture code<br>still non-empty?}
    TwoLetter -->|No| NoSuffix
    NoSuffix -->|Yes| BuildDefault[Retry with empty<br>culture code]
    BuildDefault --> FoundDefault{Resource found?}
    FoundDefault -->|Yes| Read
    FoundDefault -->|No| EndNoLoad([Return without loading;<br>prior state unchanged])
    NoSuffix -->|No| EndNoLoad
    Read --> Init[Initialize stores Text<br>and ReplacedText]
    Init --> Tokens[LoadTokens parses<br>simple and content tokens]
    Tokens --> End([Tokens available for replacement])

Failure and edge-case behavior

  • If neither the exact-culture, two-letter-culture, nor unsuffixed resource exists, LoadResource returns silently without loading content or raising an error; Text, ReplacedText, and Tokens retain whatever state they held before the call.
  • The two-letter fallback only triggers when the supplied culture code is longer than two characters, so a culture code already at two characters (e.g., en) skips directly to the unsuffixed fallback if the two-letter form is not found.
  • An empty culture code on the initial call goes straight to the unsuffixed resource name, since the fallback conditions for both the two-letter and no-suffix retries require a non-empty starting culture code.
  • The assembly loader resolves its own assembly's name as the default namespace whenever the caller omits inNamespace, so callers embedding resources under a different namespace must supply it explicitly.
  • Both loaders implement the identical three-tier fallback chain independently in their own LoadResource overrides rather than sharing a common fallback helper.*

Note: Statements marked with * were inferred from code structure, naming conventions, or contextual evidence where direct confirmation was not available in source artifacts.

Sources

  • Resources\SAIF.Resources\clsResourceManager.vb
  • Resources\SAIF.Resources\clsFileResourceManager.vb
  • Resources\SAIF.Resources\clsAssemblyResourceManager.vb