Merge remote-tracking branch 'origin' into back-office-integration

This commit is contained in:
sdarbinyan
2026-02-28 16:13:14 +04:00
217 changed files with 10170 additions and 5789 deletions

189
src/app/i18n/en.ts Normal file
View File

@@ -0,0 +1,189 @@
import { Translations } from './translations';
export const en: Translations = {
header: {
home: 'Home',
search: 'Search',
about: 'About',
contacts: 'Contacts',
searchPlaceholder: 'Search...',
catalog: 'Catalog',
},
footer: {
description: 'A modern marketplace for comfortable shopping',
company: 'Company',
aboutUs: 'About us',
contacts: 'Contacts',
requisites: 'Company details',
support: 'Support',
faq: 'FAQ',
delivery: 'Delivery',
guarantee: 'Warranty',
legal: 'Legal information',
offer: 'Public offer',
privacy: 'Privacy policy',
returns: 'Returns',
info: 'Information',
aboutCompany: 'About company',
documents: 'Documents',
paymentRules: 'Payment terms',
returnPolicy: 'Return policy',
publicOffer: 'Public offer',
help: 'Help',
payment: 'Payment',
allRightsReserved: 'All rights reserved.',
},
home: {
welcomeTo: 'Welcome to {{brand}}',
subtitle: 'Find everything you need in one place',
startSearch: 'Start search',
loading: 'Loading categories...',
errorTitle: 'Something went wrong',
retry: 'Try again',
categoriesTitle: 'Product categories',
categoriesSubtitle: 'Choose a category',
categoriesEmpty: 'Categories coming soon',
categoriesEmptyDesc: 'We are working on filling the catalog',
dexarHeroTitle: 'Find everything here',
dexarHeroSubtitle: 'Thousands of products in one place',
dexarHeroTagline: 'simple and convenient',
goToCatalog: 'Go to catalog',
findProduct: 'Find a product',
loadingDexar: 'Loading categories...',
catalogTitle: 'Product catalog',
emptyCategoriesDexar: 'No categories yet',
categoriesSoonDexar: 'Categories will appear here soon',
itemsCount: '{{count}} products',
},
cart: {
title: 'Cart',
clear: 'Clear',
empty: 'Cart is empty',
emptyDesc: 'Add products to start shopping',
goShopping: 'Start shopping',
total: 'Total',
items: 'Products',
deliveryLabel: 'Delivery',
toPay: 'To pay',
agreeWith: 'I agree with the',
publicOffer: 'public offer',
returnPolicy: 'return policy',
guaranteeTerms: 'warranty terms',
privacyPolicy: 'privacy policy',
and: 'and',
checkout: 'Place order',
close: 'Close',
creatingPayment: 'Creating payment...',
waitFewSeconds: 'Please wait a few seconds',
scanQr: 'Scan the QR code to pay',
amountToPay: 'Amount due:',
waitingPayment: 'Waiting for payment...',
copied: '✓ Copied',
copyLink: 'Copy link',
openNewTab: 'Open in new tab',
paymentSuccess: 'Congratulations! Payment successful!',
paymentSuccessDesc: 'Enter your contact details and we will send your purchase within a few minutes',
sending: 'Sending...',
send: 'Send',
paymentTimeout: 'Payment timed out',
paymentTimeoutDesc: 'We did not receive payment confirmation within 3 minutes.',
autoClose: 'Window will close automatically...',
confirmClear: 'Are you sure you want to clear the cart?',
acceptTerms: 'Please accept the offer terms, return policy, and warranty terms to proceed with the order.',
copyError: 'Copy error:',
emailSuccess: 'Email sent successfully! Check your inbox.',
emailError: 'An error occurred while sending the email. Please try again.',
phoneRequired: 'Phone number is required',
phoneMoreDigits: 'Enter {{count}} more digits',
phoneTooMany: 'Too many digits',
emailRequired: 'Email is required',
emailTooShort: 'Email is too short (minimum 5 characters)',
emailTooLong: 'Email is too long (maximum 100 characters)',
emailNeedsAt: 'Email must contain @',
emailNeedsDomain: 'Email must contain a domain (.com, .ru, etc.)',
emailInvalid: 'Invalid email format',
},
search: {
title: 'Product search',
placeholder: 'Enter product name...',
resultsCount: 'Products found:',
searching: 'Searching...',
retry: 'Try again',
noResults: 'Nothing found',
noResultsFor: 'No products found for "{{query}}"',
noResultsHint: 'Try changing your query or using different keywords',
addToCart: 'Add to cart',
loadingMore: 'Loading...',
allLoaded: 'All results loaded',
emptyState: 'Enter a query to search for products',
of: 'of',
},
category: {
retry: 'Try again',
addToCart: 'Add to cart',
loadingMore: 'Loading...',
allLoaded: 'All products loaded',
emptyTitle: 'Oops! Nothing here yet',
emptyDesc: 'There are no products in this category yet, but they will appear soon',
goHome: 'Go home',
loading: 'Loading products...',
},
subcategories: {
loading: 'Loading subcategories...',
retry: 'Try again',
emptyTitle: 'Oops! No subcategories yet',
emptyDesc: 'There are no subcategories in this section yet, but they will appear soon',
goHome: 'Go home',
},
itemDetail: {
loading: 'Loading...',
loadingDexar: 'Loading product...',
back: 'Go back',
backHome: 'Back to home',
noImage: 'No image',
stock: 'Availability:',
inStock: 'In stock',
lowStock: 'Few left',
lastItems: 'Last items',
mediumStock: 'Running low',
addToCart: 'Add to cart',
description: 'Description',
specifications: 'Specifications',
reviews: 'Reviews',
yourReview: 'Your review',
leaveReview: 'Leave a review',
rating: 'Rating:',
reviewPlaceholder: 'Share your experience with this product...',
reviewPlaceholderDexar: 'Share your thoughts on this product...',
anonymous: 'Anonymous',
submitting: 'Submitting...',
submit: 'Submit',
reviewSuccess: 'Thank you for your review!',
reviewError: 'Submission failed. Please try later.',
defaultUser: 'User',
defaultUserDexar: 'Anonymous',
noReviews: 'No reviews yet. Be the first!',
qna: 'Questions & Answers',
photo: 'Photo',
reviewsCount: 'reviews',
today: 'Today',
yesterday: 'Yesterday',
daysAgo: 'd. ago',
weeksAgo: 'w. ago',
},
app: {
connecting: 'Connecting to server...',
serverUnavailable: 'Server unavailable',
serverError: 'Could not connect to the server. Please check your internet connection.',
retryConnection: 'Retry',
pageTitle: 'Marketplace of goods and services',
},
carousel: {
loading: 'Loading products...',
addToCart: 'Add to cart',
},
common: {
retry: 'Try again',
loading: 'Loading...',
},
};

