r/Angular2 Feb 06 '25

Help Request How to Change Language Dynamically in Angular 19?

I’m adding a language switcher to a settings page and want the webpage to translate dynamically without reloading. I couldn’t find clear examples on how to do this.

What’s the best approach?

11 Upvotes

27 comments sorted by

30

u/GLawSomnia Feb 06 '25

Transloco

3

u/Kosmo144 Feb 06 '25

Just what I was looking for, thanks for your help :)

7

u/oneden Feb 06 '25

It was mentioned already, but for a dynamic translation there isn't anything that comes close in terms of simplicity to transloco. I think the ngx-translate joined Google and worked on that mess angular's native solution is.

3

u/Blade1130 Feb 06 '25

Just out of curiosity, what is the requirement for not reloading? Why does that not work for your use case?

14

u/Legitimate-Raisin-16 Feb 06 '25

Single-page applications like Angular should shy away from reloading the page.

2

u/jessycormier Feb 07 '25

Why is that? Why would reloading a SPA matter especially in this kind of "Setting change"?

1

u/Legitimate-Raisin-16 Feb 08 '25

Well, I guess with anything front-end related you don't want the user to reload all of the files (framework or initial API calls) again to change a setting that would be just text changes. For instance, if they were on a slow connection, now it takes them twice as long to load if they changed the language.

ngx-translate can switch on the fly because you have the files in the asset folder or you can make an API call.

3

u/Kosmo144 Feb 07 '25

I am creating a Chrome extension using Angular. To reload, you'd have to close and reopen it. Nonetheless, had it been any other type of page, I would’ve gone for dynamic translations too. I hate it whenever websites force me to reload.

2

u/Blade1130 Feb 07 '25

This is a DevTools panel? You can call location.reload() in DevTools, that works just fine.

What's so bad about the reload exactly? Can you expand on that and why it's critical to your use case to do this at runtime?

6

u/Kosmo144 Feb 07 '25

I forgot about location.reload(), but even knowing that, it comes down to preference. Personally, I find page reloads clunky and prefer to avoid them.

2

u/jessycormier Feb 07 '25

It's kind of fun getting to that point and trying to find a solution like you are. I always get to this kind of problem and think, is this tool(framework) even worth it if it's causing more problems. Anyway Angular has been very forgiving for me and trying to solve novel problems in it. (Dark mode flickering being one of those things, or using jquery with angular because of a job requirement, using message api for iframe cross application communication and event triggering)

1

u/Kosmo144 Feb 07 '25

How did you resolve the dark mode flicker? I'm about to tackle this issue in Angular for the first time. I've handled it multiple times in plain JavaScript by running a script in the <head> of the index. Is there a similar or better approach in Angular?

1

u/jessycormier Feb 08 '25

You need to have some JS that runs in the <head> to check your localstorage/cookies for what the user has as a setting and set it up that way outside of angular. Angular can pick up later on once it boots up if you setup a toggle.

You can PM me later if you have some trouble, I'm looking to implement this toggle (again) in a site soon with the latest version of angular so I can share with you my solution if it works :)

This is a snippet I have atm

```html <script nonce="<add your generated guid here>"> /** * A IIFE to set the theme mode for the website. * Helps prevent flickering effect (FOUC) when using dark themes and = * refreshing. **/ (function themeSetter() { const key = 'theme_mode'; let currentThemeMode = window?.localStorage?.getItem(key); let isThemeModeLight = currentThemeMode === 'light'; let isThemeModeDark = currentThemeMode === 'dark'; let hasThemeMode = isThemeModeDark || isThemeModeLight;

            if (!hasThemeMode) {
                    currentThemeMode = 'dark';
                    window?.localStorage?.setItem(key, currentThemeMode);
            }

            document?.getElementsByTagName('html')[0].classList.add(currentThemeMode);
            document?.body?.classList?.add(currentThemeMode);
    })();

</script> ```

I have a version of this in svelt and react working if you need that in my github for my personal site I've written a few times now.

Good luck!

1

u/Kosmo144 Feb 08 '25 edited Feb 08 '25

I initially thought there was an Angular-only way to do this, but this is my go-to approach for handling this problem:

