// Set to true once a Windows ARM64 build is published in a release. const windowsArm64Enabled = false; async function getOs() { // The macOS release is available for Intel and Apple silicon processors, // and the only way to get that info is through this new // `getHighEntropyValues` function (which is not available on all browsers). // So here we either return "macOs" for Intel or "macOsM1" for Apple // Silicon. If we don't know which it is, we return "macOsUndefined". // https://stackoverflow.com/a/75177111/561309 if (navigator.appVersion.indexOf("Mac")!=-1) { let platformInfo = null; try { platformInfo = await navigator.userAgentData.getHighEntropyValues(['architecture']) } catch (error) { console.warn('Failed getting Mac architecture:', error); return 'macOsUndefined'; } console.info('Got platform info:', platformInfo); if (platformInfo.architecture === 'arm') { return "macOsM1"; } else { return "macOs"; } } // Windows on ARM has the same appVersion as x64, so the architecture has to // come from getHighEntropyValues, as for Apple Silicon above. Falling back // to the x64 build is fine - it runs on ARM under emulation. if (navigator.appVersion.indexOf("Win")!=-1) { if (windowsArm64Enabled) { try { const platformInfo = await navigator.userAgentData.getHighEntropyValues(['architecture']); console.info('Got platform info:', platformInfo); if (platformInfo.architecture === 'arm') return "windowsArm64"; } catch (error) { console.warn('Failed getting Windows architecture:', error); } } return "windows"; } if (navigator.appVersion.indexOf("X11")!=-1) return "linux"; if (navigator.appVersion.indexOf("Linux")!=-1) return "linux"; return null; } function getFilename(path) { if (!path) return ''; const s = path.split('/'); const urlWithParams = s.pop(); const s2 = urlWithParams.split('?'); return s2[0]; } function getMobileOs() { var userAgent = navigator.userAgent || navigator.vendor || window.opera; // Windows Phone must come first because its UA also contains "Android" if (/windows phone/i.test(userAgent)) { return "windowsPhone"; } if (/android/i.test(userAgent)) { return "android"; } // iOS detection from: http://stackoverflow.com/a/9039885/177710 if (/iPad|iPhone|iPod/.test(userAgent) && !window.MSStream) { return "ios"; } return ""; } function setupMobileMenu() { $("#open-menu-mobile").click(function () { $("#menu-mobile").animate({ "margin-right": "0px" }, 300); }); $("#close-menu-mobile").click(function () { $("#menu-mobile").animate({ "margin-right": "-300px" }, 300); }); } async function setupDownloadPage() { if (!$('.page-download').length) return; const downloadLinks = {}; $('.page-download .get-it-desktop a').each(function() { const href = $(this).attr('href'); // The arm64 installer is also named "-Setup", so it must be excluded // from the x64 link even when disabled, or it would overwrite it. if (href.indexOf('-arm64.exe') > 0) { if (windowsArm64Enabled) downloadLinks['windowsArm64'] = href; } else if (href.indexOf('-Setup') > 0) downloadLinks['windows'] = href; if (href.indexOf('.dmg') > 0) downloadLinks['macOs'] = href; if (href.indexOf('arm64.DMG') > 0) downloadLinks['macOsM1'] = href; if (href.indexOf('.AppImage') > 0) downloadLinks['linux'] = href; }); $('.page-download .get-it-desktop').hide(); $('.page-download .download-click-here').click((event) => { event.preventDefault(); $('.page-download .get-it-desktop').show(500); }); const mobileOs = getMobileOs(); if (mobileOs) { $('.page-download .intro').hide(); } else { const os = await getOs(); console.info('Found OS: ' + os); if (os === 'macOsUndefined') { // If we don't know which macOS version it is, we let the user choose. $('.main-content .intro').html('
The macOS release is available for Intel processors or for Apple Silicon (M1) processors. Please select your version:
'); const macOsLink = $('.download-link-macOs'); const macOsM1Link = $('.download-link-macOsM1'); $('.macos-m1-info').after('To find out what processor you have, click on the Apple logo in the macOS menu bar, choose About This Mac from the dropdown menu. If you have an Apple silicon it should say"Apple M1" under "Chip". Otherwise you have an Intel processor.
'); $('.macos-m1-info').after(macOsM1Link); $('.macos-m1-info').after(macOsLink); } else if (!os || !downloadLinks[os]) { // If we don't know, display the section to manually download the app $('.page-download .get-it-desktop').show(); } else if (os === 'linux') { // If it's Linux, the user should probably install it using the // install script so we redirect to the install section window.location = 'https://joplinapp.org/help/install'; } else { // Otherwise, start the download const downloadLink = downloadLinks[os]; $('.downloaded-filename').text(getFilename(downloadLink)); window.location = downloadLink; } } } // Supported locale path prefixes (language code -> URL path) // Most languages use their code directly (fr, de), with exceptions mapped here const localePathOverrides = { 'zh': 'cn', }; // List of supported language codes const supportedLanguages = ['fr', 'de', 'hr', 'zh']; function getLocalePath(langCode) { const pathPrefix = localePathOverrides[langCode] || langCode; return '/' + pathPrefix; } function setupLocaleRedirect() { // Only redirect on the front page (root path or index.html) const path = window.location.pathname; const isRootPage = path === '/' || path === '/index.html' || path === ''; if (!isRootPage) return; // Check if user has explicitly chosen to stay on current locale const localePreference = (localStorage.getItem('joplin-locale-preference') || '').toLowerCase(); if (localePreference === 'en') return; // Get user's preferred language from browser const browserLang = (navigator.language || navigator.userLanguage || '').toLowerCase(); // Extract the base language code (e.g., 'fr' from 'fr-ca') const langCode = browserLang.split('-')[0]; // Check if we support this language if (!supportedLanguages.includes(langCode)) return; window.location.href = getLocalePath(langCode) + '/'; } // Allow users to switch language and remember their preference function setLocalePreference(locale, url) { localStorage.setItem('joplin-locale-preference', locale); window.location.href = url; } // Expose globally for language switcher links window.setLocalePreference = setLocalePreference; $(function () { setupMobileMenu(); setupLocaleRedirect(); void setupDownloadPage(); });