0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-03-31 22:51:25 -05:00

refactor: replace LanguageKey with LanguageTag (#2080)

This commit is contained in:
Xiao Yijun 2022-10-10 09:43:13 +08:00 committed by GitHub
parent 8417fc851a
commit 691bdb3ac9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 67 additions and 58 deletions

View file

@ -1,10 +1,10 @@
import type { LanguageKey } from '@logto/core-kit';
import { LanguageTag } from '@logto/language-kit';
import resources from '@logto/phrases';
import i18next from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';
const initI18n = async (language?: LanguageKey) =>
const initI18n = async (language?: LanguageTag) =>
i18next
.use(initReactI18next)
.use(LanguageDetector)

View file

@ -1,13 +1,10 @@
// https://react.i18next.com/latest/typescript#create-a-declaration-file
import { Translation, Errors } from '@logto/phrases';
import { LocalPhrase } from '@logto/phrases';
declare module 'react-i18next' {
interface CustomTypeOptions {
allowObjectInHTMLChildren: true;
resources: {
translation: Translation;
errors: Errors;
};
resources: LocalPhrase;
}
}

View file

@ -1,5 +1,7 @@
import { getDefaultLanguage } from '@logto/core-kit';
import { languageOptions } from '@logto/phrases';
import {
builtInLanguageOptions as consoleBuiltInLanguageOptions,
getDefaultLanguageTag,
} from '@logto/phrases';
import { AppearanceMode } from '@logto/schemas';
import classNames from 'classnames';
import { Controller, useForm } from 'react-hook-form';
@ -25,7 +27,7 @@ const Settings = () => {
i18n: { language },
} = useTranslation(undefined, { keyPrefix: 'admin_console' });
const defaultLanguage = getDefaultLanguage(language);
const defaultLanguage = getDefaultLanguageTag(language);
const { data, error, update, isLoading, isLoaded } = useUserPreferences();
const {
@ -63,7 +65,7 @@ const Settings = () => {
render={({ field: { value, onChange } }) => (
<Select
value={value ?? defaultLanguage}
options={languageOptions}
options={consoleBuiltInLanguageOptions}
onChange={onChange}
/>
)}

View file

@ -17,10 +17,11 @@
"stylelint": "stylelint \"src/**/*.scss\""
},
"devDependencies": {
"@logto/core-kit": "^1.0.0-beta.13",
"@logto/language-kit": "1.0.0-beta.16",
"@logto/phrases": "^1.0.0-beta.9",
"@logto/react": "1.0.0-beta.8",
"@logto/schemas": "^1.0.0-beta.9",
"@logto/core-kit": "^1.0.0-beta.13",
"@parcel/core": "2.7.0",
"@parcel/transformer-sass": "2.7.0",
"@silverhand/eslint-config": "1.0.0",

View file

@ -1,10 +1,10 @@
import type { LanguageKey } from '@logto/core-kit';
import type { LanguageTag } from '@logto/language-kit';
import resources from '@logto/phrases';
import i18next from 'i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';
const initI18n = async (language?: LanguageKey) =>
const initI18n = async (language?: LanguageTag) =>
i18next
.use(initReactI18next)
.use(LanguageDetector)

View file

@ -1,15 +1,12 @@
// https://react.i18next.com/latest/typescript#create-a-declaration-file
import { Translation, Errors } from '@logto/phrases';
import { LocalPhrase } from '@logto/phrases';
// eslint-disable-next-line unused-imports/no-unused-imports
import { CustomTypeOptions } from 'react-i18next';
declare module 'react-i18next' {
interface CustomTypeOptions {
allowObjectInHTMLChildren: true;
resources: {
translation: Translation;
errors: Errors;
};
resources: LocalPhrase;
}
}

View file

@ -29,9 +29,10 @@
"url": "https://github.com/logto-io/logto/issues"
},
"dependencies": {
"@logto/core-kit": "^1.0.0-beta.13",
"@logto/core-kit": "1.0.0-beta.16",
"@logto/language-kit": "1.0.0-beta.15",
"@silverhand/essentials": "^1.2.1"
"@silverhand/essentials": "^1.2.1",
"zod": "^3.18.0"
},
"devDependencies": {
"@silverhand/eslint-config": "1.0.0",

View file

@ -1,4 +1,7 @@
import { fallback } from '@logto/core-kit';
import { languages, LanguageTag } from '@logto/language-kit';
import { NormalizeKeyPaths } from '@silverhand/essentials';
import { z } from 'zod';
import en from './locales/en';
import fr from './locales/fr';
@ -6,16 +9,37 @@ import koKR from './locales/ko-kr';
import ptPT from './locales/pt-pt';
import trTR from './locales/tr-tr';
import zhCN from './locales/zh-cn';
import { Resource } from './types';
import { LocalPhrase } from './types';
export type { LocalPhrase } from './types';
export type I18nKey = NormalizeKeyPaths<typeof en.translation>;
export const builtInLanguages = ['en', 'fr', 'pt-PT', 'zh-CN', 'ko-KR', 'tr-TR'] as const;
export const builtInLanguageOptions = builtInLanguages.map((languageTag) => ({
value: languageTag,
title: languages[languageTag],
}));
export const builtInLanguageTagGuard = z.enum(builtInLanguages);
export type BuiltInLanguageTag = z.infer<typeof builtInLanguageTagGuard>;
export { languageOptions } from './types';
export type Translation = typeof en.translation;
export type Errors = typeof en.errors;
export type LogtoErrorCode = NormalizeKeyPaths<Errors>;
export type LogtoErrorI18nKey = `errors:${LogtoErrorCode}`;
export type I18nKey = NormalizeKeyPaths<Translation>;
export type AdminConsoleKey = NormalizeKeyPaths<typeof en.translation.admin_console>;
export const getDefaultLanguageTag = (languages: string): LanguageTag =>
builtInLanguageTagGuard.or(fallback<LanguageTag>('en')).parse(languages);
export const isBuiltInLanguageTag = (language: string): language is BuiltInLanguageTag =>
builtInLanguageTagGuard.safeParse(language).success;
export type Resource = Record<BuiltInLanguageTag, LocalPhrase>;
const resource: Resource = {
en,
fr,

View file

@ -1,8 +1,8 @@
import en from '../en';
import { LocalPhrase } from '../../types';
import errors from './errors';
import translation from './translation';
const fr: typeof en = Object.freeze({
const fr: LocalPhrase = Object.freeze({
translation,
errors,
});

View file

@ -1,8 +1,8 @@
import en from '../en';
import { LocalPhrase } from '../../types';
import errors from './errors';
import translation from './translation';
const koKR: typeof en = Object.freeze({
const koKR: LocalPhrase = Object.freeze({
translation,
errors,
});

View file

@ -1,8 +1,8 @@
import en from '../en';
import { LocalPhrase } from '../../types';
import errors from './errors';
import translation from './translation';
const ptPT: typeof en = Object.freeze({
const ptPT: LocalPhrase = Object.freeze({
translation,
errors,
});

View file

@ -1,8 +1,8 @@
import en from '../en';
import { LocalPhrase } from '../../types';
import errors from './errors';
import translation from './translation';
const trTR: typeof en = Object.freeze({
const trTR: LocalPhrase = Object.freeze({
translation,
errors,
});

View file

@ -1,8 +1,8 @@
import en from '../en';
import { LocalPhrase } from '../../types';
import errors from './errors';
import translation from './translation';
const zhCN: typeof en = Object.freeze({
const zhCN: LocalPhrase = Object.freeze({
translation,
errors,
});

View file

@ -1,21 +1,3 @@
import { LanguageKey, languageKeyGuard } from '@logto/core-kit';
import en from './locales/en';
/* Copied from i18next/index.d.ts */
export type Resource = Record<LanguageKey, ResourceLanguage>;
export type ResourceLanguage = Record<string, ResourceKey>;
export type ResourceKey = string | Record<string, unknown>;
const languageCodeAndDisplayNameMappings: Record<LanguageKey, string> = {
en: 'English',
fr: 'Français',
'pt-PT': 'Português',
'zh-CN': '简体中文',
'tr-TR': 'Türkçe',
'ko-KR': '한국어',
};
export const languageOptions: Array<{ value: LanguageKey; title: string }> = Object.entries(
languageCodeAndDisplayNameMappings
).map(([key, value]) => ({ value: languageKeyGuard.parse(key), title: value }));
export type LocalPhrase = typeof en;

11
pnpm-lock.yaml generated
View file

@ -318,6 +318,7 @@ importers:
packages/demo-app:
specifiers:
'@logto/core-kit': ^1.0.0-beta.13
'@logto/language-kit': 1.0.0-beta.16
'@logto/phrases': ^1.0.0-beta.9
'@logto/react': 1.0.0-beta.8
'@logto/schemas': ^1.0.0-beta.9
@ -344,6 +345,7 @@ importers:
typescript: ^4.7.4
devDependencies:
'@logto/core-kit': 1.0.0-beta.13
'@logto/language-kit': 1.0.0-beta.16
'@logto/phrases': link:../phrases
'@logto/react': 1.0.0-beta.8_react@18.2.0
'@logto/schemas': link:../schemas
@ -423,7 +425,7 @@ importers:
packages/phrases:
specifiers:
'@logto/core-kit': ^1.0.0-beta.13
'@logto/core-kit': 1.0.0-beta.16
'@logto/language-kit': 1.0.0-beta.15
'@silverhand/eslint-config': 1.0.0
'@silverhand/essentials': ^1.2.1
@ -432,10 +434,12 @@ importers:
lint-staged: ^13.0.0
prettier: ^2.7.1
typescript: ^4.7.4
zod: ^3.18.0
dependencies:
'@logto/core-kit': 1.0.0-beta.13
'@logto/core-kit': 1.0.0-beta.16
'@logto/language-kit': 1.0.0-beta.15
'@silverhand/essentials': 1.2.1
zod: 3.18.0
devDependencies:
'@silverhand/eslint-config': 1.0.0_swk2g7ygmfleszo5c33j4vooni
'@silverhand/ts-config': 1.0.0_typescript@4.7.4
@ -2465,7 +2469,7 @@ packages:
dependencies:
'@logto/language-kit': 1.0.0-beta.16
color: 4.2.3
nanoid: 3.1.30
nanoid: 3.3.4
zod: 3.18.0
/@logto/js/1.0.0-beta.8:
@ -11288,6 +11292,7 @@ packages:
resolution: {integrity: sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ==}
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
hasBin: true
dev: false
/nanoid/3.3.1:
resolution: {integrity: sha512-n6Vs/3KGyxPQd6uO0eH4Bv0ojGSUvuLlIHtC3Y0kEO23YRge8H9x1GCzLn28YX0H66pMkxuaeESFq4tKISKwdw==}