diff --git a/package.json b/package.json
index fd673ac5..5f29d3ab 100644
--- a/package.json
+++ b/package.json
@@ -8,7 +8,7 @@
"test": "react-scripts test --testMatch '**/__tests__/*' --passWithNoTests --watchAll=false",
"test:watch": "react-scripts test --testMatch '**/__tests__/*'",
"eject": "react-scripts eject",
- "lint": "eslint 'src/**/*.{ts,tsx}'",
+ "lint": "eslint \"src/**/*.{ts,tsx}\"",
"storybook": "start-storybook -p 9009 -s public",
"build-storybook": "build-storybook -s public"
},
diff --git a/src/config/procedures.tsx b/src/config/procedures.tsx
index 38e2a266..cbfb8f86 100644
--- a/src/config/procedures.tsx
+++ b/src/config/procedures.tsx
@@ -3,4 +3,5 @@ export const PROCEDURES = {
create_user: 'create_user',
get_cities: 'get_cities',
lst_c_country: 'lst_c_country',
+ param_lexical: 'param_lexical',
}
diff --git a/src/features/GlobalStores/index.tsx b/src/features/GlobalStores/index.tsx
index 5690cd0f..0ee68352 100644
--- a/src/features/GlobalStores/index.tsx
+++ b/src/features/GlobalStores/index.tsx
@@ -1,14 +1,16 @@
import React, { ReactNode } from 'react'
import { AuthStore } from 'features/AuthStore'
+import { LexicsStore } from 'features/LexicsStore'
type Props = {
children: ReactNode,
}
-// аутентификация, лексики и другие глобальные сторы
export const GlobalStores = ({ children }: Props) => (
- {children}
+
+ {children}
+
)
diff --git a/src/features/LexicsStore/helpers/__tests__/index.tsx b/src/features/LexicsStore/helpers/__tests__/index.tsx
new file mode 100644
index 00000000..2341a587
--- /dev/null
+++ b/src/features/LexicsStore/helpers/__tests__/index.tsx
@@ -0,0 +1,35 @@
+import { mapTranslationsToLocalKeys } from '..'
+
+const createTranslation = (id: string) => ({
+ id,
+ lang: '',
+ lexis_lang_id: '',
+ text: '',
+})
+
+it('returns empty object for empty args', () => {
+ const translations = {}
+ const config = {}
+ const expected = {}
+
+ const result = mapTranslationsToLocalKeys(translations, config)
+ expect(result).toEqual(expected)
+})
+
+it('empty translations when config is empty', () => {
+ const translations = { 1: createTranslation('1') }
+ const lexicsConfig = {}
+ const expected = {}
+
+ const result = mapTranslationsToLocalKeys(translations, lexicsConfig)
+ expect(result).toEqual(expected)
+})
+
+it('translations with lexic key specified in config', () => {
+ const translations = { 1: createTranslation('1'), 2: createTranslation('2') }
+ const lexicsConfig = { 2: 2, formInput: 1 }
+ const expected = { 2: translations[2], formInput: translations[1] }
+
+ const result = mapTranslationsToLocalKeys(translations, lexicsConfig)
+ expect(result).toEqual(expected)
+})
diff --git a/src/features/LexicsStore/helpers/index.tsx b/src/features/LexicsStore/helpers/index.tsx
new file mode 100644
index 00000000..76d939f2
--- /dev/null
+++ b/src/features/LexicsStore/helpers/index.tsx
@@ -0,0 +1,60 @@
+import isArray from 'lodash/isArray'
+import entries from 'lodash/entries'
+import reduce from 'lodash/reduce'
+import uniq from 'lodash/uniq'
+import map from 'lodash/map'
+
+import type { Translations } from 'requests'
+
+import type { LexicsId, LexicsConfig } from '../types'
+
+const LANG_KEY = 'lang'
+const defaultLang = 'en'
+
+export const writeLang = (lang: string) => {
+ localStorage.setItem(LANG_KEY, lang)
+}
+
+export const readLang = () => {
+ const lang = localStorage.getItem(LANG_KEY)
+ if (lang) return lang
+
+ writeLang(defaultLang)
+ return defaultLang
+}
+
+export const getSuffix = (lang: string) => (
+ lang === 'rus' ? 'rus' : 'eng'
+)
+
+export const getLexicIds = (ids: Array | LexicsConfig) => (
+ uniq(map(ids, (id) => Number(id)))
+)
+
+export const getObjectConfig = (ids: Array | LexicsConfig) => {
+ if (isArray(ids)) {
+ return reduce(
+ ids,
+ (acc, id) => ({ ...acc, [id]: id }),
+ {},
+ )
+ }
+ return ids
+}
+
+export const mapTranslationsToLocalKeys = (
+ translations: Translations,
+ lexicsConfig: LexicsConfig,
+) => {
+ const pairs = entries(lexicsConfig)
+ return reduce(
+ pairs,
+ (acc, [key, id]) => {
+ if (translations[id]) {
+ acc[key] = translations[id]
+ }
+ return acc
+ },
+ {} as Translations,
+ )
+}
diff --git a/src/features/LexicsStore/hooks/index.tsx b/src/features/LexicsStore/hooks/index.tsx
new file mode 100644
index 00000000..7cdbd463
--- /dev/null
+++ b/src/features/LexicsStore/hooks/index.tsx
@@ -0,0 +1,50 @@
+import { useEffect, useCallback } from 'react'
+
+import isEmpty from 'lodash/isEmpty'
+
+import { getLexics } from 'requests'
+
+import {
+ getLexicIds,
+ mapTranslationsToLocalKeys,
+} from 'features/LexicsStore/helpers'
+
+import { useLang } from './useLang'
+import { useLexicsConfig } from './useLexicsConfig'
+import { useTranslations } from './useTranslations'
+
+export const useLexics = () => {
+ const { changeLang, lang } = useLang()
+ const { addLexicsConfig, lexicsConfig } = useLexicsConfig()
+ const { addTranslations, translate } = useTranslations()
+
+ const fetchLexics = useCallback(
+ async () => {
+ const lexicIds = getLexicIds(lexicsConfig)
+ if (isEmpty(lexicIds)) return
+
+ const newTranslations = await getLexics(lang, lexicIds)
+ addTranslations(mapTranslationsToLocalKeys(newTranslations, lexicsConfig))
+ },
+ [
+ lang,
+ lexicsConfig,
+ addTranslations,
+ ],
+ )
+
+ useEffect(() => {
+ fetchLexics()
+ }, [
+ lang,
+ lexicsConfig,
+ fetchLexics,
+ ])
+
+ return {
+ addLexicsConfig,
+ changeLang,
+ lang,
+ translate,
+ }
+}
diff --git a/src/features/LexicsStore/hooks/useLang.tsx b/src/features/LexicsStore/hooks/useLang.tsx
new file mode 100644
index 00000000..e9099ec6
--- /dev/null
+++ b/src/features/LexicsStore/hooks/useLang.tsx
@@ -0,0 +1,18 @@
+import { useState, useCallback } from 'react'
+
+import { readLang, writeLang } from 'features/LexicsStore/helpers'
+
+export const useLang = () => {
+ const [lang, setLang] = useState(readLang)
+
+ const changeLang = useCallback(
+ (newLang: string) => {
+ if (newLang === lang) return
+ writeLang(newLang)
+ setLang(newLang)
+ },
+ [lang],
+ )
+
+ return { changeLang, lang }
+}
diff --git a/src/features/LexicsStore/hooks/useLexicsConfig.tsx b/src/features/LexicsStore/hooks/useLexicsConfig.tsx
new file mode 100644
index 00000000..99a9640d
--- /dev/null
+++ b/src/features/LexicsStore/hooks/useLexicsConfig.tsx
@@ -0,0 +1,19 @@
+import { useState, useCallback } from 'react'
+
+import { getObjectConfig } from 'features/LexicsStore/helpers'
+
+import type { LexicsConfig, LexicsId } from '../types'
+
+export const useLexicsConfig = () => {
+ const [lexicsConfig, setLexicsConfig] = useState({})
+
+ const addLexicsConfig = useCallback(
+ (ids: Array | LexicsConfig) => {
+ const config = getObjectConfig(ids)
+ setLexicsConfig((state) => ({ ...state, ...config }))
+ },
+ [],
+ )
+
+ return { addLexicsConfig, lexicsConfig }
+}
diff --git a/src/features/LexicsStore/hooks/useTranslations.tsx b/src/features/LexicsStore/hooks/useTranslations.tsx
new file mode 100644
index 00000000..f81d6ff2
--- /dev/null
+++ b/src/features/LexicsStore/hooks/useTranslations.tsx
@@ -0,0 +1,26 @@
+import { useState, useCallback } from 'react'
+
+import type { Translations } from 'requests'
+
+import type { LexicsId } from '../types'
+
+export const useTranslations = () => {
+ const [translations, setTranslations] = useState({})
+
+ const translate = useCallback(
+ (lexicId: LexicsId) => {
+ const translation = translations[lexicId]
+ return translation?.text || ''
+ },
+ [translations],
+ )
+
+ const addTranslations = useCallback(
+ (newTranslations: Translations) => {
+ setTranslations((state) => ({ ...state, ...newTranslations }))
+ },
+ [],
+ )
+
+ return { addTranslations, translate }
+}
diff --git a/src/features/LexicsStore/index.tsx b/src/features/LexicsStore/index.tsx
new file mode 100644
index 00000000..23325084
--- /dev/null
+++ b/src/features/LexicsStore/index.tsx
@@ -0,0 +1,19 @@
+import type { ReactNode } from 'react'
+import React, {
+ createContext,
+ useContext,
+} from 'react'
+
+import { useLexics } from './hooks'
+
+type LexicsStore = ReturnType
+type Props = { children: ReactNode }
+
+const LexicsContext = createContext({} as LexicsStore)
+
+export const LexicsStore = ({ children }: Props) => {
+ const lexics = useLexics()
+ return {children}
+}
+
+export const useLexicsStore = () => useContext(LexicsContext)
diff --git a/src/features/LexicsStore/types.tsx b/src/features/LexicsStore/types.tsx
new file mode 100644
index 00000000..aaa77b05
--- /dev/null
+++ b/src/features/LexicsStore/types.tsx
@@ -0,0 +1,3 @@
+export type LexicsId = string
+
+export type LexicsConfig = {[lexicsId: string]: number}
diff --git a/src/features/T9n/index.tsx b/src/features/T9n/index.tsx
new file mode 100644
index 00000000..de76fe61
--- /dev/null
+++ b/src/features/T9n/index.tsx
@@ -0,0 +1,16 @@
+import React from 'react'
+import styled from 'styled-components/macro'
+
+import { useLexicsStore } from 'features/LexicsStore'
+
+const Text = styled.span``
+
+type Props = {
+ className?: string,
+ t: string | number,
+}
+
+export const T9n = ({ className, t }: Props) => {
+ const { translate } = useLexicsStore()
+ return {translate(String(t))}
+}
diff --git a/src/requests/getLexics.tsx b/src/requests/getLexics.tsx
new file mode 100644
index 00000000..3f353ff1
--- /dev/null
+++ b/src/requests/getLexics.tsx
@@ -0,0 +1,30 @@
+import { DATA_URL, PROCEDURES } from 'config'
+import { callApi, getResponseData } from 'helpers'
+
+const proc = PROCEDURES.param_lexical
+
+export type Translation = {
+ id: string,
+ lang: string,
+ lexis_lang_id: string,
+ text: string,
+}
+
+export type Translations = {[id: string]: Translation}
+
+export const getLexics = (lang: string, lexicIds: Array): Promise => {
+ const config = {
+ body: {
+ params: {
+ _p_lang: lang,
+ _p_param_arr: lexicIds,
+ },
+ proc,
+ },
+ }
+
+ return callApi({
+ config,
+ url: DATA_URL,
+ }).then(getResponseData(proc))
+}
diff --git a/src/requests/index.tsx b/src/requests/index.tsx
index 46debb05..54087053 100644
--- a/src/requests/index.tsx
+++ b/src/requests/index.tsx
@@ -2,3 +2,4 @@ export * from './register'
export * from './login'
export * from './getCountries'
export * from './getCountryCities'
+export * from './getLexics'