diff --git a/aio/tools/transforms/angular-api-package/index.js b/aio/tools/transforms/angular-api-package/index.js
index 555ecd0645..79eef89996 100644
--- a/aio/tools/transforms/angular-api-package/index.js
+++ b/aio/tools/transforms/angular-api-package/index.js
@@ -86,7 +86,7 @@ module.exports =
readTypeScriptModules.ignoreExportsMatching = [/^_|^ɵɵ|^VERSION$/];
readTypeScriptModules.hidePrivateMembers = true;
- // NOTE: This list should be in sync with tools/public_api_guard/BUILD.bazel
+ // NOTE: This list should be in sync with the folders/files in `goldens/public-api`.
readTypeScriptModules.sourceFiles = [
'animations/index.ts',
'animations/browser/index.ts',
@@ -101,6 +101,8 @@ module.exports =
'core/testing/index.ts',
'elements/index.ts',
'forms/index.ts',
+ 'localize/index.ts',
+ 'localize/init/index.ts',
'platform-browser/index.ts',
'platform-browser/animations/index.ts',
'platform-browser/testing/index.ts',
diff --git a/packages/localize/PACKAGE.md b/packages/localize/PACKAGE.md
new file mode 100644
index 0000000000..a08e9ec121
--- /dev/null
+++ b/packages/localize/PACKAGE.md
@@ -0,0 +1,56 @@
+The `@angular/localize` package contains helpers and tools for localizing your application.
+
+You should install this package using `ng add @angular/localize` if you need to tag text in your
+application that you want to be translatable.
+
+The approach is based around the concept of tagging strings in code with a [template literal tag handler][tagged-templates]
+called `$localize`. The idea is that strings that need to be translated are “marked” using this tag:
+
+```ts
+const message = $localize`Hello, World!`;
+```
+
+---
+
+This `$localize` identifier can be a real function that can do the translation at runtime, in the browser.
+But, significantly, it is also a global identifier that survives minification.
+This means it can act simply as a marker in the code that a static post-processing tool can use to replace
+the original text with translated text before the code is deployed.
+
+For example, the following code:
+
+```ts
+warning = $localize`${this.process} is not right`;
+```
+
+could be replaced with:
+
+```ts
+warning = "" + this.process + ", ce n'est pas bon.";
+```
+
+The result is that all references to `$localize` are removed, and there is **zero runtime cost** to rendering
+the translated text.
+
+---
+
+The Angular template compiler also generates `$localize` tagged strings rather than doing the translation itself.
+For example, the following template:
+
+```html
+
Hello, World!
+```
+
+would be compiled to something like:
+
+```ts
+ɵɵelementStart(0, "h1"); //
+ɵɵi18n(1, $localize`Hello, World!`); // Hello, World!
+ɵɵelementEnd(); //
+```
+
+This means that after the Angular compiler has completed its work, all the template text marked with `i18n`
+attributes have been converted to `$localize` tagged strings, which can be processed just like any other
+tagged string.
+
+[tagged-templates]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates
diff --git a/packages/localize/init/PACKAGE.md b/packages/localize/init/PACKAGE.md
new file mode 100644
index 0000000000..581750ff4d
--- /dev/null
+++ b/packages/localize/init/PACKAGE.md
@@ -0,0 +1,2 @@
+The `@angular/localize` package exposes the `$localize` function in the global namespace, which can
+be used to tag i18n messages in your code that needs to be translated.
diff --git a/packages/localize/init/index.ts b/packages/localize/init/index.ts
index db1495a29d..e29960f8f3 100644
--- a/packages/localize/init/index.ts
+++ b/packages/localize/init/index.ts
@@ -7,7 +7,7 @@
*/
import {$localize, _global, LocalizeFn} from '../src/localize';
-export {LocalizeFn, TranslateFn} from '../src/localize';
+export {$localize, LocalizeFn, TranslateFn} from '../src/localize';
// Attach $localize to the global context, as a side-effect of this module.
_global.$localize = $localize;
@@ -37,7 +37,7 @@ declare global {
* ```
*
* This format is the same as that used for `i18n` markers in Angular templates. See the
- * [Angular 18n guide](guide/i18n#template-translations).
+ * [Angular 18n guide](guide/i18n#mark-text-for-translations).
*
* **Naming placeholders**
*
diff --git a/packages/localize/src/localize/src/localize.ts b/packages/localize/src/localize/src/localize.ts
index 071de81bd0..e6bb9ab66d 100644
--- a/packages/localize/src/localize/src/localize.ts
+++ b/packages/localize/src/localize/src/localize.ts
@@ -6,6 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/
+/** @nodoc */
export interface LocalizeFn {
(messageParts: TemplateStringsArray, ...expressions: readonly any[]): string;
@@ -38,6 +39,7 @@ export interface LocalizeFn {
locale?: string;
}
+/** @nodoc */
export interface TranslateFn {
(messageParts: TemplateStringsArray,
expressions: readonly any[]): [TemplateStringsArray, readonly any[]];
@@ -66,7 +68,7 @@ export interface TranslateFn {
* ```
*
* This format is the same as that used for `i18n` markers in Angular templates. See the
- * [Angular 18n guide](guide/i18n#template-translations).
+ * [Angular 18n guide](guide/i18n#mark-text-for-translations).
*
* **Naming placeholders**
*
@@ -130,9 +132,13 @@ export interface TranslateFn {
* the original template literal string without applying any translations to the parts. This
* version is used during development or where there is no need to translate the localized
* template literals.
+ *
* @param messageParts a collection of the static parts of the template string.
* @param expressions a collection of the values of each placeholder in the template string.
* @returns the translated string, with the `messageParts` and `expressions` interleaved together.
+ *
+ * @globalApi
+ * @publicApi
*/
export const $localize: LocalizeFn = function(
messageParts: TemplateStringsArray, ...expressions: readonly any[]) {
diff --git a/packages/localize/src/translate.ts b/packages/localize/src/translate.ts
index 1fb323c5cf..838df1aedd 100644
--- a/packages/localize/src/translate.ts
+++ b/packages/localize/src/translate.ts
@@ -17,21 +17,43 @@ import {MessageId, ParsedTranslation, parseTranslation, TargetMessage, translate
declare const $localize: LocalizeFn&{TRANSLATIONS: Record};
/**
- * Load translations for `$localize`.
+ * Load translations for use by `$localize`, if doing runtime translation.
*
- * The given `translations` are processed and added to a lookup based on their `MessageId`.
- * A new translation will overwrite a previous translation if it has the same `MessageId`.
+ * If the `$localize` tagged strings are not going to be replaced at compiled time, it is possible
+ * to load a set of translations that will be applied to the `$localize` tagged strings at runtime,
+ * in the browser.
*
- * * If a message is generated by the Angular compiler from an `i18n` marker in a template, the
- * `MessageId` is passed through to the `$localize` call as a custom `MessageId`. The `MessageId`
- * will match what is extracted into translation files.
+ * Loading a new translation will overwrite a previous translation if it has the same `MessageId`.
*
- * * If the translation is from a call to `$localize` in application code, and no custom `MessageId`
- * is provided, then the `MessageId` can be generated by passing the tagged string message-parts
- * to the `parseMessage()` function (not currently public API).
+ * Note that `$localize` messages are only processed once, when the tagged string is first
+ * encountered, and does not provide dynamic language changing without refreshing the browser.
+ * Loading new translations later in the application life-cycle will not change the translated text
+ * of messages that have already been translated.
*
+ * The message IDs and translations are in the same format as that rendered to "simple JSON"
+ * translation files when extracting messages. In particular, placeholders in messages are rendered
+ * using the `{$PLACEHOLDER_NAME}` syntax. For example the message from the following template:
+ *
+ * ```html
+ * preinner-preboldinner-postpost
+ * ```
+ *
+ * would have the following form in the `translations` map:
+ *
+ * ```ts
+ * {
+ * "2932901491976224757":
+ * "pre{$START_TAG_SPAN}inner-pre{$START_BOLD_TEXT}bold{$CLOSE_BOLD_TEXT}inner-post{$CLOSE_TAG_SPAN}post"
+ * }
+ * ```
+ *
+ * @param translations A map from message ID to translated message.
+ *
+ * These messages are processed and added to a lookup based on their `MessageId`.
+ *
+ * @see `clearTranslations()` for removing translations loaded using this function.
+ * @see `$localize` for tagging messages as needing to be translated.
* @publicApi
- *
*/
export function loadTranslations(translations: Record) {
// Ensure the translate function exists
@@ -47,7 +69,12 @@ export function loadTranslations(translations: Record)
}
/**
- * Remove all translations for `$localize`.
+ * Remove all translations for `$localize`, if doing runtime translation.
+ *
+ * All translations that had been loading into memory using `loadTranslations()` will be removed.
+ *
+ * @see `loadTranslations()` for loading translations at runtime.
+ * @see `$localize` for tagging messages as needing to be translated.
*
* @publicApi
*/