fix: accordion content padding for online-board-filter component
@@ -400,18 +400,27 @@
|
||||
"END_DATE": "Enddatum",
|
||||
"FLIGHT": "Flug",
|
||||
"FROM": "Von",
|
||||
"ONE_WAY": "Einzelstrecke",
|
||||
"ONE_WAY": "One Way",
|
||||
"OPERATOR": "Betreiber",
|
||||
"REMARKS": "Anmerkungen",
|
||||
"RETURN_DATE": "Rückflugdatum",
|
||||
"ROUND_TRIP": "Hin- und Rückflug",
|
||||
"ROUND_TRIP": "Round Trip",
|
||||
"ROUTE": "Route",
|
||||
"SEARCH_HISTORY": "Suchverlauf",
|
||||
"SELECT_CITY": "Stadt wählen",
|
||||
"SELECT_CITY": "Select City",
|
||||
"START_DATE": "Startdatum",
|
||||
"STATUS": "Status",
|
||||
"TO": "Nach",
|
||||
"TRIP_TYPE": "Reisetyp"
|
||||
"TRIP_TYPE": "Trip Type",
|
||||
"CABIN_CLASS": "Cabin Class",
|
||||
"ECONOMY": "Economy",
|
||||
"BUSINESS": "Business",
|
||||
"FIRST": "First Class",
|
||||
"PASSENGERS": "Passengers",
|
||||
"ADULTS": "Adults",
|
||||
"CHILDREN": "Children",
|
||||
"INFANTS": "Infants",
|
||||
"MULTICITY": "Multi-City"
|
||||
},
|
||||
"WARNING": {
|
||||
"IFLY_HIGHLIGHT": "Bitte beachten Sie:",
|
||||
|
||||
@@ -412,7 +412,16 @@
|
||||
"START_DATE": "Start Date",
|
||||
"STATUS": "Status",
|
||||
"TO": "To",
|
||||
"TRIP_TYPE": "Trip Type"
|
||||
"TRIP_TYPE": "Trip Type",
|
||||
"CABIN_CLASS": "Cabin Class",
|
||||
"ECONOMY": "Economy",
|
||||
"BUSINESS": "Business",
|
||||
"FIRST": "First Class",
|
||||
"PASSENGERS": "Passengers",
|
||||
"ADULTS": "Adults",
|
||||
"CHILDREN": "Children",
|
||||
"INFANTS": "Infants",
|
||||
"MULTICITY": "Multi-City"
|
||||
},
|
||||
"WARNING": {
|
||||
"IFLY_HIGHLIGHT": "Please note:",
|
||||
|
||||
@@ -400,18 +400,27 @@
|
||||
"END_DATE": "Fecha de finalización",
|
||||
"FLIGHT": "Vuelo",
|
||||
"FROM": "De",
|
||||
"ONE_WAY": "Solo ida",
|
||||
"ONE_WAY": "One Way",
|
||||
"OPERATOR": "Operador",
|
||||
"REMARKS": "Observaciones",
|
||||
"RETURN_DATE": "Fecha de regreso",
|
||||
"ROUND_TRIP": "Ida y vuelta",
|
||||
"ROUND_TRIP": "Round Trip",
|
||||
"ROUTE": "Ruta",
|
||||
"SEARCH_HISTORY": "Historial de búsqueda",
|
||||
"SELECT_CITY": "Seleccionar ciudad",
|
||||
"SELECT_CITY": "Select City",
|
||||
"START_DATE": "Fecha de inicio",
|
||||
"STATUS": "Estado",
|
||||
"TO": "A",
|
||||
"TRIP_TYPE": "Tipo de viaje"
|
||||
"TRIP_TYPE": "Trip Type",
|
||||
"CABIN_CLASS": "Cabin Class",
|
||||
"ECONOMY": "Economy",
|
||||
"BUSINESS": "Business",
|
||||
"FIRST": "First Class",
|
||||
"PASSENGERS": "Passengers",
|
||||
"ADULTS": "Adults",
|
||||
"CHILDREN": "Children",
|
||||
"INFANTS": "Infants",
|
||||
"MULTICITY": "Multi-City"
|
||||
},
|
||||
"WARNING": {
|
||||
"IFLY_HIGHLIGHT": "Nota:",
|
||||
|
||||
@@ -400,18 +400,27 @@
|
||||
"END_DATE": "Date de fin",
|
||||
"FLIGHT": "Vol",
|
||||
"FROM": "De",
|
||||
"ONE_WAY": "Aller simple",
|
||||
"ONE_WAY": "One Way",
|
||||
"OPERATOR": "Exploitant",
|
||||
"REMARKS": "Remarques",
|
||||
"RETURN_DATE": "Date de retour",
|
||||
"ROUND_TRIP": "Aller-retour",
|
||||
"ROUND_TRIP": "Round Trip",
|
||||
"ROUTE": "Itinéraire",
|
||||
"SEARCH_HISTORY": "Historique de recherche",
|
||||
"SELECT_CITY": "Sélectionner une ville",
|
||||
"SELECT_CITY": "Select City",
|
||||
"START_DATE": "Date de début",
|
||||
"STATUS": "Statut",
|
||||
"TO": "À",
|
||||
"TRIP_TYPE": "Type de voyage"
|
||||
"TRIP_TYPE": "Trip Type",
|
||||
"CABIN_CLASS": "Cabin Class",
|
||||
"ECONOMY": "Economy",
|
||||
"BUSINESS": "Business",
|
||||
"FIRST": "First Class",
|
||||
"PASSENGERS": "Passengers",
|
||||
"ADULTS": "Adults",
|
||||
"CHILDREN": "Children",
|
||||
"INFANTS": "Infants",
|
||||
"MULTICITY": "Multi-City"
|
||||
},
|
||||
"WARNING": {
|
||||
"IFLY_HIGHLIGHT": "Remarque:",
|
||||
|
||||
@@ -400,18 +400,27 @@
|
||||
"END_DATE": "Data di fine",
|
||||
"FLIGHT": "Volo",
|
||||
"FROM": "Da",
|
||||
"ONE_WAY": "Solo andata",
|
||||
"ONE_WAY": "One Way",
|
||||
"OPERATOR": "Operatore",
|
||||
"REMARKS": "Osservazioni",
|
||||
"RETURN_DATE": "Data di ritorno",
|
||||
"ROUND_TRIP": "Andata e ritorno",
|
||||
"ROUND_TRIP": "Round Trip",
|
||||
"ROUTE": "Percorso",
|
||||
"SEARCH_HISTORY": "Cronologia ricerche",
|
||||
"SELECT_CITY": "Seleziona città",
|
||||
"SELECT_CITY": "Select City",
|
||||
"START_DATE": "Data di inizio",
|
||||
"STATUS": "Stato",
|
||||
"TO": "A",
|
||||
"TRIP_TYPE": "Tipo di viaggio"
|
||||
"TRIP_TYPE": "Trip Type",
|
||||
"CABIN_CLASS": "Cabin Class",
|
||||
"ECONOMY": "Economy",
|
||||
"BUSINESS": "Business",
|
||||
"FIRST": "First Class",
|
||||
"PASSENGERS": "Passengers",
|
||||
"ADULTS": "Adults",
|
||||
"CHILDREN": "Children",
|
||||
"INFANTS": "Infants",
|
||||
"MULTICITY": "Multi-City"
|
||||
},
|
||||
"WARNING": {
|
||||
"IFLY_HIGHLIGHT": "Attenzione:",
|
||||
|
||||
@@ -400,18 +400,27 @@
|
||||
"END_DATE": "終了日",
|
||||
"FLIGHT": "フライト",
|
||||
"FROM": "から",
|
||||
"ONE_WAY": "片道",
|
||||
"ONE_WAY": "One Way",
|
||||
"OPERATOR": "運航者",
|
||||
"REMARKS": "備考",
|
||||
"RETURN_DATE": "帰宅日",
|
||||
"ROUND_TRIP": "往復",
|
||||
"ROUND_TRIP": "Round Trip",
|
||||
"ROUTE": "ルート",
|
||||
"SEARCH_HISTORY": "検索履歴",
|
||||
"SELECT_CITY": "都市を選択",
|
||||
"SELECT_CITY": "Select City",
|
||||
"START_DATE": "開始日",
|
||||
"STATUS": "ステータス",
|
||||
"TO": "へ",
|
||||
"TRIP_TYPE": "トリップタイプ"
|
||||
"TRIP_TYPE": "Trip Type",
|
||||
"CABIN_CLASS": "Cabin Class",
|
||||
"ECONOMY": "Economy",
|
||||
"BUSINESS": "Business",
|
||||
"FIRST": "First Class",
|
||||
"PASSENGERS": "Passengers",
|
||||
"ADULTS": "Adults",
|
||||
"CHILDREN": "Children",
|
||||
"INFANTS": "Infants",
|
||||
"MULTICITY": "Multi-City"
|
||||
},
|
||||
"WARNING": {
|
||||
"IFLY_HIGHLIGHT": "ご注意:",
|
||||
|
||||
@@ -400,18 +400,27 @@
|
||||
"END_DATE": "종료 날짜",
|
||||
"FLIGHT": "항공편",
|
||||
"FROM": "에서",
|
||||
"ONE_WAY": "편도",
|
||||
"ONE_WAY": "One Way",
|
||||
"OPERATOR": "운영사",
|
||||
"REMARKS": "비고",
|
||||
"RETURN_DATE": "귀가 날짜",
|
||||
"ROUND_TRIP": "왕복",
|
||||
"ROUND_TRIP": "Round Trip",
|
||||
"ROUTE": "경로",
|
||||
"SEARCH_HISTORY": "검색 기록",
|
||||
"SELECT_CITY": "도시 선택",
|
||||
"SELECT_CITY": "Select City",
|
||||
"START_DATE": "시작 날짜",
|
||||
"STATUS": "상태",
|
||||
"TO": "에",
|
||||
"TRIP_TYPE": "여행 유형"
|
||||
"TRIP_TYPE": "Trip Type",
|
||||
"CABIN_CLASS": "Cabin Class",
|
||||
"ECONOMY": "Economy",
|
||||
"BUSINESS": "Business",
|
||||
"FIRST": "First Class",
|
||||
"PASSENGERS": "Passengers",
|
||||
"ADULTS": "Adults",
|
||||
"CHILDREN": "Children",
|
||||
"INFANTS": "Infants",
|
||||
"MULTICITY": "Multi-City"
|
||||
},
|
||||
"WARNING": {
|
||||
"IFLY_HIGHLIGHT": "참고:",
|
||||
|
||||
@@ -412,7 +412,7 @@
|
||||
"CLEAR": "Очистить",
|
||||
"END_DATE": "Дата окончания",
|
||||
"FLIGHT": "Рейс",
|
||||
"ONE_WAY": "В одну сторону",
|
||||
"ONE_WAY": "Туда",
|
||||
"OPERATOR": "Перевозчик",
|
||||
"REMARKS": "Примечания",
|
||||
"RETURN_DATE": "Дата возврата",
|
||||
@@ -421,7 +421,16 @@
|
||||
"SELECT_CITY": "Выберите город",
|
||||
"START_DATE": "Дата начала",
|
||||
"STATUS": "Статус",
|
||||
"TRIP_TYPE": "Тип поездки"
|
||||
"TRIP_TYPE": "Тип поездки",
|
||||
"CABIN_CLASS": "Класс салона",
|
||||
"ECONOMY": "Эконом",
|
||||
"BUSINESS": "Бизнес",
|
||||
"FIRST": "Первый класс",
|
||||
"PASSENGERS": "Пассажиры",
|
||||
"ADULTS": "Взрослые",
|
||||
"CHILDREN": "Дети",
|
||||
"INFANTS": "Младенцы",
|
||||
"MULTICITY": "Многоугольный маршрут"
|
||||
},
|
||||
"WARNING": {
|
||||
"IFLY_HIGHLIGHT": "Обратите внимание!",
|
||||
|
||||
@@ -400,18 +400,27 @@
|
||||
"END_DATE": "结束日期",
|
||||
"FLIGHT": "航班",
|
||||
"FROM": "从",
|
||||
"ONE_WAY": "单程",
|
||||
"ONE_WAY": "One Way",
|
||||
"OPERATOR": "运营商",
|
||||
"REMARKS": "备注",
|
||||
"RETURN_DATE": "返回日期",
|
||||
"ROUND_TRIP": "往返",
|
||||
"ROUND_TRIP": "Round Trip",
|
||||
"ROUTE": "路线",
|
||||
"SEARCH_HISTORY": "搜索历史",
|
||||
"SELECT_CITY": "选择城市",
|
||||
"SELECT_CITY": "Select City",
|
||||
"START_DATE": "开始日期",
|
||||
"STATUS": "状态",
|
||||
"TO": "到",
|
||||
"TRIP_TYPE": "旅行类型"
|
||||
"TRIP_TYPE": "Trip Type",
|
||||
"CABIN_CLASS": "Cabin Class",
|
||||
"ECONOMY": "Economy",
|
||||
"BUSINESS": "Business",
|
||||
"FIRST": "First Class",
|
||||
"PASSENGERS": "Passengers",
|
||||
"ADULTS": "Adults",
|
||||
"CHILDREN": "Children",
|
||||
"INFANTS": "Infants",
|
||||
"MULTICITY": "Multi-City"
|
||||
},
|
||||
"WARNING": {
|
||||
"IFLY_HIGHLIGHT": "请注意:",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.page-layout {
|
||||
display: grid;
|
||||
grid-template-columns: 300px 1fr;
|
||||
grid-template-columns: 285px 1fr;
|
||||
gap: 20px;
|
||||
min-height: calc(100vh - 60px);
|
||||
padding: 20px;
|
||||
|
||||
@@ -1,23 +1,21 @@
|
||||
.online-board-filter {
|
||||
width: 100%;
|
||||
|
||||
:global {
|
||||
.p-accordion {
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
|
||||
.p-accordion-header {
|
||||
padding: 0;
|
||||
|
||||
a {
|
||||
padding: 12px 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.p-accordion-content {
|
||||
padding: 0 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.online-board-filter .p-accordion {
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.online-board-filter .p-accordion-header {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.online-board-filter .p-accordion-header a {
|
||||
padding: 12px 16px !important;
|
||||
font-weight: 500 !important;
|
||||
}
|
||||
|
||||
.online-board-filter .p-accordion-content {
|
||||
padding: 5px 20px 20px 20px !important;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
font-weight: 500;
|
||||
color: #666;
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.route-filter__swap {
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import i18n from 'i18next'
|
||||
import HttpBackend from 'i18next-http-backend'
|
||||
import { initReactI18next } from 'react-i18next'
|
||||
|
||||
// Language detection logic (simplified without additional dependency)
|
||||
// Language detection logic
|
||||
const getInitialLanguage = (): string => {
|
||||
// Try to get from localStorage
|
||||
const stored = localStorage.getItem('i18nextLng')
|
||||
if (stored) return stored
|
||||
|
||||
// Try to get from URL path (:lang parameter)
|
||||
const pathLang = window.location.pathname.split('/')[1]
|
||||
const supportedLanguages = ['ru', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'de', 'zh']
|
||||
|
||||
// Handle locale codes like ru-ru, en-us, etc.
|
||||
const langCode = pathLang?.split('-')[0]
|
||||
if (supportedLanguages.includes(langCode)) {
|
||||
return langCode
|
||||
@@ -22,45 +18,78 @@ const getInitialLanguage = (): string => {
|
||||
return pathLang
|
||||
}
|
||||
|
||||
// Try to get from navigator
|
||||
const nav = navigator.language || (navigator as any).userLanguage
|
||||
const userLang = nav.split('-')[0]
|
||||
|
||||
// Check if user language is supported
|
||||
if (supportedLanguages.includes(userLang)) {
|
||||
return userLang
|
||||
}
|
||||
|
||||
// Default to Russian
|
||||
return 'ru'
|
||||
}
|
||||
|
||||
// Flatten nested JSON structure
|
||||
const flattenTranslations = (obj: any, prefix = ''): any => {
|
||||
const result: any = {}
|
||||
for (const [key, value] of Object.entries(obj)) {
|
||||
const fullKey = prefix ? `${prefix}.${key}` : key
|
||||
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
||||
Object.assign(result, flattenTranslations(value, fullKey))
|
||||
} else {
|
||||
result[fullKey] = value
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
const lng = getInitialLanguage()
|
||||
const supportedLanguages = ['ru', 'en', 'es', 'fr', 'it', 'ja', 'ko', 'de', 'zh']
|
||||
|
||||
// Build resources object by fetching all language files
|
||||
const resources: Record<string, any> = {}
|
||||
|
||||
// Pre-populate with empty resources to avoid warnings
|
||||
for (const lang of supportedLanguages) {
|
||||
resources[lang] = { translation: {} }
|
||||
}
|
||||
|
||||
// Initialize i18next with empty resources
|
||||
i18n
|
||||
.use(HttpBackend)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
fallbackLng: 'ru',
|
||||
lng: getInitialLanguage(),
|
||||
lng,
|
||||
defaultNS: 'translation',
|
||||
ns: ['translation'],
|
||||
detection: {
|
||||
order: ['localStorage', 'navigator'],
|
||||
caches: ['localStorage'],
|
||||
},
|
||||
backend: {
|
||||
loadPath: '/assets/i18n/{{lng}}.json',
|
||||
},
|
||||
resources,
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
react: {
|
||||
useSuspense: false,
|
||||
bindI18n: 'languageChanged loaded',
|
||||
bindI18nStore: 'added removed',
|
||||
transEmptyNodeValue: '',
|
||||
transSupportBasicHtmlNodes: true,
|
||||
},
|
||||
nonExplicitSupportedLngs: true,
|
||||
})
|
||||
|
||||
// Load and add translations asynchronously
|
||||
const loadAllTranslations = async () => {
|
||||
for (const lang of supportedLanguages) {
|
||||
try {
|
||||
const response = await fetch(`/assets/i18n/${lang}.json`)
|
||||
if (response.ok) {
|
||||
const data = await response.json()
|
||||
const flattened = flattenTranslations(data)
|
||||
// Use addResourceBundle to add the translations AFTER initialization
|
||||
i18n.addResourceBundle(lang, 'translation', flattened, true, true)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`[i18n] Error loading ${lang}:`, error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loadAllTranslations().then(() => {
|
||||
// Change language after all translations are loaded
|
||||
i18n.changeLanguage(lng)
|
||||
})
|
||||
|
||||
export default i18n
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// Static translations - bundled at build time
|
||||
import ru from '../../public/assets/i18n/ru.json'
|
||||
import en from '../../public/assets/i18n/en.json'
|
||||
import es from '../../public/assets/i18n/es.json'
|
||||
import fr from '../../public/assets/i18n/fr.json'
|
||||
import it from '../../public/assets/i18n/it.json'
|
||||
import ja from '../../public/assets/i18n/ja.json'
|
||||
import ko from '../../public/assets/i18n/ko.json'
|
||||
import de from '../../public/assets/i18n/de.json'
|
||||
import zh from '../../public/assets/i18n/zh.json'
|
||||
|
||||
export const translations = {
|
||||
ru,
|
||||
en,
|
||||
es,
|
||||
fr,
|
||||
it,
|
||||
ja,
|
||||
ko,
|
||||
de,
|
||||
zh,
|
||||
} as const
|
||||
|
Before Width: | Height: | Size: 545 KiB After Width: | Height: | Size: 539 KiB |
|
Before Width: | Height: | Size: 547 KiB After Width: | Height: | Size: 545 KiB |
|
Before Width: | Height: | Size: 544 KiB After Width: | Height: | Size: 543 KiB |
|
Before Width: | Height: | Size: 593 KiB |
|
Before Width: | Height: | Size: 569 KiB |
|
Before Width: | Height: | Size: 592 KiB |
|
Before Width: | Height: | Size: 551 KiB After Width: | Height: | Size: 545 KiB |
|
Before Width: | Height: | Size: 533 KiB After Width: | Height: | Size: 539 KiB |
|
Before Width: | Height: | Size: 566 KiB |
|
Before Width: | Height: | Size: 582 KiB After Width: | Height: | Size: 578 KiB |
|
Before Width: | Height: | Size: 548 KiB |
|
Before Width: | Height: | Size: 523 KiB |
|
Before Width: | Height: | Size: 547 KiB |
|
Before Width: | Height: | Size: 553 KiB After Width: | Height: | Size: 577 KiB |
|
Before Width: | Height: | Size: 599 KiB |
|
Before Width: | Height: | Size: 589 KiB |
|
Before Width: | Height: | Size: 598 KiB |
|
Before Width: | Height: | Size: 556 KiB After Width: | Height: | Size: 553 KiB |
|
Before Width: | Height: | Size: 548 KiB After Width: | Height: | Size: 546 KiB |
|
Before Width: | Height: | Size: 581 KiB After Width: | Height: | Size: 581 KiB |