Add language support #3

Merged
xelopsys merged 8 commits from add-language-support into main 2026-04-10 12:37:10 +00:00
xelopsys commented 2026-04-02 11:22:21 +00:00 (Migrated from github.com)
No description provided.
orzklv (Migrated from github.com) reviewed 2026-04-02 11:22:21 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2026-04-02 11:31:00 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull request overview

Adds internationalization (i18n) support to the Next.js App Router setup using next-intl, introducing locale-based routing and translated UI/content across the marketing site.

Changes:

  • Introduces locale segment routing (/[locale]) and next-intl configuration (routing, request config, navigation helpers).
  • Replaces hardcoded Uzbek UI strings with translation keys backed by messages/{uz,ru,en}.json.
  • Adds localized privacy policy MDX content for RU/EN and updates config/build setup (Next config, deps, TypeScript).

Reviewed changes

Copilot reviewed 29 out of 36 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
tsconfig.json Updates JSX mode and expands includes for Next-generated types.
src/proxy.ts Adds next-intl middleware wrapper (intended for locale routing).
src/i18n/routing.ts Defines supported locales and default locale.
src/i18n/request.ts Defines per-request locale + message loading for next-intl.
src/i18n/navigation.ts Adds locale-aware navigation helpers/wrappers.
src/content/uz.md Updates Uzbek effective date format.
src/content/ru.md Adds Russian privacy policy content.
src/content/en.md Adds English privacy policy content.
src/components/SecondaryFeatures.tsx Switches secondary features section to translations.
src/components/PrimaryFeatures.tsx Switches primary features + chat UI strings to translations; other UI tweaks.
src/components/NavLinks.tsx Makes header/footer nav links locale-aware and translated.
src/components/Layout.tsx Minor layout whitespace change.
src/components/Hero.tsx Moves hero copy to translations and adjusts sizing classes.
src/components/Header.tsx Adds language picker + translated nav labels; switches to locale-aware Link.
src/components/Footer.tsx Translates footer copy/copyright and adjusts layout wrapping.
src/components/Faqs.tsx Converts FAQs to translated strings and simplifies rendering structure.
src/components/CallToAction.tsx Translates call-to-action copy.
src/components/AppDemo.tsx Translates demo UI labels.
src/app/layout.tsx Removes non-locale root layout in favor of locale layout.
src/app/[locale]/layout.tsx Adds locale-aware root layout, next-intl provider, and wraps pages in shared Layout.
src/app/[locale]/(main)/privacy/page.tsx Adds locale-specific privacy page loading MDX per locale.
src/app/[locale]/(main)/privacy/layout.tsx Adds locale-aware layout wrapper for privacy MDX pages.
src/app/[locale]/(main)/page.tsx Makes home page locale-aware and sets request locale.
src/app/[locale]/(main)/not-found.tsx Adds locale-segment 404 page.
src/app/(main)/layout.tsx Removes old segment layout export (now handled in locale layout).
public/favicon.ico Adds/updates favicon asset.
package.json Upgrades Next/React/TS and adds next-intl + other dependencies.
next.config.ts Converts config to TS and wires in next-intl + MDX plugins.
next.config.js Removes old JS Next config.
messages/uz.json Adds Uzbek UI message catalog.
messages/ru.json Adds Russian UI message catalog.
messages/en.json Adds English UI message catalog.
mdx-components.tsx Changes MDX components hook implementation.
.gitignore Ignores .vscode workspace folder.
Comments suppressed due to low confidence (2)

src/app/[locale]/(main)/page.tsx:12

  • PageProps is used as a type but isn’t imported or defined anywhere in the repository. Unless you rely on generated .next/types being present during type-checking, this will fail tsc in CI. Prefer typing props inline (e.g. {params: {locale: string}}) or import the correct type from Next if available in your version.
    src/app/[locale]/(main)/privacy/layout.tsx:6
  • LayoutProps<'/[locale]/privacy'> is used but not imported/declared anywhere in the repository, which can break type-checking. Prefer an explicit props type for this layout (e.g. { children: React.ReactNode; params: { locale: string } }) or import the correct Next type if your version provides it.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

