1

I am looking for a solution that will store state locally when refreshing the browser.

Our app has many translations with a language selector but currently upon a browser refresh this state is reset to the default.

Within the app, as authorised we save the chosen language to Firebase and onMount the chosen user language is shown, however, on our page without authentication, such as the login page and create page, this is not possible.

Currently, language is selected and stored as a state using Context as

import React, { useReducer } from 'react';

// Translations
import EN from '../../../constants/translations/en.json';
import TR from '../../../constants/translations/tr.json';
import ES from '../../../constants/translations/es.json';

interface InterfaceState {
  langCode?: string;
  translate?: any;
  dispatch: any;
}

const translations: any = {
  en: EN,
  tr: TR,
  es: ES
};

const getTranslate = (langCode: string) => (key: string | number) =>
  translations[langCode][key] || key;

const initialState = {
  langCode: 'en',
  translate: getTranslate('en'),
  dispatch: ''
};

export const I18nContext = React.createContext<InterfaceState>(initialState);

export const I18nContextProvider = ({ children }: any) => {
  const reducer = (state: any, action: { type: any; payload: any }) => {
    switch (action.type) {
      case 'setLanguage':
        return {
          langCode: action.payload,
          translate: getTranslate(action.payload)
        };
      default:
        return { ...initialState };
    }
  };

  const [state, dispatch] = useReducer(reducer, initialState);
  const value = { ...state, dispatch };

  return <I18nContext.Provider value={value as any}>{children}</I18nContext.Provider>;
};

The language selector uses useContext to set state and this works fine until the user refreshes the browser and the default langCode is applied.

One solution I've tried that works but has required much to keep maintained, especially as it requires me to add additional steps to Link components, is to history.push(pathname) and add a string query with the langCode in a string as

const onLanguageSelect = (data: any) => {
  dispatch({ type: 'setLanguage', payload: data.value });
  history.push(location.pathname + `?lang=` + data.value);
};

My question, how can I store the chosen state to session or local storage? And is this a viable and scalable solution, especially across multiple domains as app.example.com and example.com?

Darren
  • 1,591
  • 4
  • 24
  • 66

2 Answers2

1

You can use iframe to share what you have saved in localStorage/sessionStorage

Here is the link

Dominik Matis
  • 1,719
  • 5
  • 14
0

Good question. I think local or session is not the option. As it is not saved across different subdomains. I think an option might be to use a cookie. Cookies can be shared with multiple sub domains without a problem.

Just save it in a cookie when you language is selected and fetch in in the default value of your context if it is defined.

Only downside is that some people have set their cookies off by default. So you might need to add a prompt that suggests the user to turn on their cookies for you application.

Raoul
  • 201
  • 1
  • 9
  • Default cookies handeling https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies – Raoul Aug 23 '19 at 09:34
  • https://levelup.gitconnected.com/share-localstorage-sessionstorage-between-different-domains-eb07581e9384 with this, you can share `localStorage` across domains – Dominik Matis Aug 23 '19 at 09:34
  • Handy package if you want it a bit easier: https://www.npmjs.com/package/universal-cookie – Raoul Aug 23 '19 at 09:34
  • @DominikMatis First implementation step use a iFrame... That's a bit tacky IMO. – Raoul Aug 23 '19 at 09:35
  • Thank you Raoul. Great answer but it looks as if @DominikMatis has a solution the the cookies off problem. – Darren Aug 23 '19 at 09:37