189
src/app/i18n/hy.ts Normal file
View File

@@ -0,0 +1,189 @@
import { Translations } from './translations';
export const hy: Translations = {
header: {
home: '╘│╒м╒н╒б╒╛╒╕╓А',
search: '╒И╓А╒╕╒╢╒╕╓В╒┤',
about: '╒Д╒е╓А ╒┤╒б╒╜╒л╒╢',
contacts: '╘┐╒б╒║',
searchPlaceholder: '╒И╓А╒╕╒╢╒е╒м...',
catalog: '╘┐╒б╒┐╒б╒м╒╕╒г',
},
footer: {
description: '╘║╒б╒┤╒б╒╢╒б╒п╒б╒п╒л╓Б ╒┤╒б╓А╓Д╒е╒й╓Г╒м╒е╒╡╒╜ ╒░╒б╓А╒┤╒б╓А ╒г╒╢╒╕╓В╒┤╒╢╒е╓А╒л ╒░╒б╒┤╒б╓А',
company: '╘╕╒╢╒п╒е╓А╒╕╓В╒й╒╡╒╕╓В╒╢',
aboutUs: '╒Д╒е╓А ╒┤╒б╒╜╒л╒╢',
contacts: '╘┐╒б╒║',
requisites: '╒О╒б╒╛╒е╓А╒б╒║╒б╒╡╒┤╒б╒╢╒╢╒е╓А',
support: '╘▒╒╗╒б╒п╓Б╒╕╓В╒й╒╡╒╕╓В╒╢',
faq: '╒А╒П╒А',
delivery: '╘▒╒╝╒б╓Д╒╕╓В╒┤',
guarantee: '╘╡╓А╒б╒╖╒н╒л╓Д',
legal: '╘╗╓А╒б╒╛╒б╒п╒б╒╢ ╒┐╒е╒▓╒е╒п╒б╒┐╒╛╒╕╓В╒й╒╡╒╕╓В╒╢',
offer: '╒Х╓Ж╒е╓А╒┐╒б',
privacy: '╘│╒б╒▓╒┐╒╢╒л╒╕╓В╒й╒╡╒╕╓В╒╢',
returns: '╒О╒е╓А╒б╒д╒б╓А╒▒',
info: '╒П╒е╒▓╒е╒п╒б╒┐╒╛╒╕╓В╒й╒╡╒╕╓В╒╢',
aboutCompany: '╘╕╒╢╒п╒е╓А╒╕╓В╒й╒╡╒б╒╢ ╒┤╒б╒╜╒л╒╢',
documents: '╒У╒б╒╜╒┐╒б╒й╒▓╒й╒е╓А',
paymentRules: '╒О╒│╒б╓А╒┤╒б╒╢ ╒п╒б╒╢╒╕╒╢╒╢╒е╓А',
returnPolicy: '╒О╒е╓А╒б╒д╒б╓А╒▒╒л ╓Д╒б╒▓╒б╓Д╒б╒п╒б╒╢╒╕╓В╒й╒╡╒╕╓В╒╢',
publicOffer: '╒А╒б╒╢╓А╒б╒╡╒л╒╢ ╓Е╓Ж╒е╓А╒┐╒б',
help: '╒Х╒г╒╢╒╕╓В╒й╒╡╒╕╓В╒╢',
payment: '╒О╒│╒б╓А╒╕╓В╒┤',
allRightsReserved: '╘▓╒╕╒м╒╕╓А ╒л╓А╒б╒╛╒╕╓В╒╢╓Д╒╢╒е╓А╒и ╒║╒б╒╖╒┐╒║╒б╒╢╒╛╒б╒о ╒е╒╢╓Й',
},
home: {
welcomeTo: '╘▓╒б╓А╒л ╒г╒б╒м╒╕╓В╒╜╒┐ {{brand}}',
subtitle: '╘│╒┐╒е╓Д ╒б╒┤╒е╒╢ ╒л╒╢╒╣ ╒┤╒е╒п ╒╛╒б╒╡╓А╒╕╓В╒┤',
startSearch: '╒Н╒п╒╜╒е╒м ╒╕╓А╒╕╒╢╒╕╓В╒┤╒и',
loading: '╘┐╒б╒┐╒е╒г╒╕╓А╒л╒б╒╢╒е╓А╒и ╒в╒е╒╝╒╢╒╛╒╕╓В╒┤ ╒е╒╢...',
errorTitle: '╘╗╒╢╒╣-╒╕╓А ╒в╒б╒╢ ╒╜╒н╒б╒м ╒з ╒г╒╢╒б╓Б╒е╒м',
retry: '╒У╒╕╓А╒▒╒е╒м ╒п╓А╒п╒л╒╢',
categoriesTitle: '╘▒╒║╓А╒б╒╢╓Д╒╢╒е╓А╒л ╒п╒б╒┐╒е╒г╒╕╓А╒л╒б╒╢╒е╓А',
categoriesSubtitle: '╘╕╒╢╒┐╓А╒е╓Д ╒░╒е╒┐╒б╓Д╓А╓Д╓А╒╕╒▓ ╒п╒б╒┐╒е╒г╒╕╓А╒л╒б╒╢',
categoriesEmpty: '╘┐╒б╒┐╒е╒г╒╕╓А╒л╒б╒╢╒е╓А╒и ╒╖╒╕╓В╒┐╒╕╒╛ ╒п╒░╒б╒╡╒┐╒╢╒╛╒е╒╢',
categoriesEmptyDesc: '╒Д╒е╒╢╓Д ╒б╒╖╒н╒б╒┐╒╕╓В╒┤ ╒е╒╢╓Д ╒п╒б╒┐╒б╒м╒╕╒г╒л ╒░╒б╒┤╒б╒м╓А╒┤╒б╒╢ ╒╛╓А╒б',
dexarHeroTitle: '╘▒╒╡╒╜╒┐╒е╒▓ ╒д╒╕╓В ╒п╒г╒┐╒╢╒е╒╜ ╒б╒┤╒е╒╢ ╒л╒╢╒╣',
dexarHeroSubtitle: '╒А╒б╒ж╒б╓А╒б╒╛╒╕╓А ╒б╒║╓А╒б╒╢╓Д╒╢╒е╓А ╒┤╒е╒п ╒╛╒б╒╡╓А╒╕╓В╒┤',
dexarHeroTagline: '╒║╒б╓А╒ж ╓З ╒░╒б╓А╒┤╒б╓А',
goToCatalog: '╘▒╒╢╓Б╒╢╒е╒м ╒п╒б╒┐╒б╒м╒╕╒г',
findProduct: '╘│╒┐╒╢╒е╒м ╒б╒║╓А╒б╒╢╓Д',
loadingDexar: '╘┐╒б╒┐╒е╒г╒╕╓А╒л╒б╒╢╒е╓А╒и ╒в╒е╒╝╒╢╒╛╒╕╓В╒┤ ╒е╒╢...',
catalogTitle: '╘▒╒║╓А╒б╒╢╓Д╒╢╒е╓А╒л ╒п╒б╒┐╒б╒м╒╕╒г',
emptyCategoriesDexar: '╘┐╒б╒┐╒е╒г╒╕╓А╒л╒б╒╢╒е╓А╒и ╒д╒е╒╝ ╒╣╒п╒б╒╢',
categoriesSoonDexar: '╒З╒╕╓В╒┐╒╕╒╛ ╒б╒╡╒╜╒┐╒е╒▓ ╒п╒░╒б╒╡╒┐╒╢╒╛╒е╒╢ ╒б╒║╓А╒б╒╢╓Д╒╢╒е╓А╒л ╒п╒б╒┐╒е╒г╒╕╓А╒л╒б╒╢╒е╓А',
itemsCount: '{{count}} ╒б╒║╓А╒б╒╢╓Д',
},
cart: {
title: '╘╢╒б╒┤╒в╒╡╒╕╓В╒▓',
clear: '╒Д╒б╓Д╓А╒е╒м',
empty: '╘╢╒б╒┤╒в╒╡╒╕╓В╒▓╒и ╒д╒б╒┐╒б╓А╒п ╒з',
emptyDesc: '╘▒╒╛╒е╒м╒б╓Б╓А╒е╓Д ╒б╒║╓А╒б╒╢╓Д╒╢╒е╓А ╒г╒╢╒╕╓В╒┤╒╢╒е╓А╒и ╒╜╒п╒╜╒е╒м╒╕╓В ╒░╒б╒┤╒б╓А',
goShopping: '╘▒╒╢╓Б╒╢╒е╒м ╒г╒╢╒╕╓В╒┤╒╢╒е╓А╒л',
total: '╘╕╒╢╒д╒б╒┤╒е╒╢╒и',
items: '╘▒╒║╓А╒б╒╢╓Д╒╢╒е╓А',
deliveryLabel: '╘▒╒╝╒б╓Д╒╕╓В╒┤',
toPay: '╒О╒│╒б╓А╒┤╒б╒╢ ╒е╒╢╒й╒б╒п╒б',
agreeWith: '╘╡╒╜ ╒░╒б╒┤╒б╒▒╒б╒╡╒╢ ╒е╒┤',
publicOffer: '╒░╒б╒╢╓А╒б╒╡╒л╒╢ ╓Е╓Ж╒е╓А╒┐╒б╒╡╒л╒╢',
returnPolicy: '╒╛╒е╓А╒б╒д╒б╓А╒▒╒л ╓Д╒б╒▓╒б╓Д╒б╒п╒б╒╢╒╕╓В╒й╒╡╒б╒╢╒и',
guaranteeTerms: '╒е╓А╒б╒╖╒н╒л╓Д╒б╒╡╒л╒╢ ╒║╒б╒╡╒┤╒б╒╢╒╢╒е╓А╒л╒╢',
privacyPolicy: '╒г╒б╒▓╒┐╒╢╒л╒╕╓В╒й╒╡╒б╒╢ ╓Д╒б╒▓╒б╓Д╒б╒п╒б╒╢╒╕╓В╒й╒╡╒б╒╢╒и',
and: '╓З',
checkout: '╒Б╓З╒б╒п╒е╓А╒║╒е╒м ╒║╒б╒┐╒╛╒е╓А',
close: '╒У╒б╒п╒е╒м',
creatingPayment: '╒О╒│╒б╓А╒╕╓В╒┤╒и ╒╜╒┐╒е╒▓╒о╒╛╒╕╓В╒┤ ╒з...',
waitFewSeconds: '╒Н╒║╒б╒╜╒е╓Д ╒┤╒л ╓Д╒б╒╢╒л ╒╛╒б╒╡╓А╒п╒╡╒б╒╢',
scanQr: '╒Н╒п╒б╒╢╒б╒╛╒╕╓А╒е╓Д QR ╒п╒╕╒д╒и ╒╛╒│╒б╓А╒┤╒б╒╢ ╒░╒б╒┤╒б╓А',
amountToPay: '╒О╒│╒б╓А╒┤╒б╒╢ ╒г╒╕╓В╒┤╒б╓А╒и╒Э',
waitingPayment: '╒Н╒║╒б╒╜╒╕╓В╒┤ ╒е╒╢╓Д ╒╛╒│╒б╓А╒┤╒б╒╢╒и...',
copied: 'тЬУ ╒К╒б╒┐╒│╒е╒╢╒╛╒б╒о ╒з',
copyLink: '╒К╒б╒┐╒│╒е╒╢╒е╒м ╒░╒▓╒╕╓В╒┤╒и',
openNewTab: '╘▓╒б╓Б╒е╒м ╒╢╒╕╓А ╒╢╒е╓А╒д╒л╓А╒╕╓В╒┤',
paymentSuccess: '╒З╒╢╒╕╓А╒░╒б╒╛╒╕╓А╒╕╓В╒┤ ╒е╒╢╓Д╓Й ╒О╒│╒б╓А╒╕╓В╒┤╒и ╒░╒б╒╗╒╕╒▓╒╕╓В╒й╒╡╒б╒┤╒в ╒п╒б╒┐╒б╓А╒╛╒е╒м ╒з╓Й',
paymentSuccessDesc: '╒Д╒╕╓В╒┐╓Д╒б╒г╓А╒е╓Д ╒▒╒е╓А ╒п╒╕╒╢╒┐╒б╒п╒┐╒б╒╡╒л╒╢ ╒┐╒╛╒╡╒б╒м╒╢╒е╓А╒и, ╓З ╒┤╒е╒╢╓Д ╒п╒╕╓В╒▓╒б╓А╒п╒е╒╢╓Д ╒г╒╢╒╕╓В╒┤╒и ╒┤╒л ╓Д╒б╒╢╒л ╓А╒╕╒║╒е╒л ╒и╒╢╒й╒б╓Б╓Д╒╕╓В╒┤',
sending: '╒И╓В╒▓╒б╓А╒п╒╛╒╕╓В╒┤ ╒з...',
send: '╒И╓В╒▓╒б╓А╒п╒е╒м',
paymentTimeout: '╒Н╒║╒б╒╜╒┤╒б╒╢ ╒к╒б╒┤╒б╒╢╒б╒п╒и ╒╜╒║╒б╒╝╒╛╒е╒м ╒з',
paymentTimeoutDesc: '╒Д╒е╒╢╓Д ╒╣╒е╒╢╓Д ╒╜╒┐╒б╓Б╒е╒м ╒╛╒│╒б╓А╒┤╒б╒╢ ╒░╒б╒╜╒┐╒б╒┐╒╕╓В╒┤ 3 ╓А╒╕╒║╒е╒л ╒и╒╢╒й╒б╓Б╓Д╒╕╓В╒┤╓Й',
autoClose: '╒К╒б╒┐╒╕╓В╒░╒б╒╢╒и ╒п╓Г╒б╒п╒╛╒л ╒б╒╛╒┐╒╕╒┤╒б╒┐...',
confirmClear: '╒А╒б╒┤╒╕╒ж╒╛╒б╒Ю╒о ╒е╓Д, ╒╕╓А ╓Б╒б╒╢╒п╒б╒╢╒╕╓В╒┤ ╒е╓Д ╒┤╒б╓Д╓А╒е╒м ╒ж╒б╒┤╒в╒╡╒╕╓В╒▓╒и╓Й',
acceptTerms: '╘╜╒╢╒д╓А╒╕╓В╒┤ ╒е╒╢╓Д ╒и╒╢╒д╒╕╓В╒╢╒е╒м ╓Е╓Ж╒е╓А╒┐╒б╒╡╒л, ╒╛╒е╓А╒б╒д╒б╓А╒▒╒л ╓З ╒е╓А╒б╒╖╒н╒л╓Д╒л ╒║╒б╒╡╒┤╒б╒╢╒╢╒е╓А╒и ╒║╒б╒┐╒╛╒е╓А╒и ╒░╒б╒╜╒┐╒б╒┐╒е╒м╒╕╓В ╒░╒б╒┤╒б╓А╓Й',
copyError: '╒К╒б╒┐╒│╒е╒╢╒┤╒б╒╢ ╒╜╒н╒б╒м╒Э',
emailSuccess: 'Email-╒и ╒░╒б╒╗╒╕╒▓╒╕╓В╒й╒╡╒б╒┤╒в ╒╕╓В╒▓╒б╓А╒п╒╛╒е╒м ╒з╓Й ╒Н╒┐╒╕╓В╒г╒е╓Д ╒▒╒е╓А ╓Г╒╕╒╜╒┐╒и╓Й',
emailError: 'Email ╒╕╓В╒▓╒б╓А╒п╒е╒м╒╕╓В ╒к╒б╒┤╒б╒╢╒б╒п ╒┐╒е╒▓╒л ╒╕╓В╒╢╒е╓Б╒б╒╛ ╒╜╒н╒б╒м╓Й ╘╜╒╢╒д╓А╒╕╓В╒┤ ╒е╒╢╓Д ╓Г╒╕╓А╒▒╒е╒м ╒п╓А╒п╒л╒╢╓Й',
phoneRequired: '╒А╒е╒╝╒б╒н╒╕╒╜╒б╒░╒б╒┤╒б╓А╒и ╒║╒б╓А╒┐╒б╒д╒л╓А ╒з',
phoneMoreDigits: '╒Д╒╕╓В╒┐╓Д╒б╒г╓А╒е╓Д ╓З╒╜ {{count}} ╒й╒л╒╛',
phoneTooMany: '╒Й╒б╓Г╒б╒ж╒б╒╢╓Б ╒╖╒б╒┐ ╒й╒╛╒е╓А',
emailRequired: 'Email-╒и ╒║╒б╓А╒┐╒б╒д╒л╓А ╒з',
emailTooShort: 'Email-╒и ╒╣╒б╓Г╒б╒ж╒б╒╢╓Б ╒п╒б╓А╒│ ╒з (╒╢╒╛╒б╒ж╒б╒г╒╕╓В╒╡╒╢╒и 5 ╒╢╒л╒╖)',
emailTooLong: 'Email-╒и ╒╣╒б╓Г╒б╒ж╒б╒╢╓Б ╒е╓А╒п╒б╓А ╒з (╒б╒╝╒б╒╛╒е╒м╒б╒г╒╕╓В╒╡╒╢╒и 100 ╒╢╒л╒╖)',
emailNeedsAt: 'Email-╒и ╒║╒е╒┐╓Д ╒з ╒║╒б╓А╒╕╓В╒╢╒б╒п╒л @ ╒╢╒╖╒б╒╢╒и',
emailNeedsDomain: 'Email-╒и ╒║╒е╒┐╓Д ╒з ╒║╒б╓А╒╕╓В╒╢╒б╒п╒л ╒д╒╕╒┤╒е╒╢ (.com, .ru ╓З ╒б╒╡╒м╒╢)',
emailInvalid: 'Email-╒л ╒▒╓З╒б╒╣╒б╓Г╒и ╒╜╒н╒б╒м ╒з',
},
search: {
title: '╘▒╒║╓А╒б╒╢╓Д╒╢╒е╓А╒л ╒╕╓А╒╕╒╢╒╕╓В╒┤',
placeholder: '╒Д╒╕╓В╒┐╓Д╒б╒г╓А╒е╓Д ╒б╒║╓А╒б╒╢╓Д╒л ╒б╒╢╒╕╓В╒╢╒и...',
resultsCount: '╘│╒┐╒╢╒╛╒б╒о ╒б╒║╓А╒б╒╢╓Д╒╢╒е╓А╒Э',
searching: '╒И╓А╒╕╒╢╒╕╓В╒┤...',
retry: '╒У╒╕╓А╒▒╒е╒м ╒п╓А╒п╒л╒╢',
noResults: '╒И╒╣╒л╒╢╒╣ ╒╣╒л ╒г╒┐╒╢╒╛╒е╒м',
noResultsFor: '"{{query}}" ╒░╒б╓А╓Б╒┤╒б╒╢ ╒░╒б╒┤╒б╓А ╒б╒║╓А╒б╒╢╓Д╒╢╒е╓А ╒╣╒е╒╢ ╒г╒┐╒╢╒╛╒е╒м',
noResultsHint: '╒У╒╕╓А╒▒╒е╓Д ╓Г╒╕╒н╒е╒м ╒░╒б╓А╓Б╒╕╓В╒┤╒и ╒п╒б╒┤ ╓Е╒г╒┐╒б╒г╒╕╓А╒о╒е╒м ╒б╒╡╒м ╒в╒б╒╢╒б╒м╒л ╒в╒б╒╝╒е╓А',
addToCart: '╘▒╒╛╒е╒м╒б╓Б╒╢╒е╒м ╒ж╒б╒┤╒в╒╡╒╕╓В╒▓',
loadingMore: '╘▓╒е╒╝╒╢╒╛╒╕╓В╒┤ ╒з...',
allLoaded: '╘▓╒╕╒м╒╕╓А ╒б╓А╒д╒╡╒╕╓В╒╢╓Д╒╢╒е╓А╒и ╒в╒е╒╝╒╢╒╛╒б╒о ╒е╒╢',
emptyState: '╒Д╒╕╓В╒┐╓Д╒б╒г╓А╒е╓Д ╒░╒б╓А╓Б╒╕╓В╒┤ ╒б╒║╓А╒б╒╢╓Д╒╢╒е╓А ╒╕╓А╒╕╒╢╒е╒м╒╕╓В ╒░╒б╒┤╒б╓А',
of: '╒л╓Б',
},
category: {
retry: '╒У╒╕╓А╒▒╒е╒м ╒п╓А╒п╒л╒╢',
addToCart: '╘▒╒╛╒е╒м╒б╓Б╒╢╒е╒м ╒ж╒б╒┤╒в╒╡╒╕╓В╒▓',
loadingMore: '╘▓╒е╒╝╒╢╒╛╒╕╓В╒┤ ╒з...',
allLoaded: '╘▓╒╕╒м╒╕╓А ╒б╒║╓А╒б╒╢╓Д╒╢╒е╓А╒и ╒в╒е╒╝╒╢╒╛╒б╒о ╒е╒╢',
emptyTitle: '╒И╓В╒║╒╜╓Й ╘▒╒╡╒╜╒┐╒е╒▓ ╒д╒е╒╝ ╒д╒б╒┐╒б╓А╒п ╒з',
emptyDesc: '╘▒╒╡╒╜ ╒п╒б╒┐╒е╒г╒╕╓А╒л╒б╒╡╒╕╓В╒┤ ╒д╒е╒╝ ╒б╒║╓А╒б╒╢╓Д╒╢╒е╓А ╒╣╒п╒б╒╢, ╒в╒б╒╡╓Б ╒╖╒╕╓В╒┐╒╕╒╛ ╒п╒░╒б╒╡╒┐╒╢╒╛╒е╒╢',
goHome: '╘│╒м╒н╒б╒╛╒╕╓А ╒з╒╗',
loading: '╘▒╒║╓А╒б╒╢╓Д╒╢╒е╓А╒и ╒в╒е╒╝╒╢╒╛╒╕╓В╒┤ ╒е╒╢...',
},
subcategories: {
loading: '╘╡╒╢╒й╒б╒п╒б╒┐╒е╒г╒╕╓А╒л╒б╒╢╒е╓А╒и ╒в╒е╒╝╒╢╒╛╒╕╓В╒┤ ╒е╒╢...',
retry: '╒У╒╕╓А╒▒╒е╒м ╒п╓А╒п╒л╒╢',
emptyTitle: '╒И╓В╒║╒╜╓Й ╘╡╒╢╒й╒б╒п╒б╒┐╒е╒г╒╕╓А╒л╒б╒╢╒е╓А ╒д╒е╒╝ ╒╣╒п╒б╒╢',
emptyDesc: '╘▒╒╡╒╜ ╒в╒б╒к╒╢╒╕╓В╒┤ ╒д╒е╒╝ ╒е╒╢╒й╒б╒п╒б╒┐╒е╒г╒╕╓А╒л╒б╒╢╒е╓А ╒╣╒п╒б╒╢, ╒в╒б╒╡╓Б ╒╖╒╕╓В╒┐╒╕╒╛ ╒п╒░╒б╒╡╒┐╒╢╒╛╒е╒╢',
goHome: '╘│╒м╒н╒б╒╛╒╕╓А ╒з╒╗',
},
itemDetail: {
loading: '╘▓╒е╒╝╒╢╒╛╒╕╓В╒┤ ╒з...',
loadingDexar: '╘▒╒║╓А╒б╒╢╓Д╒и ╒в╒е╒╝╒╢╒╛╒╕╓В╒┤ ╒з...',
back: '╒О╒е╓А╒б╒д╒б╒╝╒╢╒б╒м',
backHome: '╒О╒е╓А╒б╒д╒б╒╝╒╢╒б╒м ╒г╒м╒н╒б╒╛╒╕╓А ╒з╒╗',
noImage: '╒К╒б╒┐╒п╒е╓А ╒╣╒п╒б',
stock: '╘▒╒╝╒п╒б╒╡╒╕╓В╒й╒╡╒╕╓В╒╢╒Э',
inStock: '╘▒╒╝╒п╒б ╒з',
lowStock: '╒Д╒╢╒б╓Б╒е╒м ╒з ╓Д╒л╒╣',
lastItems: '╒О╒е╓А╒╗╒л╒╢ ╒░╒б╒┐╒е╓А╒и',
mediumStock: '╒О╒е╓А╒╗╒б╒╢╒╕╓В╒┤ ╒з',
addToCart: '╘▒╒╛╒е╒м╒б╓Б╒╢╒е╒м ╒ж╒б╒┤╒в╒╡╒╕╓В╒▓',
description: '╒Ж╒п╒б╓А╒б╒г╓А╒╕╓В╒й╒╡╒╕╓В╒╢',
specifications: 'u{0532}u{0576}u{0578}u{0582}u{0569}u{0561}u{0563}u{0580}u{0565}u{0580}',
reviews: '╘┐╒б╓А╒о╒л╓Д╒╢╒е╓А',
yourReview: '╒Б╒е╓А ╒п╒б╓А╒о╒л╓Д╒и',
leaveReview: '╘╣╒╕╒▓╒╢╒е╒м ╒п╒б╓А╒о╒л╓Д',
rating: '╘│╒╢╒б╒░╒б╒┐╒б╒п╒б╒╢╒Э',
reviewPlaceholder: '╘┐╒л╒╜╒╛╒е╓Д ╒▒╒е╓А ╒┐╒║╒б╒╛╒╕╓А╒╕╓В╒й╒╡╒╕╓В╒╢╒╢╒е╓А╒╕╒╛ ╒б╒║╓А╒б╒╢╓Д╒л ╒┤╒б╒╜╒л╒╢...',
reviewPlaceholderDexar: '╘┐╒л╒╜╒╛╒е╓Д ╒▒╒е╓А ╒┐╒║╒б╒╛╒╕╓А╒╕╓В╒й╒╡╒╕╓В╒╢╒╢╒е╓А╒╕╒╛...',
anonymous: '╘▒╒╢╒б╒╢╒╕╓В╒╢',
submitting: '╒И╓В╒▓╒б╓А╒п╒╛╒╕╓В╒┤ ╒з...',
submit: '╒И╓В╒▓╒б╓А╒п╒е╒м',
reviewSuccess: '╒З╒╢╒╕╓А╒░╒б╒п╒б╒м╒╕╓В╒й╒╡╒╕╓В╒╢ ╒▒╒е╓А ╒п╒б╓А╒о╒л╓Д╒л ╒░╒б╒┤╒б╓А╓Й',
reviewError: '╒И╓В╒▓╒б╓А╒п╒┤╒б╒╢ ╒╜╒н╒б╒м╓Й ╒У╒╕╓А╒▒╒е╓Д ╒б╒╛╒е╒м╒л ╒╕╓В╒╖╓Й',
defaultUser: '╒Х╒г╒┐╒б╒┐╒е╓А',
defaultUserDexar: '╘▒╒╢╒б╒╢╒╕╓В╒╢',
noReviews: '╘┤╒е╒╝ ╒п╒б╓А╒о╒л╓Д╒╢╒е╓А ╒╣╒п╒б╒╢╓Й ╘┤╒б╓А╒▒╒е╓Д ╒б╒╝╒б╒╗╒л╒╢╒и╓Й',
qna: '╒А╒б╓А╓Б╒е╓А ╓З ╒║╒б╒┐╒б╒╜╒н╒б╒╢╒╢╒е╓А',
photo: '╘╝╒╕╓В╒╜╒б╒╢╒п╒б╓А',
reviewsCount: '╒п╒б╓А╒о╒л╓Д',
today: '╘▒╒╡╒╜╓Е╓А',
yesterday: '╘╡╓А╒е╒п',
daysAgo: '╓Е╓А ╒б╒╝╒б╒╗',
weeksAgo: '╒╖╒б╒в╒б╒й ╒б╒╝╒б╒╗',
},
app: {
connecting: '╒Д╒л╒б╓Б╒╕╓В╒┤ ╒╜╒е╓А╒╛╒е╓А╒л╒╢...',
serverUnavailable: '╒Н╒е╓А╒╛╒е╓А╒и ╒░╒б╒╜╒б╒╢╒е╒м╒л ╒╣╒з',
serverError: '╒Й╒░╒б╒╗╒╕╒▓╒╛╒е╓Б ╒┤╒л╒б╒╢╒б╒м ╒╜╒е╓А╒╛╒е╓А╒л╒╢╓Й ╒Н╒┐╒╕╓В╒г╒е╓Д ╒л╒╢╒┐╒е╓А╒╢╒е╒┐ ╒п╒б╒║╒и╓Й',
retryConnection: '╘┐╓А╒п╒╢╒е╒м ╓Г╒╕╓А╒▒╒и',
pageTitle: '╘▒╒║╓А╒б╒╢╓Д╒╢╒е╓А╒л ╓З ╒о╒б╒╝╒б╒╡╒╕╓В╒й╒╡╒╕╓В╒╢╒╢╒е╓А╒л ╒┤╒б╓А╓Д╒е╒й╓Г╒м╒е╒╡╒╜',
},
carousel: {
loading: '╘▒╒║╓А╒б╒╢╓Д╒╢╒е╓А╒и ╒в╒е╒╝╒╢╒╛╒╕╓В╒┤ ╒е╒╢...',
addToCart: '╘▒╒╛╒е╒м╒б╓Б╒╢╒е╒м ╒ж╒б╒┤╒в╒╡╒╕╓В╒▓',
},
common: {
retry: '╒У╒╕╓А╒▒╒е╒м ╒п╓А╒п╒л╒╢',
loading: '╘▓╒е╒╝╒╢╒╛╒╕╓В╒┤ ╒з...',
},
};

