Files
netrunner-landing/lib/IDict.ts
T
nineap 32b4460b66 Локализует лендинг на 10 языков + RTL для арабского и персидского
Добавляет zh-CN, fa, ar, tr, uk, be, vi, uz словари (170 ключей, идентичная
вложенная структура) к существующим en/ru. lib/locales.ts — единый источник
списка локалей/дефолтной локали/RTL-набора вместо захардкоженного ["en","ru"]
в proxy.ts. language-switcher.tsx: переключение языка резало только
двухбуквенные коды регэкспом (/^\/[a-z]{2}/), из-за чего zh-CN никогда не
матчился и путь задваивался — заменено на honest-поиск по списку locales.

app/[lang]/layout.tsx — dir="rtl"/"ltr" на <html> по локали (SSR, в отличие
от реактивного клиентского переключения в netrunner-app). Header.tsx/
Footer.tsx — разбитое на три <span> имя бренда визуально переворачивалось
Flexbox'ом под dir=rtl ("VPNrunnerNet"), исправлено через dir="ltr" на
самом враппере.

BlogPreview/Faq/Pricing и обе blog-страницы: fallback на *_en-коллекцию
PocketBase, если для языка ещё нет переведённого контента (FAQ-ответы,
детали тарифов, посты блога не тянутся автоматически — это отдельный от
статических словарей CMS-контент), плюс i18n-ключи period1m/period6m/
period1y вместо захардкоженных ru/en-подписей периодов в Pricing.tsx.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-08 22:53:37 +07:00

222 lines
4.7 KiB
TypeScript

// Форма JSON-словарей из dictionaries/en.json и dictionaries/ru.json — оба файла
// должны точно соответствовать этой структуре, иначе TypeScript подсветит расхождение
// в местах, где used dict.<section>.<key> (см. lib/dictionaries.ts).
export interface Dictionary {
nav: {
features: string;
pricing: string;
faq: string;
profile: string;
blog: string;
terminal: string;
docs: string;
cta: string;
menu: string;
speedtest: string; // Новое
doom: string; // Новое
};
hero: {
badge: string;
badgeSecure: string;
titleStart: string;
titleHighlight: string;
subtitle: string;
switchLabel: string;
ctaPrimary: string;
ctaSecondary: string;
};
features: {
title: string;
items: { title: string; description: string }[];
};
pricing: {
badge: string;
title: string;
perMonth: string;
recommend: string;
syncing: string;
empty: string;
discount: string;
mo: string;
billedOnce: string;
period1m: string;
period6m: string;
period1y: string;
};
faq: {
title: string;
empty: string;
};
blog: {
badge: string;
title: string;
more: string;
readMore: string;
empty: string;
archive: string;
systemLogs: string;
emptySector: string;
decrypt: string;
backBtn: string;
readTime: string;
verified: string;
endTransmission: string;
};
footer: {
brand: string;
tagline: string;
sections: {
product: string;
resources: string;
legal: string;
};
links: {
features: string;
pricing: string;
faq: string;
protocol: string;
comms: string;
privacy: string;
terms: string;
profile: string;
};
rights: string;
protocolStatus: string;
uplinkStatus: string;
activeNode: string;
latency: string;
};
download: {
title: string;
subtitle: string;
badges: { active: string; dev: string };
buttons: {
direct: string;
store: string;
github: string;
notify: string;
soon: string;
pending: string;
};
platforms: {
windows: string;
android: string;
linux: string;
macos: string;
ios: string;
};
accessingBuild: string;
};
terminal: {
title: string;
description: string;
alias: string;
message: string;
send: string;
systemReady: string;
loadingHistory: string;
noMoreLogs: string;
encrypting: string;
cooldown: string;
manifestoTitle: string;
manifestoText: string;
rulesTitle: string;
rule1: string;
rule2: string;
rule3: string;
statusReady: string;
};
loading: {
establishing: string;
};
notFound: {
errorBadge: string;
message: string;
returnHome: string;
};
nodes: {
title: string;
subtitle: string;
status: {
online: string;
full: string;
maintenance: string;
};
labels: {
load: string;
latency: string;
};
};
guestbook: {
title: string;
subtitle: string;
description: string;
philosophyTitle: string;
philosophyText: string;
liveFeed: string;
noTransmissions: string;
labelAlias: string;
labelPayload: string;
placeholderAlias: string;
placeholderPayload: string;
statusSuccess: string;
statusErrorBreach: string;
statusErrorEmpty: string;
statusErrorSize: string;
statusErrorFirewall: string;
statusErrorOffline: string;
statusErrorFilter?: string;
btnEncrypting: string;
btnBroadcast: string;
cooldown: string;
};
auth: {
title: string;
processing: string;
verifying: string;
granted: string;
denied: string;
noToken: string;
redirecting: string;
toBot: string;
awaiting: string;
authPrompt: string;
logs: {
waitInit: string;
sigValid: string;
apiRejected: string;
coreOffline: string;
authPayload: string;
verifyHmac: string;
invalidSig: string;
networkError: string;
};
};
docs: {
establishing: string;
vaultTitle: string;
vaultSubtitle: string;
searchPlaceholder: string;
empty: string;
closeSession: string;
noContent: string;
eof: string;
};
speedtest: {
title: string;
mockMode: string;
prodMode: string;
btnError: string;
btnDone: string;
btnIdle: string;
statusPinging: string;
statusDownloading: string;
statusUploading: string;
latency: string;
download: string;
upload: string;
unitMs: string;
unitMbps: string;
};
}