feat: add custom navigation link to org landing page (#569)

* feat: custom navbar UI complete

* chore: added translations

* fear: attending to reviews

* add orgname to org landing page

---------

Co-authored-by: Rotimi Best <best@classroomio.com>
This commit is contained in:
Nwosu Emmanuel
2025-10-09 01:13:06 +01:00
committed by GitHub
co-authored by Rotimi Best
parent 9a7018eb34
commit 27ee51155e
48 changed files with 2845 additions and 106 deletions
@@ -0,0 +1,54 @@
<script>
import YoutubeVideo from './YoutubeVideo.svelte';
import UploadVideo from './UploadVideo.svelte';
import EmbedLink from './EmbedLink.svelte';
import * as CONSTANTS from './constants';
import { t } from '$lib/utils/functions/translations';
import { isFreePlan } from '$lib/utils/store/org';
import FlashFilled from 'carbon-icons-svelte/lib/FlashFilled.svelte';
export let lessonId = '';
const tabs = CONSTANTS.videoTabs;
let currentTab = tabs[0].value;
const onChange = (tab) => () => (currentTab = tab);
</script>
<section class="flex h-full w-full flex-col items-start gap-3 md:flex-row">
<div class="flex flex-row items-center gap-2 md:flex-col">
<p class="mb-3 w-full text-start text-sm font-normal text-[#4F4B4B] dark:text-[#b0a9a9]">
{$t('course.navItem.lessons.materials.tabs.video.add_video.add_by')}
</p>
{#each tabs as item (item.value)}
<button
on:click={onChange(item.value)}
class={`my-1 w-full border px-4 py-3 ${
currentTab === item.value
? 'border border-[#0233BD] bg-[#F5F8FE] dark:text-black'
: 'border border-gray-200 dark:border-neutral-600'
} flex cursor-pointer flex-row items-center justify-start gap-2 whitespace-nowrap rounded-md`}
>
{#if $isFreePlan && item.value === 3}
<FlashFilled size={20} class="text-blue-700" />
{:else}
<svelte:component
this={item.icon}
size={20}
color={`${currentTab === item.value ? 'dark:invert-0' : 'dark:invert'}`}
/>
{/if}
<p>{$t(item.title)}</p>
</button>
{/each}
</div>
<main class="h-full w-full">
{#if currentTab === 1}
<YoutubeVideo />
{:else if currentTab === 2}
<EmbedLink />
{:else}
<UploadVideo {lessonId} />
{/if}
</main>
</section>
@@ -0,0 +1,47 @@
<script lang="ts">
import { goto } from '$app/navigation';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import { t } from '$lib/utils/functions/translations';
export let disableSignup = false;
export let redirect = '';
export let isMobile = false;
export let onMobileClick: (() => void) | undefined = undefined;
function handleLogin() {
if (onMobileClick) onMobileClick();
goto('/login' + redirect);
}
function handleSignup() {
if (onMobileClick) onMobileClick();
goto('/signup' + redirect);
}
</script>
<div class="flex {isMobile ? 'flex-col items-center justify-center space-y-3' : ''}">
<li class={isMobile ? '' : 'block'}>
<div class="flex">
<PrimaryButton
label={$t('navigation.login')}
variant={VARIANTS.TEXT}
onClick={handleLogin}
className={isMobile ? 'w-full justify-center' : ''}
/>
</div>
</li>
{#if !disableSignup}
<li class={isMobile ? '' : 'block'}>
<div class="flex">
<PrimaryButton
label={$t('navigation.signup')}
variant={VARIANTS.CONTAINED}
onClick={handleSignup}
className={isMobile ? 'w-full justify-center' : ''}
/>
</div>
</li>
{/if}
</div>
@@ -0,0 +1,31 @@
<script lang="ts">
import type { TCustomLinks } from './types';
export let customLinks: TCustomLinks | undefined = undefined;
export let isMobile = false;
export let onMobileClick: (() => void) | undefined = undefined;
function handleLinkClick() {
if (onMobileClick) onMobileClick();
}
</script>
{#if customLinks}
<div class={isMobile ? 'space-y-4' : 'mr-4 hidden items-center space-x-6 lg:flex'}>
{#each customLinks.links as link}
<li>
<a
href={link.url}
target={link.openInNewTab ? '_blank' : '_self'}
rel={link.openInNewTab ? 'noopener noreferrer' : ''}
class={isMobile
? 'hover:text-primary-600 block rounded-md px-3 py-2 font-medium text-gray-700 transition-colors duration-200 hover:bg-gray-50'
: 'hover:text-primary-600 rounded-md px-4 py-2 font-medium text-gray-700 no-underline transition-all duration-200 ease-in-out hover:bg-gray-100'}
on:click={handleLinkClick}
>
{link.label}
</a>
</li>
{/each}
</div>
{/if}
@@ -0,0 +1,25 @@
<script lang="ts">
import { t } from '$lib/utils/functions/translations';
export let logo: string | undefined;
export let orgName: string | undefined;
</script>
<div class="logo">
<a
href="/"
title={`${$t('navigation.goto')} ${orgName || 'ClassroomIO'} ${$t('navigation.home')}`}
id="logo"
data-hveid="8"
>
<img
src={logo || '/logo-192.png'}
alt={`${orgName || 'ClassroomIO'} logo`}
class="mx-auto inline-block w-9 rounded"
data-atf="1"
/>
{#if orgName}
<span class="line-clamp-1 hidden text-sm font-medium md:block">{orgName}</span>
{/if}
</a>
</div>
@@ -0,0 +1,100 @@
<script lang="ts">
import { page } from '$app/stores';
import { user } from '$lib/utils/store/user';
import { type TCustomLinks } from './types';
import CustomLinks from './CustomLinks.svelte';
import AuthButtons from './AuthButtons.svelte';
export let mobileMenuOpen = false;
export let customLinks: TCustomLinks | undefined = undefined;
export let disableSignup = false;
export let redirect = '';
let mobileMenuRef: HTMLElement;
function closeMobileMenu() {
mobileMenuOpen = false;
}
</script>
<!-- Mobile Menu Overlay -->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
{#if mobileMenuOpen}
<div
class="mobile-menu-overlay fixed inset-0 z-50 bg-black bg-opacity-50 lg:hidden"
on:click={closeMobileMenu}
>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
<div
bind:this={mobileMenuRef}
class="mobile-menu-sidebar absolute right-0 top-0 h-full w-64 transform bg-white shadow-lg transition-transform duration-300 ease-in-out"
on:click|stopPropagation
>
<div class="flex items-center justify-between border-b border-gray-200 p-4">
<h3 class="text-lg font-semibold text-gray-800">Menu</h3>
<button
on:click={closeMobileMenu}
class="rounded-md p-2 text-gray-500 transition-colors duration-200 hover:bg-gray-100 hover:text-gray-700"
>
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
></path>
</svg>
</button>
</div>
<nav>
<ul class="space-y-4 divide-y-[1px]">
<CustomLinks {customLinks} isMobile={true} onMobileClick={closeMobileMenu} />
<!-- Login/Signup buttons in mobile menu -->
{#if !$user.isLoggedIn && !$page.url.pathname?.includes('/404')}
<li class="pt-4">
<AuthButtons
{disableSignup}
{redirect}
isMobile={true}
onMobileClick={closeMobileMenu}
/>
</li>
{/if}
</ul>
</nav>
</div>
</div>
{/if}
<style>
/* Mobile menu styles */
.mobile-menu-overlay {
animation: fadeIn 0.2s ease-in-out;
}
.mobile-menu-sidebar {
animation: slideIn 0.3s ease-in-out;
}
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideIn {
from {
transform: translateX(100%);
}
to {
transform: translateX(0);
}
}
</style>
@@ -1,119 +1,81 @@
<script>
import { goto } from '$app/navigation';
<script lang="ts">
import { page } from '$app/stores';
import { user } from '$lib/utils/store/user';
import { isCoursePage } from '$lib/utils/functions/app';
import PrimaryButton from '$lib/components/PrimaryButton/index.svelte';
import { VARIANTS } from '$lib/components/PrimaryButton/constants';
import { t } from '$lib/utils/functions/translations';
import type { TCustomLinks } from './types';
import Logo from './Logo.svelte';
import CustomLinks from './CustomLinks.svelte';
import AuthButtons from './AuthButtons.svelte';
import MobileMenu from './MobileMenu.svelte';
export let disableSignup = false;
export let logo;
export let orgName;
export let logo: string | undefined = undefined;
export let orgName: string | undefined = undefined;
export let isOrgSite = false;
export let backgroundColor = 'bg-white dark:bg-black';
export let customLinks: TCustomLinks | undefined = undefined;
let navClass = '';
let mobileMenuOpen = false;
const redirect = isCoursePage($page.url.pathname) ? `?redirect=${$page.url.pathname}` : '';
$: redirect = isCoursePage($page.url.pathname) ? `?redirect=${$page.url.pathname}` : '';
$: showLinks =
customLinks && customLinks.show && customLinks.links && customLinks.links.length > 0;
$: navClass = '';
function toggleMobileMenu() {
mobileMenuOpen = !mobileMenuOpen;
}
</script>
<nav
class="{navClass} {backgroundColor} sticky top-0 z-50 flex w-full border-b border-l-0 border-r-0 border-t-0 border-gray-300 px-2 py-1"
>
<ul class="flex w-full items-center">
<div class="logo">
<a
href="/"
title={`${$t('navigation.goto')} ${orgName || 'ClassroomIO'} ${$t('navigation.home')}`}
data-hveid="8"
>
<img
src={logo || '/logo-192.png'}
alt={`${orgName || 'ClassroomIO'} logo`}
class="mx-auto inline-block w-9 rounded"
data-atf="1"
/>
{#if orgName}
<span class="line-clamp-1 hidden text-sm font-medium md:block">{orgName}</span>
{/if}
</a>
</div>
{#if $user.isLoggedIn}
<li class="hidden">
<a class="block" href="dashboard"> {$t('navigation.dashboard')} </a>
</li>
<li class="hidden">
<a class="block" href="courses"> {$t('navigation.courses')} </a>
</li>
<li class="hidden">
<a class="block" href="discussions"> {$t('navigation.discussion')} </a>
</li>
<li class="hidden">
<a class="block" href="people">{$t('navigation.people')} </a>
</li>
{/if}
<Logo {logo} {orgName} />
<span class="flex-grow" />
<!-- Mobile Menu Button - Only show when custom links exist -->
{#if isOrgSite && showLinks}
<button
class="mobile-menu-btn hover:text-primary-600 rounded-md p-2 text-gray-700 transition-colors duration-200 hover:bg-gray-100 lg:hidden"
on:click={toggleMobileMenu}
aria-label="Toggle mobile menu"
>
<svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M4 6h16M4 12h16M4 18h16"
></path>
</svg>
</button>
{/if}
{#if customLinks && showLinks}
<CustomLinks {customLinks} />
{/if}
{#if $user.isLoggedIn}
{#if isOrgSite}
<li><a class="block" href="/lms"> {$t('navigation.goto_lms')} </a></li>
{/if}
{:else if !$page.url.pathname?.includes('/404')}
<li>
<div class="flex">
<PrimaryButton
label={$t('navigation.login')}
variant={VARIANTS.TEXT}
onClick={() => goto('/login' + redirect)}
/>
</div>
</li>
<li>
{#if !disableSignup}
<div class="flex">
<PrimaryButton
label={$t('navigation.signup')}
variant={VARIANTS.CONTAINED}
onClick={() => goto('/signup' + redirect)}
/>
</div>
{/if}
</li>
{:else if isOrgSite && !$page.url.pathname?.includes('/404')}
<!-- Hide login/signup buttons on mobile when custom links exist -->
<div class="hidden lg:block">
<AuthButtons {disableSignup} {redirect} />
</div>
{:else if !isOrgSite && !$page.url.pathname?.includes('/404')}
<AuthButtons {disableSignup} {redirect} />
{/if}
<!-- <li class="hidden">
<a
class="flex items-center"
href="https://t.me/classroomio"
target="_blank"
>
<img
alt="File:Telegram logo.svg"
class="mr-1"
src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Telegram_alternative_logo.svg/50px-Telegram_alternative_logo.svg.png"
decoding="async"
width="25"
height="25"
srcset="https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Telegram_alternative_logo.svg/50px-Telegram_alternative_logo.svg.png 1.5x, https://upload.wikimedia.org/wikipedia/commons/thumb/8/82/Telegram_logo.svg/1024px-Telegram_logo.svg.png 2x"
data-file-width="25"
data-file-height="25"
/>
<span><SendAlt32 class="carbon-icon dark:text-white" /> Канал</span>
<SendAlt32 class="carbon-icon dark:text-white" />
<span>Канал</span>
</a>
</li> -->
<!-- <li class="new-question">
<NewQuestion />
</li> -->
</ul>
{#if showLinks}
<MobileMenu bind:mobileMenuOpen {customLinks} {disableSignup} {redirect} />
{/if}
</nav>
<style>
@@ -122,17 +84,12 @@
padding: 0;
}
/* clearfix */
ul::after {
content: '';
display: block;
clear: both;
}
/* li.new-question {
margin-top: 10px;
} */
a {
text-decoration: none;
color: var(--main-primary-color);
@@ -141,9 +98,15 @@
display: flex;
gap: 0.5rem;
align-items: center;
flex-direction: column;
}
@media only screen and (max-width: 1002px) {
/* Mobile menu button styles */
.mobile-menu-btn {
display: none;
}
@media only screen and (max-width: 1023px) {
nav.hide {
display: none;
}
@@ -154,5 +117,9 @@
a {
padding: 0 0.5em;
}
.mobile-menu-btn {
display: block;
}
}
</style>
@@ -0,0 +1,20 @@
export type CustomLink = {
id: number;
label: string;
url: string;
openInNewTab: boolean;
};
export type TCustomLinks = {
show: boolean;
links: CustomLink[];
};
export type TNavigationProps = {
disableSignup?: boolean;
logo?: string;
orgName?: string;
isOrgSite?: boolean;
backgroundColor?: string;
customLinks?: TCustomLinks | null;
};
@@ -177,6 +177,13 @@
<PageLoader />
{:else}
<main>
<Navigation
logo={org.avatar_url}
orgName={org.name}
disableSignup={true}
isOrgSite={true}
customLinks={$landingPageSettings.customLinks}
/>
<!-- Header Section -->
{#if $landingPageSettings.header.show}
<header
@@ -188,13 +195,6 @@
}`}
style="background-image: {getBgImage($landingPageSettings)}"
>
<Navigation
logo={org.avatar_url}
orgName={org.name}
disableSignup={true}
isOrgSite={true}
/>
<div class="absolute top-0 z-10 h-[100vh] w-full bg-white opacity-80 md:h-[90vh]" />
{#if $landingPageSettings.header.banner.show}
<div class="flex items-center justify-center py-2 md:h-full">
@@ -27,6 +27,7 @@
let isSaving = false;
let creatingNewQuestion = false;
let creatingNewCustomLink = false;
let hasUnsavedChanges = false;
let widgetKey = '';
const banner = [
@@ -40,6 +41,12 @@
content: ''
};
let newCustomLink = {
label: '',
url: '',
openInNewTab: false
};
function widgetControl(key: string) {
widgetKey = key;
$handleOpenWidget.open = true;
@@ -77,6 +84,40 @@
$landingPageSettings.faq.questions = filteredFaq;
}
function createNewCustomLink() {
newCustomLink = {
label: '',
url: '',
openInNewTab: false
};
creatingNewCustomLink = true;
}
function saveNewCustomLink() {
if (newCustomLink.label !== '' && newCustomLink.url !== '') {
$landingPageSettings.customLinks.links = [
...$landingPageSettings.customLinks.links,
{
id: new Date().getTime(),
label: newCustomLink.label,
url: newCustomLink.url,
openInNewTab: newCustomLink.openInNewTab
}
];
creatingNewCustomLink = false;
}
}
function cancelNewCustomLink() {
creatingNewCustomLink = false;
}
function deleteCustomLink(id: number) {
let customLinks = $landingPageSettings.customLinks.links;
const filteredCustomLinks = customLinks.filter((link) => link.id !== id);
$landingPageSettings.customLinks.links = filteredCustomLinks;
}
const checkPrefix = (inputValue: string) => {
if (!inputValue) return;
@@ -103,7 +144,7 @@
const message = error?.message || 'snackbar.lms.error.try_again';
snackbar.error(`snackbar.lms.error.update ${message}`);
} else {
$currentOrg.landingpage = $landingPageSettings;
$currentOrg.landingpage = $landingPageSettings as any;
snackbar.success('snackbar.success_update');
hasUnsavedChanges = false;
}
@@ -124,7 +165,7 @@
$landingPageSettings = {
...landingpage
};
} as OrgLandingPageJson;
}
}
$: setDefault($currentOrg?.landingpage as unknown as OrgLandingPageJson);
@@ -578,6 +619,99 @@
</Column>
</Row>
<Row class="border-bottom-c flex flex-col py-7 lg:flex-row">
<Column sm={4} md={4} lg={4}
><SectionTitle>{$t('settings.landing_page.custom_links.heading')}</SectionTitle>
<Toggle bind:toggled={$landingPageSettings.customLinks.show} size="sm">
<span slot="labelA" style="color: gray"
>{$t('settings.landing_page.custom_links.hide_links')}</span
>
<span slot="labelB" style="color: gray"
>{$t('settings.landing_page.custom_links.show_links')}</span
>
</Toggle>
</Column>
<Column sm={8} md={8} lg={8} class="mt-4 lg:mt-0">
<p class="mb-4 text-sm text-gray-600">
{$t('settings.landing_page.custom_links.description')}
</p>
{#each $landingPageSettings.customLinks.links as link (link.id)}
<div class="mb-4 rounded-lg border border-gray-200 p-4">
<div class="mb-3 grid grid-cols-1 gap-4 md:grid-cols-2">
<TextField
label={$t('settings.landing_page.custom_links.label')}
placeholder={$t('settings.landing_page.custom_links.label_placeholder')}
bind:value={link.label}
className="mb-3"
/>
<TextField
label={$t('settings.landing_page.custom_links.url')}
placeholder={$t('settings.landing_page.custom_links.url_placeholder')}
bind:value={link.url}
className="mb-3"
/>
</div>
<div class="flex items-center justify-between">
<label class="flex items-center">
<input type="checkbox" bind:checked={link.openInNewTab} class="mr-2" />
<span class="text-sm">{$t('settings.landing_page.custom_links.new_tab')}</span>
</label>
<IconButton onClick={() => deleteCustomLink(link.id)}>
<TrashCan size={20} class="fill-red-700" />
</IconButton>
</div>
</div>
{/each}
{#if creatingNewCustomLink}
<div class="mb-4 rounded-lg border border-gray-200 bg-gray-50 p-4">
<div class="mb-3 grid grid-cols-1 gap-4 md:grid-cols-2">
<TextField
label={$t('settings.landing_page.custom_links.label')}
placeholder={$t('settings.landing_page.custom_links.label_placeholder')}
bind:value={newCustomLink.label}
className="mb-3"
/>
<TextField
label={$t('settings.landing_page.custom_links.url')}
placeholder={$t('settings.landing_page.custom_links.url_placeholder')}
bind:value={newCustomLink.url}
className="mb-3"
/>
</div>
<div class="flex items-center justify-between">
<label class="flex items-center">
<input type="checkbox" bind:checked={newCustomLink.openInNewTab} class="mr-2" />
<span class="text-sm">{$t('settings.landing_page.custom_links.new_tab')}</span>
</label>
<div class="flex gap-2">
<PrimaryButton
variant={VARIANTS.OUTLINED}
label={$t('settings.landing_page.custom_links.save')}
onClick={saveNewCustomLink}
className="text-sm px-3 py-1"
/>
<PrimaryButton
variant={VARIANTS.OUTLINED}
label={$t('settings.landing_page.custom_links.cancel')}
onClick={cancelNewCustomLink}
className="text-sm px-3 py-1"
/>
</div>
</div>
</div>
{:else}
<PrimaryButton
variant={VARIANTS.OUTLINED}
label={$t('settings.landing_page.custom_links.add')}
onClick={createNewCustomLink}
className="mt-2"
/>
{/if}
</Column>
</Row>
<Row class="flex flex-col py-7 lg:flex-row">
<Column sm={4} md={4} lg={4}
><SectionTitle>{$t('settings.landing_page.footer.heading')}</SectionTitle>
@@ -640,7 +774,7 @@
>
<span>
<IconButton onClick={handleSave} disabled={isSaving}>
<Save size={40} class=" rounded-full bg-blue-700 p-1" />
<Save size={32} class=" rounded-full bg-blue-700 p-1" />
</IconButton>
</span>
</div>
@@ -17,7 +17,7 @@ export interface OrgLandingPageJson {
type: string;
show: boolean;
};
background?: {
background: {
image: string;
show: boolean;
};
@@ -59,6 +59,15 @@ export interface OrgLandingPageJson {
buttonLabel: string;
show: boolean;
};
customLinks: {
show: boolean;
links: Array<{
id: number;
label: string;
url: string;
openInNewTab: boolean;
}>;
};
footer: {
facebook: string;
instagram: string;
@@ -145,6 +154,35 @@ export const landingPageSettings: Writable<OrgLandingPageJson> = writable({
buttonLabel: 'Subscribe',
show: true
},
customLinks: {
show: true,
links: [
{
id: 1,
label: 'About Us',
url: '#aboutus',
openInNewTab: false
},
{
id: 2,
label: 'Courses',
url: '#courses',
openInNewTab: false
},
{
id: 3,
label: 'FAQ',
url: '#faq',
openInNewTab: false
},
{
id: 4,
label: 'Contact Us',
url: '#contact',
openInNewTab: false
}
]
},
footer: {
facebook: '#',
instagram: '#',
@@ -60,6 +60,35 @@
"buttonLabel": "Subscribe",
"show": true
},
"customLinks": {
"show": true,
"links": [
{
"id": 1,
"label": "About Us",
"url": "#about-us",
"openInNewTab": false
},
{
"id": 2,
"label": "Courses",
"url": "#courses",
"openInNewTab": false
},
{
"id": 3,
"label": "FAQ",
"url": "#faq",
"openInNewTab": false
},
{
"id": 4,
"label": "Contact Us",
"url": "#contact",
"openInNewTab": false
}
]
},
"footer": {
"facebook": "#",
"instagram": "#",
@@ -1286,6 +1286,20 @@
"title": "Hintergrundbild",
"show_background": "Hintergrund anzeigen",
"hide_background": "Hintergrund ausblenden"
},
"custom_links": {
"heading": "Benutzerdefinierte Links",
"hide_links": "Links verbergen",
"show_links": "Links anzeigen",
"description": "Fügen Sie benutzerdefinierte Navigationslinks hinzu, die in der Header -Navigationsleiste angezeigt werden.",
"label": "Etikett",
"url": "URL",
"label_placeholder": "z. B. über uns",
"url_placeholder": "z. B. #über- oder https://example.com",
"new_tab": "Offen in neuer Registerkarte",
"save": "Speichern",
"cancel": "Stornieren",
"add": "Neuen Link hinzufügen"
}
},
"organization": {
@@ -226,6 +226,21 @@
"twitter": "Twitter",
"linkedin": "LinkedIn"
},
"custom_links": {
"heading": "Custom Links",
"hide_links": "Hide Links",
"show_links": "Show Links",
"description": "Add custom navigation links that will appear in the header navigation bar.",
"label": "Label",
"url": "URL",
"label_placeholder": "e.g., About Us",
"url_placeholder": "e.g., #about-us or https://example.com",
"new_tab": "Open in new tab",
"save": "Save",
"cancel": "Cancel",
"add": "Add New Link"
},
"save_changes": "Save Changes"
},
"integrations": {
@@ -1286,6 +1286,20 @@
"title": "Imagen de fondo",
"show_background": "Mostrar fondo",
"hide_background": "Ocultar fondo"
},
"custom_links": {
"heading": "Enlaces personalizados",
"hide_links": "Ocultar enlaces",
"show_links": "Mostrar enlaces",
"description": "Agregue enlaces de navegación personalizados que aparecerán en la barra de navegación del encabezado.",
"label": "Etiqueta",
"url": "Url",
"label_placeholder": "por ejemplo, sobre nosotros",
"url_placeholder": "por ejemplo, #About-US o https://example.com",
"new_tab": "Abrir en una nueva pestaña",
"save": "Ahorrar",
"cancel": "Cancelar",
"add": "Agregar nuevo enlace"
}
},
"organization": {
@@ -1286,6 +1286,20 @@
"title": "Image d'arrière-plan",
"show_background": "Afficher l'arrière-plan",
"hide_background": "Masquer l'arrière-plan"
},
"custom_links": {
"heading": "Liens personnalisés",
"hide_links": "Masquer les liens",
"show_links": "Montrer des liens",
"description": "Ajoutez des liens de navigation personnalisés qui apparaîtront dans la barre de navigation d'en-tête.",
"label": "Étiquette",
"url": "URL",
"label_placeholder": "par exemple, à propos de nous",
"url_placeholder": "par exemple, # à peu près ou https://example.com",
"new_tab": "Ouvert dans un nouvel onglet",
"save": "Sauvegarder",
"cancel": "Annuler",
"add": "Ajouter un nouveau lien"
}
},
"organization": {
@@ -1286,6 +1286,20 @@
"title": "पृष्ठभूमि छवि",
"show_background": "पृष्ठभूमि दिखाएँ",
"hide_background": "पृष्ठभूमि छिपाएँ"
},
"custom_links": {
"heading": "कस्टम लिंक",
"hide_links": "लिंक छिपाएं",
"show_links": "लिंक दिखाएं",
"description": "हेडर नेविगेशन बार में दिखाई देने वाले कस्टम नेविगेशन लिंक जोड़ें।",
"label": "लेबल",
"url": "यूआरएल",
"label_placeholder": "जैसे, हमारे बारे में",
"url_placeholder": "उदा।, #के बारे में या https://example.com",
"new_tab": "वेब टेब में खोलें",
"save": "बचाना",
"cancel": "रद्द करना",
"add": "नया लिंक जोड़ें"
}
},
"organization": {
@@ -1402,6 +1402,20 @@
"title": "Obraz tła",
"show_background": "Pokaż tło",
"hide_background": "Ukryj tło"
},
"custom_links": {
"heading": "Niestandardowe linki",
"hide_links": "Ukryj linki",
"show_links": "Pokaż linki",
"description": "Dodaj niestandardowe linki nawigacyjne, które pojawią się na pasku nawigacji nagłówka.",
"label": "Etykieta",
"url": "URL",
"label_placeholder": "np. O nas",
"url_placeholder": "np. #About-US lub https://example.com",
"new_tab": "Otwórz w nowej zakładce",
"save": "Ratować",
"cancel": "Anulować",
"add": "Dodaj nowy link"
}
},
"organization": {
@@ -1286,6 +1286,20 @@
"title": "Imagem de fundo",
"show_background": "Mostrar plano de fundo",
"hide_background": "Ocultar plano de fundo"
},
"custom_links": {
"heading": "Links personalizados",
"hide_links": "Ocultar links",
"show_links": "Mostre links",
"description": "Adicione links de navegação personalizados que aparecerão na barra de navegação do cabeçalho.",
"label": "Rótulo",
"url": "Url",
"label_placeholder": "por exemplo, sobre nós",
"url_placeholder": "por exemplo, #sobre-us ou https://example.com",
"new_tab": "Abrir na nova guia",
"save": "Salvar",
"cancel": "Cancelar",
"add": "Adicione um novo link"
}
},
"organization": {
@@ -1286,6 +1286,20 @@
"title": "Фоновое изображение",
"show_background": "Показать фон",
"hide_background": "Скрыть фон"
},
"custom_links": {
"heading": "Пользовательские ссылки",
"hide_links": "Скрыть ссылки",
"show_links": "Показать ссылки",
"description": "Добавьте пользовательские навигационные ссылки, которые появятся в панели навигации заголовка.",
"label": "Этикетка",
"url": "URL",
"label_placeholder": "например, о нас",
"url_placeholder": "Например, #about-us или https://example.com",
"new_tab": "Открыто в новой вкладке",
"save": "Сохранять",
"cancel": "Отмена",
"add": "Добавить новую ссылку"
}
},
"organization": {
@@ -1286,6 +1286,20 @@
"title": "Hình nền",
"show_background": "Hiển thị nền",
"hide_background": "Ẩn nền"
},
"custom_links": {
"heading": "Liên kết tùy chỉnh",
"hide_links": "Ẩn liên kết",
"show_links": "Hiển thị liên kết",
"description": "Thêm các liên kết điều hướng tùy chỉnh sẽ xuất hiện trong thanh điều hướng tiêu đề.",
"label": "Nhãn",
"url": "URL",
"label_placeholder": "ví dụ: về chúng tôi",
"url_placeholder": "ví dụ: #abing-us hoặc https://example.com",
"new_tab": "Mở trong tab mới",
"save": "Cứu",
"cancel": "Hủy bỏ",
"add": "Thêm liên kết mới"
}
},
"organization": {