189
src/app/i18n/ru.ts Normal file
View File

@@ -0,0 +1,189 @@
import { Translations } from './translations';
export const ru: Translations = {
header: {
home: 'Главная',
search: 'Поиск',
about: 'О нас',
contacts: 'Контакты',
searchPlaceholder: 'Искать...',
catalog: 'Каталог',
},
footer: {
description: 'Современный маркетплейс для комфортных покупок',
company: 'Компания',
aboutUs: 'О нас',
contacts: 'Контакты',
requisites: 'Реквизиты',
support: 'Поддержка',
faq: 'FAQ',
delivery: 'Доставка',
guarantee: 'Гарантия',
legal: 'Правовая информация',
offer: 'Оферта',
privacy: 'Конфиденциальность',
returns: 'Возврат',
info: 'Информация',
aboutCompany: 'О компании',
documents: 'Документы',
paymentRules: 'Правила оплаты',
returnPolicy: 'Политика возврата',
publicOffer: 'Публичная оферта',
help: 'Помощь',
payment: 'Оплата',
allRightsReserved: 'Все права защищены.',
},
home: {
welcomeTo: 'Добро пожаловать в {{brand}}',
subtitle: 'Найдите всё, что нужно, в одном месте',
startSearch: 'Начать поиск',
loading: 'Загружаем категории...',
errorTitle: 'Что-то пошло не так',
retry: 'Попробовать снова',
categoriesTitle: 'Категории товаров',
categoriesSubtitle: 'Выберите интересующую категорию',
categoriesEmpty: 'Категории скоро появятся',
categoriesEmptyDesc: 'Мы работаем над наполнением каталога',
dexarHeroTitle: 'Здесь ты найдёшь всё',
dexarHeroSubtitle: 'Тысячи товаров в одном месте',
dexarHeroTagline: 'просто и удобно',
goToCatalog: 'Перейти в каталог',
findProduct: 'Найти товар',
loadingDexar: 'Загрузка категорий...',
catalogTitle: 'Каталог товаров',
emptyCategoriesDexar: 'Категории пока отсутствуют',
categoriesSoonDexar: 'Скоро здесь появятся категории товаров',
itemsCount: '{{count}} товаров',
},
cart: {
title: 'Корзина',
clear: 'Очистить',
empty: 'Корзина пуста',
emptyDesc: 'Добавьте товары, чтобы начать покупки',
goShopping: 'Перейти к покупкам',
total: 'Итого',
items: 'Товары',
deliveryLabel: 'Доставка',
toPay: 'К оплате',
agreeWith: 'Я согласен с',
publicOffer: 'публичной офертой',
returnPolicy: 'политикой возврата',
guaranteeTerms: 'условиями гарантии',
privacyPolicy: 'политикой конфиденциальности',
and: 'и',
checkout: 'Оформить заказ',
close: 'Закрыть',
creatingPayment: 'Создание платежа...',
waitFewSeconds: 'Подождите несколько секунд',
scanQr: 'Сканируйте QR-код для оплаты',
amountToPay: 'Сумма к оплате:',
waitingPayment: 'Ожидание оплаты...',
copied: '✓ Скопировано',
copyLink: 'Скопировать ссылку',
openNewTab: 'Открыть в новой вкладке',
paymentSuccess: 'Поздравляем! Оплата прошла успешно!',
paymentSuccessDesc: 'Введите ваши контактные данные, и мы отправим вам покупку в течение нескольких минут',
sending: 'Отправка...',
send: 'Отправить',
paymentTimeout: 'Время ожидания истекло',
paymentTimeoutDesc: 'Мы не получили подтверждение оплаты в течение 3 минут.',
autoClose: 'Окно закроется автоматически...',
confirmClear: 'Вы уверены, что хотите очистить корзину?',
acceptTerms: 'Пожалуйста, примите условия оферты, политику возврата и возврата для подтверждения оформления заказа.',
copyError: 'Ошибка копирования:',
emailSuccess: 'Email успешно отправлен! Проверьте свою почту.',
emailError: 'Произошла ошибка при отправке email. Пожалуйста, попробуйте снова.',
phoneRequired: 'Номер телефона обязателен',
phoneMoreDigits: 'Введите ещё {{count}} цифр',
phoneTooMany: 'Слишком много цифр',
emailRequired: 'Email обязателен',
emailTooShort: 'Email слишком короткий (минимум 5 символов)',
emailTooLong: 'Email слишком длинный (максимум 100 символов)',
emailNeedsAt: 'Email должен содержать @',
emailNeedsDomain: 'Email должен содержать домен (.com, .ru и т.д.)',
emailInvalid: 'Некорректный формат email',
},
search: {
title: 'Поиск товаров',
placeholder: 'Введите название товара...',
resultsCount: 'Найдено товаров:',
searching: 'Поиск...',
retry: 'Попробовать снова',
noResults: 'Ничего не найдено',
noResultsFor: 'По запросу "{{query}}" товары не найдены',
noResultsHint: 'Попробуйте изменить запрос или используйте другие ключевые слова',
addToCart: 'В корзину',
loadingMore: 'Загрузка...',
allLoaded: 'Все результаты загружены',
emptyState: 'Введите запрос для поиска товаров',
of: 'из',
},
category: {
retry: 'Попробовать снова',
addToCart: 'В корзину',
loadingMore: 'Загрузка...',
allLoaded: 'Все товары загружены',
emptyTitle: 'Упс! Здесь пока пусто',
emptyDesc: 'В этой категории ещё нет товаров, но скоро они появятся',
goHome: 'На главную',
loading: 'Загрузка товаров...',
},
subcategories: {
loading: 'Загрузка подкатегорий...',
retry: 'Попробовать снова',
emptyTitle: 'Упс! Подкатегорий пока нет',
emptyDesc: 'В этом разделе ещё нет подкатегорий, но скоро они появятся',
goHome: 'На главную',
},
itemDetail: {
loading: 'Загрузка...',
loadingDexar: 'Загрузка товара...',
back: 'Вернуться',
backHome: 'Вернуться на главную',
noImage: 'Нет изображения',
stock: 'Наличие:',
inStock: 'В наличии',
lowStock: 'Осталось немного',
lastItems: 'Последние штуки',
mediumStock: 'Заканчивается',
addToCart: 'Добавить в корзину',
description: 'Описание',
specifications: 'Характеристики',
reviews: 'Отзывы',
yourReview: 'Ваш отзыв',
leaveReview: 'Оставить отзыв',
rating: 'Оценка:',
reviewPlaceholder: 'Поделитесь своими впечатлениями о товаре...',
reviewPlaceholderDexar: 'Поделитесь впечатлениями о товаре...',
anonymous: 'Анонимно',
submitting: 'Отправка...',
submit: 'Отправить',
reviewSuccess: 'Спасибо за ваш отзыв!',
reviewError: 'Ошибка отправки. Попробуйте позже.',
defaultUser: 'Пользователь',
defaultUserDexar: 'Аноним',
noReviews: 'Пока нет отзывов. Станьте первым!',
qna: 'Вопросы и ответы',
photo: 'Фото',
reviewsCount: 'отзывов',
today: 'Сегодня',
yesterday: 'Вчера',
daysAgo: 'дн. назад',
weeksAgo: 'нед. назад',
},
app: {
connecting: 'Подключение к серверу...',
serverUnavailable: 'Сервер недоступен',
serverError: 'Не удалось подключиться к серверу. Проверьте подключение к интернету.',
retryConnection: 'Повторить попытку',
pageTitle: 'Маркетплейс товаров и услуг',
},
carousel: {
loading: 'Загрузка товаров...',
addToCart: 'Добавить в корзину',
},
common: {
retry: 'Попробовать снова',
loading: 'Загрузка...',
},
};

