TASKS-1823 WebManager module

This commit is contained in:
Igor Martyniuk
2026-08-28 08:35:58 +00:00
parent fdb2cf3837
commit c93d8c025b
654 changed files with 26232 additions and 6075 deletions
+21
View File
@@ -0,0 +1,21 @@
import { hasLocale } from 'next-intl';
import { routing } from './routing';
/**
* Internal hrefs in page content are locale-prefixed (`/{locale}/{path}`);
* when the site serves unprefixed URLs, the prefix is stripped at render
* time so navigation does not bounce through the proxy redirect.
*/
export function toPublicHref(href: string): string {
if (routing.localePrefix !== 'never') {
return href;
}
const [, first = '', ...rest] = href.split('/');
if (!hasLocale(routing.locales, first)) {
return href;
}
return `/${rest.join('/')}`;
}
+4
View File
@@ -0,0 +1,4 @@
import { createNavigation } from 'next-intl/navigation';
import { routing } from './routing';
export const { Link, redirect, usePathname, useRouter, getPathname } = createNavigation(routing);
+28
View File
@@ -0,0 +1,28 @@
import { hasLocale } from 'next-intl';
import { getRequestConfig } from 'next-intl/server';
import { routing } from './routing';
async function loadTranslationType(type: string, locale: string) {
try {
return (await import(`./translations/${type}/${locale}.json`)).default;
} catch {
return (await import(`./translations/${type}/${routing.defaultLocale}.json`)).default;
}
}
async function loadMessages(locale: string) {
const resources = ['messages', 'pages', 'components', 'errors', 'form'].map((type) => {
return loadTranslationType(type, locale);
});
const loaded = await Promise.all(resources);
return Object.assign({}, ...loaded);
}
export default getRequestConfig(async ({ requestLocale }) => {
const requested = await requestLocale;
const locale = hasLocale(routing.locales, requested) ? requested : routing.defaultLocale;
const messages = await loadMessages(locale);
return { locale, messages };
});
+8
View File
@@ -0,0 +1,8 @@
import { defineRouting } from 'next-intl/routing';
import { siteConfig } from '#site.config';
export const routing = defineRouting({
locales: siteConfig.locales,
defaultLocale: siteConfig.defaultLocale,
localePrefix: siteConfig.locales.length > 1 ? 'always' : 'never'
});
@@ -0,0 +1,17 @@
{
"Components": {
"Navigation": {
"home": "Crux home",
"main": "Main navigation",
"open": "Open navigation",
"close": "Close navigation",
"languages": "Languages"
},
"Footer": {
"navigation": "Footer navigation",
"legal": "Legal",
"privacy": "Privacy",
"terms": "Terms"
}
}
}
@@ -0,0 +1,3 @@
{
"Errors": {}
}
+7
View File
@@ -0,0 +1,7 @@
{
"Form": {
"fields": {},
"actions": {},
"validation": {}
}
}
@@ -0,0 +1,8 @@
{
"Metadata": {
"title": "Crux",
"template": "%s | Crux",
"description": "Crux web app"
},
"Common": {}
}
+21
View File
@@ -0,0 +1,21 @@
{
"Pages": {
"NotFoundPage": {
"metaTitle": "Page not found",
"title": "That page is not available.",
"description": "Check the address or return to the site.",
"cta": "Return home"
},
"BlogPage": {
"empty": "No posts have been published yet.",
"readMore": "Read more",
"pagination": "Blog pages",
"previous": "Previous page",
"next": "Next page"
},
"PreviewPage": {
"title": "Preview unavailable",
"description": "The preview link is invalid or has expired. Open the page in the admin editor and start a new preview."
}
}
}
+13
View File
@@ -0,0 +1,13 @@
import type components from './translations/components/en.json';
import type errors from './translations/errors/en.json';
import type form from './translations/form/en.json';
import type messages from './translations/messages/en.json';
import type pages from './translations/pages/en.json';
type Messages = typeof messages & typeof pages & typeof components & typeof errors & typeof form;
declare module 'next-intl' {
interface AppConfig {
Messages: Messages;
}
}