## Pull request overview Adds internationalization (i18n) support to the Next.js App Router setup using `next-intl`, introducing locale-based routing and translated UI/content across the marketing site. **Changes:** - Introduces locale segment routing (`/[locale]`) and `next-intl` configuration (routing, request config, navigation helpers). - Replaces hardcoded Uzbek UI strings with translation keys backed by `messages/{uz,ru,en}.json`. - Adds localized privacy policy MDX content for RU/EN and updates config/build setup (Next config, deps, TypeScript). ### Reviewed changes Copilot reviewed 29 out of 36 changed files in this pull request and generated 11 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | tsconfig.json | Updates JSX mode and expands includes for Next-generated types. | | src/proxy.ts | Adds `next-intl` middleware wrapper (intended for locale routing). | | src/i18n/routing.ts | Defines supported locales and default locale. | | src/i18n/request.ts | Defines per-request locale + message loading for `next-intl`. | | src/i18n/navigation.ts | Adds locale-aware navigation helpers/wrappers. | | src/content/uz.md | Updates Uzbek effective date format. | | src/content/ru.md | Adds Russian privacy policy content. | | src/content/en.md | Adds English privacy policy content. | | src/components/SecondaryFeatures.tsx | Switches secondary features section to translations. | | src/components/PrimaryFeatures.tsx | Switches primary features + chat UI strings to translations; other UI tweaks. | | src/components/NavLinks.tsx | Makes header/footer nav links locale-aware and translated. | | src/components/Layout.tsx | Minor layout whitespace change. | | src/components/Hero.tsx | Moves hero copy to translations and adjusts sizing classes. | | src/components/Header.tsx | Adds language picker + translated nav labels; switches to locale-aware Link. | | src/components/Footer.tsx | Translates footer copy/copyright and adjusts layout wrapping. | | src/components/Faqs.tsx | Converts FAQs to translated strings and simplifies rendering structure. | | src/components/CallToAction.tsx | Translates call-to-action copy. | | src/components/AppDemo.tsx | Translates demo UI labels. | | src/app/layout.tsx | Removes non-locale root layout in favor of locale layout. | | src/app/[locale]/layout.tsx | Adds locale-aware root layout, `next-intl` provider, and wraps pages in shared Layout. | | src/app/[locale]/(main)/privacy/page.tsx | Adds locale-specific privacy page loading MDX per locale. | | src/app/[locale]/(main)/privacy/layout.tsx | Adds locale-aware layout wrapper for privacy MDX pages. | | src/app/[locale]/(main)/page.tsx | Makes home page locale-aware and sets request locale. | | src/app/[locale]/(main)/not-found.tsx | Adds locale-segment 404 page. | | src/app/(main)/layout.tsx | Removes old segment layout export (now handled in locale layout). | | public/favicon.ico | Adds/updates favicon asset. | | package.json | Upgrades Next/React/TS and adds `next-intl` + other dependencies. | | next.config.ts | Converts config to TS and wires in `next-intl` + MDX plugins. | | next.config.js | Removes old JS Next config. | | messages/uz.json | Adds Uzbek UI message catalog. | | messages/ru.json | Adds Russian UI message catalog. | | messages/en.json | Adds English UI message catalog. | | mdx-components.tsx | Changes MDX components hook implementation. | | .gitignore | Ignores `.vscode` workspace folder. | </details> <details> <summary>Comments suppressed due to low confidence (2)</summary> **src/app/[locale]/(main)/page.tsx:12** * `PageProps` is used as a type but isn’t imported or defined anywhere in the repository. Unless you rely on generated `.next/types` being present during type-checking, this will fail `tsc` in CI. Prefer typing `props` inline (e.g. `{params: {locale: string}}`) or import the correct type from Next if available in your version. **src/app/[locale]/(main)/privacy/layout.tsx:6** * `LayoutProps<'/[locale]/privacy'>` is used but not imported/declared anywhere in the repository, which can break type-checking. Prefer an explicit props type for this layout (e.g. `{ children: React.ReactNode; params: { locale: string } }`) or import the correct Next type if your version provides it. </details> --- 💡 <a href="/uchar-org/website/new/main?filename=.github/instructions/*.instructions.md" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Add Copilot custom instructions</a> for smarter, more guided reviews. <a href="https://docs.github.com/en/copilot/customizing-copilot/adding-repository-custom-instructions-for-github-copilot" class="Link--inTextBlock" target="_blank" rel="noopener noreferrer">Learn how to get started</a>.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-02 11:30:59 +00:00

useMDXComponents no longer merges in the components argument and always returns an empty object. This can break MDX rendering where callers pass custom components (and diverges from Next MDX’s expected pattern). Keep the (components: MDXComponents) => ({...components, ...custom}) shape so passed components aren’t dropped.