View File

@@ -0,0 +1,14 @@
import { Pipe, PipeTransform, inject } from '@angular/core';
import { TranslateService } from './translate.service';
@Pipe({
name: 'translate',
pure: false,
})
export class TranslatePipe implements PipeTransform {
private translateService = inject(TranslateService);
transform(key: string, params?: Record<string, string | number>): string {
return this.translateService.t(key, params);
}
}

View File

@@ -0,0 +1,48 @@
import { Injectable, computed, inject } from '@angular/core';
import { LanguageService } from '../services/language.service';
import { Translations } from './translations';
import { ru } from './ru';
import { en } from './en';
import { hy } from './hy';
const translationMap: Record<string, Translations> = { ru, en, hy };
@Injectable({
providedIn: 'root',
})
export class TranslateService {
private langService = inject(LanguageService);
readonly translations = computed<Translations>(
() => translationMap[this.langService.currentLanguage()] ?? ru,
);
/**
* Translate a dot-separated key with optional interpolation params.
* Usage: t('cart.phoneMoreDigits', { count: 3 }) → "Введите ещё 3 цифр"
*/
t(key: string, params?: Record<string, string | number>): string {
const parts = key.split('.');
let result: unknown = this.translations();
for (const part of parts) {
if (result && typeof result === 'object') {
result = (result as Record<string, unknown>)[part];
} else {
return key;
}
}
if (typeof result !== 'string') {
return key;
}
if (params) {
return result.replace(/\{\{(\w+)\}\}/g, (_, k) =>
params[k] !== undefined ? String(params[k]) : `{{${k}}}`,
);
}
return result;
}
}

