---
title: Replace a token in loaded text
summary: Looks up a parsed token by name and replaces every occurrence of its pattern in the loaded template's working text.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-07-30
library: SAIF.Resources
reference_type: package
operation_id: OP-RES-02
trigger: Caller invokes ReplaceToken on a clsResourceManager (or a derived loader) after LoadResource has parsed tokens
---

# Replace a token in loaded text

After a template has been loaded and tokenized (see [Load and tokenize a localized text template](load-and-tokenize-text-template.md)), a caller replaces a named placeholder with a supplied value by calling `ReplaceToken`. The method normalizes the requested token name, looks it up case-insensitively among the tokens parsed from the template, and — if found — applies a case-insensitive regular-expression replacement against the current `ReplacedText`, so repeated calls compose against previously replaced content.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-RES-02 |
| **Trigger** | Caller invokes the instance method `ReplaceToken(inTokenName, inReplacement)` on a `clsResourceManager` (or a `clsFileResourceManager` / `clsAssemblyResourceManager` instance after loading), or the shared static overload `clsResourceManager.ReplaceToken(text, inTokenName, inReplacement)` for one-off replacement against arbitrary text |
| **Inputs** | Token name and replacement string |
| **Outputs** | Updated `ReplacedText` string, also returned directly from the call |
| **Primary components** | `clsResourceManager.ReplaceToken`, `clsResourceManager.GetToken` |
| **Entry point** | `Resources\SAIF.Resources\clsResourceManager.vb` |

## Steps

1. **Caller supplies a token name and replacement.** The caller passes `inTokenName` and `inReplacement` to `ReplaceToken`.
2. **Normalize the token name.** `GetToken` trims the configured `TokenStartDelimiter` and `TokenEndDelimiter` characters (default `{` and `}`) from both ends of `inTokenName`, so callers may pass either the bare name or the fully delimited form (e.g., `userID` or `{userID}`).
3. **Look up the token.** `GetToken` searches the `Tokens` list parsed during loading for a case-insensitive name match and returns the first match, or `Nothing` if the list is empty/unset or no match exists.
4. **Apply the replacement if found.** If a matching token is returned, `ReplaceToken` calls `Regex.Replace` against the current `_ReplacedText`, using the token's stored pattern and `RegexOptions.IgnoreCase`, replacing every occurrence of that pattern with `inReplacement`.
   - If no matching token is found: `_ReplacedText` is left unchanged.
5. **Return the current state.** The method returns `_ReplacedText`, reflecting either the newly applied replacement or the prior unchanged value.
6. **Static one-off variant.** The shared `ReplaceToken(text, inTokenName, inReplacement)` overload constructs a new `clsResourceManager` directly from `text` (which re-runs `Initialize`/`LoadTokens` on that text) and then performs steps 2–5 against that fresh instance, returning the result without requiring a caller-managed loader instance.

## Process flow

The following diagram visualizes the token lookup and replacement flow.

```mermaid
flowchart TD
	Start([Caller calls ReplaceToken<br>with name and replacement]) --> Trim[Trim delimiter characters<br>from token name]
	Trim --> Lookup[Search Tokens list<br>case-insensitively]
	Lookup --> Found{Token found?}
	Found -->|No| Unchanged([ReplacedText unchanged;<br>return current value])
	Found -->|Yes| Replace[Regex.Replace all occurrences<br>of the token pattern]
	Replace --> Updated([Return updated ReplacedText])
```

## Failure and edge-case behavior

- A token name that does not match any parsed token (case-insensitively) is silently ignored — `ReplaceToken` returns the unchanged `ReplacedText` without raising an error.
- Because the lookup and replacement operate on the token's stored pattern rather than a literal string match, content-bearing tokens (those parsed with a colon, e.g. `{token:content}`) are matched and replaced as a whole unit via their token-specific pattern.
- Replacement is applied against `_ReplacedText` (not the original `_Text`), so multiple sequential `ReplaceToken` calls compose — each call's replacement text becomes part of the input for the next call's regex match.
- If `Tokens` is `Nothing` (i.e., no `LoadResource`/`Initialize` call has populated it yet), `GetToken` returns `Nothing` immediately and the replacement is a no-op.
- The static `ReplaceToken(text, ...)` overload always starts from a fresh single-use instance, so it does not benefit from or affect any previously loaded/replaced state elsewhere in the application.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- `Resources\SAIF.Resources\clsResourceManager.vb`
