diff --git a/assemblies/assembly-configuring-a-floating-action-button.adoc b/assemblies/assembly-configuring-a-floating-action-button.adoc
index 319cb61067..d2d36469d2 100644
--- a/assemblies/assembly-configuring-a-floating-action-button.adoc
+++ b/assemblies/assembly-configuring-a-floating-action-button.adoc
@@ -8,4 +8,8 @@ You can use the floating action button plugin to configure any action as a float
include::modules/configuring-a-floating-action-button/proc-configuring-floating-action-button-as-a-dynamic-plugin.adoc[leveloffset=+1]
+// Localization
+include::modules/configuring-a-floating-action-button/con-localization-support-for-the-floating-action-button.adoc[leveloffset=+1]
+// END Localization
+
include::modules/configuring-a-floating-action-button/ref-floating-action-button-parameters.adoc[leveloffset=+1]
diff --git a/assemblies/assembly-configuring-the-quickstarts.adoc b/assemblies/assembly-configuring-the-quickstarts.adoc
index 34d76f4d57..59f87c0a84 100644
--- a/assemblies/assembly-configuring-the-quickstarts.adoc
+++ b/assemblies/assembly-configuring-the-quickstarts.adoc
@@ -12,4 +12,4 @@ include::modules/configuring-the-quickstarts/proc-disabling-rhdh-quickstart.adoc
include::modules/configuring-the-quickstarts/proc-starting-and-completing-modules-in-quickstarts.adoc[leveloffset=+1]
-include::modules/configuring-the-quickstarts/con-using-rbac-with-quickstarts.adoc[leveloffset=+1]
+include::modules/customizing-the-appearance/proc-enabling-localization-in-quickstarts.adoc[leveloffset=+1]
diff --git a/assemblies/assembly-customizing-the-appearance.adoc b/assemblies/assembly-customizing-the-appearance.adoc
index 2c69959e63..04358576b8 100644
--- a/assemblies/assembly-customizing-the-appearance.adoc
+++ b/assemblies/assembly-customizing-the-appearance.adoc
@@ -32,6 +32,8 @@ include::modules/customizing-the-appearance/con-about-rhdh-sidebar-menuitems.ado
include::modules/customizing-the-appearance/proc-customize-rhdh-sidebar-menuitems.adoc[leveloffset=+2]
+include::modules/customizing-the-appearance/proc-enabling-localization-in-sidebar-items.adoc[leveloffset=+2]
+
include::modules/customizing-the-appearance/proc-configuring-dynamic-plugin-menuitem.adoc[leveloffset=+2]
include::modules/customizing-the-appearance/proc-modifying-or-adding-rhdh-custom-menuitem.adoc[leveloffset=+2]
diff --git a/assemblies/assembly-localization-in-rhdh.adoc b/assemblies/assembly-localization-in-rhdh.adoc
new file mode 100644
index 0000000000..8785703aef
--- /dev/null
+++ b/assemblies/assembly-localization-in-rhdh.adoc
@@ -0,0 +1,26 @@
+:_mod-docs-content-type: ASSEMBLY
+:context: assembly-localization-in-rhdh
+
+[id="assembly-localization-in-rhdh_{context}"]
+= Localization in {product}
+
+include::modules/customizing-the-appearance/proc-enabling-localization-in-rhdh.adoc[leveloffset=+1]
+
+include::modules/customizing-the-appearance/proc-select-rhdh-language.adoc[leveloffset=+1]
+
+include::modules/customizing-the-appearance/con-language-persistence.adoc[leveloffset=+2]
+
+// include::modules/customizing-the-appearance/proc-enabling-localization-in-quickstarts.adoc[leveloffset=+1]
+
+// include::modules/customizing-the-appearance/proc-enabling-localization-in-sidebar-items.adoc[leveloffset=+1]
+
+//include::modules/customizing-the-appearance/proc-enabling-localization-in-floating-action-button.adoc[leveloffset=+1]
+
+== Localization support for plugins
+
+include::modules/customizing-the-appearance/proc-overriding-translations.adoc[leveloffset=+2]
+
+include::modules/customizing-the-appearance/ref-best-practices-for-localization.adoc[leveloffset=+2]
+
+include::modules/customizing-the-appearance/proc-adding-localization-to-custom-plugins.adoc[leveloffset=+2]
+
diff --git a/images/rhdh/customize-language-dropdown.png b/images/rhdh/customize-language-dropdown.png
new file mode 100644
index 0000000000..ab668d60f3
Binary files /dev/null and b/images/rhdh/customize-language-dropdown.png differ
diff --git a/modules/configuring-a-floating-action-button/con-localization-support-for-the-floating-action-button.adoc b/modules/configuring-a-floating-action-button/con-localization-support-for-the-floating-action-button.adoc
new file mode 100644
index 0000000000..6794473a93
--- /dev/null
+++ b/modules/configuring-a-floating-action-button/con-localization-support-for-the-floating-action-button.adoc
@@ -0,0 +1,60 @@
+[id="proc-enabling-localization-in-floating-action-button_{context}"]
+= Enabling floating action button localization in {product-very-short}
+
+You can enable translation key support for floating action buttons, so that users can onboard in their preferred language. In {product-short}, all existing and newly created floating action buttons support localization using dedicated translation keys.
+
+The Global Floating Action Button plugin supports internationalization (i18n) through translation keys. You can use `labelKey` and `toolTipKey` properties to provide translation keys instead of static text.
+
+The plugin provides the following built-in translation keys organized under the `fab` namespace:
+
+* `fab.create.label` - "Create"
+* `fab.create.tooltip` - "Create entity"
+* `fab.docs.label` - "Docs"
+* `fab.docs.tooltip` - "Documentation"
+* `fab.apis.label` - "APIs"
+* `fab.apis.tooltip` - "API Documentation"
+* `fab.github.label` - "GitHub"
+* `fab.github.tooltip` - "GitHub Repository"
+* `fab.bulkImport.label` - "Bulk Import"
+* `fab.bulkImport.tooltip` - "Register multiple repositories in bulk"
+* `fab.quay.label` - "Quay"
+* `fab.quay.tooltip` - "Quay Container Registry"
+
+The plugin includes translations for the following supported languages:
+
+* English (default)
+// * German (de)
+* French (fr)
+// * Spanish (es)
+
+// [NOTE]
+// ====
+// To add localization support for a new floating action button item, you can add any arbitrary key name for the `labelKey` and `toolTipKey` properties and provide corresponding translations for those keys.
+
+// If you add a new floating action button item, you can add localization support by adding an arbitary label key and tool tip key
+
+// ====
+
+To ensure backward compatibility while providing translation support when available, the following order is used to resolve string translations:
+
+. If the `labelKey` is provided, the plugin will attempt to resolve the translation key
+. If the translation key is found, it will be used as the label
+. If the translation key is not found, the plugin will fall back to the label property
+
+[NOTE]
+====
+The same logic applies to `toolTipKey` and `toolTip`.
+====
+
+== Internal translation implementation
+The plugin uses a centralized translation system where:
+
+* The `useTranslation()` hook is called in components that render floating action buttons to ensure proper translation context initialization
+* The translation function (`t`) is passed down to child components that need to resolve translation keys
+* This internal architecture prevents infinite re-render loops and ensures stable component rendering
+* All components that use `CustomFab` must provide the translation function as a prop
+
+[NOTE]
+====
+When extending or modifying the plugin components, ensure that the `useTranslation()` hook is called in parent components and the `t` prop is passed to `CustomFab` instances to maintain proper translation functionality and prevent rendering issues.
+====
\ No newline at end of file
diff --git a/modules/configuring-a-floating-action-button/proc-configuring-floating-action-button-as-a-dynamic-plugin.adoc b/modules/configuring-a-floating-action-button/proc-configuring-floating-action-button-as-a-dynamic-plugin.adoc
index 4193f14924..a523dc2c5e 100644
--- a/modules/configuring-a-floating-action-button/proc-configuring-floating-action-button-as-a-dynamic-plugin.adoc
+++ b/modules/configuring-a-floating-action-button/proc-configuring-floating-action-button-as-a-dynamic-plugin.adoc
@@ -203,3 +203,43 @@ To configure a floating action button as a dynamic plugin, complete any of the f
text: Bulk import
----
`frontend:mountPoints:importName`:: Enter the import name with an associated component to the mount point.
+
+= Translation support
+The Global Floating Action Button plugin supports internationalization (i18n) through translation keys. You can use `labelKey` and `toolTipKey` properties to provide translation keys instead of static text.
+
+Example for using translation keys in dynamic configuration:
+[source,yaml]
+----
+- package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-global-floating-action-button
+ disabled: false
+ pluginConfig:
+ dynamicPlugins:
+ frontend:
+ red-hat-developer-hub.backstage-plugin-global-floating-action-button:
+ translationResources:
+ - importName: globalFloatingActionButtonTranslations
+ ref: globalFloatingActionButtonTranslationRef
+ mountPoints:
+ - mountPoint: application/listener
+ importName: DynamicGlobalFloatingActionButton
+ - mountPoint: global.floatingactionbutton/config
+ importName: NullComponent
+ config:
+ icon: github
+ label: 'GitHub' # Fallback text
+ labelKey: 'fab.github.label' # Translation key
+ toolTip: 'GitHub Repository' # Fallback text
+ toolTipKey: 'fab.github.tooltip' # Translation key
+ to: https://github.com/redhat-developer/rhdh-plugins
+ - mountPoint: global.floatingactionbutton/config
+ importName: NullComponent
+ config:
+ color: 'success'
+ icon: search
+ label: 'Create' # Fallback text
+ labelKey: 'fab.create.label' # Translation key
+ toolTip: 'Create entity' # Fallback text
+ toolTipKey: 'fab.create.tooltip' # Translation key
+ to: '/create'
+ showLabel: true
+----
\ No newline at end of file
diff --git a/modules/configuring-a-floating-action-button/ref-floating-action-button-parameters.adoc b/modules/configuring-a-floating-action-button/ref-floating-action-button-parameters.adoc
index 1f2c3d54e4..d6be21b37c 100644
--- a/modules/configuring-a-floating-action-button/ref-floating-action-button-parameters.adoc
+++ b/modules/configuring-a-floating-action-button/ref-floating-action-button-parameters.adoc
@@ -21,6 +21,12 @@ Use the parameters as shown in the following table to configure your floating ac
| Not applicable
| Yes
+| `labelKey`
+| Translation key for the label. If provided, will be used instead of label when translations are available.
+| `String`
+| Not applicable
+| No
+
| `icon`
| Icon of the floating action button. Recommended to use filled icons from the link:https://fonts.google.com/icons[Material Design library]. You can also use an svg icon. For example: ``
| `String`, `React.ReactElement`, `SVG image icon`, `HTML image icon`
@@ -63,6 +69,12 @@ Use the parameters as shown in the following table to configure your floating ac
| Not applicable
| No
+| `toolTipKey`
+| Translation key for the tooltip. If provided, will be used instead of toolTip when translations are available.
+| `String`
+| Not applicable
+| No
+
| `priority`
| Order of the floating action buttons displayed in the submenu. A larger value means higher priority.
| `number`
diff --git a/modules/customizing-the-appearance/con-language-persistence.adoc b/modules/customizing-the-appearance/con-language-persistence.adoc
new file mode 100644
index 0000000000..5e6097f3d3
--- /dev/null
+++ b/modules/customizing-the-appearance/con-language-persistence.adoc
@@ -0,0 +1,27 @@
+:_mod-docs-content-type: CONCEPT
+
+[id="con-language-persistence_{context}"]
+= Language persistence
+
+When you change the language in the UI, your preference is saved to storage. On next login or refresh, your chosen language setting is restored. Guest users cannot persist language preferences.
+
+Default language selection uses the following priority order:
+
+. *Browser language priority*: The system first checks the user's browser language preferences to provide a personalized experience.
+
+. *Configuration priority*: If no browser language matches the supported locales, the `defaultLocale` from the `i18n` configuration is used as a fallback.
+
+. *Fallback priority*: If neither browser preferences nor configuration provide a match, defaults to `en`.
+
+{product} automatically saves and restores user language settings across browser sessions. This feature is enabled by default and uses database storage. To opt-out and use browser storage instead, add the following to your `{my-app-config-file}` configuration file:
+[source,yaml,subs="+quotes"]
+----
+userSettings:
+ persistence: browser
+----
+
+where:
+
+userSettings:persistence::
+Enter `browser` to opt-out and use browser local storage. Optionally, set this value to `database` to persist across browsers and devices. This is the default setting and does not require this configuration to be set.
+
diff --git a/modules/customizing-the-appearance/proc-adding-localization-to-custom-plugins.adoc b/modules/customizing-the-appearance/proc-adding-localization-to-custom-plugins.adoc
new file mode 100644
index 0000000000..cfd33bc50e
--- /dev/null
+++ b/modules/customizing-the-appearance/proc-adding-localization-to-custom-plugins.adoc
@@ -0,0 +1,252 @@
+:_mod-docs-content-type: PROCEDURE
+
+[id="proc-adding-localization-to-custom-plugins_{context}"]
+= Implementing localization support for your custom plugins
+You can implement localization support in your custom {product-very-short} plugins so that your plugins are accessible to a diverse, international user base and follow recommended best practices.
+
+.Procedure
+. Create the following translation files in your plugin's `src/translations/` directory:
++
+.`src/translations/ref.ts` English reference
+[source,json]
+----
+import { createTranslationRef } from "@backstage/core-plugin-api/alpha";
+
+export const myPluginMessages = {
+ page: {
+ title: "My Plugin",
+ subtitle: "Plugin description",
+ },
+ common: {
+ exportCSV: "Export CSV",
+ noResults: "No results found",
+ },
+ table: {
+ headers: {
+ name: "Name",
+ count: "Count",
+ },
+ },
+};
+
+export const myPluginTranslationRef = createTranslationRef({
+ id: "plugin.my-plugin",
+ messages: myPluginMessages,
+});
+----
++
+.`src/translations/de.ts` German translation
+[source,json]
+----
+import { createTranslationMessages } from "@backstage/core-plugin-api/alpha";
+import { myPluginTranslationRef } from "./ref";
+
+const myPluginTranslationDe = createTranslationMessages({
+ ref: myPluginTranslationRef,
+ messages: {
+ "page.title": "Mein Plugin",
+ "page.subtitle": "Plugin-Beschreibung",
+ "common.exportCSV": "CSV exportieren",
+ "common.noResults": "Keine Ergebnisse gefunden",
+ "table.headers.name": "Name",
+ "table.headers.count": "Anzahl",
+ },
+});
+
+export default myPluginTranslationDe;
+----
++
+.`src/translations/fr.ts` French translation
+[source,json]
+----
+import { createTranslationMessages } from "@backstage/core-plugin-api/alpha";
+import { myPluginTranslationRef } from "./ref";
+
+const myPluginTranslationFr = createTranslationMessages({
+ ref: myPluginTranslationRef,
+ messages: {
+ "page.title": "Mon Plugin",
+ "page.subtitle": "Description du plugin",
+ "common.exportCSV": "Exporter CSV",
+ "common.noResults": "Aucun résultat trouvé",
+ "table.headers.name": "Nom",
+ "table.headers.count": "Nombre",
+ },
+});
+
+export default myPluginTranslationFr;
+----
++
+.`src/translations/index.ts` Translation resource
+[source,json]
+----
+import { createTranslationResource } from "@backstage/core-plugin-api/alpha";
+import { myPluginTranslationRef } from "./ref";
+
+export const myPluginTranslations = createTranslationResource({
+ ref: myPluginTranslationRef,
+ translations: {
+ de: () => import("./de"),
+ fr: () => import("./fr"),
+ },
+});
+
+export { myPluginTranslationRef };
+----
+
+. Create translation hooks file, as follows:
++
+.`src/hooks/useTranslation.ts` Translation hooks
+[source,json]
+----
+import { useTranslationRef } from "@backstage/core-plugin-api/alpha";
+import { myPluginTranslationRef } from "../translations";
+
+export const useTranslation = () => useTranslationRef(myPluginTranslationRef);
+----
+
+. Update your plugin components to replace hard-coded strings with translation calls as shown in the following example:
++
+.Before (hardcoded):
+[source,json]
+----
+const MyComponent = () => {
+ return (
+
+ );
+};
+----
+
+. (Optional) If your content contains variables, use interpolation:
++
+[source,json]
+----
+// In your translation files
+'table.pagination.topN': 'Top {{count}} items'
+
+// In your component
+const { t } = useTranslation();
+const message = t('table.pagination.topN', { count: '10' });
+----
+
+. (Optional) If your content contains dynamic translation keys (for example, from your plugin configuration):
++
+[source,json]
+----
+// Configuration object with translation keys
+const CARD_CONFIGS = [
+ { id: 'overview', titleKey: 'cards.overview.title' },
+ { id: 'details', titleKey: 'cards.details.title' },
+ { id: 'settings', titleKey: 'cards.settings.title' },
+];
+
+// In your component
+const { t } = useTranslation();
+
+const CardComponent = ({ config }) => {
+ return (
+
+
{t(config.titleKey as any)}
+ {/* Use 'as any' for dynamic keys */}
+
+ );
+};
+----
+
+. Export the translation resources
++
+[source,json]
+.`src/alpha.ts` file fragment
+----
+// Export your plugin
+export { myPlugin } from "./plugin";
+
+// Export translation resources for RHDH
+export { myPluginTranslations, myPluginTranslationRef } from "./translations";
+----
+
+. Update your `dynamic-plugins.default.yaml` file, as follows:
++
+[source,json]
+.`dynamic-plugins.default.yaml` file fragment
+----
+backstage-community.plugin-my-plugin:
+ translationResources:
+ - importName: myPluginTranslations
+ ref: myPluginTranslationRef
+ module: Alpha
+----
+
+.Verification
+To verify your translations, create a test mock file. For example:
+
+.`src/test-utils/mockTranslations.ts` Test mock file
+[source,json]
+----
+import { myPluginMessages } from "../translations/ref";
+
+function flattenMessages(obj: any, prefix = ""): Record {
+ const flattened: Record = {};
+ for (const key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ const value = obj[key];
+ const newKey = prefix ? `${prefix}.${key}` : key;
+ if (typeof value === "object" && value !== null) {
+ Object.assign(flattened, flattenMessages(value, newKey));
+ } else {
+ flattened[newKey] = value;
+ }
+ }
+ }
+ return flattened;
+}
+
+const flattenedMessages = flattenMessages(myPluginMessages);
+
+export const mockT = (key: string, params?: any) => {
+ let message = flattenedMessages[key] || key;
+ if (params) {
+ for (const [paramKey, paramValue] of Object.entries(params)) {
+ message = message.replace(
+ new RegExp(`{{${paramKey}}}`, "g"),
+ String(paramValue),
+ );
+ }
+ }
+ return message;
+};
+
+export const mockUseTranslation = () => ({ t: mockT });
+----
+
+.Update your tests
+[source,json]
+----
+import { mockUseTranslation } from "../test-utils/mockTranslations";
+
+jest.mock("../hooks/useTranslation", () => ({
+ useTranslation: mockUseTranslation,
+}));
+
+// Your test code...
+----
\ No newline at end of file
diff --git a/modules/customizing-the-appearance/proc-customize-rhdh-language.adoc b/modules/customizing-the-appearance/proc-customize-rhdh-language.adoc
new file mode 100644
index 0000000000..a64e242f67
--- /dev/null
+++ b/modules/customizing-the-appearance/proc-customize-rhdh-language.adoc
@@ -0,0 +1,26 @@
+:_mod-docs-content-type: PROCEDURE
+
+[id="proc-customize-rhdh-language_{context}"]
+= Customizing the language for your {product-short} instance
+
+The language settings of {product-very-short} use English by default. You can choose to use one of the following languages instead.
+
+.Supported languages
+* English
+* French
+
+[NOTE]
+====
+English and French are the supported languages in {product-very-short} 1.8. You can add other languages in the the `i18n` section of your `{my-app-config-file}` configuration file.
+====
+
+.Prerequisites
+
+* You are logged in to the {product-short} web console.
+
+.Procedure
+
+. From the {product-short} web console, click *Settings*.
+. From the *Appearance* panel, click the language dropdown to select your language of choice.
++
+image::rhdh/customize-language-dropdown.png[]
\ No newline at end of file
diff --git a/modules/customizing-the-appearance/proc-enabling-localization-in-quickstarts.adoc b/modules/customizing-the-appearance/proc-enabling-localization-in-quickstarts.adoc
new file mode 100644
index 0000000000..52033fbb39
--- /dev/null
+++ b/modules/customizing-the-appearance/proc-enabling-localization-in-quickstarts.adoc
@@ -0,0 +1,89 @@
+:_mod-docs-content-type: CONCEPT
+
+[id="proc-enabling-localization-in-quickstarts_{context}"]
+= Enabling Quickstart localization in {product-very-short}
+
+You can enable translation key support for Quickstart titles, descriptions, and CTAs, so that users can onboard in their preferred language. In {product-short}, all existing and newly created Quickstart steps support localization using dedicated translation keys (`titleKey`, `descriptionKey`, `cta.textKey`).
+
+[NOTE]
+====
+If a translation key is present but the corresponding localized string is missing, the system defaults to the original text defined in the Quickstart configuration (`title`, `description`, `text`). If no translation key is defined at all, the original text is displayed.
+====
+
+.Prerequisites
+* You have enabled localization in your {product-very-short} application.
+
+.Procedure
+
+. For *all* Quickstart steps (both existing and new) in your configuration file, you must define both the original text and the new localization keys. For example, in the `quickstart` section of your custom `{my-app-config-file}` file, add the `titleKey`, `descriptionKey`, and `textKey` values, as follows:
++
+.`{my-app-config-file}` fragment
+[source,yaml,subs="+quotes"]
+----
+app:
+ quickstart:
+ # Existing Quickstart steps should also be updated with keys
+ - title: 'Setup Authentication'
+ titleKey: steps.setupAuth.title
+ description: 'Learn the basics of navigating the Developer Hub interface'
+ descriptionKey: steps.setupAuth.description
+ icon: 'home'
+ cta:
+ text: 'Get Started'
+ textKey: steps.setupAuth.ctaTitle
+ link: '/catalog'
+# ...
+----
++
+where:
+
+`title`:: (Mandatory) Fallback for the title.
+`titleKey`:: Key for the translated title.
+`description`:: (Mandatory) Fallback for the description.
+`descriptionKey`:: Key for the translated description.
+`text`:: (Mandatory) Fallback for the CTA text.
+`textKey`:: Key for the translated CTA text.
+
+. In your `dynamic-plugins.yaml` file, add the `translationResources` section to your `red-hat-developer-hub-backstage-plugin-quickstart` configuration, as follows:
++
+.`{my-app-config-file}` fragment
+[source,yaml,subs="+quotes"]
+----
+plugins:
+ - package: ./dynamic-plugins/dist/red-hat-developer-hub-backstage-plugin-quickstart
+ disabled: false
+ pluginConfig:
+ dynamicPlugins:
+ frontend:
+ red-hat-developer-hub.backstage-plugin-quickstart:
+ # translationResources definition is required for translations to work
+ translationResources:
+ - importName: quickstartTranslations
+ ref: quickstartTranslationRef
+ # ... other configurations like mountPoints ...
+----
++
+where:
+
+importName::
+Enter the name used to reference the import.
+ref::
+Reference to the resource definition.
+. In your translation file, map the keys from the first step to the localized strings for each supported language.
++
+.`allTranslations.json` fragment
+[source,yaml,subs="+quotes"]
+----
+"plugin.quickstart": {
+ "en": {
+ "steps.setupAuth.title": "Manage plugins EN",
+ "steps.setupAuth.description": "EN Browse and install extensions to add features, connect with external tools, and customize your experience.",
+ "steps.setupAuth.ctaTitle": "Start"
+ },
+ "fr": {
+ "steps.setupAuth.title": "Gérer les plugins FR",
+ "steps.setupAuth.description": "FR Parcourez et installez des extensions pour ajouter des fonctionnalités, vous connecter à des outils externes et personnaliser votre expérience.",
+ "steps.setupAuth.ctaTitle": "Commencer"
+ }
+}
+----
\ No newline at end of file
diff --git a/modules/customizing-the-appearance/proc-enabling-localization-in-rhdh.adoc b/modules/customizing-the-appearance/proc-enabling-localization-in-rhdh.adoc
new file mode 100644
index 0000000000..50c1c05076
--- /dev/null
+++ b/modules/customizing-the-appearance/proc-enabling-localization-in-rhdh.adoc
@@ -0,0 +1,28 @@
+:_mod-docs-content-type: PROCEDURE
+
+[id="proc-enabling-localization-in-rhdh_{context}"]
+= Enabling the localization framework in {product-short}
+Enabling localization enhances accessibility, improves the user experience for a global audience, and assists organizations in meeting language requirements in specific regions.
+
+The language settings of {product} ({product-very-short}) use English by default. In {product-very-short} {product-version}, you can choose to use one of the following supported languages:
+
+* English (en)
+* French (fr)
+
+.Prerequisites
+
+.Procedure
+. To enable the localization framework in your {product-very-short} application, add the `i18n` section to your custom {product-short} `{my-app-config-file}` configuration file:
++
+[id=i18n]
+.`{my-app-config-file}` fragment with localization `i18n` fields
+[source,yaml,subs="+quotes"]
+----
+...
+i18n:
+ locales: # List of supported locales. Must include `en`, otherwise the translation framework will fail to load.
+ - en
+ - fr
+ defaultLocale: en # Optional. Defaults to `en` if not specified.
+...
+----
\ No newline at end of file
diff --git a/modules/customizing-the-appearance/proc-enabling-localization-in-sidebar-items.adoc b/modules/customizing-the-appearance/proc-enabling-localization-in-sidebar-items.adoc
new file mode 100644
index 0000000000..175bfcd6df
--- /dev/null
+++ b/modules/customizing-the-appearance/proc-enabling-localization-in-sidebar-items.adoc
@@ -0,0 +1,49 @@
+:_mod-docs-content-type: CONCEPT
+
+[id="proc-enabling-localization-in-sidebar-menu-items_{context}"]
+= Enabling sidebar menu items localization in {product-very-short}
+
+You can add translation key support for sidebar menu items, so that users can onboard in their preferred language. In {product-short}, all existing and newly created sidebar menu items support localization using the `titleKey` translation key.
+
+[NOTE]
+====
+If a translation key is present but the corresponding localized string is missing, the system defaults to the original text defined in the sidebar menu items configuration (`title`). If no translation key is defined at all, the original text is displayed.
+====
+
+.Prerequisites
+* You have enabled localization in your {product-very-short} application.
+
+.Procedure
+
+. For sidebar menu items in your configuration file, you must define both the original text and the new localization keys. For example, in the `dynamicPlugins.frontend.default.main-menu-items.menuItems.default.favorites` section of your `{my-app-config-file}` file, add the `titleKey`, as follows:
++
+.Example `{my-app-config-file}` fragment
+[source,yaml,subs="+quotes"]
+----
+dynamicPlugins:
+ frontend:
+ default.main-menu-items:
+ menuItems:
+ default.favorites:
+ title: Favorites
+ titleKey: menuItem.favorites
+ icon: favorite
+ priority: 100
+ enabled: true
+----
+. In your translation file, map the `titleKey` from the first step to the localized strings for each supported language.
++
+.Example `allTranslations.json` fragment
+[source,yaml,subs="+quotes"]
+----
+{
+ "rhdh": {
+ "en": {
+ "menuItem.favorites": "Favorites"
+ },
+ "fr": {
+ "menuItem.favorites": "Favoris"
+ }
+ }
+}
+----
\ No newline at end of file
diff --git a/modules/customizing-the-appearance/proc-overriding-translations.adoc b/modules/customizing-the-appearance/proc-overriding-translations.adoc
new file mode 100644
index 0000000000..e5264a0319
--- /dev/null
+++ b/modules/customizing-the-appearance/proc-overriding-translations.adoc
@@ -0,0 +1,120 @@
+:_mod-docs-content-type: CONCEPT
+
+[id="prov-overriding-translations_{context}"]
+= Overriding translations
+In {product-very-short} 1.8, you can override plugin translation strings without modifying the plugin source code.
+
+.Prerequisites
+* You have enabled localization in your {product-very-short} application.
+* For an Operator-installed {product-very-short} instance, you have installed the {openshift-cli}. For more information about installing `oc`, see {ocp-docs-link}/html/cli_tools/openshift-cli-oc#installing-openshift-cli[Installing the OpenShift CLI].
+
+.Procedure
+// This feature is not being included in 1.8
+// . In the top user menu, go to *Settings* > *General*.
+// . Click on the download link in the *Translations* panel to download the default English translation strings.
+. Create a JSON file containing the translation strings that you want to override, as shown in the following example:
++
+[id=i18n-enable]
+.`allTranslations.json` fragment with translation string overrides
+[source,json]
+----
+{
+ "plugin.global-floating-action-button": {
+ "en": {
+ "fab.quay.label": "QUAY EN JSON",
+ "fab.rbac.label": "RBAC EN JSON",
+ "fab.rbac.tooltip": "RBAC EN tooltip JSON"
+ },
+ "fr": {
+ "fab.quay.label": "QUAY French JSON",
+ "fab.quay.tooltip": "QUAY french tooltip JSON",
+ "fab.rbac.label": "RBAC French JSON",
+ "fab.rbac.tooltip": "RBAC french tooltip JSON"
+ }
+ },
+ "plugin.global-header": {
+ "en": {
+ "applicationLauncher.developerHub": "Developer Hub EN JSON"
+ },
+ "fr": {
+ "applicationLauncher.developerHub": "Developer Hub French JSON"
+ }
+ }
+}
+----
+. Log in to your cluster and create a config map for your translations override strings:
++
+[source,bash]
+----
+oc create configmap all-translations \
+ --from-file=//allTranslations.json
+----
+
+. Update your deployment configuration based on your installation method:
+
+.. For an Operator-installed {product-very-short} instance, update your `{product-custom-resource-type}` custom resource (CR). For more information about configuring a CR, see link::https://docs.redhat.com/en/documentation/red_hat_developer_hub/{product-version}/html/configuring_red_hat_developer_hub/provisioning-and-using-your-custom-configuration#using-the-operator-to-run-rhdh-with-your-custom-configuration[Using the Red Hat Developer Hub Operator to run Developer Hub with your custom configuration].
+... In the `spec.application.extraFiles` section, add the translations custom app configuration as shown in the following example:
++
+.{product-custom-resource-type} custom resource fragment
+[source,yaml,subs="+quotes"]
+----
+apiVersion: rhdh.redhat.com/v1alpha3
+kind: Backstage
+spec:
+ application:
+ extraFiles:
+ mountPath: /opt/app-root/src/translations
+ configMaps:
+ - name: all-translations
+----
+
+.. For a Helm-installed {product-very-short} instance, update your {product-short} `{backstage}` Helm chart to mount in the {product-short} filesystem your files from the `all-translations` config map:
+
+... In the {product-short} Helm chart, go to *Root Schema* → *Backstage chart schema* → *Backstage parameters* → *Backstage container additional volume mounts*.
+
+... Select *Add {backstage} container additional volume mounts* and add the following values:
+
+mountPath::
+`/opt/app-root/src/translations`
+name::
+`all-translations`
+
+... Add the translations to the *{backstage} container additional volumes* in the {product-short} Helm chart:
+
+name::
+`all-translations`
+configMap::
+defaultMode:::
+ `420`
+name:::
+`all-translations`
+
+. Update the `i18n` section to your custom {product-short} `{my-app-config-file}` configuration file to include the following translation override file:
++
+[id=i18n-override]
+.`{my-app-config-file}` fragment with localization `i18n` fields
+[source,yaml,subs="+quotes"]
+----
+i18n:
+ locales: # List of supported locales. Must include `en`, otherwise the translation framework will fail to load.
+ - en
+ - fr
+ defaultLocale: en # Optional. Defaults to `en` if not specified.
+ overrides: # List of JSON translation files applied in order (last file wins). Each file may override/add translations for one or more plugins/locales
+ - /opt/app-root/src/translations/all-translations.json
+----
+
+.Additional resources
+// * link:{customizing-book-link}#configuring-templates[Enabling floating button localization in {product-short}]
+// * link:{customizing-book-link}#configuring-templates[Enabling Quickstart localization in {product-short}]
+// * link:{customizing-book-link}#configuring-templates[Enabling sidebar menu items localization in {product-short}]
+
+{context}
+
+* xref:proc-enabling-localization-in-floating-action-button_configuring-a-floating-action-button[Enabling floating button localization in {product-short}]
+* xref:proc-enabling-localization-in-quickstarts_customizing-the-quickstarts[Enabling Quickstart localization in {product-short}]
+* xref:proc-enabling-localization-in-sidebar-menu-items_customizing-appearance[Enabling sidebar menu items localization in {product-short}]
+
+// * xref:proc-enabling-localization-in-floating-action-button_{context}[fggdsg]
+// * xref:proc-enabling-localization-in-quickstarts_{context}[fggdsg]
+// * xref:proc-enabling-localization-in-sidebar-menu-items_{context}[fggdsg]
\ No newline at end of file
diff --git a/modules/customizing-the-appearance/proc-select-rhdh-language.adoc b/modules/customizing-the-appearance/proc-select-rhdh-language.adoc
new file mode 100644
index 0000000000..3bb91ca3fc
--- /dev/null
+++ b/modules/customizing-the-appearance/proc-select-rhdh-language.adoc
@@ -0,0 +1,21 @@
+:_mod-docs-content-type: PROCEDURE
+
+[id="proc-selecting-rhdh-language_{context}"]
+= Selecting the language for your {product-short} instance
+
+You can choose to use one of the following supported languages:
+
+* English (default)
+* French
+
+.Prerequisites
+
+* You are logged in to the {product-short} web console.
+* You have xref:proc-enabling-localization-in-rhdh_{context}[enabled the localization framework] in your {product-very-short} instance.
+
+.Procedure
+
+. From the {product-short} web console, click the down arrow next to your profile name, then click *Settings*.
+. From the *Appearance* panel, click the language dropdown to select your language of choice.
++
+image::rhdh/customize-language-dropdown.png[]
\ No newline at end of file
diff --git a/modules/customizing-the-appearance/ref-best-practices-for-localization.adoc b/modules/customizing-the-appearance/ref-best-practices-for-localization.adoc
new file mode 100644
index 0000000000..a8e1b36646
--- /dev/null
+++ b/modules/customizing-the-appearance/ref-best-practices-for-localization.adoc
@@ -0,0 +1,34 @@
+:_mod-docs-content-type: REFERENCE
+
+[id="ref-best-practices-for-localization_{context}"]
+= Best practices for implementing localization support for custom plugins in {product-very-short}
+When you add localization support to your {product-very-short} plugins, the following best practices help ensure that you establish a robust, type-safe, and future-proof localization workflow, separating the immutable source text from the organized key structure, and ensuring reliable deployment across all targeted languages:
+
+Do not modify original English strings:: This preserves the source of truth for all translators, preventing unexpected changes that would invalidate existing translations and ensuring consistency across all versions.
+
+Use flat dot notation in translation files:: Flat dot notation, for example `page.title`, follows the standard `i18next` library convention, which optimizes runtime lookups and keeps the actual translation values concise and easy to manage for translation services.
+
+Use nested objects in the reference file for TypeScript support:: This allows the TypeScript compiler to enforce structural type checking on your translation keys, catching errors during development rather than at runtime.
+
+Test with mocks to ensure translations work correctly:: This isolates the translation logic, guaranteeing the correct keys are passed and rendered without relying on a full environment setup or external translation files during unit testing.
+
+Add all languages to your application configuration:: This ensures that the {product-very-short} application initializes and loads all necessary language resources at startup, making the locales immediately available for users to select in the UI.
+
+.Common patterns
+
+[cols="20%,35%,45%", frame="all", options="header"]
+|===
+| Use case | Pattern | Example
+
+| Simple text
+| `t('key')`
+| `t('page.title')`
+
+| With variables
+| `t('key', {param})`
+| `t('table.topN', {count: '5'})`
+
+| Dynamic keys
+| `t(config.titleKey as any)`
+| `t('cards.overview.title' as any)`
+|===
\ No newline at end of file
diff --git a/titles/customizing/master.adoc b/titles/customizing/master.adoc
index db68b5602e..2ebd714f11 100644
--- a/titles/customizing/master.adoc
+++ b/titles/customizing/master.adoc
@@ -45,3 +45,5 @@ include::assemblies/assembly-customizing-the-quick-access-card.adoc[leveloffset=
include::modules/customizing/proc-customizing-rhdh-metadata-card.adoc[leveloffset=+1]
+
+include::assemblies/assembly-localization-in-rhdh.adoc[leveloffset=+1]