export function useMDXComponents(customComponents: MDXComponents): MDXComponents {
  return { ...components, ...customComponents }
`useMDXComponents` no longer merges in the `components` argument and always returns an empty object. This can break MDX rendering where callers pass custom components (and diverges from Next MDX’s expected pattern). Keep the `(components: MDXComponents) => ({...components, ...custom})` shape so passed components aren’t dropped. ```suggestion export function useMDXComponents(customComponents: MDXComponents): MDXComponents { return { ...components, ...customComponents } ```
@ -0,0 +12,4 @@
}
export default async function Privacy(props: PageProps<"/[locale]/privacy">) {
const { locale } = await (props.params)
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-02 11:30:59 +00:00

PageProps is referenced but not imported/declared in the repo, which will break type-checking unless .next/types is generated and included. Consider typing the params explicitly (e.g. { params: { locale: string } }) or importing the appropriate Next type for your version.

export default async function Privacy(props: { params: { locale: string } }) {
    const { locale } = props.params
`PageProps` is referenced but not imported/declared in the repo, which will break type-checking unless `.next/types` is generated and included. Consider typing the params explicitly (e.g. `{ params: { locale: string } }`) or importing the appropriate Next type for your version. ```suggestion export default async function Privacy(props: { params: { locale: string } }) { const { locale } = props.params ```
@ -0,0 +1,50 @@
import { type Metadata } from 'next'
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-02 11:30:57 +00:00

In a Next.js App Router layout, <body> must be a direct child of <html>. Wrapping <body> with NextIntlClientProvider will produce invalid layout structure and can error at runtime. Move the provider inside <body> (wrapping the app content).

      <body>
        <NextIntlClientProvider>
          <Layout>
            {children}
          </Layout>
        </NextIntlClientProvider>
      </body>
In a Next.js App Router layout, `<body>` must be a direct child of `<html>`. Wrapping `<body>` with `NextIntlClientProvider` will produce invalid layout structure and can error at runtime. Move the provider inside `<body>` (wrapping the app content). ```suggestion <body> <NextIntlClientProvider> <Layout> {children} </Layout> </NextIntlClientProvider> </body> ```
@ -0,0 +7,4 @@
import { hasLocale, NextIntlClientProvider } from 'next-intl'
import { notFound } from 'next/navigation'
import { getMessages, setRequestLocale } from 'next-intl/server'
import { Layout } from '@/components/Layout'
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-02 11:30:57 +00:00

NextIntlClientProvider is rendered without messages (and optionally locale). Since client components use useTranslations, the messages need to be provided/serialized (typically via getMessages()/useMessages() from next-intl/server). Without this, translations in client components can fail at runtime. Load messages for the current locale and pass them into the provider.

`NextIntlClientProvider` is rendered without `messages` (and optionally `locale`). Since client components use `useTranslations`, the messages need to be provided/serialized (typically via `getMessages()`/`useMessages()` from `next-intl/server`). Without this, translations in client components can fail at runtime. Load messages for the current locale and pass them into the provider.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-02 11:30:59 +00:00

This file introduces //@ts-ignore directives and also uses semicolons/double quotes, which conflicts with the repo’s Prettier config (semi: false, singleQuote: true). Please run Prettier and replace @ts-ignore with a typed fix or @ts-expect-error plus a reason so suppression is intentional and tracked.

import { usePathname, useRouter } from '@/i18n/navigation'
This file introduces `//@ts-ignore` directives and also uses semicolons/double quotes, which conflicts with the repo’s Prettier config (`semi: false`, `singleQuote: true`). Please run Prettier and replace `@ts-ignore` with a typed fix or `@ts-expect-error` plus a reason so suppression is intentional and tracked. ```suggestion import { usePathname, useRouter } from '@/i18n/navigation' ```
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-02 11:30:58 +00:00

This introduces Tailwind classes like h-256.5, w-256.5, h-112, and max-w-91.5 that aren’t part of Tailwind’s default scale and aren’t defined in the project’s theme. These styles likely won’t be generated, causing layout regressions. Use arbitrary values (e.g. h-[1026px], max-w-[366px]) or define matching theme tokens.

            <BackgroundIllustration className="absolute top-4 left-1/2 h-[1026px] w-[1026px] -translate-x-1/3 stroke-brand sm:top-16 sm:-translate-x-1/2 lg:-top-16 lg:ml-12 xl:-top-14 xl:ml-0" />
            <div className="-mx-4 h-[678px] mask-[linear-gradient(to_bottom,white_60%,transparent)] px-9 sm:mx-0 lg:absolute lg:-inset-x-10 lg:-top-10 lg:-bottom-20 lg:h-auto lg:px-0 lg:pt-10 xl:-bottom-32">
              <PhoneFrame className="mx-auto max-w-[366px]" priority>
This introduces Tailwind classes like `h-256.5`, `w-256.5`, `h-112`, and `max-w-91.5` that aren’t part of Tailwind’s default scale and aren’t defined in the project’s theme. These styles likely won’t be generated, causing layout regressions. Use arbitrary values (e.g. `h-[1026px]`, `max-w-[366px]`) or define matching theme tokens. ```suggestion <BackgroundIllustration className="absolute top-4 left-1/2 h-[1026px] w-[1026px] -translate-x-1/3 stroke-brand sm:top-16 sm:-translate-x-1/2 lg:-top-16 lg:ml-12 xl:-top-14 xl:ml-0" /> <div className="-mx-4 h-[678px] mask-[linear-gradient(to_bottom,white_60%,transparent)] px-9 sm:mx-0 lg:absolute lg:-inset-x-10 lg:-top-10 lg:-bottom-20 lg:h-auto lg:px-0 lg:pt-10 xl:-bottom-32"> <PhoneFrame className="mx-auto max-w-[366px]" priority> ```
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-02 11:31:00 +00:00

//@ts-ignore on the Framer Motion element hides the underlying type mismatch. Prefer fixing the component typings (or using @ts-expect-error with a short reason) to avoid silently masking future issues.

            // @ts-expect-error Framer Motion motion.span typings conflict with this project's JSX configuration
`//@ts-ignore` on the Framer Motion element hides the underlying type mismatch. Prefer fixing the component typings (or using `@ts-expect-error` with a short reason) to avoid silently masking future issues. ```suggestion // @ts-expect-error Framer Motion motion.span typings conflict with this project's JSX configuration ```
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-02 11:30:58 +00:00

usePrevious no longer returns undefined on the first render because the ref is initialized with 0 as unknown as T. This changes behavior and breaks the prevIndex === undefined check below (it will never be true), which can affect animation direction on first render. Initialize the ref as undefined (e.g. useRef<T | undefined>(undefined)) and update the return type/logic accordingly.

`usePrevious` no longer returns `undefined` on the first render because the ref is initialized with `0 as unknown as T`. This changes behavior and breaks the `prevIndex === undefined` check below (it will never be true), which can affect animation direction on first render. Initialize the ref as `undefined` (e.g. `useRef<T | undefined>(undefined)`) and update the return type/logic accordingly.
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-02 11:30:58 +00:00

//@ts-ignore is being used to silence type errors on motion.div. This can hide real issues and makes upgrades harder. Prefer fixing the typing (e.g., ensure correct motion component typings / as usage) or use a narrower suppression (@ts-expect-error with a reason) so CI fails if the issue disappears.

                // @ts-expect-error Known Framer Motion typing issue for animated background div
`//@ts-ignore` is being used to silence type errors on `motion.div`. This can hide real issues and makes upgrades harder. Prefer fixing the typing (e.g., ensure correct `motion` component typings / `as` usage) or use a narrower suppression (`@ts-expect-error` with a reason) so CI fails if the issue disappears. ```suggestion // @ts-expect-error Known Framer Motion typing issue for animated background div ```
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-02 11:30:58 +00:00

Tailwind classes like max-w-91.5 are not valid with the current Tailwind theme (no custom spacing scale is defined in src/styles/tailwind.css). These styles likely won’t be generated, changing layout sizing. Prefer arbitrary values (e.g. max-w-[366px]) or add explicit theme tokens.

        <PhoneFrame className="z-10 mx-auto w-full max-w-[366px]">
Tailwind classes like `max-w-91.5` are not valid with the current Tailwind theme (no custom spacing scale is defined in src/styles/tailwind.css). These styles likely won’t be generated, changing layout sizing. Prefer arbitrary values (e.g. `max-w-[366px]`) or add explicit theme tokens. ```suggestion <PhoneFrame className="z-10 mx-auto w-full max-w-[366px]"> ```
@ -0,0 +6,4 @@
export const proxy = async (request: NextRequest) => {
return i18middleware(request)
}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2026-04-02 11:30:57 +00:00

This file won’t be picked up by Next.js as middleware. Next expects a top-level middleware.ts/middleware.js (or src/middleware.ts) exporting middleware/default, not an exported proxy function in src/proxy.ts. Rename/move this to src/middleware.ts and export the middleware function accordingly so config.matcher is applied.

This file won’t be picked up by Next.js as middleware. Next expects a top-level `middleware.ts`/`middleware.js` (or `src/middleware.ts`) exporting `middleware`/default, not an exported `proxy` function in `src/proxy.ts`. Rename/move this to `src/middleware.ts` and export the middleware function accordingly so `config.matcher` is applied.
orzklv commented 2026-04-02 14:48:35 +00:00 (Migrated from github.com)

I kindly request @xelopsys to turn off AI reviews, this contradicts our Anti-AI stance & policy.

I kindly request @xelopsys to turn off AI reviews, this contradicts our Anti-AI stance & policy.
Sign in to join this conversation.
No description provided.