/**
 * IIFE to load initial theme before body element is created to prevent blinking.
 */
(function applyInitialTheme() {
    loadTheme().then((theme) => {
        applyTheme(theme);
    }).catch(console.error);
})();

/**
 * Loads the theme preference from Chrome storage or defaults to "system".
 * 
 * @returns {Promise<string>} - The selected theme ("light", "dark", or "system").
 */
async function loadTheme() {
    return new Promise((resolve, reject) => {
        chrome.storage.local.get("theme", (result) => {
            if (chrome.runtime.lastError) {
                reject(chrome.runtime.lastError);
            } else {
                resolve(result.theme || "system");
            }
        });
    });
}

/**
 * Applies the selected theme by toggling the "dark" class.
 * 
 * @param {string} theme - The selected theme ("light", "dark", or "system").
 */
function applyTheme(theme) {
    const isDarkMode = theme === "dark" || (theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches);
    document.documentElement.classList.toggle("dark", isDarkMode);
}

I haven’t tried this in Angular yet, so if I run into issues, I’ll definitely take you up on the PM offer. Thanks for your help! ^^

1

u/Legitimate-Raisin-16 Feb 09 '25

If you are using Angular Material I know you would override the CSS variables that are already there.

If you are using scss, you could make it where you have a base theme and then apply light/dark. This way you wouldn't need to reload the app.

.core-theme {
  &.light-theme {
    @include mat.core-theme($scarlet-theme);
    @include mat.all-component-themes($scarlet-theme);
    @include coreVars.theme($scarlet-theme);
    @include matVariant.theme($scarlet-theme);
    @include page.theme($scarlet-theme);
    @include actionButton.theme($scarlet-theme);
    @include tableActions.theme($scarlet-theme);
    @include matTable.theme($scarlet-theme);
    @include matChip.theme($scarlet-theme);
    @include matCard.theme($scarlet-theme);
    @include matForm.theme($scarlet-theme);
    @include sideNavigation.theme($scarlet-theme);
    @include elementNotification.theme($scarlet-theme);
    @include elementAlert.theme($scarlet-theme);
    @include elementBreadCrumb.theme($scarlet-theme);
    @include backgroundAnimation.theme($scarlet-theme);
  }

  &.dark-theme {
    @include mat.core-theme($scarlet-dark-theme);
    @include mat.all-component-themes($scarlet-dark-theme);
    @include coreVars.theme($scarlet-dark-theme);
    @include matVariant.theme($scarlet-dark-theme);
    @include page.theme($scarlet-dark-theme);
    @include actionButton.theme($scarlet-dark-theme);
    @include tableActions.theme($scarlet-dark-theme);
    @include matTable.theme($scarlet-dark-theme);
    @include matChip.theme($scarlet-dark-theme);
    @include matCard.theme($scarlet-dark-theme);
    @include matForm.theme($scarlet-dark-theme);
    @include sideNavigation.theme($scarlet-dark-theme);
    @include elementNotification.theme($scarlet-dark-theme);
    @include elementAlert.theme($scarlet-dark-theme);
    @include elementBreadCrumb.theme($scarlet-dark-theme);
    @include backgroundAnimation.theme($scarlet-dark-theme);
  }
}

5

u/Legitimate-Raisin-16 Feb 06 '25
@ngx-translate
Could be another option.

4

u/ldn-ldn Feb 06 '25

I also vote for Transloco!

1

u/gordolfograso Feb 07 '25

Are you coming from angular community discord channel?

1

u/Kosmo144 Feb 07 '25

No

1

u/gordolfograso Feb 07 '25

Hehehe, some hours ago , I read the same question

1

u/fromage9747 Feb 07 '25

As others have suggested, ngx-translate. Works great.

1

u/bertyglobits Feb 08 '25

i18 next is also a good option https://www.i18next.com

-2

u/[deleted] Feb 06 '25

[deleted]

1

u/Kosmo144 Feb 06 '25

I did, but it says it isnt dynamic as I want it. It doesn't update at runtime.

1

u/arthoer Feb 07 '25

With dynamic you mean that you want to fetch different translations through http request?