/*
* Copyright (C) 2026 Fluxer Contributors
*
* This file is part of Fluxer.
*
* Fluxer is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Fluxer is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Fluxer. If not, see .
*/
/** @jsxRuntime automatic */
/** @jsxImportSource hono/jsx */
import {AllLocales} from '@fluxer/constants/src/Locales';
import {getLocaleName} from '@fluxer/locale/src/LocaleService';
import {FlagSvg} from '@fluxer/marketing/src/components/Flags';
import {TranslateIcon} from '@fluxer/marketing/src/components/icons/TranslateIcon';
import type {MarketingContext} from '@fluxer/marketing/src/MarketingContext';
import {href, prependBasePath} from '@fluxer/marketing/src/UrlUtils';
import {CsrfInput} from '@fluxer/ui/src/components/CsrfInput';
interface LocaleSelectorProps {
ctx: MarketingContext;
currentPath: string;
}
export function LocaleSelector(props: LocaleSelectorProps): JSX.Element {
return (
);
}
interface LocaleSelectorTriggerProps {
ctx: MarketingContext;
className?: string;
text?: string;
}
export function LocaleSelectorTrigger(props: LocaleSelectorTriggerProps): JSX.Element {
const {ctx, className, text} = props;
const label = ctx.i18n.getMessage('languages.change_language', ctx.locale);
const baseClass = 'locale-toggle flex items-center justify-center rounded-lg p-2 transition-colors hover:bg-gray-100';
const classes = [baseClass, className].filter(Boolean).join(' ');
return (
{text ? {text} : null}
);
}
export function LocaleSelectorModal(props: LocaleSelectorProps): JSX.Element {
const ctx = props.ctx;
const currentPath = props.currentPath;
const title = ctx.i18n.getMessage('languages.choose_your_language', ctx.locale);
const notice = ctx.i18n.getMessage(
'company_and_resources.source_and_contribution.translation.llm_translation_note',
ctx.locale,
);
return (
{notice}
{AllLocales.map((locale) => {
const isCurrent = locale === ctx.locale;
const nativeName = getLocaleName(locale);
const localizedName = getLocalizedLocaleName(ctx, locale);
const localeCode = locale;
return (
);
})}
);
}
function getLocalizedLocaleName(ctx: MarketingContext, locale: string): string {
switch (locale) {
case 'ar':
return ctx.i18n.getMessage('languages.list.arabic', ctx.locale);
case 'bg':
return ctx.i18n.getMessage('languages.list.bulgarian', ctx.locale);
case 'cs':
return ctx.i18n.getMessage('languages.list.czech', ctx.locale);
case 'da':
return ctx.i18n.getMessage('languages.list.danish', ctx.locale);
case 'de':
return ctx.i18n.getMessage('languages.list.german', ctx.locale);
case 'el':
return ctx.i18n.getMessage('languages.list.greek', ctx.locale);
case 'en-GB':
return ctx.i18n.getMessage('languages.list.english', ctx.locale);
case 'en-US':
return ctx.i18n.getMessage('languages.list.english_us', ctx.locale);
case 'es-ES':
return ctx.i18n.getMessage('languages.list.spanish_spain', ctx.locale);
case 'es-419':
return ctx.i18n.getMessage('languages.list.spanish_latin_america', ctx.locale);
case 'fi':
return ctx.i18n.getMessage('languages.list.finnish', ctx.locale);
case 'fr':
return ctx.i18n.getMessage('languages.list.french', ctx.locale);
case 'he':
return ctx.i18n.getMessage('languages.list.hebrew', ctx.locale);
case 'hi':
return ctx.i18n.getMessage('languages.list.hindi', ctx.locale);
case 'hr':
return ctx.i18n.getMessage('languages.list.croatian', ctx.locale);
case 'hu':
return ctx.i18n.getMessage('languages.list.hungarian', ctx.locale);
case 'id':
return ctx.i18n.getMessage('languages.list.indonesian', ctx.locale);
case 'it':
return ctx.i18n.getMessage('languages.list.italian', ctx.locale);
case 'ja':
return ctx.i18n.getMessage('languages.list.japanese', ctx.locale);
case 'ko':
return ctx.i18n.getMessage('languages.list.korean', ctx.locale);
case 'lt':
return ctx.i18n.getMessage('languages.list.lithuanian', ctx.locale);
case 'nl':
return ctx.i18n.getMessage('languages.list.dutch', ctx.locale);
case 'no':
return ctx.i18n.getMessage('languages.list.norwegian', ctx.locale);
case 'pl':
return ctx.i18n.getMessage('languages.list.polish', ctx.locale);
case 'pt-BR':
return ctx.i18n.getMessage('languages.list.portuguese_brazil', ctx.locale);
case 'ro':
return ctx.i18n.getMessage('languages.list.romanian', ctx.locale);
case 'ru':
return ctx.i18n.getMessage('languages.list.russian', ctx.locale);
case 'sv-SE':
return ctx.i18n.getMessage('languages.list.swedish', ctx.locale);
case 'th':
return ctx.i18n.getMessage('languages.list.thai', ctx.locale);
case 'tr':
return ctx.i18n.getMessage('languages.list.turkish', ctx.locale);
case 'uk':
return ctx.i18n.getMessage('languages.list.ukrainian', ctx.locale);
case 'vi':
return ctx.i18n.getMessage('languages.list.vietnamese', ctx.locale);
case 'zh-CN':
return ctx.i18n.getMessage('languages.list.chinese_simplified', ctx.locale);
case 'zh-TW':
return ctx.i18n.getMessage('languages.list.chinese_traditional', ctx.locale);
default:
return locale;
}
}