Permalink
Cannot retrieve contributors at this time
195 lines (173 sloc)
6.09 KB
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
kernel-v2/src/modules/localization/useTranslation.js /
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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 { useContext } from "react"; | |
| import { useLocation } from "@reach/router"; | |
| import { TranslationContext } from "./context"; | |
| import { DEFAULT_LOCALE } from "./index"; | |
| //NOTE(Rejon): This is a react hook I pulled inspiration from: https://w11i.me/how-to-build-multilingual-website-in-next-js | |
| // I've expanded to add some features like plurals, secondary level spaces (dubbed langspace), variables, and secondary locales. | |
| //NOTE(Rejon): For the sake of security I've chosen NOT to support HTML parsing. | |
| // It's possible to pass in an initialLangSpace when initializing the hook in your component. | |
| // without ILS: useTranslation() -> t('error_code', 'errors') | |
| // with ILS: useTranslation('errors') -> t('error_code') | |
| export default function useTranslation(initialLangSpace) { | |
| const { allLocales, localeStrings } = useContext(TranslationContext); | |
| //NOTE(Rejon): We trust the path for locale. If it doesn't exist fallback to DEFAULT LOCALE | |
| const { pathname } = useLocation(); | |
| const localeFromPath = pathname.replace(/\/+$/, "").split("/")[1]; | |
| const locale = | |
| localeFromPath && allLocales.includes(localeFromPath) | |
| ? localeFromPath | |
| : DEFAULT_LOCALE; | |
| //key[String] - Key name of the text from the locale you want. Best practice is write it like you would english, replace all spaces with '_' | |
| //lang_space[String] - Language space keyname to access for your keys. ie. {'lang_space': {'key': 'Localized Text'}} | |
| //variables[Object] - Object of variables to insert into the string. Replaces {{value}} with variable value. ie. {value: 123} -> '123' | |
| //otherLocale[String] - In the case you want to display a string in another locale. | |
| function t(key, lang_space, variables, otherLocale) { | |
| let usingInitialLangSpace = false; | |
| //If an initialLangSpace is passed in when useTranslation is used then use it, but only if the call for this function doesn't include a lang_space. | |
| if ( | |
| lang_space !== null && | |
| lang_space !== undefined && | |
| initialLangSpace !== null && | |
| initialLangSpace !== undefined | |
| ) { | |
| lang_space = initialLangSpace; | |
| usingInitialLangSpace = true; | |
| } | |
| if (lang_space && !usingInitialLangSpace) { | |
| //Check if langspace is provided. For example: en:{home:{Hello user: "string"}} | |
| if ( | |
| !localeStrings[locale][lang_space] || | |
| !localeStrings[locale][lang_space][key] | |
| ) { | |
| console.warn( | |
| `Translation of '${key}' of language space '${lang_space}' for locale '${locale}' not found.` | |
| ); | |
| return key; | |
| } | |
| } else if (usingInitialLangSpace) { | |
| //NOTE(Rejon): I do this because if we're using an intialLangSpace and it fails then it should default to No lang_space. | |
| if ( | |
| !localeStrings[locale][lang_space] || | |
| !localeStrings[locale][lang_space][key] | |
| ) { | |
| lang_space = null; | |
| } | |
| } else if (!localeStrings[locale][key] && !otherLocale) { | |
| //Check for common base key in locale. For example: en:{settings:"string"} | |
| if (typeof window !== "undefined") { | |
| console.warn( | |
| `Translation of '${key}' for locale '${locale}' not found.` | |
| ); | |
| } | |
| return key; | |
| } else if (otherLocale && !localeStrings[otherLocale][key]) { | |
| //Check for common base key in locale. For example: en:{settings:"string"} | |
| if (typeof window !== "undefined") { | |
| console.warn( | |
| `Translation of '${key}' for other locale '${otherLocale}' not found.` | |
| ); | |
| } | |
| return key; | |
| } | |
| var pluralString = ""; | |
| //Plurals check | |
| if ( | |
| variables !== null && | |
| variables !== undefined && | |
| variables.count !== null && | |
| variables.count !== undefined | |
| ) { | |
| //If strict is true, then "Mutli-Plurals" take priority. | |
| if (variables.strict === true) { | |
| switch (variables.count) { | |
| case 0: { | |
| //Zero | |
| pluralString = "_0"; | |
| break; | |
| } | |
| case 1: { | |
| //Singular | |
| pluralString = "_1"; | |
| break; | |
| } | |
| case 2: { | |
| //Two | |
| pluralString = "_2"; | |
| break; | |
| } | |
| case 3: { | |
| // Few | |
| pluralString = "_3"; | |
| break; | |
| } | |
| case 4: { | |
| //Many | |
| pluralString = "_4"; | |
| break; | |
| } | |
| default: { | |
| //Other | |
| pluralString = "_5"; | |
| break; | |
| } | |
| } | |
| } else { | |
| //Not strict, use general "_plural"/"_none" | |
| if (variables.count === 0) { | |
| pluralString = "_none"; | |
| } else if (variables.count !== 1) { | |
| pluralString = "_plural"; | |
| } | |
| } | |
| } | |
| //Add plural key if necessary. | |
| key += pluralString; | |
| let finalString = key ? localeStrings[locale][key] || "" : ""; | |
| if ( | |
| lang_space !== null && | |
| lang_space !== undefined && | |
| localeStrings[locale][lang_space] !== null && | |
| localeStrings[locale][lang_space] !== undefined | |
| ) { | |
| finalString = key | |
| ? localeStrings[locale][lang_space][key] || | |
| localeStrings[locale][key] || | |
| "" | |
| : ""; | |
| } | |
| //Querying otherLocale and otherLocale exists in app locales. | |
| if ( | |
| otherLocale && | |
| localeStrings[otherLocale] !== null && | |
| localeStrings[otherLocale] !== undefined | |
| ) { | |
| if ( | |
| localeStrings[otherLocale][lang_space] !== null && | |
| localeStrings[otherLocale][lang_space] !== undefined | |
| ) { | |
| finalString = key | |
| ? localeStrings[otherLocale][lang_space][key] || "" | |
| : ""; | |
| } else { | |
| finalString = key ? localeStrings[otherLocale][key] || "" : ""; | |
| } | |
| } | |
| //Variable Replacement | |
| if (variables && typeof variables === "object") { | |
| Object.keys(variables).forEach((key) => { | |
| let variableToReplace = `{{${key}}}`; | |
| if (finalString.indexOf(variableToReplace) !== -1) { | |
| //Replace other variables. | |
| finalString = finalString.replace(variableToReplace, variables[key]); | |
| } | |
| }); | |
| } | |
| return finalString; | |
| } | |
| return { | |
| t, | |
| locale, | |
| allLocales, | |
| DEFAULT_LOCALE, | |
| }; | |
| } |