Last active
August 25, 2021 07:02
-
-
Save Gerhut/07d4edfba836171710e15721df299293 to your computer and use it in GitHub Desktop.
Simple React I18n
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useCallback } from 'react' | |
import { createGlobalState } from 'react-use' | |
/** @typedef {{ [language: string] : { [text: string]: string} }} Translations */ | |
/** | |
* @param {Translations} translations | |
* @param {string} defaultLanguage | |
*/ | |
export function createI18n(translations, defaultLanguage) { | |
const useI18nLanguage = createGlobalState(defaultLanguage) | |
function useI18n() { | |
const [language] = useI18nLanguage() | |
return useCallback( | |
function i18n(text) { | |
return translations?.[language]?.[text] ?? text | |
}, | |
[language] | |
) | |
} | |
/** | |
* @param {object} props | |
* @param {string} props.children | |
*/ | |
function I18n({ children }) { | |
const t = useI18n() | |
return t(children) | |
} | |
return { useI18nLanguage, useI18n, I18n } | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createContext, createElement, useContext, useState, useCallback } from 'react' | |
/** @typedef {{ [language: string] : { [text: string]: string} }} Translations */ | |
const I18nContext = createContext({ | |
/** @type {string} */ | |
language: '', | |
/** @param {string} language */ | |
setLanguage(language) {}, | |
/** @type {Translations} */ | |
translations: {}, | |
/** @param {string} text */ | |
i18n(text) { | |
return text | |
} | |
}) | |
/** | |
* @param {object} props | |
* @param {Translations} props.translations | |
* @param {string} props.defaultLanguage | |
* @param {import('react').ReactNode} props.children | |
*/ | |
export function I18nProvier({ translations, defaultLanguage, children }) { | |
const [language, setLanguage] = useState(defaultLanguage) | |
const i18n = useCallback( | |
/** @param {string} text */ | |
function (text) { | |
return translations?.[language]?.[text] ?? text | |
}, | |
[translations, language] | |
) | |
return createElement(I18nContext.Provider, { value: { language, setLanguage, translations, i18n } }, children) | |
} | |
/** | |
* @param {object} props | |
* @param {string} props.children | |
*/ | |
export function I18n({ children }) { | |
const { i18n } = useContext(I18nContext) | |
return i18n(children) | |
} | |
export function useI18n() { | |
const { i18n } = useContext(I18nContext) | |
return i18n | |
} | |
/** | |
* @returns {[string, (language: string) => void]} | |
*/ | |
export function useI18nLanguage() { | |
const { language, setLanguage } = useContext(I18nContext) | |
return [language, setLanguage] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment