refactor: move from next-international to next-intl (#1368)

* refactor: move from next-international to next-intl

* refactor: restructure translation package,

* chore: change i18n-allay framework to next-intl

* fix: add missing bold html tag to translation

* fix: format issue

* fix: address deepsource issues

* fix: remove international-types dependency

* fix: lint and typecheck issues

* fix: typecheck issue

* fix: typecheck issue

* fix: issue with translations
This commit is contained in:
Meier Lukas
2024-10-26 22:46:14 +02:00
committed by GitHub
parent db198c6dab
commit 4502569223
33 changed files with 331 additions and 160 deletions

View File

@@ -1,12 +0,0 @@
import type { PropsWithChildren } from "react";
import { defaultLocale } from "@homarr/translation";
import { I18nProviderClient } from "@homarr/translation/client";
export const NextInternationalProvider = ({ children, locale }: PropsWithChildren<{ locale: string }>) => {
return (
<I18nProviderClient locale={locale} fallback={defaultLocale}>
{children}
</I18nProviderClient>
);
};

View File

@@ -7,18 +7,20 @@ import "@homarr/ui/styles.css";
import "~/styles/scroll-area.scss";
import { cookies } from "next/headers";
import { notFound } from "next/navigation";
import { NextIntlClientProvider } from "next-intl";
import { env } from "@homarr/auth/env.mjs";
import { auth } from "@homarr/auth/next";
import { ModalProvider } from "@homarr/modals";
import { Notifications } from "@homarr/notifications";
import { getScopedI18n } from "@homarr/translation/server";
import { isLocaleSupported } from "@homarr/translation";
import { getI18nMessages, getScopedI18n } from "@homarr/translation/server";
import { Analytics } from "~/components/layout/analytics";
import { SearchEngineOptimization } from "~/components/layout/search-engine-optimization";
import { JotaiProvider } from "./_client-providers/jotai";
import { CustomMantineProvider } from "./_client-providers/mantine";
import { NextInternationalProvider } from "./_client-providers/next-international";
import { AuthProvider } from "./_client-providers/session";
import { TRPCReactProvider } from "./_client-providers/trpc";
import { composeWrappers } from "./compose";
@@ -59,10 +61,15 @@ export const viewport: Viewport = {
};
export default async function Layout(props: { children: React.ReactNode; params: { locale: string } }) {
if (!isLocaleSupported(props.params.locale)) {
notFound();
}
const session = await auth();
const colorScheme = getColorScheme();
const tCommon = await getScopedI18n("common");
const direction = tCommon("direction");
const i18nMessages = await getI18nMessages();
const StackedProvider = composeWrappers([
(innerProps) => {
@@ -70,7 +77,7 @@ export default async function Layout(props: { children: React.ReactNode; params:
},
(innerProps) => <JotaiProvider {...innerProps} />,
(innerProps) => <TRPCReactProvider {...innerProps} />,
(innerProps) => <NextInternationalProvider {...innerProps} locale={props.params.locale} />,
(innerProps) => <NextIntlClientProvider {...innerProps} messages={i18nMessages} />,
(innerProps) => <CustomMantineProvider {...innerProps} />,
(innerProps) => <ModalProvider {...innerProps} />,
]);
@@ -78,7 +85,7 @@ export default async function Layout(props: { children: React.ReactNode; params:
return (
// Instead of ColorSchemScript we use data-mantine-color-scheme to prevent flickering
<html
lang="en"
lang={props.params.locale}
dir={direction}
data-mantine-color-scheme={colorScheme}
style={{

View File

@@ -60,7 +60,10 @@ export const UserCreateStepperComponent = () => {
})
.refine((data) => data.password === data.confirmPassword, {
path: ["confirmPassword"],
params: createCustomErrorParams("passwordsDoNotMatch"),
params: createCustomErrorParams({
key: "passwordsDoNotMatch",
params: {},
}),
}),
{
initialValues: {

View File

@@ -10,8 +10,8 @@ export const ReservedGroupAlert = async () => {
return (
<Alert variant="light" color="yellow" icon={<IconExclamationCircle size="1rem" stroke={1.5} />}>
{t("group.reservedNotice.message", {
checkoutDocs: (
{t.rich("group.reservedNotice.message", {
checkoutDocs: () => (
<Anchor
size="sm"
component={Link}

View File

@@ -1,11 +1,11 @@
"use client";
import React from "react";
import { Combobox, Group, InputBase, Text, useCombobox } from "@mantine/core";
import { Combobox, Group, InputBase, Loader, Text, useCombobox } from "@mantine/core";
import { IconCheck } from "@tabler/icons-react";
import type { SupportedLanguage } from "@homarr/translation";
import { localeAttributes, supportedLanguages } from "@homarr/translation";
import { localeConfigurations, supportedLanguages } from "@homarr/translation";
import { useChangeLocale, useCurrentLocale } from "@homarr/translation/client";
import classes from "./language-combobox.module.css";
@@ -15,7 +15,7 @@ export const LanguageCombobox = () => {
onDropdownClose: () => combobox.resetSelectedOption(),
});
const currentLocale = useCurrentLocale();
const changeLocale = useChangeLocale();
const { changeLocale, isPending } = useChangeLocale();
const handleOnOptionSubmit = React.useCallback(
(value: string) => {
@@ -39,6 +39,7 @@ export const LanguageCombobox = () => {
component="button"
type="button"
pointer
leftSection={isPending ? <Loader size={16} /> : null}
rightSection={<Combobox.Chevron />}
rightSectionPointerEvents="none"
onClick={handleOnClick}
@@ -72,11 +73,11 @@ const OptionItem = ({
return (
<Group wrap="nowrap" justify="space-between">
<Group wrap="nowrap">
<span className={`fi fi-${localeAttributes[localeKey].flagIcon} ${classes.flagIcon}`}></span>
<span className={`fi fi-${localeConfigurations[localeKey].flagIcon} ${classes.flagIcon}`}></span>
<Group wrap="nowrap" gap="xs">
<Text>{localeAttributes[localeKey].name}</Text>
<Text>{localeConfigurations[localeKey].name}</Text>
<Text size="xs" c="dimmed" inherit>
({localeAttributes[localeKey].translatedName})
({localeConfigurations[localeKey].translatedName})
</Text>
</Group>
</Group>