View File

@@ -0,0 +1,187 @@
export interface Translations {
header: {
home: string;
search: string;
about: string;
contacts: string;
searchPlaceholder: string;
catalog: string;
};
footer: {
description: string;
company: string;
aboutUs: string;
contacts: string;
requisites: string;
support: string;
faq: string;
delivery: string;
guarantee: string;
legal: string;
offer: string;
privacy: string;
returns: string;
info: string;
aboutCompany: string;
documents: string;
paymentRules: string;
returnPolicy: string;
publicOffer: string;
help: string;
payment: string;
allRightsReserved: string;
};
home: {
welcomeTo: string;
subtitle: string;
startSearch: string;
loading: string;
errorTitle: string;
retry: string;
categoriesTitle: string;
categoriesSubtitle: string;
categoriesEmpty: string;
categoriesEmptyDesc: string;
dexarHeroTitle: string;
dexarHeroSubtitle: string;
dexarHeroTagline: string;
goToCatalog: string;
findProduct: string;
loadingDexar: string;
catalogTitle: string;
emptyCategoriesDexar: string;
categoriesSoonDexar: string;
itemsCount: string;
};
cart: {
title: string;
clear: string;
empty: string;
emptyDesc: string;
goShopping: string;
total: string;
items: string;
deliveryLabel: string;
toPay: string;
agreeWith: string;
publicOffer: string;
returnPolicy: string;
guaranteeTerms: string;
privacyPolicy: string;
and: string;
checkout: string;
close: string;
creatingPayment: string;
waitFewSeconds: string;
scanQr: string;
amountToPay: string;
waitingPayment: string;
copied: string;
copyLink: string;
openNewTab: string;
paymentSuccess: string;
paymentSuccessDesc: string;
sending: string;
send: string;
paymentTimeout: string;
paymentTimeoutDesc: string;
autoClose: string;
confirmClear: string;
acceptTerms: string;
copyError: string;
emailSuccess: string;
emailError: string;
phoneRequired: string;
phoneMoreDigits: string;
phoneTooMany: string;
emailRequired: string;
emailTooShort: string;
emailTooLong: string;
emailNeedsAt: string;
emailNeedsDomain: string;
emailInvalid: string;
};
search: {
title: string;
placeholder: string;
resultsCount: string;
searching: string;
retry: string;
noResults: string;
noResultsFor: string;
noResultsHint: string;
addToCart: string;
loadingMore: string;
allLoaded: string;
emptyState: string;
of: string;
};
category: {
retry: string;
addToCart: string;
loadingMore: string;
allLoaded: string;
emptyTitle: string;
emptyDesc: string;
goHome: string;
loading: string;
};
subcategories: {
loading: string;
retry: string;
emptyTitle: string;
emptyDesc: string;
goHome: string;
};
itemDetail: {
loading: string;
loadingDexar: string;
back: string;
backHome: string;
noImage: string;
stock: string;
inStock: string;
lowStock: string;
lastItems: string;
mediumStock: string;
addToCart: string;
description: string;
specifications: string;
reviews: string;
yourReview: string;
leaveReview: string;
rating: string;
reviewPlaceholder: string;
reviewPlaceholderDexar: string;
anonymous: string;
submitting: string;
submit: string;
reviewSuccess: string;
reviewError: string;
defaultUser: string;
defaultUserDexar: string;
noReviews: string;
qna: string;
photo: string;
reviewsCount: string;
today: string;
yesterday: string;
daysAgo: string;
weeksAgo: string;
};
app: {
connecting: string;
serverUnavailable: string;
serverError: string;
retryConnection: string;
pageTitle: string;
};
carousel: {
loading: string;
addToCart: string;
};
common: {
retry: string;
loading: string;
};
}