ttag-org / ttag

:orange_book: simple approach for javascript localization
https://ttag.js.org/
MIT License
337 stars 40 forks source link

Is this required reload page to load new language state? #245

Open ghost opened 2 years ago

ghost commented 2 years ago

Same the title, Is it required reload page to load new language? I tried don't reload but the language will not show new. Please check

e-tsakhlo commented 1 year ago

There is no need in reloading page.

Make sure you used runtime translations: https://ttag.js.org/docs/create-react-app.html#runtime-translations

huykon commented 1 year ago

@e-tsakhlo I think you haven't check code yet. https://github.com/ttag-org/CRA-runtime-example/blob/master/app/src/App.js#L11

e-tsakhlo commented 1 year ago

@e-tsakhlo I think you haven't check code yet. https://github.com/ttag-org/CRA-runtime-example/blob/master/app/src/App.js#L11

This example truly uses page reload, but overoll there is no need in it.

You can import all translations (use async import if you wish performance boost), add all locales (addLocale) and then run useLocale(locale) whenever you need to change one.

Here is an example from my project using contexts:

LocaleContextProvider

import { FC, ReactNode, useEffect, useMemo, useState } from 'react';
import { addLocale, useLocale } from 'ttag';

import { Locale } from 'types';
import { DEFAULT_LOCALE, LOCALE_STORAGE_KEYS } from 'utils/constants';
import { LocaleContext } from 'components/app/LocaleContext';

import noLocaleTranslationsObject from 'i18n/no.po.json';

const getCurrentLocale = (): Locale => {
  const localStorageLocale = localStorage.getItem(LOCALE_STORAGE_KEYS.locale);

  if (localStorageLocale) return localStorageLocale;
  return DEFAULT_LOCALE;
};

const setCurrentLocale = (locale: Locale): void => {
  localStorage.setItem(
    LOCALE_STORAGE_KEYS.locale,
    locale
  );
};

const loadLocales = () => {
  addLocale('no', noLocaleTranslationsObject);
};

export interface LocaleContextProviderProps {
  children?: ReactNode;
}

export const LocaleContextProvider: FC<LocaleContextProviderProps> = ({
  children,
}) => {
  const [locale, setLocale] = useState<Locale>(() => getCurrentLocale());

  useEffect(() => {
    loadLocales();
  }, []);

  useEffect(() => {
    setCurrentLocale(locale);
    useLocale(locale);
  }, [locale]);

  const value = useMemo(
    () => ({
      locale,
      setLocale,
    }),
    [locale, setLocale]
  );

  return (
    <LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>
  );
};

LocaleContext

import { createContext } from 'react';

import { Locale } from 'types';

export type LocaleContextValue = {
  locale: Locale;
  setLocale: (locale: Locale) => void;
};

export const LocaleContext = createContext<LocaleContextValue>({
  locale: 'en',
  setLocale: () => {},
});

types.d.ts

export type Locale = 'en' | 'no';
AlexMost commented 8 months ago

Hey @e-tsakhlo, thanks for a good example! We are using page reload for our projects and it works ok for us. Looks like we should add some documentation about how it should work without page reload.

dasbego commented 4 months ago

I just think the https://ttag.js.org/docs/library-api.html#uselocale section can be better explained, but it's all there.