Files
SnapOtter/apps/docs/.vitepress/theme/MachineTranslationBanner.vue
T
SnapOtterandGitHub 00b651c9f8 feat(i18n): 21-language pipeline, landing/docs/API wiring, landing+API translations
Shared Claude Code translation pipeline (scripts/i18n, no API key) plus Astro/VitePress/Scalar i18n wiring. Landing and API reference translated into all 20 languages; docs i18n wiring + English source anchors. The translated docs markdown (apps/docs/<locale>/**, 3,620 files) follows in a companion PR because it exceeds GitHub's per-PR CI file limit.
2026-07-11 13:01:55 +08:00

65 lines
1.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { useData } from "vitepress";
import { computed, ref } from "vue";
import { normalizeLocale, t } from "../i18n/ui.mjs";
const { lang } = useData();
// Guard both existence AND callability: VitePress SSR defines a `localStorage`
// global that is not a real Storage, so `getItem` may not be a function there.
function readDismissed() {
try {
return (
typeof localStorage?.getItem === "function" && localStorage.getItem("so-mt-banner") === "1"
);
} catch {
return false;
}
}
const dismissed = ref(readDismissed());
const locale = computed(() => normalizeLocale(lang.value));
const show = computed(() => locale.value !== "en" && !dismissed.value);
const text = computed(() => t(locale.value, "banner.text"));
const cta = computed(() => t(locale.value, "banner.cta"));
function dismiss() {
dismissed.value = true;
try {
localStorage.setItem("so-mt-banner", "1");
} catch {
// ignore storage failures (private mode)
}
}
</script>
<template>
<div v-if="show" class="mt-banner" role="note">
<span>{{ text }}</span>
<a href="https://github.com/snapotter-hq/snapotter/blob/main/apps/docs/guide/translations.md">{{ cta }}</a>
<button type="button" class="mt-dismiss" aria-label="Dismiss" @click="dismiss">×</button>
</div>
</template>
<style scoped>
.mt-banner {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 16px;
font-size: 13px;
background: #FFF5ED;
border-bottom: 1px solid #EBDDCC;
color: #7A4A1E;
}
.mt-banner a { color: #A85518; font-weight: 600; }
.mt-dismiss {
margin-inline-start: auto;
border: 0;
background: transparent;
font-size: 18px;
line-height: 1;
cursor: pointer;
color: inherit;
}
:root.dark .mt-banner { background: #241A13; border-color: #3A2C20; color: #E0C6A8; }
</style>